31 import java.security.InvalidAlgorithmParameterException; |
31 import java.security.InvalidAlgorithmParameterException; |
32 import java.security.InvalidKeyException; |
32 import java.security.InvalidKeyException; |
33 import java.security.Key; |
33 import java.security.Key; |
34 import java.security.NoSuchAlgorithmException; |
34 import java.security.NoSuchAlgorithmException; |
35 import java.security.SecureRandom; |
35 import java.security.SecureRandom; |
|
36 import java.security.ProviderException; |
36 import java.security.spec.AlgorithmParameterSpec; |
37 import java.security.spec.AlgorithmParameterSpec; |
37 import java.security.spec.InvalidKeySpecException; |
38 import java.security.spec.InvalidKeySpecException; |
38 import javax.crypto.KeyAgreementSpi; |
39 import javax.crypto.KeyAgreementSpi; |
39 import javax.crypto.ShortBufferException; |
40 import javax.crypto.ShortBufferException; |
40 import javax.crypto.SecretKey; |
41 import javax.crypto.SecretKey; |
232 * completed yet |
233 * completed yet |
233 */ |
234 */ |
234 protected byte[] engineGenerateSecret() |
235 protected byte[] engineGenerateSecret() |
235 throws IllegalStateException |
236 throws IllegalStateException |
236 { |
237 { |
237 if (generateSecret == false) { |
238 int expectedLen = (init_p.bitLength() + 7) >>> 3; |
238 throw new IllegalStateException |
239 byte[] result = new byte[expectedLen]; |
239 ("Key agreement has not been completed yet"); |
240 try { |
240 } |
241 engineGenerateSecret(result, 0); |
241 |
242 } catch (ShortBufferException sbe) { |
242 // Reset the key agreement here (in case anything goes wrong) |
243 // should never happen since length are identical |
243 generateSecret = false; |
244 } |
244 |
245 return result; |
245 // get the modulus |
|
246 BigInteger modulus = init_p; |
|
247 |
|
248 BigInteger tmpResult = y.modPow(x, modulus); |
|
249 byte[] secret = tmpResult.toByteArray(); |
|
250 |
|
251 /* |
|
252 * BigInteger.toByteArray will sometimes put a sign byte up front, but |
|
253 * we NEVER want one. |
|
254 */ |
|
255 if ((tmpResult.bitLength() % 8) == 0) { |
|
256 byte retval[] = new byte[secret.length - 1]; |
|
257 System.arraycopy(secret, 1, retval, 0, retval.length); |
|
258 return retval; |
|
259 } else { |
|
260 return secret; |
|
261 } |
|
262 } |
246 } |
263 |
247 |
264 /** |
248 /** |
265 * Generates the shared secret, and places it into the buffer |
249 * Generates the shared secret, and places it into the buffer |
266 * <code>sharedSecret</code>, beginning at <code>offset</code>. |
250 * <code>sharedSecret</code>, beginning at <code>offset</code>. |
299 throw new ShortBufferException |
283 throw new ShortBufferException |
300 ("No buffer provided for shared secret"); |
284 ("No buffer provided for shared secret"); |
301 } |
285 } |
302 |
286 |
303 BigInteger modulus = init_p; |
287 BigInteger modulus = init_p; |
|
288 int expectedLen = (modulus.bitLength() + 7) >>> 3; |
|
289 if ((sharedSecret.length - offset) < expectedLen) { |
|
290 throw new ShortBufferException |
|
291 ("Buffer too short for shared secret"); |
|
292 } |
|
293 |
|
294 // Reset the key agreement after checking for ShortBufferException |
|
295 // above, so user can recover w/o losing internal state |
|
296 generateSecret = false; |
|
297 |
|
298 /* |
|
299 * NOTE: BigInteger.toByteArray() returns a byte array containing |
|
300 * the two's-complement representation of this BigInteger with |
|
301 * the most significant byte is in the zeroth element. This |
|
302 * contains the minimum number of bytes required to represent |
|
303 * this BigInteger, including at least one sign bit whose value |
|
304 * is always 0. |
|
305 * |
|
306 * Keys are always positive, and the above sign bit isn't |
|
307 * actually used when representing keys. (i.e. key = new |
|
308 * BigInteger(1, byteArray)) To obtain an array containing |
|
309 * exactly expectedLen bytes of magnitude, we strip any extra |
|
310 * leading 0's, or pad with 0's in case of a "short" secret. |
|
311 */ |
304 byte[] secret = this.y.modPow(this.x, modulus).toByteArray(); |
312 byte[] secret = this.y.modPow(this.x, modulus).toByteArray(); |
305 |
313 if (secret.length == expectedLen) { |
306 // BigInteger.toByteArray will sometimes put a sign byte up front, |
314 System.arraycopy(secret, 0, sharedSecret, offset, |
307 // but we NEVER want one. |
315 secret.length); |
308 if ((secret.length << 3) != modulus.bitLength()) { |
316 } else { |
309 if ((sharedSecret.length - offset) < (secret.length - 1)) { |
317 // Array too short, pad it w/ leading 0s |
310 throw new ShortBufferException |
318 if (secret.length < expectedLen) { |
311 ("Buffer too short for shared secret"); |
319 System.arraycopy(secret, 0, sharedSecret, |
|
320 offset + (expectedLen - secret.length), |
|
321 secret.length); |
|
322 } else { |
|
323 // Array too long, check and trim off the excess |
|
324 if ((secret.length == (expectedLen+1)) && secret[0] == 0) { |
|
325 // ignore the leading sign byte |
|
326 System.arraycopy(secret, 1, sharedSecret, offset, expectedLen); |
|
327 } else { |
|
328 throw new ProviderException("Generated secret is out-of-range"); |
|
329 } |
312 } |
330 } |
313 System.arraycopy(secret, 1, sharedSecret, offset, |
331 } |
314 secret.length - 1); |
332 return expectedLen; |
315 |
|
316 // Reset the key agreement here (not earlier!), so that people |
|
317 // can recover from ShortBufferException above without losing |
|
318 // internal state |
|
319 generateSecret = false; |
|
320 |
|
321 return secret.length - 1; |
|
322 |
|
323 } else { |
|
324 if ((sharedSecret.length - offset) < secret.length) { |
|
325 throw new ShortBufferException |
|
326 ("Buffer too short to hold shared secret"); |
|
327 } |
|
328 System.arraycopy(secret, 0, sharedSecret, offset, secret.length); |
|
329 |
|
330 // Reset the key agreement here (not earlier!), so that people |
|
331 // can recover from ShortBufferException above without losing |
|
332 // internal state |
|
333 generateSecret = false; |
|
334 |
|
335 return secret.length; |
|
336 } |
|
337 } |
333 } |
338 |
334 |
339 /** |
335 /** |
340 * Creates the shared secret and returns it as a secret key object |
336 * Creates the shared secret and returns it as a secret key object |
341 * of the requested algorithm type. |
337 * of the requested algorithm type. |