1 /* |
1 /* |
2 * Copyright (c) 2001, 2007, Oracle and/or its affiliates. All rights reserved. |
2 * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * |
4 * |
5 * This code is free software; you can redistribute it and/or modify it |
5 * This code is free software; you can redistribute it and/or modify it |
6 * under the terms of the GNU General Public License version 2 only, as |
6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. Oracle designates this |
7 * published by the Free Software Foundation. Oracle designates this |
78 throws IOException { |
78 throws IOException { |
79 if (encoded == null) { |
79 if (encoded == null) { |
80 throw new NullPointerException("the encoded parameter " + |
80 throw new NullPointerException("the encoded parameter " + |
81 "must be non-null"); |
81 "must be non-null"); |
82 } |
82 } |
83 this.encoded = (byte[])encoded.clone(); |
83 this.encoded = encoded.clone(); |
84 DerValue val = new DerValue(this.encoded); |
84 DerValue val = new DerValue(this.encoded); |
85 |
85 |
86 DerValue[] seq = new DerValue[2]; |
86 DerValue[] seq = new DerValue[2]; |
87 |
87 |
88 seq[0] = val.data.getDerValue(); |
88 seq[0] = val.data.getDerValue(); |
141 "parameter must be non-null"); |
141 "parameter must be non-null"); |
142 } else if (encryptedData.length == 0) { |
142 } else if (encryptedData.length == 0) { |
143 throw new IllegalArgumentException("the encryptedData " + |
143 throw new IllegalArgumentException("the encryptedData " + |
144 "parameter must not be empty"); |
144 "parameter must not be empty"); |
145 } else { |
145 } else { |
146 this.encryptedData = (byte[])encryptedData.clone(); |
146 this.encryptedData = encryptedData.clone(); |
147 } |
147 } |
148 // delay the generation of ASN.1 encoding until |
148 // delay the generation of ASN.1 encoding until |
149 // getEncoded() is called |
149 // getEncoded() is called |
150 this.encoded = null; |
150 this.encoded = null; |
151 } |
151 } |
181 throw new NullPointerException("encryptedData must be non-null"); |
181 throw new NullPointerException("encryptedData must be non-null"); |
182 } else if (encryptedData.length == 0) { |
182 } else if (encryptedData.length == 0) { |
183 throw new IllegalArgumentException("the encryptedData " + |
183 throw new IllegalArgumentException("the encryptedData " + |
184 "parameter must not be empty"); |
184 "parameter must not be empty"); |
185 } else { |
185 } else { |
186 this.encryptedData = (byte[])encryptedData.clone(); |
186 this.encryptedData = encryptedData.clone(); |
187 } |
187 } |
188 |
188 |
189 // delay the generation of ASN.1 encoding until |
189 // delay the generation of ASN.1 encoding until |
190 // getEncoded() is called |
190 // getEncoded() is called |
191 this.encoded = null; |
191 this.encoded = null; |
220 * Returns the encrypted data. |
220 * Returns the encrypted data. |
221 * @return the encrypted data. Returns a new array |
221 * @return the encrypted data. Returns a new array |
222 * each time this method is called. |
222 * each time this method is called. |
223 */ |
223 */ |
224 public byte[] getEncryptedData() { |
224 public byte[] getEncryptedData() { |
225 return (byte[])this.encryptedData.clone(); |
225 return this.encryptedData.clone(); |
226 } |
226 } |
227 |
227 |
228 /** |
228 /** |
229 * Extract the enclosed PKCS8EncodedKeySpec object from the |
229 * Extract the enclosed PKCS8EncodedKeySpec object from the |
230 * encrypted data and return it. |
230 * encrypted data and return it. |
245 */ |
245 */ |
246 public PKCS8EncodedKeySpec getKeySpec(Cipher cipher) |
246 public PKCS8EncodedKeySpec getKeySpec(Cipher cipher) |
247 throws InvalidKeySpecException { |
247 throws InvalidKeySpecException { |
248 byte[] encoded = null; |
248 byte[] encoded = null; |
249 try { |
249 try { |
250 encoded = cipher.doFinal((byte[])encryptedData); |
250 encoded = cipher.doFinal(encryptedData); |
251 checkPKCS8Encoding(encoded); |
251 checkPKCS8Encoding(encoded); |
252 } catch (GeneralSecurityException gse) { |
252 } catch (GeneralSecurityException | |
253 InvalidKeySpecException ikse = new |
253 IOException | |
254 InvalidKeySpecException( |
254 IllegalStateException ex) { |
255 "Cannot retrieve the PKCS8EncodedKeySpec"); |
255 throw new InvalidKeySpecException( |
256 ikse.initCause(gse); |
256 "Cannot retrieve the PKCS8EncodedKeySpec", ex); |
257 throw ikse; |
|
258 } catch (IOException ioe) { |
|
259 InvalidKeySpecException ikse = new |
|
260 InvalidKeySpecException( |
|
261 "Cannot retrieve the PKCS8EncodedKeySpec"); |
|
262 ikse.initCause(ioe); |
|
263 throw ikse; |
|
264 } catch (IllegalStateException ise) { |
|
265 InvalidKeySpecException ikse = new |
|
266 InvalidKeySpecException( |
|
267 "Cannot retrieve the PKCS8EncodedKeySpec"); |
|
268 ikse.initCause(ise); |
|
269 throw ikse; |
|
270 } |
257 } |
271 return new PKCS8EncodedKeySpec(encoded); |
258 return new PKCS8EncodedKeySpec(encoded); |
272 } |
259 } |
273 |
260 |
274 private PKCS8EncodedKeySpec getKeySpecImpl(Key decryptKey, |
261 private PKCS8EncodedKeySpec getKeySpecImpl(Key decryptKey, |
287 encoded = c.doFinal(encryptedData); |
274 encoded = c.doFinal(encryptedData); |
288 checkPKCS8Encoding(encoded); |
275 checkPKCS8Encoding(encoded); |
289 } catch (NoSuchAlgorithmException nsae) { |
276 } catch (NoSuchAlgorithmException nsae) { |
290 // rethrow |
277 // rethrow |
291 throw nsae; |
278 throw nsae; |
292 } catch (GeneralSecurityException gse) { |
279 } catch (GeneralSecurityException | IOException ex) { |
293 InvalidKeyException ike = new InvalidKeyException |
280 throw new InvalidKeyException( |
294 ("Cannot retrieve the PKCS8EncodedKeySpec"); |
281 "Cannot retrieve the PKCS8EncodedKeySpec", ex); |
295 ike.initCause(gse); |
|
296 throw ike; |
|
297 } catch (IOException ioe) { |
|
298 InvalidKeyException ike = new InvalidKeyException |
|
299 ("Cannot retrieve the PKCS8EncodedKeySpec"); |
|
300 ike.initCause(ioe); |
|
301 throw ike; |
|
302 } |
282 } |
303 return new PKCS8EncodedKeySpec(encoded); |
283 return new PKCS8EncodedKeySpec(encoded); |
304 } |
284 } |
305 |
285 |
306 /** |
286 /** |
411 |
391 |
412 // wrap everything into a SEQUENCE |
392 // wrap everything into a SEQUENCE |
413 out.write(DerValue.tag_Sequence, tmp); |
393 out.write(DerValue.tag_Sequence, tmp); |
414 this.encoded = out.toByteArray(); |
394 this.encoded = out.toByteArray(); |
415 } |
395 } |
416 return (byte[])this.encoded.clone(); |
396 return this.encoded.clone(); |
417 } |
397 } |
418 |
398 |
419 private static void checkTag(DerValue val, byte tag, String valName) |
399 private static void checkTag(DerValue val, byte tag, String valName) |
420 throws IOException { |
400 throws IOException { |
421 if (val.getTag() != tag) { |
401 if (val.getTag() != tag) { |
422 throw new IOException("invalid key encoding - wrong tag for " + |
402 throw new IOException("invalid key encoding - wrong tag for " + |
423 valName); |
403 valName); |
424 } |
404 } |
425 } |
405 } |
426 |
406 |
|
407 @SuppressWarnings("fallthrough") |
427 private static void checkPKCS8Encoding(byte[] encodedKey) |
408 private static void checkPKCS8Encoding(byte[] encodedKey) |
428 throws IOException { |
409 throws IOException { |
429 DerInputStream in = new DerInputStream(encodedKey); |
410 DerInputStream in = new DerInputStream(encodedKey); |
430 DerValue[] values = in.getSequence(3); |
411 DerValue[] values = in.getSequence(3); |
431 |
412 |
432 switch (values.length) { |
413 switch (values.length) { |
433 case 4: |
414 case 4: |
434 checkTag(values[3], DerValue.TAG_CONTEXT, "attributes"); |
415 checkTag(values[3], DerValue.TAG_CONTEXT, "attributes"); |
|
416 /* fall through */ |
435 case 3: |
417 case 3: |
436 checkTag(values[0], DerValue.tag_Integer, "version"); |
418 checkTag(values[0], DerValue.tag_Integer, "version"); |
437 DerInputStream algid = values[1].toDerInputStream(); |
419 DerInputStream algid = values[1].toDerInputStream(); |
438 algid.getOID(); |
420 algid.getOID(); |
439 if (algid.available() != 0) { |
421 if (algid.available() != 0) { |