266 (javax.crypto.interfaces.PBEKey) key; |
267 (javax.crypto.interfaces.PBEKey) key; |
267 passwdChars = pbeKey.getPassword(); |
268 passwdChars = pbeKey.getPassword(); |
268 salt = pbeKey.getSalt(); // maybe null if unspecified |
269 salt = pbeKey.getSalt(); // maybe null if unspecified |
269 iCount = pbeKey.getIterationCount(); // maybe 0 if unspecified |
270 iCount = pbeKey.getIterationCount(); // maybe 0 if unspecified |
270 } else if (key instanceof SecretKey) { |
271 } else if (key instanceof SecretKey) { |
271 byte[] passwdBytes = key.getEncoded(); |
272 byte[] passwdBytes; |
272 if ((passwdBytes == null) || |
273 if (!(key.getAlgorithm().regionMatches(true, 0, "PBE", 0, 3)) || |
273 !(key.getAlgorithm().regionMatches(true, 0, "PBE", 0, 3))) { |
274 (passwdBytes = key.getEncoded()) == null) { |
274 throw new InvalidKeyException("Missing password"); |
275 throw new InvalidKeyException("Missing password"); |
275 } |
276 } |
276 passwdChars = new char[passwdBytes.length]; |
277 passwdChars = new char[passwdBytes.length]; |
277 for (int i=0; i<passwdChars.length; i++) { |
278 for (int i=0; i<passwdChars.length; i++) { |
278 passwdChars[i] = (char) (passwdBytes[i] & 0x7f); |
279 passwdChars[i] = (char) (passwdBytes[i] & 0x7f); |
279 } |
280 } |
|
281 Arrays.fill(passwdBytes, (byte)0x00); |
280 } else { |
282 } else { |
281 throw new InvalidKeyException("SecretKey of PBE type required"); |
283 throw new InvalidKeyException("SecretKey of PBE type required"); |
282 } |
284 } |
283 |
285 |
284 if (((opmode == Cipher.DECRYPT_MODE) || |
286 try { |
285 (opmode == Cipher.UNWRAP_MODE)) && |
287 if (((opmode == Cipher.DECRYPT_MODE) || |
286 ((params == null) && ((salt == null) || (iCount == 0)))) { |
288 (opmode == Cipher.UNWRAP_MODE)) && |
287 throw new InvalidAlgorithmParameterException |
289 ((params == null) && ((salt == null) || (iCount == 0)))) { |
288 ("Parameters missing"); |
290 throw new InvalidAlgorithmParameterException |
289 } |
291 ("Parameters missing"); |
290 |
292 } |
291 if (params == null) { |
293 |
292 // generate default for salt and iteration count if necessary |
294 if (params == null) { |
293 if (salt == null) { |
295 // generate default for salt and iteration count if necessary |
294 salt = new byte[DEFAULT_SALT_LENGTH]; |
296 if (salt == null) { |
295 if (random != null) { |
297 salt = new byte[DEFAULT_SALT_LENGTH]; |
296 random.nextBytes(salt); |
298 if (random != null) { |
|
299 random.nextBytes(salt); |
|
300 } else { |
|
301 SunJCE.getRandom().nextBytes(salt); |
|
302 } |
|
303 } |
|
304 if (iCount == 0) iCount = DEFAULT_COUNT; |
|
305 } else if (!(params instanceof PBEParameterSpec)) { |
|
306 throw new InvalidAlgorithmParameterException |
|
307 ("PBEParameterSpec type required"); |
|
308 } else { |
|
309 PBEParameterSpec pbeParams = (PBEParameterSpec) params; |
|
310 // make sure the parameter values are consistent |
|
311 if (salt != null) { |
|
312 if (!Arrays.equals(salt, pbeParams.getSalt())) { |
|
313 throw new InvalidAlgorithmParameterException |
|
314 ("Inconsistent value of salt between key and params"); |
|
315 } |
297 } else { |
316 } else { |
298 SunJCE.getRandom().nextBytes(salt); |
317 salt = pbeParams.getSalt(); |
299 } |
318 } |
300 } |
319 if (iCount != 0) { |
301 if (iCount == 0) iCount = DEFAULT_COUNT; |
320 if (iCount != pbeParams.getIterationCount()) { |
302 } else if (!(params instanceof PBEParameterSpec)) { |
321 throw new InvalidAlgorithmParameterException |
303 throw new InvalidAlgorithmParameterException |
322 ("Different iteration count between key and params"); |
304 ("PBEParameterSpec type required"); |
323 } |
305 } else { |
324 } else { |
306 PBEParameterSpec pbeParams = (PBEParameterSpec) params; |
325 iCount = pbeParams.getIterationCount(); |
307 // make sure the parameter values are consistent |
|
308 if (salt != null) { |
|
309 if (!Arrays.equals(salt, pbeParams.getSalt())) { |
|
310 throw new InvalidAlgorithmParameterException |
|
311 ("Inconsistent value of salt between key and params"); |
|
312 } |
326 } |
|
327 } |
|
328 // salt is recommended to be ideally as long as the output |
|
329 // of the hash function. However, it may be too strict to |
|
330 // force this; so instead, we'll just require the minimum |
|
331 // salt length to be 8-byte which is what PKCS#5 recommends |
|
332 // and openssl does. |
|
333 if (salt.length < 8) { |
|
334 throw new InvalidAlgorithmParameterException |
|
335 ("Salt must be at least 8 bytes long"); |
|
336 } |
|
337 if (iCount <= 0) { |
|
338 throw new InvalidAlgorithmParameterException |
|
339 ("IterationCount must be a positive number"); |
|
340 } |
|
341 byte[] derivedKey = derive(passwdChars, salt, iCount, |
|
342 keySize, CIPHER_KEY); |
|
343 SecretKey cipherKey = new SecretKeySpec(derivedKey, algo); |
|
344 |
|
345 if (cipherImpl != null && cipherImpl instanceof ARCFOURCipher) { |
|
346 ((ARCFOURCipher)cipherImpl).engineInit(opmode, cipherKey, random); |
|
347 |
313 } else { |
348 } else { |
314 salt = pbeParams.getSalt(); |
349 byte[] derivedIv = derive(passwdChars, salt, iCount, 8, |
315 } |
350 CIPHER_IV); |
316 if (iCount != 0) { |
351 IvParameterSpec ivSpec = new IvParameterSpec(derivedIv, 0, 8); |
317 if (iCount != pbeParams.getIterationCount()) { |
352 |
318 throw new InvalidAlgorithmParameterException |
353 // initialize the underlying cipher |
319 ("Different iteration count between key and params"); |
354 cipher.init(opmode, cipherKey, ivSpec, random); |
320 } |
355 } |
321 } else { |
356 } finally { |
322 iCount = pbeParams.getIterationCount(); |
357 Arrays.fill(passwdChars, '\0'); |
323 } |
|
324 } |
|
325 // salt is recommended to be ideally as long as the output |
|
326 // of the hash function. However, it may be too strict to |
|
327 // force this; so instead, we'll just require the minimum |
|
328 // salt length to be 8-byte which is what PKCS#5 recommends |
|
329 // and openssl does. |
|
330 if (salt.length < 8) { |
|
331 throw new InvalidAlgorithmParameterException |
|
332 ("Salt must be at least 8 bytes long"); |
|
333 } |
|
334 if (iCount <= 0) { |
|
335 throw new InvalidAlgorithmParameterException |
|
336 ("IterationCount must be a positive number"); |
|
337 } |
|
338 byte[] derivedKey = derive(passwdChars, salt, iCount, |
|
339 keySize, CIPHER_KEY); |
|
340 SecretKey cipherKey = new SecretKeySpec(derivedKey, algo); |
|
341 |
|
342 if (cipherImpl != null && cipherImpl instanceof ARCFOURCipher) { |
|
343 ((ARCFOURCipher)cipherImpl).engineInit(opmode, cipherKey, random); |
|
344 |
|
345 } else { |
|
346 byte[] derivedIv = derive(passwdChars, salt, iCount, 8, |
|
347 CIPHER_IV); |
|
348 IvParameterSpec ivSpec = new IvParameterSpec(derivedIv, 0, 8); |
|
349 |
|
350 // initialize the underlying cipher |
|
351 cipher.init(opmode, cipherKey, ivSpec, random); |
|
352 } |
358 } |
353 } |
359 } |
354 |
360 |
355 void implInit(int opmode, Key key, AlgorithmParameters params, |
361 void implInit(int opmode, Key key, AlgorithmParameters params, |
356 SecureRandom random) |
362 SecureRandom random) |