diff options
Diffstat (limited to 'bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/PBE.java')
-rw-r--r-- | bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/PBE.java | 123 |
1 files changed, 92 insertions, 31 deletions
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/PBE.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/PBE.java index 8fead80a..2e4f96b5 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/PBE.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/PBE.java @@ -1,26 +1,27 @@ package org.bouncycastle.jcajce.provider.symmetric.util; +import java.lang.reflect.Method; import java.security.InvalidAlgorithmParameterException; import java.security.spec.AlgorithmParameterSpec; import javax.crypto.SecretKey; +// BEGIN android-added +import javax.crypto.spec.IvParameterSpec; +// END android-added import javax.crypto.spec.PBEKeySpec; import javax.crypto.spec.PBEParameterSpec; import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.crypto.PBEParametersGenerator; +// BEGIN android-added +import org.bouncycastle.crypto.digests.AndroidDigestFactory; +// END android-added // BEGIN android-removed // import org.bouncycastle.crypto.digests.GOST3411Digest; // import org.bouncycastle.crypto.digests.MD2Digest; -// import org.bouncycastle.crypto.digests.MD5Digest; // import org.bouncycastle.crypto.digests.RIPEMD160Digest; -// import org.bouncycastle.crypto.digests.SHA1Digest; -// import org.bouncycastle.crypto.digests.SHA256Digest; // import org.bouncycastle.crypto.digests.TigerDigest; // END android-removed -// BEGIN android-added -import org.bouncycastle.crypto.digests.AndroidDigestFactory; -// END android-added import org.bouncycastle.crypto.generators.OpenSSLPBEParametersGenerator; import org.bouncycastle.crypto.generators.PKCS12ParametersGenerator; import org.bouncycastle.crypto.generators.PKCS5S1ParametersGenerator; @@ -28,6 +29,9 @@ import org.bouncycastle.crypto.generators.PKCS5S2ParametersGenerator; import org.bouncycastle.crypto.params.DESParameters; import org.bouncycastle.crypto.params.KeyParameter; import org.bouncycastle.crypto.params.ParametersWithIV; +// BEGIN android-removed +// import org.bouncycastle.crypto.util.DigestFactory; +// END android-removed public interface PBE { @@ -45,6 +49,9 @@ public interface PBE // static final int MD2 = 5; // static final int GOST3411 = 6; // END android-removed + static final int SHA224 = 7; + static final int SHA384 = 8; + static final int SHA512 = 9; static final int PKCS5S1 = 0; static final int PKCS5S2 = 1; @@ -53,6 +60,7 @@ public interface PBE static final int PKCS5S1_UTF8 = 4; static final int PKCS5S2_UTF8 = 5; + /** * uses the appropriate mixer to generate the key and IV if necessary. */ @@ -101,6 +109,7 @@ public interface PBE generator = new PKCS5S2ParametersGenerator(AndroidDigestFactory.getMD5()); // END android-changed break; + case SHA1: // BEGIN android-changed generator = new PKCS5S2ParametersGenerator(AndroidDigestFactory.getSHA1()); @@ -114,16 +123,24 @@ public interface PBE // generator = new PKCS5S2ParametersGenerator(new TigerDigest()); // break; // END android-removed + // BEGIN android-added + case SHA224: + generator = new PKCS5S2ParametersGenerator(AndroidDigestFactory.getSHA224()); + break; + // END android-added case SHA256: // BEGIN android-changed generator = new PKCS5S2ParametersGenerator(AndroidDigestFactory.getSHA256()); // END android-changed break; - // BEGIN android-removed - // case GOST3411: - // generator = new PKCS5S2ParametersGenerator(new GOST3411Digest()); - // break; - // END android-removed + // BEGIN android-added + case SHA384: + generator = new PKCS5S2ParametersGenerator(AndroidDigestFactory.getSHA384()); + break; + case SHA512: + generator = new PKCS5S2ParametersGenerator(AndroidDigestFactory.getSHA512()); + break; + // END android-added default: throw new IllegalStateException("unknown digest scheme for PBE PKCS5S2 encryption."); } @@ -155,16 +172,23 @@ public interface PBE // generator = new PKCS12ParametersGenerator(new TigerDigest()); // break; // END android-removed + // BEGIN android-added + case SHA224: + generator = new PKCS12ParametersGenerator(AndroidDigestFactory.getSHA224()); + break; + // END android-added case SHA256: // BEGIN android-changed generator = new PKCS12ParametersGenerator(AndroidDigestFactory.getSHA256()); // END android-changed break; - // BEGIN android-removed - // case GOST3411: - // generator = new PKCS12ParametersGenerator(new GOST3411Digest()); - // break; - // END android-removed + // BEGIN android-added + case SHA384: + generator = new PKCS12ParametersGenerator(AndroidDigestFactory.getSHA384()); + break; + case SHA512: + generator = new PKCS12ParametersGenerator(AndroidDigestFactory.getSHA512()); + break; default: throw new IllegalStateException("unknown digest scheme for PBE encryption."); } @@ -211,6 +235,21 @@ public interface PBE if (ivSize != 0) { param = generator.generateDerivedParameters(keySize, ivSize); + // BEGIN ANDROID-ADDED + // PKCS5S2 doesn't specify that the IV must be generated from the password. If the + // IV is passed as a parameter, use it. + AlgorithmParameterSpec parameterSpecFromPBEParameterSpec = + getParameterSpecFromPBEParameterSpec(pbeParam); + if ((scheme == PKCS5S2 || scheme == PKCS5S2_UTF8) + && parameterSpecFromPBEParameterSpec instanceof IvParameterSpec) { + ParametersWithIV parametersWithIV = (ParametersWithIV) param; + IvParameterSpec ivParameterSpec = + (IvParameterSpec) parameterSpecFromPBEParameterSpec; + param = new ParametersWithIV( + (KeyParameter) parametersWithIV.getParameters(), + ivParameterSpec.getIV()); + } + // END ANDROID-ADDED } else { @@ -233,11 +272,6 @@ public interface PBE } } - for (int i = 0; i != key.length; i++) - { - key[i] = 0; - } - return param; } @@ -270,6 +304,21 @@ public interface PBE if (pbeKey.getIvSize() != 0) { param = generator.generateDerivedParameters(pbeKey.getKeySize(), pbeKey.getIvSize()); + // BEGIN ANDROID-ADDED + // PKCS5S2 doesn't specify that the IV must be generated from the password. If the + // IV is passed as a parameter, use it. + AlgorithmParameterSpec parameterSpecFromPBEParameterSpec = + getParameterSpecFromPBEParameterSpec(pbeParam); + if ((pbeKey.getType() == PKCS5S2 || pbeKey.getType() == PKCS5S2_UTF8) + && parameterSpecFromPBEParameterSpec instanceof IvParameterSpec) { + ParametersWithIV parametersWithIV = (ParametersWithIV) param; + IvParameterSpec ivParameterSpec = + (IvParameterSpec) parameterSpecFromPBEParameterSpec; + param = new ParametersWithIV( + (KeyParameter) parametersWithIV.getParameters(), + ivParameterSpec.getIV()); + } + // END ANDROID-ADDED } else { @@ -292,11 +341,6 @@ public interface PBE } } - for (int i = 0; i != key.length; i++) - { - key[i] = 0; - } - return param; } @@ -322,11 +366,6 @@ public interface PBE generator.init(key, pbeParam.getSalt(), pbeParam.getIterationCount()); param = generator.generateDerivedMacParameters(pbeKey.getKeySize()); - - for (int i = 0; i != key.length; i++) - { - key[i] = 0; - } return param; } @@ -425,6 +464,28 @@ public interface PBE return param; } + // BEGIN android-added + /** + * Invokes the method {@link PBEParameterSpec#getParameterSpec()} via reflection. + * + * Needed as the method was introduced in Java 1.8 and Bouncycastle level is 1.5. + * + * @return the parameter spec, or null if the method is not available. + */ + public static AlgorithmParameterSpec getParameterSpecFromPBEParameterSpec( + PBEParameterSpec pbeParameterSpec) { + try { + Method getParameterSpecMethod = PBE.class.getClassLoader() + .loadClass("javax.crypto.spec.PBEParameterSpec") + .getMethod("getParameterSpec"); + return (AlgorithmParameterSpec) getParameterSpecMethod.invoke(pbeParameterSpec); + } catch (Exception e) { + return null; + } + } + // END android-added + + private static byte[] convertPassword(int type, PBEKeySpec keySpec) { byte[] key; |