|
8 | 8 |
|
9 | 9 | import javax.crypto.Cipher; |
10 | 10 | import javax.crypto.SecretKey; |
| 11 | +import javax.crypto.spec.SecretKeySpec; |
11 | 12 |
|
| 13 | +import org.bouncycastle.asn1.misc.MiscObjectIdentifiers; |
| 14 | +import org.bouncycastle.asn1.misc.ScryptParams; |
12 | 15 | import org.bouncycastle.asn1.pkcs.EncryptionScheme; |
13 | 16 | import org.bouncycastle.asn1.pkcs.KeyDerivationFunc; |
14 | 17 | import org.bouncycastle.asn1.pkcs.PBEParameter; |
|
17 | 20 | import org.bouncycastle.asn1.pkcs.PKCS12PBEParams; |
18 | 21 | import org.bouncycastle.asn1.x509.AlgorithmIdentifier; |
19 | 22 | import org.bouncycastle.crypto.CharToByteConverter; |
| 23 | +import org.bouncycastle.crypto.generators.SCrypt; |
20 | 24 | import org.bouncycastle.jcajce.PBKDF1KeyWithParameters; |
21 | 25 | import org.bouncycastle.jcajce.PKCS12KeyWithParameters; |
22 | 26 | import org.bouncycastle.jcajce.io.CipherInputStream; |
@@ -73,24 +77,43 @@ public InputDecryptor get(final AlgorithmIdentifier algorithm) |
73 | 77 | PBES2Parameters params = PBES2Parameters.getInstance(algorithm.getParameters()); |
74 | 78 | KeyDerivationFunc func = params.getKeyDerivationFunc(); |
75 | 79 | EncryptionScheme scheme = params.getEncryptionScheme(); |
76 | | - PBKDF2Params defParams = (PBKDF2Params)func.getParameters(); |
77 | | - |
78 | | - int iterationCount = defParams.getIterationCount().intValue(); |
79 | | - byte[] salt = defParams.getSalt(); |
80 | 80 |
|
81 | 81 | String oid = scheme.getAlgorithm().getId(); |
82 | | - |
83 | 82 | SecretKey key; |
84 | 83 |
|
85 | | - if (PEMUtilities.isHmacSHA1(defParams.getPrf())) |
| 84 | + if (MiscObjectIdentifiers.id_scrypt.equals(func.getAlgorithm())) |
86 | 85 | { |
87 | | - key = PEMUtilities.generateSecretKeyForPKCS5Scheme2(helper, oid, password, salt, iterationCount); |
| 86 | + // RFC 7914 / RFC 8018 scrypt KDF inside PBES2. |
| 87 | + // OpenSSL 1.1+ "openssl pkcs8 -topk8 -scrypt" produces this form; |
| 88 | + // the caller-supplied char[] password is fed as UTF-8 bytes, |
| 89 | + // matching OpenSSL's raw-bytes treatment (github #400). |
| 90 | + ScryptParams scrypt = ScryptParams.getInstance(func.getParameters()); |
| 91 | + int keySizeBits = PEMUtilities.getKeySize(oid); |
| 92 | + byte[] derived = SCrypt.generate(Strings.toUTF8ByteArray(password), |
| 93 | + scrypt.getSalt(), |
| 94 | + scrypt.getCostParameter().intValue(), |
| 95 | + scrypt.getBlockSize().intValue(), |
| 96 | + scrypt.getParallelizationParameter().intValue(), |
| 97 | + (keySizeBits + 7) / 8); |
| 98 | + key = new SecretKeySpec(derived, PEMUtilities.getAlgorithmName(oid)); |
88 | 99 | } |
89 | 100 | else |
90 | 101 | { |
91 | | - key = PEMUtilities.generateSecretKeyForPKCS5Scheme2(helper, oid, password, salt, iterationCount, defParams.getPrf()); |
| 102 | + PBKDF2Params defParams = (PBKDF2Params)func.getParameters(); |
| 103 | + |
| 104 | + int iterationCount = defParams.getIterationCount().intValue(); |
| 105 | + byte[] salt = defParams.getSalt(); |
| 106 | + |
| 107 | + if (PEMUtilities.isHmacSHA1(defParams.getPrf())) |
| 108 | + { |
| 109 | + key = PEMUtilities.generateSecretKeyForPKCS5Scheme2(helper, oid, password, salt, iterationCount); |
| 110 | + } |
| 111 | + else |
| 112 | + { |
| 113 | + key = PEMUtilities.generateSecretKeyForPKCS5Scheme2(helper, oid, password, salt, iterationCount, defParams.getPrf()); |
| 114 | + } |
92 | 115 | } |
93 | | - |
| 116 | + |
94 | 117 | cipher = helper.createCipher(PEMUtilities.getCipherName(scheme.getAlgorithm())); |
95 | 118 | AlgorithmParameters algParams = helper.createAlgorithmParameters(oid); |
96 | 119 |
|
|
0 commit comments