|
30 | 30 | import javax.crypto.BadPaddingException;
|
31 | 31 | import javax.crypto.Cipher;
|
32 | 32 | import javax.crypto.IllegalBlockSizeException;
|
| 33 | +import javax.crypto.SecretKey; |
| 34 | +import javax.crypto.SecretKeyFactory; |
| 35 | +import javax.crypto.spec.IvParameterSpec; |
| 36 | +import javax.crypto.spec.PBEKeySpec; |
| 37 | +import javax.crypto.spec.PBEParameterSpec; |
33 | 38 | import javax.crypto.spec.SecretKeySpec;
|
34 | 39 |
|
35 | 40 | import org.mindrot.jbcrypt.BCrypt;
|
|
70 | 75 | public class SecurityUtils {
|
71 | 76 | private static Logger logger = Logger.getLogger(SecurityUtils.class.getName());
|
72 | 77 |
|
73 |
| - /* Blowfish AES encryption with SHA key */ |
74 |
| - private static final String KEY_FACTORY = "PBEWITHSHA-256AND256BITAES-CBC-BC"; |
| 78 | + // Factory to use for version 2 of encryption. |
| 79 | + private static final String KEY_FACTORY_V2 = "AES"; |
| 80 | + private static final String CIPHER_FACTORY_V2 = "AES/CBC/PKCS5Padding"; |
| 81 | + |
| 82 | + private static final String KEY_FACTORY = "AES"; |
| 83 | + private static final String CIPHER_FACTORY = "AES/CBC/PKCS5Padding"; |
| 84 | + |
75 | 85 | /* encrypted file header id */
|
76 | 86 | static final byte[] SIGNATURE = {0x22, 0x34, 0x56, 0x79};
|
77 | 87 |
|
@@ -301,12 +311,16 @@ public static CipherInfo createCiphers(byte[] password, CipherParms cipherParms)
|
301 | 311 | // generate the ciphers
|
302 | 312 | BCrypt bcrypt = new BCrypt();
|
303 | 313 | byte[] rawBytes = bcrypt.crypt_raw(passwordWithDelim, info.parms.salt, info.parms.rounds, plaintext);
|
304 |
| - SecretKeySpec spec = new SecretKeySpec(rawBytes, KEY_FACTORY); |
305 |
| - info.encryptCipher = Cipher.getInstance(KEY_FACTORY); |
306 |
| - info.encryptCipher.init(Cipher.ENCRYPT_MODE, spec); |
| 314 | + SecretKeySpec spec = new SecretKeySpec(rawBytes, KEY_FACTORY); |
| 315 | + // For backwards compatibility with secrets created on Android M and |
| 316 | + // earlier, create an initial vector of all zeros. |
| 317 | + IvParameterSpec params = new IvParameterSpec(new byte[16]); |
| 318 | + |
| 319 | + info.encryptCipher = Cipher.getInstance(CIPHER_FACTORY); |
| 320 | + info.encryptCipher.init(Cipher.ENCRYPT_MODE, spec, params); |
307 | 321 |
|
308 |
| - info.decryptCipher = Cipher.getInstance(KEY_FACTORY); |
309 |
| - info.decryptCipher.init(Cipher.DECRYPT_MODE, spec); |
| 322 | + info.decryptCipher = Cipher.getInstance(CIPHER_FACTORY); |
| 323 | + info.decryptCipher.init(Cipher.DECRYPT_MODE, spec, params); |
310 | 324 | } catch (Exception ex) {
|
311 | 325 | String msg = "Error creating ciphers - " + ex;
|
312 | 326 | logger.log(Level.SEVERE, msg, ex);
|
@@ -339,6 +353,8 @@ public static CipherParms getCipherParms(InputStream input) throws IOException {
|
339 | 353 | byte[] salt = null;
|
340 | 354 | int rounds = 0;
|
341 | 355 |
|
| 356 | + logger.log(Level.INFO, "getCipherParms"); |
| 357 | + input.reset(); |
342 | 358 | input.read(); // version, not currently used
|
343 | 359 | input.read(signature); // signature bytes
|
344 | 360 | if (Arrays.equals(signature, SIGNATURE)) {
|
@@ -404,12 +420,15 @@ public static void writeSecurityHeader(CipherParms parms, OutputStream os) throw
|
404 | 420 | public static void main(String[] args) throws UnsupportedEncodingException {
|
405 | 421 |
|
406 | 422 | long start = System.currentTimeMillis();
|
| 423 | + checkBCProvider(); |
| 424 | + SecretsProperties.getInitialInstance(".", true); |
407 | 425 |
|
408 | 426 | try {
|
409 | 427 | CipherInfo cipherInfo = createCiphers("secretstring".getBytes("UTF-8"), null);
|
410 | 428 |
|
411 | 429 | // Our cleartext
|
412 |
| - byte[] cleartext = "This is another example".getBytes(); |
| 430 | + byte[] cleartext = "This is another example ".getBytes(); |
| 431 | + System.out.println("Clear string: " + Strings.toHex(cleartext)); |
413 | 432 |
|
414 | 433 | // Encrypt the cleartext
|
415 | 434 | byte[] ciphertext = cipherInfo.encryptCipher.doFinal(cleartext);
|
|
0 commit comments