From fe7da345dcbcf61e4c8561006f0c15c64902b249 Mon Sep 17 00:00:00 2001 From: David Hook Date: Thu, 30 May 2013 21:40:58 +1000 Subject: UTF8 patch for PBKDF2 --- .../bouncycastle/jcajce/provider/digest/SHA1.java | 2 +- .../jcajce/provider/symmetric/util/BCPBEKey.java | 4 ++ .../jcajce/provider/symmetric/util/PBE.java | 47 +++++++++++++--------- .../bouncycastle/jce/provider/test/PBETest.java | 14 +++++++ 4 files changed, 46 insertions(+), 21 deletions(-) diff --git a/src/main/java/org/bouncycastle/jcajce/provider/digest/SHA1.java b/src/main/java/org/bouncycastle/jcajce/provider/digest/SHA1.java index 8033e590..289d2a56 100644 --- a/src/main/java/org/bouncycastle/jcajce/provider/digest/SHA1.java +++ b/src/main/java/org/bouncycastle/jcajce/provider/digest/SHA1.java @@ -131,7 +131,7 @@ public class SHA1 throw new IllegalArgumentException("password empty"); } - int scheme = PKCS5S2; + int scheme = PBKDF2; int digest = SHA1; int keySize = pbeSpec.getKeyLength(); int ivSize = -1; // JDK 1,2 and earlier does not understand simplified version. diff --git a/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BCPBEKey.java b/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BCPBEKey.java index 9c4c8316..93aa78e9 100644 --- a/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BCPBEKey.java +++ b/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BCPBEKey.java @@ -78,6 +78,10 @@ public class BCPBEKey { return PBEParametersGenerator.PKCS12PasswordToBytes(pbeKeySpec.getPassword()); } + else if (type == PBE.PBKDF2) + { + return PBEParametersGenerator.PKCS5PasswordToUTF8Bytes(pbeKeySpec.getPassword()); + } else { return PBEParametersGenerator.PKCS5PasswordToBytes(pbeKeySpec.getPassword()); diff --git a/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/PBE.java b/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/PBE.java index f41f98b2..439b0cca 100644 --- a/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/PBE.java +++ b/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/PBE.java @@ -39,6 +39,7 @@ public interface PBE static final int PKCS5S2 = 1; static final int PKCS12 = 2; static final int OPENSSL = 3; + static final int PBKDF2 = 4; /** * uses the appropriate mixer to generate the key and IV if necessary. @@ -68,7 +69,7 @@ public interface PBE throw new IllegalStateException("PKCS5 scheme 1 only supports MD2, MD5 and SHA1."); } } - else if (type == PKCS5S2) + else if (type == PKCS5S2 || type == PBKDF2) { generator = new PKCS5S2ParametersGenerator(); } @@ -218,16 +219,9 @@ public interface PBE PBEParametersGenerator generator = makePBEGenerator(type, hash); byte[] key; CipherParameters param; - - if (type == PKCS12) - { - key = PBEParametersGenerator.PKCS12PasswordToBytes(keySpec.getPassword()); - } - else - { - key = PBEParametersGenerator.PKCS5PasswordToBytes(keySpec.getPassword()); - } - + + key = convertPassword(type, keySpec); + generator.init(key, keySpec.getSalt(), keySpec.getIterationCount()); if (ivSize != 0) @@ -246,7 +240,8 @@ public interface PBE return param; } - + + /** * generate a PBE based key suitable for a MAC algorithm, the * key size is chosen according the MAC size, or the hashing algorithm, @@ -262,14 +257,7 @@ public interface PBE byte[] key; CipherParameters param; - if (type == PKCS12) - { - key = PBEParametersGenerator.PKCS12PasswordToBytes(keySpec.getPassword()); - } - else - { - key = PBEParametersGenerator.PKCS5PasswordToBytes(keySpec.getPassword()); - } + key = convertPassword(type, keySpec); generator.init(key, keySpec.getSalt(), keySpec.getIterationCount()); @@ -282,5 +270,24 @@ public interface PBE return param; } + + private static byte[] convertPassword(int type, PBEKeySpec keySpec) + { + byte[] key; + + if (type == PKCS12) + { + key = PBEParametersGenerator.PKCS12PasswordToBytes(keySpec.getPassword()); + } + else if (type == PBKDF2) + { + key = PBEParametersGenerator.PKCS5PasswordToUTF8Bytes(keySpec.getPassword()); + } + else + { + key = PBEParametersGenerator.PKCS5PasswordToBytes(keySpec.getPassword()); + } + return key; + } } } diff --git a/src/test/java/org/bouncycastle/jce/provider/test/PBETest.java b/src/test/java/org/bouncycastle/jce/provider/test/PBETest.java index ed56dd4e..0d0ba87f 100644 --- a/src/test/java/org/bouncycastle/jce/provider/test/PBETest.java +++ b/src/test/java/org/bouncycastle/jce/provider/test/PBETest.java @@ -4,6 +4,7 @@ import java.security.AlgorithmParameters; import java.security.SecureRandom; import java.security.Security; import java.security.spec.InvalidParameterSpecException; +import java.security.spec.KeySpec; import javax.crypto.Cipher; import javax.crypto.KeyGenerator; @@ -607,6 +608,19 @@ public class PBETest testCipherNameWithWrap("PBEWITHSHA256AND128BITAES-CBC-BC", "AES/CBC/PKCS5Padding"); testCipherNameWithWrap("PBEWITHSHAAND40BITRC4", "RC4"); testCipherNameWithWrap("PBEWITHSHAAND128BITRC4", "RC4"); + + SecretKeyFactory f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1", "BC"); + KeySpec ks1 = new PBEKeySpec("\u0141\u0142".toCharArray(), new byte[20], 4096, 160); + if (!Arrays.areEqual(Hex.decode("f14687fc31a66e2f7cc01d0a65f687961bd27e20"), f.generateSecret(ks1).getEncoded())) + { + fail("wrong PBKDF2 k1 key generated"); + } + + KeySpec ks2 = new PBEKeySpec("\u0041\u0042".toCharArray(), new byte[20], 4096, 160); + if (!Arrays.areEqual(Hex.decode("6f6579193d6433a3e4600b243bb390674f04a615"), f.generateSecret(ks2).getEncoded())) + { + fail("wrong PBKDF2 k2 key generated"); + } } public String getName() -- cgit v1.2.3