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 rndm = 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(); 103 } 104 synchronized (engine) { 105 engine.getInstance(algorithm, null); 106 return new KeyAgreement((KeyAgreementSpi) engine.spi, engine.provider, 107 algorithm); 108 } 109 } 110 111 /** 112 * Creates a new {@code KeyAgreement} for the specified algorithm from the 113 * specified provider. 114 * 115 * @param algorithm 116 * the name of the key agreement algorithm to create. 117 * @param provider 118 * the name of the provider that provides the requested 119 * algorithm. 120 * @return a key agreement for the specified algorithm from the specified 121 * provider. 122 * @throws NoSuchAlgorithmException 123 * if the specified provider cannot provide the requested 124 * algorithm. 125 * @throws NoSuchProviderException 126 * if the specified provider does not exist. 127 * @throws IllegalArgumentException 128 * if the specified provider name is {@code null} or empty. 129 */ 130 public static final KeyAgreement getInstance(String algorithm, 131 String provider) throws NoSuchAlgorithmException, 132 NoSuchProviderException { 133 if (provider == null || provider.isEmpty()) { 134 throw new IllegalArgumentException("Provider is null or empty"); 135 } 136 Provider impProvider = Security.getProvider(provider); 137 if (impProvider == null) { 138 throw new NoSuchProviderException(provider); 139 } 140 return getInstance(algorithm, impProvider); 141 } 142 143 /** 144 * Create a new {@code KeyAgreement} for the specified algorithm from the 145 * specified provider. 146 * 147 * @param algorithm 148 * the name of the key agreement algorithm to create. 149 * @param provider 150 * the provider that provides the requested algorithm. 151 * @return a key agreement for the specified algorithm from the specified 152 * provider. 153 * @throws NoSuchAlgorithmException 154 * if the specified provider cannot provide the requested 155 * algorithm. 156 * @throws IllegalArgumentException 157 * if the specified provider is {@code null}. 158 * @throws NullPointerException 159 * if the specified algorithm name is {@code null}. 160 */ 161 public static final KeyAgreement getInstance(String algorithm, 162 Provider provider) throws NoSuchAlgorithmException { 163 if (provider == null) { 164 throw new IllegalArgumentException("provider == null"); 165 } 166 if (algorithm == null) { 167 throw new NullPointerException(); 168 } 169 synchronized (engine) { 170 engine.getInstance(algorithm, provider, null); 171 return new KeyAgreement((KeyAgreementSpi) engine.spi, provider, 172 algorithm); 173 } 174 } 175 176 /** 177 * Initializes this {@code KeyAgreement} with the specified key. 178 * 179 * @param key 180 * the key to initialize this key agreement. 181 * @throws InvalidKeyException 182 * if the specified key cannot be used to initialize this key 183 * agreement. 184 */ 185 public final void init(Key key) throws InvalidKeyException { 186 spiImpl.engineInit(key, rndm);//new SecureRandom()); 187 } 188 189 /** 190 * Initializes this {@code KeyAgreement} with the specified key and the 191 * specified randomness source. 192 * 193 * @param key 194 * the key to initialize this key agreement. 195 * @param random 196 * the source for any randomness needed. 197 * @throws InvalidKeyException 198 * if the specified key cannot be used to initialize this key 199 * agreement. 200 */ 201 public final void init(Key key, SecureRandom random) 202 throws InvalidKeyException { 203 spiImpl.engineInit(key, random); 204 } 205 206 /** 207 * Initializes this {@code KeyAgreement} with the specified key and the 208 * algorithm parameters. 209 * 210 * @param key 211 * the key to initialize this key agreement. 212 * @param params 213 * the parameters for this key agreement algorithm. 214 * @throws InvalidKeyException 215 * if the specified key cannot be used to initialize this key 216 * agreement. 217 * @throws InvalidAlgorithmParameterException 218 * if the specified parameters are invalid for this key 219 * agreement algorithm. 220 */ 221 public final void init(Key key, AlgorithmParameterSpec params) 222 throws InvalidKeyException, InvalidAlgorithmParameterException { 223 spiImpl.engineInit(key, params, rndm);//new SecureRandom()); 224 } 225 226 /** 227 * Initializes this {@code KeyAgreement} with the specified key, algorithm 228 * parameters and randomness source. 229 * 230 * @param key 231 * the key to initialize this key agreement. 232 * @param params 233 * the parameters for this key agreement algorithm. 234 * @param random 235 * the source for any randomness needed. 236 * @throws InvalidKeyException 237 * if the specified key cannot be used to initialize this key 238 * agreement. 239 * @throws InvalidAlgorithmParameterException 240 * if the specified parameters are invalid for this key 241 * agreement algorithm. 242 */ 243 public final void init(Key key, AlgorithmParameterSpec params, 244 SecureRandom random) throws InvalidKeyException, 245 InvalidAlgorithmParameterException { 246 spiImpl.engineInit(key, params, random); 247 } 248 249 /** 250 * Does the next (or the last) phase of the key agreement, using the 251 * specified key. 252 * 253 * @param key 254 * the key received from the other party for this phase. 255 * @param lastPhase 256 * set to {@code true} if this is the last phase of this key 257 * agreement. 258 * @return the intermediate key from this phase or {@code null} if there is 259 * no intermediate key for this phase. 260 * @throws InvalidKeyException 261 * if the specified key cannot be used in this key agreement or 262 * this phase, 263 * @throws IllegalStateException 264 * if this instance has not been initialized. 265 */ 266 public final Key doPhase(Key key, boolean lastPhase) 267 throws InvalidKeyException, IllegalStateException { 268 return spiImpl.engineDoPhase(key, lastPhase); 269 } 270 271 /** 272 * Generates the shared secret. 273 * 274 * @return the generated shared secret. 275 * @throws IllegalStateException 276 * if this key agreement is not complete. 277 */ 278 public final byte[] generateSecret() throws IllegalStateException { 279 return spiImpl.engineGenerateSecret(); 280 } 281 282 /** 283 * Generates the shared secret and stores it into the buffer {@code 284 * sharedSecred} at {@code offset}. 285 * 286 * @param sharedSecret 287 * the buffer to store the shared secret. 288 * @param offset 289 * the offset in the buffer. 290 * @return the number of bytes stored in the buffer. 291 * @throws IllegalStateException 292 * if this key agreement is not complete. 293 * @throws ShortBufferException 294 * if the specified buffer is too small for the shared secret. 295 */ 296 public final int generateSecret(byte[] sharedSecret, int offset) 297 throws IllegalStateException, ShortBufferException { 298 return spiImpl.engineGenerateSecret(sharedSecret, offset); 299 } 300 301 /** 302 * Generates the shared secret. 303 * 304 * @param algorithm 305 * the algorithm to for the {@code SecretKey} 306 * @return the shared secret as a {@code SecretKey} of the specified 307 * algorithm. 308 * @throws IllegalStateException 309 * if this key agreement is not complete. 310 * @throws NoSuchAlgorithmException 311 * if the specified algorithm for the secret key does not 312 * exists. 313 * @throws InvalidKeyException 314 * if a {@code SecretKey} with the specified algorithm cannot be 315 * created using the generated shared secret. 316 */ 317 public final SecretKey generateSecret(String algorithm) 318 throws IllegalStateException, NoSuchAlgorithmException, 319 InvalidKeyException { 320 return spiImpl.engineGenerateSecret(algorithm); 321 } 322 323 } 324