106 (javax.crypto.interfaces.PBEKey) key; |
106 (javax.crypto.interfaces.PBEKey) key; |
107 passwdChars = pbeKey.getPassword(); |
107 passwdChars = pbeKey.getPassword(); |
108 salt = pbeKey.getSalt(); // maybe null if unspecified |
108 salt = pbeKey.getSalt(); // maybe null if unspecified |
109 iCount = pbeKey.getIterationCount(); // maybe 0 if unspecified |
109 iCount = pbeKey.getIterationCount(); // maybe 0 if unspecified |
110 } else if (key instanceof SecretKey) { |
110 } else if (key instanceof SecretKey) { |
111 byte[] passwdBytes = key.getEncoded(); |
111 byte[] passwdBytes; |
112 if ((passwdBytes == null) || |
112 if (!(key.getAlgorithm().regionMatches(true, 0, "PBE", 0, 3)) || |
113 !(key.getAlgorithm().regionMatches(true, 0, "PBE", 0, 3))) { |
113 (passwdBytes = key.getEncoded()) == null) { |
114 throw new InvalidKeyException("Missing password"); |
114 throw new InvalidKeyException("Missing password"); |
115 } |
115 } |
116 passwdChars = new char[passwdBytes.length]; |
116 passwdChars = new char[passwdBytes.length]; |
117 for (int i=0; i<passwdChars.length; i++) { |
117 for (int i=0; i<passwdChars.length; i++) { |
118 passwdChars[i] = (char) (passwdBytes[i] & 0x7f); |
118 passwdChars[i] = (char) (passwdBytes[i] & 0x7f); |
119 } |
119 } |
|
120 Arrays.fill(passwdBytes, (byte)0x00); |
120 } else { |
121 } else { |
121 throw new InvalidKeyException("SecretKey of PBE type required"); |
122 throw new InvalidKeyException("SecretKey of PBE type required"); |
122 } |
123 } |
123 if (params == null) { |
124 |
124 // should not auto-generate default values since current |
125 PBEKeySpec pbeSpec; |
125 // javax.crypto.Mac api does not have any method for caller to |
126 try { |
126 // retrieve the generated defaults. |
127 if (params == null) { |
127 if ((salt == null) || (iCount == 0)) { |
128 // should not auto-generate default values since current |
|
129 // javax.crypto.Mac api does not have any method for caller to |
|
130 // retrieve the generated defaults. |
|
131 if ((salt == null) || (iCount == 0)) { |
|
132 throw new InvalidAlgorithmParameterException |
|
133 ("PBEParameterSpec required for salt and iteration count"); |
|
134 } |
|
135 } else if (!(params instanceof PBEParameterSpec)) { |
128 throw new InvalidAlgorithmParameterException |
136 throw new InvalidAlgorithmParameterException |
129 ("PBEParameterSpec required for salt and iteration count"); |
137 ("PBEParameterSpec type required"); |
130 } |
138 } else { |
131 } else if (!(params instanceof PBEParameterSpec)) { |
139 PBEParameterSpec pbeParams = (PBEParameterSpec) params; |
132 throw new InvalidAlgorithmParameterException |
140 // make sure the parameter values are consistent |
133 ("PBEParameterSpec type required"); |
141 if (salt != null) { |
134 } else { |
142 if (!Arrays.equals(salt, pbeParams.getSalt())) { |
135 PBEParameterSpec pbeParams = (PBEParameterSpec) params; |
143 throw new InvalidAlgorithmParameterException |
136 // make sure the parameter values are consistent |
144 ("Inconsistent value of salt between key and params"); |
137 if (salt != null) { |
145 } |
138 if (!Arrays.equals(salt, pbeParams.getSalt())) { |
146 } else { |
139 throw new InvalidAlgorithmParameterException |
147 salt = pbeParams.getSalt(); |
140 ("Inconsistent value of salt between key and params"); |
|
141 } |
148 } |
142 } else { |
149 if (iCount != 0) { |
143 salt = pbeParams.getSalt(); |
150 if (iCount != pbeParams.getIterationCount()) { |
144 } |
151 throw new InvalidAlgorithmParameterException |
145 if (iCount != 0) { |
152 ("Different iteration count between key and params"); |
146 if (iCount != pbeParams.getIterationCount()) { |
153 } |
147 throw new InvalidAlgorithmParameterException |
154 } else { |
148 ("Different iteration count between key and params"); |
155 iCount = pbeParams.getIterationCount(); |
149 } |
156 } |
150 } else { |
157 } |
151 iCount = pbeParams.getIterationCount(); |
158 // For security purpose, we need to enforce a minimum length |
152 } |
159 // for salt; just require the minimum salt length to be 8-byte |
153 } |
160 // which is what PKCS#5 recommends and openssl does. |
154 // For security purpose, we need to enforce a minimum length |
161 if (salt.length < 8) { |
155 // for salt; just require the minimum salt length to be 8-byte |
162 throw new InvalidAlgorithmParameterException |
156 // which is what PKCS#5 recommends and openssl does. |
163 ("Salt must be at least 8 bytes long"); |
157 if (salt.length < 8) { |
164 } |
158 throw new InvalidAlgorithmParameterException |
165 if (iCount <= 0) { |
159 ("Salt must be at least 8 bytes long"); |
166 throw new InvalidAlgorithmParameterException |
160 } |
167 ("IterationCount must be a positive number"); |
161 if (iCount <= 0) { |
168 } |
162 throw new InvalidAlgorithmParameterException |
169 |
163 ("IterationCount must be a positive number"); |
170 pbeSpec = new PBEKeySpec(passwdChars, salt, iCount, blockLength); |
164 } |
|
165 |
|
166 PBEKeySpec pbeSpec = |
|
167 new PBEKeySpec(passwdChars, salt, iCount, blockLength); |
|
168 // password char[] was cloned in PBEKeySpec constructor, |
171 // password char[] was cloned in PBEKeySpec constructor, |
169 // so we can zero it out here |
172 // so we can zero it out here |
170 java.util.Arrays.fill(passwdChars, ' '); |
173 } finally { |
171 |
174 Arrays.fill(passwdChars, '\0'); |
172 SecretKey s = null; |
175 } |
|
176 |
|
177 SecretKey s; |
173 PBKDF2Core kdf = getKDFImpl(kdfAlgo); |
178 PBKDF2Core kdf = getKDFImpl(kdfAlgo); |
174 try { |
179 try { |
175 s = kdf.engineGenerateSecret(pbeSpec); |
180 s = kdf.engineGenerateSecret(pbeSpec); |
176 |
|
177 } catch (InvalidKeySpecException ikse) { |
181 } catch (InvalidKeySpecException ikse) { |
178 InvalidKeyException ike = |
182 InvalidKeyException ike = |
179 new InvalidKeyException("Cannot construct PBE key"); |
183 new InvalidKeyException("Cannot construct PBE key"); |
180 ike.initCause(ikse); |
184 ike.initCause(ikse); |
181 throw ike; |
185 throw ike; |