1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package javax.crypto; 19 20 import java.security.InvalidAlgorithmParameterException; 21 import java.security.InvalidKeyException; 22 import java.security.Key; 23 import java.security.NoSuchAlgorithmException; 24 import java.security.NoSuchProviderException; 25 import java.security.Provider; 26 import java.security.SecureRandom; 27 import java.security.Security; 28 import java.security.spec.AlgorithmParameterSpec; 29 import org.apache.harmony.security.fortress.Engine; 30 31 /** 32 * This class provides the functionality for a key exchange protocol. This 33 * enables two or more parties to agree on a secret key for symmetric 34 * cryptography. 35 */ 36 public class KeyAgreement { 37 38 // Used to access common engine functionality 39 private static final Engine ENGINE = new Engine("KeyAgreement"); 40 41 // Store SecureRandom 42 private static final SecureRandom RANDOM = new SecureRandom(); 43 44 // Store used provider 45 private final Provider provider; 46 47 // Store used spi implementation 48 private final KeyAgreementSpi spiImpl; 49 50 // Store used algorithm name 51 private final String algorithm; 52 53 /** 54 * Creates a new {@code KeyAgreement} instance. 55 * 56 * @param keyAgreeSpi 57 * the <b>SPI</b> delegate. 58 * @param provider 59 * the provider providing this KeyAgreement. 60 * @param algorithm 61 * the name of the key agreement algorithm. 62 */ 63 protected KeyAgreement(KeyAgreementSpi keyAgreeSpi, Provider provider, 64 String algorithm) { 65 this.provider = provider; 66 this.algorithm = algorithm; 67 this.spiImpl = keyAgreeSpi; 68 } 69 70 /** 71 * Returns the name of the key agreement algorithm. 72 * 73 * @return the name of the key agreement algorithm. 74 */ 75 public final String getAlgorithm() { 76 return algorithm; 77 } 78 79 /** 80 * Returns the provider for this {@code KeyAgreement} instance. 81 * 82 * @return the provider for this {@code KeyAgreement} instance. 83 */ 84 public final Provider getProvider() { 85 return provider; 86 } 87 88 /** 89 * Creates a new {@code KeyAgreement} for the specified algorithm. 90 * 91 * @param algorithm 92 * the name of the key agreement algorithm to create. 93 * @return a key agreement for the specified algorithm. 94 * @throws NoSuchAlgorithmException 95 * if no installed provider can provide the requested algorithm. 96 * @throws NullPointerException 97 * if the specified algorithm is {@code null}. 98 */ 99 public static final KeyAgreement getInstance(String algorithm) 100 throws NoSuchAlgorithmException { 101 if (algorithm == null) { 102 throw new NullPointerException("algorithm == null"); 103 } 104 Engine.SpiAndProvider sap = ENGINE.getInstance(algorithm, null); 105 return new KeyAgreement((KeyAgreementSpi) sap.spi, sap.provider, algorithm); 106 } 107 108 /** 109 * Creates a new {@code KeyAgreement} for the specified algorithm from the 110 * specified provider. 111 * 112 * @param algorithm 113 * the name of the key agreement algorithm to create. 114 * @param provider 115 * the name of the provider that provides the requested 116 * algorithm. 117 * @return a key agreement for the specified algorithm from the specified 118 * provider. 119 * @throws NoSuchAlgorithmException 120 * if the specified provider cannot provide the requested 121 * algorithm. 122 * @throws NoSuchProviderException 123 * if the specified provider does not exist. 124 * @throws IllegalArgumentException 125 * if the specified provider name is {@code null} or empty. 126 */ 127 public static final KeyAgreement getInstance(String algorithm, 128 String provider) throws NoSuchAlgorithmException, 129 NoSuchProviderException { 130 if (provider == null || provider.isEmpty()) { 131 throw new IllegalArgumentException("Provider is null or empty"); 132 } 133 Provider impProvider = Security.getProvider(provider); 134 if (impProvider == null) { 135 throw new NoSuchProviderException(provider); 136 } 137 return getInstance(algorithm, impProvider); 138 } 139 140 /** 141 * Create a new {@code KeyAgreement} for the specified algorithm from the 142 * specified provider. 143 * 144 * @param algorithm 145 * the name of the key agreement algorithm to create. 146 * @param provider 147 * the provider that provides the requested algorithm. 148 * @return a key agreement for the specified algorithm from the specified 149 * provider. 150 * @throws NoSuchAlgorithmException 151 * if the specified provider cannot provide the requested 152 * algorithm. 153 * @throws IllegalArgumentException 154 * if the specified provider is {@code null}. 155 * @throws NullPointerException 156 * if the specified algorithm name is {@code null}. 157 */ 158 public static final KeyAgreement getInstance(String algorithm, 159 Provider provider) throws NoSuchAlgorithmException { 160 if (provider == null) { 161 throw new IllegalArgumentException("provider == null"); 162 } 163 if (algorithm == null) { 164 throw new NullPointerException("algorithm == null"); 165 } 166 Object spi = ENGINE.getInstance(algorithm, provider, null); 167 return new KeyAgreement((KeyAgreementSpi) spi, provider, algorithm); 168 } 169 170 /** 171 * Initializes this {@code KeyAgreement} with the specified key. 172 * 173 * @param key 174 * the key to initialize this key agreement. 175 * @throws InvalidKeyException 176 * if the specified key cannot be used to initialize this key 177 * agreement. 178 */ 179 public final void init(Key key) throws InvalidKeyException { 180 spiImpl.engineInit(key, RANDOM);//new SecureRandom()); 181 } 182 183 /** 184 * Initializes this {@code KeyAgreement} with the specified key and the 185 * specified randomness source. 186 * 187 * @param key 188 * the key to initialize this key agreement. 189 * @param random 190 * the source for any randomness needed. 191 * @throws InvalidKeyException 192 * if the specified key cannot be used to initialize this key 193 * agreement. 194 */ 195 public final void init(Key key, SecureRandom random) 196 throws InvalidKeyException { 197 spiImpl.engineInit(key, random); 198 } 199 200 /** 201 * Initializes this {@code KeyAgreement} with the specified key and the 202 * algorithm parameters. 203 * 204 * @param key 205 * the key to initialize this key agreement. 206 * @param params 207 * the parameters for this key agreement algorithm. 208 * @throws InvalidKeyException 209 * if the specified key cannot be used to initialize this key 210 * agreement. 211 * @throws InvalidAlgorithmParameterException 212 * if the specified parameters are invalid for this key 213 * agreement algorithm. 214 */ 215 public final void init(Key key, AlgorithmParameterSpec params) 216 throws InvalidKeyException, InvalidAlgorithmParameterException { 217 spiImpl.engineInit(key, params, RANDOM);//new SecureRandom()); 218 } 219 220 /** 221 * Initializes this {@code KeyAgreement} with the specified key, algorithm 222 * parameters and randomness source. 223 * 224 * @param key 225 * the key to initialize this key agreement. 226 * @param params 227 * the parameters for this key agreement algorithm. 228 * @param random 229 * the source for any randomness needed. 230 * @throws InvalidKeyException 231 * if the specified key cannot be used to initialize this key 232 * agreement. 233 * @throws InvalidAlgorithmParameterException 234 * if the specified parameters are invalid for this key 235 * agreement algorithm. 236 */ 237 public final void init(Key key, AlgorithmParameterSpec params, 238 SecureRandom random) throws InvalidKeyException, 239 InvalidAlgorithmParameterException { 240 spiImpl.engineInit(key, params, random); 241 } 242 243 /** 244 * Does the next (or the last) phase of the key agreement, using the 245 * specified key. 246 * 247 * @param key 248 * the key received from the other party for this phase. 249 * @param lastPhase 250 * set to {@code true} if this is the last phase of this key 251 * agreement. 252 * @return the intermediate key from this phase or {@code null} if there is 253 * no intermediate key for this phase. 254 * @throws InvalidKeyException 255 * if the specified key cannot be used in this key agreement or 256 * this phase, 257 * @throws IllegalStateException 258 * if this instance has not been initialized. 259 */ 260 public final Key doPhase(Key key, boolean lastPhase) 261 throws InvalidKeyException, IllegalStateException { 262 return spiImpl.engineDoPhase(key, lastPhase); 263 } 264 265 /** 266 * Generates the shared secret. 267 * 268 * @return the generated shared secret. 269 * @throws IllegalStateException 270 * if this key agreement is not complete. 271 */ 272 public final byte[] generateSecret() throws IllegalStateException { 273 return spiImpl.engineGenerateSecret(); 274 } 275 276 /** 277 * Generates the shared secret and stores it into the buffer {@code 278 * sharedSecred} at {@code offset}. 279 * 280 * @param sharedSecret 281 * the buffer to store the shared secret. 282 * @param offset 283 * the offset in the buffer. 284 * @return the number of bytes stored in the buffer. 285 * @throws IllegalStateException 286 * if this key agreement is not complete. 287 * @throws ShortBufferException 288 * if the specified buffer is too small for the shared secret. 289 */ 290 public final int generateSecret(byte[] sharedSecret, int offset) 291 throws IllegalStateException, ShortBufferException { 292 return spiImpl.engineGenerateSecret(sharedSecret, offset); 293 } 294 295 /** 296 * Generates the shared secret. 297 * 298 * @param algorithm 299 * the algorithm to for the {@code SecretKey} 300 * @return the shared secret as a {@code SecretKey} of the specified 301 * algorithm. 302 * @throws IllegalStateException 303 * if this key agreement is not complete. 304 * @throws NoSuchAlgorithmException 305 * if the specified algorithm for the secret key does not 306 * exists. 307 * @throws InvalidKeyException 308 * if a {@code SecretKey} with the specified algorithm cannot be 309 * created using the generated shared secret. 310 */ 311 public final SecretKey generateSecret(String algorithm) 312 throws IllegalStateException, NoSuchAlgorithmException, 313 InvalidKeyException { 314 return spiImpl.engineGenerateSecret(algorithm); 315 } 316 317 } 318