summaryrefslogtreecommitdiff
path: root/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/PBE.java
diff options
context:
space:
mode:
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.java56
1 files changed, 56 insertions, 0 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 d81ad32d..be131f4e 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,9 +1,13 @@
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;
@@ -243,6 +247,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
{
@@ -302,6 +321,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
{
@@ -457,6 +491,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;