1 package javax.crypto; 2 3 import java.security.Key; 4 import java.security.Provider; 5 import java.security.SecureRandom; 6 import java.security.InvalidKeyException; 7 import java.security.NoSuchProviderException; 8 import java.security.NoSuchAlgorithmException; 9 import java.security.InvalidAlgorithmParameterException; 10 import java.security.spec.AlgorithmParameterSpec; 11 12 /** 13 * This class provides the functionality of a key agreement (or key 14 * exchange) protocol. 15 * The keys involved in establishing a shared secret are created by one of the 16 * key generators (<code>KeyPairGenerator</code> or 17 * <code>KeyGenerator</code>), a <code>KeyFactory</code>, or as a result from 18 * an intermediate phase of the key agreement protocol 19 * (see <a href = "#doPhase(java.security.Key, boolean)">doPhase</a>). 20 * 21 * For each of the correspondents in the key exchange, <code>doPhase</code> 22 * needs to be called. For example, if this key exchange is with one other 23 * party, <code>doPhase</code> needs to be called once, with the 24 * <code>lastPhase</code> flag set to <code>true</code>. 25 * If this key exchange is 26 * with two other parties, <code>doPhase</code> needs to be called twice, 27 * the first time setting the <code>lastPhase</code> flag to 28 * <code>false</code>, and the second time setting it to <code>true</code>. 29 * There may be any number of parties involved in a key exchange. 30 * 31 * @see KeyGenerator 32 * @see SecretKey 33 */ 34 public class KeyAgreement 35 { 36 KeyAgreementSpi keyAgreeSpi; 37 Provider provider; 38 String algorithm; 39 40 /** 41 * Creates a KeyAgreement object. 42 * 43 * @param keyAgreeSpi the delegate 44 * @param provider the provider 45 * @param algorithm the algorithm 46 */ KeyAgreement( KeyAgreementSpi keyAgreeSpi, Provider provider, String algorithm)47 protected KeyAgreement( 48 KeyAgreementSpi keyAgreeSpi, 49 Provider provider, 50 String algorithm) 51 { 52 this.keyAgreeSpi = keyAgreeSpi; 53 this.provider = provider; 54 this.algorithm = algorithm; 55 } 56 57 /** 58 * Returns the algorithm name of this <code>KeyAgreement</code> object. 59 * <p> 60 * This is the same name that was specified in one of the 61 * <code>getInstance</code> calls that created this 62 * <code>KeyAgreement</code> object. 63 * 64 * @return the algorithm name of this <code>KeyAgreement</code> object. 65 */ getAlgorithm()66 public final String getAlgorithm() 67 { 68 return algorithm; 69 } 70 71 /** 72 * Generates a <code>KeyAgreement</code> object that implements the 73 * specified key agreement algorithm. 74 * If the default provider package provides an implementation of the 75 * requested key agreement algorithm, an instance of 76 * <code>KeyAgreement</code> containing that implementation is returned. 77 * If the algorithm is not available in the default provider package, 78 * other provider packages are searched. 79 * 80 * @param algorithm the standard name of the requested key agreement algorithm. 81 * See Appendix A in the Java Cryptography Extension API Specification & Reference 82 * for information about standard algorithm names. 83 * @return the new <code>KeyAgreement</code> object 84 * @exception NoSuchAlgorithmException if the specified algorithm is not 85 * available in the default provider package or any of the other provider 86 * packages that were searched. 87 */ getInstance( String algorithm)88 public static final KeyAgreement getInstance( 89 String algorithm) 90 throws NoSuchAlgorithmException 91 { 92 try 93 { 94 JCEUtil.Implementation imp = JCEUtil.getImplementation("KeyAgreement", algorithm, (String) null); 95 96 if (imp == null) 97 { 98 throw new NoSuchAlgorithmException(algorithm + " not found"); 99 } 100 101 KeyAgreement keyAgree = new KeyAgreement((KeyAgreementSpi)imp.getEngine(), imp.getProvider(), algorithm); 102 103 return keyAgree; 104 } 105 catch (NoSuchProviderException e) 106 { 107 throw new NoSuchAlgorithmException(algorithm + " not found"); 108 } 109 } 110 111 /** 112 * Generates a <code>KeyAgreement</code> object for the specified key 113 * agreement algorithm from the specified provider. 114 * 115 * @param algorithm the standard name of the requested key agreement algorithm. 116 * See Appendix A in the Java Cryptography Extension API Specification & Reference 117 * for information about standard algorithm names. 118 * @param provider the provider 119 * @return the new <code>KeyAgreement</code> object 120 * @exception NoSuchAlgorithmException if the specified algorithm is not 121 * available from the specified provider. 122 */ getInstance( String algorithm, Provider provider)123 public static final KeyAgreement getInstance( 124 String algorithm, 125 Provider provider) 126 throws NoSuchAlgorithmException 127 { 128 if (provider == null) 129 { 130 throw new IllegalArgumentException("No provider specified to KeyAgreement.getInstance()"); 131 } 132 133 JCEUtil.Implementation imp = JCEUtil.getImplementation("KeyAgreement", algorithm, provider); 134 135 if (imp == null) 136 { 137 throw new NoSuchAlgorithmException(algorithm + " not found"); 138 } 139 140 KeyAgreement keyAgree = new KeyAgreement((KeyAgreementSpi)imp.getEngine(), imp.getProvider(), algorithm); 141 142 return keyAgree; 143 } 144 145 /** 146 * Generates a <code>KeyAgreement</code> object for the specified key 147 * agreement algorithm from the specified provider. 148 * 149 * @param algorithm the standard name of the requested key agreement algorithm. 150 * See Appendix A in the Java Cryptography Extension API Specification & Reference 151 * for information about standard algorithm names. 152 * @param provider the name of the provider 153 * @return the new <code>KeyAgreement</code> object 154 * @exception NoSuchAlgorithmException if the specified algorithm is not 155 * available from the specified provider. 156 * @exception NoSuchProviderException if the specified provider has not 157 * been configured. 158 */ getInstance( String algorithm, String provider)159 public static final KeyAgreement getInstance( 160 String algorithm, 161 String provider) 162 throws NoSuchAlgorithmException, NoSuchProviderException 163 { 164 if (provider == null) 165 { 166 throw new IllegalArgumentException("No provider specified to KeyAgreement.getInstance()"); 167 } 168 169 JCEUtil.Implementation imp = JCEUtil.getImplementation("KeyAgreement", algorithm, provider); 170 171 if (imp == null) 172 { 173 throw new NoSuchAlgorithmException(algorithm + " not found"); 174 } 175 176 KeyAgreement keyAgree = new KeyAgreement((KeyAgreementSpi)imp.getEngine(), imp.getProvider(), algorithm); 177 178 return keyAgree; 179 } 180 181 /** 182 * Returns the provider of this <code>KeyAgreement</code> object. 183 * 184 * @return the provider of this <code>KeyAgreement</code> object 185 */ getProvider()186 public final Provider getProvider() 187 { 188 return provider; 189 } 190 191 /** 192 * Initializes this key agreement with the given key, which is required to 193 * contain all the algorithm parameters required for this key agreement. 194 * <p> 195 * If this key agreement requires any random bytes, it will get 196 * them using the <a href="http://java.sun.com/products/jdk/1.2/docs/api/java.security.SecureRandom.html"> 197 * <code>SecureRandom</code></a> implementation of the highest-priority 198 * installed provider as the source of randomness. 199 * (If none of the installed providers supply an implementation of 200 * SecureRandom, a system-provided source of randomness will be used.) 201 * 202 * @param key the party's private information. For example, in the case 203 * of the Diffie-Hellman key agreement, this would be the party's own 204 * Diffie-Hellman private key. 205 * @exception InvalidKeyException if the given key is 206 * inappropriate for this key agreement, e.g., is of the wrong type or 207 * has an incompatible algorithm type. 208 */ init( Key key)209 public final void init( 210 Key key) 211 throws InvalidKeyException 212 { 213 keyAgreeSpi.engineInit(key, null); 214 } 215 216 /** 217 * Initializes this key agreement with the given key and source of 218 * randomness. The given key is required to contain all the algorithm 219 * parameters required for this key agreement. 220 * <p> 221 * If the key agreement algorithm requires random bytes, it gets them 222 * from the given source of randomness, <code>random</code>. 223 * However, if the underlying 224 * algorithm implementation does not require any random bytes, 225 * <code>random</code> is ignored. 226 * 227 * @param key the party's private information. For example, in the case 228 * of the Diffie-Hellman key agreement, this would be the party's own 229 * Diffie-Hellman private key. 230 * @param random the source of randomness 231 * @exception InvalidKeyException if the given key is 232 * inappropriate for this key agreement, e.g., is of the wrong type or 233 * has an incompatible algorithm type. 234 */ init( Key key, SecureRandom random)235 public final void init( 236 Key key, 237 SecureRandom random) 238 throws InvalidKeyException 239 { 240 keyAgreeSpi.engineInit(key, random); 241 } 242 243 /** 244 * Initializes this key agreement with the given key and set of 245 * algorithm parameters. 246 * <p> 247 * If this key agreement requires any random bytes, it will get 248 * them using the <a href="http://java.sun.com/products/jdk/1.2/docs/api/java.security.SecureRandom.html"> 249 * <code>SecureRandom</code></a> implementation of the highest-priority 250 * installed provider as the source of randomness. 251 * (If none of the installed providers supply an implementation of 252 * SecureRandom, a system-provided source of randomness will be used.) 253 * 254 * @param key the party's private information. For example, in the case 255 * of the Diffie-Hellman key agreement, this would be the party's own 256 * Diffie-Hellman private key. 257 * @param params the key agreement parameters 258 * @exception InvalidKeyException if the given key is inappropriate for this 259 * key agreement, e.g., is of the wrong type or has an incompatible algorithm type. 260 * @exception InvalidAlgorithmParameterException if the given parameters 261 * are inappropriate for this key agreement. 262 */ init( Key key, AlgorithmParameterSpec params)263 public final void init( 264 Key key, 265 AlgorithmParameterSpec params) 266 throws InvalidKeyException, InvalidAlgorithmParameterException 267 { 268 keyAgreeSpi.engineInit(key, params, null); 269 } 270 271 /** 272 * Initializes this key agreement with the given key, set of 273 * algorithm parameters, and source of randomness. 274 * 275 * @param key the party's private information. For example, in the case 276 * of the Diffie-Hellman key agreement, this would be the party's own 277 * Diffie-Hellman private key. 278 * @param params the key agreement parameters 279 * @param random the source of randomness 280 * @exception InvalidKeyException if the given key is 281 * inappropriate for this key agreement, e.g., is of the wrong type or 282 * has an incompatible algorithm type. 283 * @exception InvalidAlgorithmParameterException if the given parameters 284 * are inappropriate for this key agreement. 285 */ init( Key key, AlgorithmParameterSpec params, SecureRandom random)286 public final void init( 287 Key key, 288 AlgorithmParameterSpec params, 289 SecureRandom random) 290 throws InvalidKeyException, InvalidAlgorithmParameterException 291 { 292 keyAgreeSpi.engineInit(key, params, random); 293 } 294 295 /** 296 * Executes the next phase of this key agreement with the given 297 * key that was received from one of the other parties involved in this key 298 * agreement. 299 * 300 * @param key the key for this phase. For example, in the case of 301 * Diffie-Hellman between 2 parties, this would be the other party's 302 * Diffie-Hellman public key. 303 * @param lastPhase flag which indicates whether or not this is the last 304 * phase of this key agreement. 305 * @return the (intermediate) key resulting from this phase, or null 306 * if this phase does not yield a key 307 * @exception InvalidKeyException if the given key is inappropriate for this phase. 308 * @exception IllegalStateException if this key agreement has not been 309 * initialized. 310 */ doPhase( Key key, boolean lastPhase)311 public final Key doPhase( 312 Key key, 313 boolean lastPhase) 314 throws InvalidKeyException, IllegalStateException 315 { 316 return keyAgreeSpi.engineDoPhase(key, lastPhase); 317 } 318 319 /** 320 * Generates the shared secret and returns it in a new buffer. 321 * <p> 322 * This method resets this <code>KeyAgreement</code> object, so that it 323 * can be reused for further key agreements. Unless this key agreement is 324 * reinitialized with one of the <code>init</code> methods, the same 325 * private information and algorithm parameters will be used for 326 * subsequent key agreements. 327 * 328 * @return the new buffer with the shared secret 329 * @exception IllegalStateException if this key agreement has not been completed yet 330 */ generateSecret()331 public final byte[] generateSecret() 332 throws IllegalStateException 333 { 334 return keyAgreeSpi.engineGenerateSecret(); 335 } 336 337 /** 338 * Generates the shared secret, and places it into the buffer 339 * <code>sharedSecret</code>, beginning at <code>offset</code> inclusive. 340 * <p> 341 * If the <code>sharedSecret</code> buffer is too small to hold the 342 * result, a <code>ShortBufferException</code> is thrown. 343 * In this case, this call should be repeated with a larger output buffer. 344 * <p> 345 * This method resets this <code>KeyAgreement</code> object, so that it 346 * can be reused for further key agreements. Unless this key agreement is 347 * reinitialized with one of the <code>init</code> methods, the same 348 * private information and algorithm parameters will be used for 349 * subsequent key agreements. 350 * 351 * @param sharedSecret the buffer for the shared secret 352 * @param offset the offset in <code>sharedSecret</code> where the 353 * shared secret will be stored 354 * @return the number of bytes placed into <code>sharedSecret</code> 355 * @exception IllegalStateException if this key agreement has not been 356 * completed yet 357 * @exception ShortBufferException if the given output buffer is too small 358 * to hold the secret 359 */ generateSecret( byte[] sharedSecret, int offset)360 public final int generateSecret( 361 byte[] sharedSecret, 362 int offset) 363 throws IllegalStateException, ShortBufferException 364 { 365 return keyAgreeSpi.engineGenerateSecret(sharedSecret, offset); 366 } 367 368 /** 369 * Creates the shared secret and returns it as a <code>SecretKey</code> 370 * object of the specified algorithm. 371 * <p> 372 * This method resets this <code>KeyAgreement</code> object, so that it 373 * can be reused for further key agreements. Unless this key agreement is 374 * reinitialized with one of the <code>init</code> methods, the same 375 * private information and algorithm parameters will be used for 376 * subsequent key agreements. 377 * 378 * @param algorithm the requested secret-key algorithm 379 * @return the shared secret key 380 * @exception IllegalStateException if this key agreement has not been 381 * completed yet 382 * @exception NoSuchAlgorithmException if the specified secret-key 383 * algorithm is not available 384 * @exception InvalidKeyException if the shared secret-key material cannot 385 * be used to generate a secret key of the specified algorithm (e.g., 386 * the key material is too short) 387 */ generateSecret( String algorithm)388 public final SecretKey generateSecret( 389 String algorithm) 390 throws IllegalStateException, NoSuchAlgorithmException, InvalidKeyException 391 { 392 return keyAgreeSpi.engineGenerateSecret(algorithm); 393 } 394 } 395