summaryrefslogtreecommitdiff
path: root/bcprov/src/main/java/org/bouncycastle/jcajce
diff options
context:
space:
mode:
authorSergio Giro <sgiro@google.com>2016-02-02 15:27:40 +0000
committerSergio Giro <sgiro@google.com>2016-02-02 15:30:05 +0000
commit11975162f2da08e65157d37cd272721485f2b34b (patch)
treee2d9c4866d82c0e93854d5e9a6200cfce47e6232 /bcprov/src/main/java/org/bouncycastle/jcajce
parentbdb7b3d37025690a0434040b4e0d0623d9fa74af (diff)
downloadbouncycastle-11975162f2da08e65157d37cd272721485f2b34b.tar.gz
bouncycastle: Android tree with upstream code for version 1.54.
Adding missing files Change-Id: Ife77e8b1df7ec05555b29fb48a984f4c0da2e562
Diffstat (limited to 'bcprov/src/main/java/org/bouncycastle/jcajce')
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/PBKDF1Key.java67
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/PBKDF1KeyWithParameters.java53
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/PBKDF2Key.java65
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/PBKDF2KeyWithParameters.java53
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/PBKDFKey.java11
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/AlgorithmParametersSpi.java167
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/ECUtils.java45
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/BaseAgreementSpi.java314
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/DESUtil.java53
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/Blake2b.java114
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/Keccak.java195
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/GcmSpecUtil.java78
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/OpenSSLPBKDF.java86
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/SM4.java162
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/spec/KTSParameterSpec.java157
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/spec/MQVParameterSpec.java70
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/spec/UserKeyingMaterialSpec.java21
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/util/AlgorithmParametersUtils.java68
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/util/MessageDigestUtils.java55
19 files changed, 1834 insertions, 0 deletions
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/PBKDF1Key.java b/bcprov/src/main/java/org/bouncycastle/jcajce/PBKDF1Key.java
new file mode 100644
index 00000000..7f7581c0
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/PBKDF1Key.java
@@ -0,0 +1,67 @@
+package org.bouncycastle.jcajce;
+
+import org.bouncycastle.crypto.CharToByteConverter;
+
+/**
+ * A password based key for use with PBKDF1 as defined in PKCS#5.
+ */
+public class PBKDF1Key
+ implements PBKDFKey
+{
+ private final char[] password;
+ private final CharToByteConverter converter;
+
+ /**
+ * Basic constructor for a password based key with generation parameters for PBKDF1.
+ *
+ * @param password password to use.
+ * @param converter the converter to use to turn the char array into octets.
+ */
+ public PBKDF1Key(char[] password, CharToByteConverter converter)
+ {
+ this.password = new char[password.length];
+ this.converter = converter;
+
+ System.arraycopy(password, 0, this.password, 0, password.length);
+ }
+
+ /**
+ * Return a reference to the char[] array holding the password.
+ *
+ * @return a reference to the password array.
+ */
+ public char[] getPassword()
+ {
+ return password;
+ }
+
+ /**
+ * Return the password based key derivation function this key is for,
+ *
+ * @return the string "PBKDF1"
+ */
+ public String getAlgorithm()
+ {
+ return "PBKDF1";
+ }
+
+ /**
+ * Return the format encoding.
+ *
+ * @return the type name representing a char[] to byte[] conversion.
+ */
+ public String getFormat()
+ {
+ return converter.getType();
+ }
+
+ /**
+ * Return the password converted to bytes.
+ *
+ * @return the password converted to a byte array.
+ */
+ public byte[] getEncoded()
+ {
+ return converter.convert(password);
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/PBKDF1KeyWithParameters.java b/bcprov/src/main/java/org/bouncycastle/jcajce/PBKDF1KeyWithParameters.java
new file mode 100644
index 00000000..d0899c1d
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/PBKDF1KeyWithParameters.java
@@ -0,0 +1,53 @@
+package org.bouncycastle.jcajce;
+
+import javax.crypto.interfaces.PBEKey;
+
+import org.bouncycastle.crypto.CharToByteConverter;
+import org.bouncycastle.util.Arrays;
+
+/**
+ * A password based key for use with PBKDF1 as defined in PKCS#5 with full PBE parameters.
+ */
+public class PBKDF1KeyWithParameters
+ extends PBKDF1Key
+ implements PBEKey
+{
+ private final byte[] salt;
+ private final int iterationCount;
+
+ /**
+ * Basic constructor for a password based key with generation parameters for PBKDF1.
+ *
+ * @param password password to use.
+ * @param converter the converter to use to turn the char array into octets.
+ * @param salt salt for generation algorithm
+ * @param iterationCount iteration count for generation algorithm.
+ */
+ public PBKDF1KeyWithParameters(char[] password, CharToByteConverter converter, byte[] salt, int iterationCount)
+ {
+ super(password, converter);
+
+ this.salt = Arrays.clone(salt);
+ this.iterationCount = iterationCount;
+ }
+
+ /**
+ * Return the salt to use in the key derivation function.
+ *
+ * @return the salt to use in the KDF.
+ */
+ public byte[] getSalt()
+ {
+ return salt;
+ }
+
+ /**
+ * Return the iteration count to use in the key derivation function.
+ *
+ * @return the iteration count to use in the KDF.
+ */
+ public int getIterationCount()
+ {
+ return iterationCount;
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/PBKDF2Key.java b/bcprov/src/main/java/org/bouncycastle/jcajce/PBKDF2Key.java
new file mode 100644
index 00000000..d9dc6e75
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/PBKDF2Key.java
@@ -0,0 +1,65 @@
+package org.bouncycastle.jcajce;
+
+import org.bouncycastle.crypto.CharToByteConverter;
+import org.bouncycastle.util.Arrays;
+
+/**
+ * A password based key for use with PBKDF2 as defined in PKCS#5.
+ */
+public class PBKDF2Key
+ implements PBKDFKey
+{
+ private final char[] password;
+ private final CharToByteConverter converter;
+
+ /**
+ * Basic constructor for a password based key using PBKDF - secret key generation parameters will be passed separately..
+ *
+ * @param password password to use.
+ */
+ public PBKDF2Key(char[] password, CharToByteConverter converter)
+ {
+ this.password = Arrays.clone(password);
+ this.converter = converter;
+ }
+
+ /**
+ * Return a reference to the char[] array holding the password.
+ *
+ * @return a reference to the password array.
+ */
+ public char[] getPassword()
+ {
+ return password;
+ }
+
+ /**
+ * Return the password based key derivation function this key is for,
+ *
+ * @return the string "PBKDF2"
+ */
+ public String getAlgorithm()
+ {
+ return "PBKDF2";
+ }
+
+ /**
+ * Return the format encoding.
+ *
+ * @return the type name representing a char[] to byte[] conversion.
+ */
+ public String getFormat()
+ {
+ return converter.getType();
+ }
+
+ /**
+ * Return the password converted to bytes.
+ *
+ * @return the password converted to a byte array.
+ */
+ public byte[] getEncoded()
+ {
+ return converter.convert(password);
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/PBKDF2KeyWithParameters.java b/bcprov/src/main/java/org/bouncycastle/jcajce/PBKDF2KeyWithParameters.java
new file mode 100644
index 00000000..b356cfbd
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/PBKDF2KeyWithParameters.java
@@ -0,0 +1,53 @@
+package org.bouncycastle.jcajce;
+
+import javax.crypto.interfaces.PBEKey;
+
+import org.bouncycastle.crypto.CharToByteConverter;
+import org.bouncycastle.util.Arrays;
+
+/**
+ * A password based key for use with PBKDF2 as defined in PKCS#5 with full PBE parameters.
+ */
+public class PBKDF2KeyWithParameters
+ extends PBKDF2Key
+ implements PBEKey
+{
+ private final byte[] salt;
+ private final int iterationCount;
+
+ /**
+ * Basic constructor for a password based key with generation parameters using FIPS PBKDF.
+ *
+ * @param password password to use.
+ * @param converter converter to use for transforming characters into bytes.
+ * @param salt salt for generation algorithm
+ * @param iterationCount iteration count for generation algorithm.
+ */
+ public PBKDF2KeyWithParameters(char[] password, CharToByteConverter converter, byte[] salt, int iterationCount)
+ {
+ super(password, converter);
+
+ this.salt = Arrays.clone(salt);
+ this.iterationCount = iterationCount;
+ }
+
+ /**
+ * Return the salt to use in the key derivation function.
+ *
+ * @return the salt to use in the KDF.
+ */
+ public byte[] getSalt()
+ {
+ return salt;
+ }
+
+ /**
+ * Return the iteration count to use in the key derivation function.
+ *
+ * @return the iteration count to use in the KDF.
+ */
+ public int getIterationCount()
+ {
+ return iterationCount;
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/PBKDFKey.java b/bcprov/src/main/java/org/bouncycastle/jcajce/PBKDFKey.java
new file mode 100644
index 00000000..ae3d2ebd
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/PBKDFKey.java
@@ -0,0 +1,11 @@
+package org.bouncycastle.jcajce;
+
+import javax.crypto.SecretKey;
+
+/**
+ * Base interface for keys associated with various password based key derivation functions (PBKDF).
+ */
+public interface PBKDFKey
+ extends SecretKey
+{
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/AlgorithmParametersSpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/AlgorithmParametersSpi.java
new file mode 100644
index 00000000..6af71e80
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/AlgorithmParametersSpi.java
@@ -0,0 +1,167 @@
+package org.bouncycastle.jcajce.provider.asymmetric.ec;
+
+import java.io.IOException;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.ECGenParameterSpec;
+import java.security.spec.ECParameterSpec;
+import java.security.spec.InvalidParameterSpecException;
+
+import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import org.bouncycastle.asn1.DERNull;
+import org.bouncycastle.asn1.x9.ECNamedCurveTable;
+import org.bouncycastle.asn1.x9.X962Parameters;
+import org.bouncycastle.asn1.x9.X9ECParameters;
+import org.bouncycastle.jcajce.provider.asymmetric.util.EC5Util;
+import org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.math.ec.ECCurve;
+
+public class AlgorithmParametersSpi
+ extends java.security.AlgorithmParametersSpi
+{
+ private ECParameterSpec ecParameterSpec;
+ private String curveName;
+
+ protected boolean isASN1FormatString(String format)
+ {
+ return format == null || format.equals("ASN.1");
+ }
+
+ @Override
+ protected void engineInit(AlgorithmParameterSpec algorithmParameterSpec)
+ throws InvalidParameterSpecException
+ {
+ if (algorithmParameterSpec instanceof ECGenParameterSpec)
+ {
+ ECGenParameterSpec ecGenParameterSpec = (ECGenParameterSpec)algorithmParameterSpec;
+ X9ECParameters params = ECUtils.getDomainParametersFromGenSpec(ecGenParameterSpec);
+
+ if (params == null)
+ {
+ throw new InvalidParameterSpecException("EC curve name not recognized: " + ecGenParameterSpec.getName());
+ }
+ curveName = ecGenParameterSpec.getName();
+ ecParameterSpec = EC5Util.convertToSpec(params);
+ }
+ else if (algorithmParameterSpec instanceof ECParameterSpec)
+ {
+ curveName = null;
+ ecParameterSpec = (ECParameterSpec)algorithmParameterSpec;
+ }
+ else
+ {
+ throw new InvalidParameterSpecException("AlgorithmParameterSpec class not recognized: " + algorithmParameterSpec.getClass().getName());
+ }
+ }
+
+ @Override
+ protected void engineInit(byte[] bytes)
+ throws IOException
+ {
+ engineInit(bytes, "ASN.1");
+ }
+
+ @Override
+ protected void engineInit(byte[] bytes, String format)
+ throws IOException
+ {
+ if (isASN1FormatString(format))
+ {
+ X962Parameters params = X962Parameters.getInstance(bytes);
+
+ ECCurve curve = EC5Util.getCurve(BouncyCastleProvider.CONFIGURATION, params);
+
+ if (params.isNamedCurve())
+ {
+ curveName = ECNamedCurveTable.getName(ASN1ObjectIdentifier.getInstance(params.getParameters()));
+ }
+
+ ecParameterSpec = EC5Util.convertToSpec(params, curve);
+ }
+ else
+ {
+ throw new IOException("Unknown encoded parameters format in AlgorithmParameters object: " + format);
+ }
+ }
+
+ @Override
+ protected <T extends AlgorithmParameterSpec> T engineGetParameterSpec(Class<T> paramSpec)
+ throws InvalidParameterSpecException
+ {
+ if (ECParameterSpec.class.isAssignableFrom(paramSpec) || paramSpec == AlgorithmParameterSpec.class)
+ {
+ return (T)ecParameterSpec;
+ }
+ else if (ECGenParameterSpec.class.isAssignableFrom(paramSpec))
+ {
+ if (curveName != null)
+ {
+ ASN1ObjectIdentifier namedCurveOid = ECUtil.getNamedCurveOid(curveName);
+
+ if (namedCurveOid != null)
+ {
+ return (T)new ECGenParameterSpec(namedCurveOid.getId());
+ }
+ return (T)new ECGenParameterSpec(curveName);
+ }
+ else
+ {
+ ASN1ObjectIdentifier namedCurveOid = ECUtil.getNamedCurveOid(EC5Util.convertSpec(ecParameterSpec, false));
+
+ if (namedCurveOid != null)
+ {
+ return (T)new ECGenParameterSpec(namedCurveOid.getId());
+ }
+ }
+ }
+ throw new InvalidParameterSpecException("EC AlgorithmParameters cannot convert to " + paramSpec.getName());
+ }
+
+ @Override
+ protected byte[] engineGetEncoded()
+ throws IOException
+ {
+ return engineGetEncoded("ASN.1");
+ }
+
+ @Override
+ protected byte[] engineGetEncoded(String format)
+ throws IOException
+ {
+ if (isASN1FormatString(format))
+ {
+ X962Parameters params;
+
+ if (ecParameterSpec == null) // implicitly CA
+ {
+ params = new X962Parameters(DERNull.INSTANCE);
+ }
+ else if (curveName != null)
+ {
+ params = new X962Parameters(ECUtil.getNamedCurveOid(curveName));
+ }
+ else
+ {
+ org.bouncycastle.jce.spec.ECParameterSpec ecSpec = EC5Util.convertSpec(ecParameterSpec, false);
+ X9ECParameters ecP = new X9ECParameters(
+ ecSpec.getCurve(),
+ ecSpec.getG(),
+ ecSpec.getN(),
+ ecSpec.getH(),
+ ecSpec.getSeed());
+
+ params = new X962Parameters(ecP);
+ }
+
+ return params.getEncoded();
+ }
+
+ throw new IOException("Unknown parameters format in AlgorithmParameters object: " + format);
+ }
+
+ @Override
+ protected String engineToString()
+ {
+ return "EC AlgorithmParameters ";
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/ECUtils.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/ECUtils.java
new file mode 100644
index 00000000..dc92e0e4
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/ECUtils.java
@@ -0,0 +1,45 @@
+package org.bouncycastle.jcajce.provider.asymmetric.ec;
+
+import java.security.spec.ECGenParameterSpec;
+
+import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import org.bouncycastle.asn1.x9.X9ECParameters;
+import org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil;
+
+class ECUtils
+{
+ static X9ECParameters getDomainParametersFromGenSpec(ECGenParameterSpec genSpec)
+ {
+ return getDomainParametersFromName(genSpec.getName());
+ }
+
+ static X9ECParameters getDomainParametersFromName(String curveName)
+ {
+ X9ECParameters domainParameters;
+ try
+ {
+ if (curveName.charAt(0) >= '0' && curveName.charAt(0) <= '2')
+ {
+ ASN1ObjectIdentifier oidID = new ASN1ObjectIdentifier(curveName);
+ domainParameters = ECUtil.getNamedCurveByOid(oidID);
+ }
+ else
+ {
+ if (curveName.indexOf(' ') > 0)
+ {
+ curveName = curveName.substring(curveName.indexOf(' ') + 1);
+ domainParameters = ECUtil.getNamedCurveByName(curveName);
+ }
+ else
+ {
+ domainParameters = ECUtil.getNamedCurveByName(curveName);
+ }
+ }
+ }
+ catch (IllegalArgumentException ex)
+ {
+ domainParameters = ECUtil.getNamedCurveByName(curveName);
+ }
+ return domainParameters;
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/BaseAgreementSpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/BaseAgreementSpi.java
new file mode 100644
index 00000000..8dc0d2dd
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/BaseAgreementSpi.java
@@ -0,0 +1,314 @@
+package org.bouncycastle.jcajce.provider.asymmetric.util;
+
+import java.math.BigInteger;
+import java.security.NoSuchAlgorithmException;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Map;
+
+import javax.crypto.KeyAgreementSpi;
+import javax.crypto.SecretKey;
+import javax.crypto.ShortBufferException;
+import javax.crypto.spec.SecretKeySpec;
+
+import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
+import org.bouncycastle.asn1.gnu.GNUObjectIdentifiers;
+import org.bouncycastle.asn1.kisa.KISAObjectIdentifiers;
+import org.bouncycastle.asn1.misc.MiscObjectIdentifiers;
+import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
+import org.bouncycastle.asn1.ntt.NTTObjectIdentifiers;
+import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
+import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
+import org.bouncycastle.crypto.DerivationFunction;
+import org.bouncycastle.crypto.agreement.kdf.DHKDFParameters;
+import org.bouncycastle.crypto.agreement.kdf.DHKEKGenerator;
+import org.bouncycastle.crypto.params.DESParameters;
+import org.bouncycastle.crypto.params.KDFParameters;
+import org.bouncycastle.util.Integers;
+import org.bouncycastle.util.Strings;
+
+public abstract class BaseAgreementSpi
+ extends KeyAgreementSpi
+{
+ private static final Map<String, ASN1ObjectIdentifier> defaultOids = new HashMap<String, ASN1ObjectIdentifier>();
+ private static final Map<String, Integer> keySizes = new HashMap<String, Integer>();
+ private static final Map<String, String> nameTable = new HashMap<String, String>();
+
+ private static final Hashtable oids = new Hashtable();
+ private static final Hashtable des = new Hashtable();
+
+ static
+ {
+ Integer i64 = Integers.valueOf(64);
+ Integer i128 = Integers.valueOf(128);
+ Integer i192 = Integers.valueOf(192);
+ Integer i256 = Integers.valueOf(256);
+
+ keySizes.put("DES", i64);
+ keySizes.put("DESEDE", i192);
+ keySizes.put("BLOWFISH", i128);
+ keySizes.put("AES", i256);
+
+ keySizes.put(NISTObjectIdentifiers.id_aes128_ECB.getId(), i128);
+ keySizes.put(NISTObjectIdentifiers.id_aes192_ECB.getId(), i192);
+ keySizes.put(NISTObjectIdentifiers.id_aes256_ECB.getId(), i256);
+ keySizes.put(NISTObjectIdentifiers.id_aes128_CBC.getId(), i128);
+ keySizes.put(NISTObjectIdentifiers.id_aes192_CBC.getId(), i192);
+ keySizes.put(NISTObjectIdentifiers.id_aes256_CBC.getId(), i256);
+ keySizes.put(NISTObjectIdentifiers.id_aes128_CFB.getId(), i128);
+ keySizes.put(NISTObjectIdentifiers.id_aes192_CFB.getId(), i192);
+ keySizes.put(NISTObjectIdentifiers.id_aes256_CFB.getId(), i256);
+ keySizes.put(NISTObjectIdentifiers.id_aes128_OFB.getId(), i128);
+ keySizes.put(NISTObjectIdentifiers.id_aes192_OFB.getId(), i192);
+ keySizes.put(NISTObjectIdentifiers.id_aes256_OFB.getId(), i256);
+ keySizes.put(NISTObjectIdentifiers.id_aes128_wrap.getId(), i128);
+ keySizes.put(NISTObjectIdentifiers.id_aes192_wrap.getId(), i192);
+ keySizes.put(NISTObjectIdentifiers.id_aes256_wrap.getId(), i256);
+ keySizes.put(NISTObjectIdentifiers.id_aes128_CCM.getId(), i128);
+ keySizes.put(NISTObjectIdentifiers.id_aes192_CCM.getId(), i192);
+ keySizes.put(NISTObjectIdentifiers.id_aes256_CCM.getId(), i256);
+ keySizes.put(NISTObjectIdentifiers.id_aes128_GCM.getId(), i128);
+ keySizes.put(NISTObjectIdentifiers.id_aes192_GCM.getId(), i192);
+ keySizes.put(NISTObjectIdentifiers.id_aes256_GCM.getId(), i256);
+ keySizes.put(NTTObjectIdentifiers.id_camellia128_wrap.getId(), i128);
+ keySizes.put(NTTObjectIdentifiers.id_camellia192_wrap.getId(), i192);
+ keySizes.put(NTTObjectIdentifiers.id_camellia256_wrap.getId(), i256);
+ keySizes.put(KISAObjectIdentifiers.id_npki_app_cmsSeed_wrap.getId(), i128);
+
+ keySizes.put(PKCSObjectIdentifiers.id_alg_CMS3DESwrap.getId(), i192);
+ keySizes.put(PKCSObjectIdentifiers.des_EDE3_CBC.getId(), i192);
+ keySizes.put(OIWObjectIdentifiers.desCBC.getId(), i64);
+
+ keySizes.put(PKCSObjectIdentifiers.id_hmacWithSHA1.getId(), Integers.valueOf(160));
+ keySizes.put(PKCSObjectIdentifiers.id_hmacWithSHA256.getId(), i256);
+ keySizes.put(PKCSObjectIdentifiers.id_hmacWithSHA384.getId(), Integers.valueOf(384));
+ keySizes.put(PKCSObjectIdentifiers.id_hmacWithSHA512.getId(), Integers.valueOf(512));
+
+ defaultOids.put("DESEDE", PKCSObjectIdentifiers.des_EDE3_CBC);
+ defaultOids.put("AES", NISTObjectIdentifiers.id_aes256_CBC);
+ defaultOids.put("CAMELLIA", NTTObjectIdentifiers.id_camellia256_cbc);
+ defaultOids.put("SEED", KISAObjectIdentifiers.id_seedCBC);
+ defaultOids.put("DES", OIWObjectIdentifiers.desCBC);
+
+ nameTable.put(MiscObjectIdentifiers.cast5CBC.getId(), "CAST5");
+ nameTable.put(MiscObjectIdentifiers.as_sys_sec_alg_ideaCBC.getId(), "IDEA");
+ nameTable.put(MiscObjectIdentifiers.cryptlib_algorithm_blowfish_ECB.getId(), "Blowfish");
+ nameTable.put(MiscObjectIdentifiers.cryptlib_algorithm_blowfish_CBC.getId(), "Blowfish");
+ nameTable.put(MiscObjectIdentifiers.cryptlib_algorithm_blowfish_CFB.getId(), "Blowfish");
+ nameTable.put(MiscObjectIdentifiers.cryptlib_algorithm_blowfish_OFB.getId(), "Blowfish");
+ nameTable.put(OIWObjectIdentifiers.desECB.getId(), "DES");
+ nameTable.put(OIWObjectIdentifiers.desCBC.getId(), "DES");
+ nameTable.put(OIWObjectIdentifiers.desCFB.getId(), "DES");
+ nameTable.put(OIWObjectIdentifiers.desOFB.getId(), "DES");
+ nameTable.put(OIWObjectIdentifiers.desEDE.getId(), "DESede");
+ nameTable.put(PKCSObjectIdentifiers.des_EDE3_CBC.getId(), "DESede");
+ nameTable.put(PKCSObjectIdentifiers.id_alg_CMS3DESwrap.getId(), "DESede");
+ nameTable.put(PKCSObjectIdentifiers.id_alg_CMSRC2wrap.getId(), "RC2");
+ nameTable.put(PKCSObjectIdentifiers.id_hmacWithSHA1.getId(), "HmacSHA1");
+ nameTable.put(PKCSObjectIdentifiers.id_hmacWithSHA224.getId(), "HmacSHA224");
+ nameTable.put(PKCSObjectIdentifiers.id_hmacWithSHA256.getId(), "HmacSHA256");
+ nameTable.put(PKCSObjectIdentifiers.id_hmacWithSHA384.getId(), "HmacSHA384");
+ nameTable.put(PKCSObjectIdentifiers.id_hmacWithSHA512.getId(), "HmacSHA512");
+ nameTable.put(NTTObjectIdentifiers.id_camellia128_cbc.getId(), "Camellia");
+ nameTable.put(NTTObjectIdentifiers.id_camellia192_cbc.getId(), "Camellia");
+ nameTable.put(NTTObjectIdentifiers.id_camellia256_cbc.getId(), "Camellia");
+ nameTable.put(NTTObjectIdentifiers.id_camellia128_wrap.getId(), "Camellia");
+ nameTable.put(NTTObjectIdentifiers.id_camellia192_wrap.getId(), "Camellia");
+ nameTable.put(NTTObjectIdentifiers.id_camellia256_wrap.getId(), "Camellia");
+ nameTable.put(KISAObjectIdentifiers.id_npki_app_cmsSeed_wrap.getId(), "SEED");
+ nameTable.put(KISAObjectIdentifiers.id_seedCBC.getId(), "SEED");
+ nameTable.put(KISAObjectIdentifiers.id_seedMAC.getId(), "SEED");
+ nameTable.put(CryptoProObjectIdentifiers.gostR28147_gcfb.getId(), "GOST28147");
+
+ nameTable.put(NISTObjectIdentifiers.id_aes128_wrap.getId(), "AES");
+ nameTable.put(NISTObjectIdentifiers.id_aes128_CCM.getId(), "AES");
+ nameTable.put(NISTObjectIdentifiers.id_aes128_CCM.getId(), "AES");
+
+ oids.put("DESEDE", PKCSObjectIdentifiers.des_EDE3_CBC);
+ oids.put("AES", NISTObjectIdentifiers.id_aes256_CBC);
+ oids.put("DES", OIWObjectIdentifiers.desCBC);
+
+ des.put("DES", "DES");
+ des.put("DESEDE", "DES");
+ des.put(OIWObjectIdentifiers.desCBC.getId(), "DES");
+ des.put(PKCSObjectIdentifiers.des_EDE3_CBC.getId(), "DES");
+ des.put(PKCSObjectIdentifiers.id_alg_CMS3DESwrap.getId(), "DES");
+ }
+
+ private final String kaAlgorithm;
+ private final DerivationFunction kdf;
+
+ protected BigInteger result;
+ protected byte[] ukmParameters;
+
+ public BaseAgreementSpi(String kaAlgorithm, DerivationFunction kdf)
+ {
+ this.kaAlgorithm = kaAlgorithm;
+ this.kdf = kdf;
+ }
+
+ protected static String getAlgorithm(String algDetails)
+ {
+ if (algDetails.indexOf('[') > 0)
+ {
+ return algDetails.substring(0, algDetails.indexOf('['));
+ }
+
+ if (algDetails.startsWith(NISTObjectIdentifiers.aes.getId()))
+ {
+ return "AES";
+ }
+ if (algDetails.startsWith(GNUObjectIdentifiers.Serpent.getId()))
+ {
+ return "Serpent";
+ }
+
+ String name = (String)nameTable.get(Strings.toUpperCase(algDetails));
+
+ if (name != null)
+ {
+ return name;
+ }
+
+ return algDetails;
+ }
+
+ protected static int getKeySize(String algDetails)
+ {
+ if (algDetails.indexOf('[') > 0)
+ {
+ return (Integer.parseInt(algDetails.substring(algDetails.indexOf('[') + 1, algDetails.indexOf(']'))) + 7) / 8;
+ }
+
+ String algKey = Strings.toUpperCase(algDetails);
+ if (!keySizes.containsKey(algKey))
+ {
+ return -1;
+ }
+
+ return ((Integer)keySizes.get(algKey)).intValue();
+ }
+
+ protected static byte[] trimZeroes(byte[] secret)
+ {
+ if (secret[0] != 0)
+ {
+ return secret;
+ }
+ else
+ {
+ int ind = 0;
+ while (ind < secret.length && secret[ind] == 0)
+ {
+ ind++;
+ }
+
+ byte[] rv = new byte[secret.length - ind];
+
+ System.arraycopy(secret, ind, rv, 0, rv.length);
+
+ return rv;
+ }
+ }
+
+ protected byte[] engineGenerateSecret()
+ throws IllegalStateException
+ {
+ if (kdf != null)
+ {
+ throw new UnsupportedOperationException(
+ "KDF can only be used when algorithm is known");
+ }
+
+ return bigIntToBytes(result);
+ }
+
+ protected int engineGenerateSecret(
+ byte[] sharedSecret,
+ int offset)
+ throws IllegalStateException, ShortBufferException
+ {
+ byte[] secret = engineGenerateSecret();
+
+ if (sharedSecret.length - offset < secret.length)
+ {
+ throw new ShortBufferException(kaAlgorithm + " key agreement: need " + secret.length + " bytes");
+ }
+
+ System.arraycopy(secret, 0, sharedSecret, offset, secret.length);
+
+ return secret.length;
+ }
+
+ protected SecretKey engineGenerateSecret(
+ String algorithm)
+ throws NoSuchAlgorithmException
+ {
+ byte[] secret = bigIntToBytes(result);
+ String algKey = Strings.toUpperCase(algorithm);
+ String oidAlgorithm = algorithm;
+
+ if (oids.containsKey(algKey))
+ {
+ oidAlgorithm = ((ASN1ObjectIdentifier)oids.get(algKey)).getId();
+ }
+
+ int keySize = getKeySize(oidAlgorithm);
+
+ if (kdf != null)
+ {
+ if (keySize < 0)
+ {
+ throw new NoSuchAlgorithmException("unknown algorithm encountered: " + oidAlgorithm);
+ }
+ byte[] keyBytes = new byte[keySize / 8];
+
+ if (kdf instanceof DHKEKGenerator)
+ {
+ ASN1ObjectIdentifier oid;
+ try
+ {
+ oid = new ASN1ObjectIdentifier(oidAlgorithm);
+ }
+ catch (IllegalArgumentException e)
+ {
+ throw new NoSuchAlgorithmException("no OID for algorithm: " + oidAlgorithm);
+ }
+ DHKDFParameters params = new DHKDFParameters(oid, keySize, secret, ukmParameters);
+
+ kdf.init(params);
+ }
+ else
+ {
+ KDFParameters params = new KDFParameters(secret, ukmParameters);
+
+ kdf.init(params);
+ }
+
+ kdf.generateBytes(keyBytes, 0, keyBytes.length);
+
+ secret = keyBytes;
+ }
+ else
+ {
+ if (keySize > 0)
+ {
+ byte[] keyBytes = new byte[keySize / 8];
+
+ System.arraycopy(secret, 0, keyBytes, 0, keyBytes.length);
+
+ secret = keyBytes;
+ }
+ }
+
+ if (des.containsKey(oidAlgorithm))
+ {
+ DESParameters.setOddParity(secret);
+ }
+
+ return new SecretKeySpec(secret, getAlgorithm(algorithm));
+ }
+
+ protected abstract byte[] bigIntToBytes(BigInteger result);
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/DESUtil.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/DESUtil.java
new file mode 100644
index 00000000..2409fb03
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/DESUtil.java
@@ -0,0 +1,53 @@
+package org.bouncycastle.jcajce.provider.asymmetric.util;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
+import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
+import org.bouncycastle.util.Strings;
+
+public class DESUtil
+{
+ private static final Set<String> des = new HashSet<String>();
+
+ static
+ {
+ des.add("DES");
+ des.add("DESEDE");
+ des.add(OIWObjectIdentifiers.desCBC.getId());
+ des.add(PKCSObjectIdentifiers.des_EDE3_CBC.getId());
+ des.add(PKCSObjectIdentifiers.des_EDE3_CBC.getId());
+ des.add(PKCSObjectIdentifiers.id_alg_CMS3DESwrap.getId());
+ }
+
+ public static boolean isDES(String algorithmID)
+ {
+ String name = Strings.toUpperCase(algorithmID);
+
+ return des.contains(name);
+ }
+
+ /**
+ * DES Keys use the LSB as the odd parity bit. This can
+ * be used to check for corrupt keys.
+ *
+ * @param bytes the byte array to set the parity on.
+ */
+ public static void setOddParity(
+ byte[] bytes)
+ {
+ for (int i = 0; i < bytes.length; i++)
+ {
+ int b = bytes[i];
+ bytes[i] = (byte)((b & 0xfe) |
+ ((((b >> 1) ^
+ (b >> 2) ^
+ (b >> 3) ^
+ (b >> 4) ^
+ (b >> 5) ^
+ (b >> 6) ^
+ (b >> 7)) ^ 0x01) & 0x01));
+ }
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/Blake2b.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/Blake2b.java
new file mode 100644
index 00000000..0eb978a9
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/Blake2b.java
@@ -0,0 +1,114 @@
+package org.bouncycastle.jcajce.provider.digest;
+
+import org.bouncycastle.asn1.misc.MiscObjectIdentifiers;
+import org.bouncycastle.crypto.digests.Blake2bDigest;
+import org.bouncycastle.jcajce.provider.config.ConfigurableProvider;
+
+public class Blake2b
+{
+ private Blake2b()
+ {
+
+ }
+
+ static public class Blake2b512
+ extends BCMessageDigest
+ implements Cloneable
+ {
+ public Blake2b512()
+ {
+ super(new Blake2bDigest(512));
+ }
+
+ public Object clone()
+ throws CloneNotSupportedException
+ {
+ Blake2b512 d = (Blake2b512)super.clone();
+ d.digest = new Blake2bDigest((Blake2bDigest)digest);
+
+ return d;
+ }
+ }
+
+ static public class Blake2b384
+ extends BCMessageDigest
+ implements Cloneable
+ {
+ public Blake2b384()
+ {
+ super(new Blake2bDigest(384));
+ }
+
+ public Object clone()
+ throws CloneNotSupportedException
+ {
+ Blake2b384 d = (Blake2b384)super.clone();
+ d.digest = new Blake2bDigest((Blake2bDigest)digest);
+
+ return d;
+ }
+ }
+
+ static public class Blake2b256
+ extends BCMessageDigest
+ implements Cloneable
+ {
+ public Blake2b256()
+ {
+ super(new Blake2bDigest(256));
+ }
+
+ public Object clone()
+ throws CloneNotSupportedException
+ {
+ Blake2b256 d = (Blake2b256)super.clone();
+ d.digest = new Blake2bDigest((Blake2bDigest)digest);
+
+ return d;
+ }
+ }
+
+ static public class Blake2b160
+ extends BCMessageDigest
+ implements Cloneable
+ {
+ public Blake2b160()
+ {
+ super(new Blake2bDigest(160));
+ }
+
+ public Object clone()
+ throws CloneNotSupportedException
+ {
+ Blake2b160 d = (Blake2b160)super.clone();
+ d.digest = new Blake2bDigest((Blake2bDigest)digest);
+
+ return d;
+ }
+ }
+
+ public static class Mappings
+ extends DigestAlgorithmProvider
+ {
+ private static final String PREFIX = Blake2b.class.getName();
+
+ public Mappings()
+ {
+ }
+
+ public void configure(ConfigurableProvider provider)
+ {
+ provider.addAlgorithm("MessageDigest.BLAKE2B-512", PREFIX + "$Blake2b512");
+ provider.addAlgorithm("Alg.Alias.MessageDigest." + MiscObjectIdentifiers.id_blake2b512, "BLAKE2B-512");
+
+ provider.addAlgorithm("MessageDigest.BLAKE2B-384", PREFIX + "$Blake2b384");
+ provider.addAlgorithm("Alg.Alias.MessageDigest." + MiscObjectIdentifiers.id_blake2b384, "BLAKE2B-384");
+
+ provider.addAlgorithm("MessageDigest.BLAKE2B-256", PREFIX + "$Blake2b256");
+ provider.addAlgorithm("Alg.Alias.MessageDigest." + MiscObjectIdentifiers.id_blake2b256, "BLAKE2B-256");
+
+ provider.addAlgorithm("MessageDigest.BLAKE2B-160", PREFIX + "$Blake2b160");
+ provider.addAlgorithm("Alg.Alias.MessageDigest." + MiscObjectIdentifiers.id_blake2b160, "BLAKE2B-160");
+ }
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/Keccak.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/Keccak.java
new file mode 100644
index 00000000..f8b989bf
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/Keccak.java
@@ -0,0 +1,195 @@
+package org.bouncycastle.jcajce.provider.digest;
+
+import org.bouncycastle.crypto.CipherKeyGenerator;
+import org.bouncycastle.crypto.digests.KeccakDigest;
+import org.bouncycastle.crypto.macs.HMac;
+import org.bouncycastle.jcajce.provider.config.ConfigurableProvider;
+import org.bouncycastle.jcajce.provider.symmetric.util.BaseKeyGenerator;
+import org.bouncycastle.jcajce.provider.symmetric.util.BaseMac;
+
+public class Keccak
+{
+ private Keccak()
+ {
+
+ }
+
+ static public class DigestKeccak
+ extends BCMessageDigest
+ implements Cloneable
+ {
+ public DigestKeccak(int size)
+ {
+ super(new KeccakDigest(size));
+ }
+
+ public Object clone()
+ throws CloneNotSupportedException
+ {
+ BCMessageDigest d = (BCMessageDigest)super.clone();
+ d.digest = new KeccakDigest((KeccakDigest)digest);
+
+ return d;
+ }
+ }
+
+ static public class Digest224
+ extends DigestKeccak
+ {
+ public Digest224()
+ {
+ super(224);
+ }
+ }
+
+ static public class Digest256
+ extends DigestKeccak
+ {
+ public Digest256()
+ {
+ super(256);
+ }
+ }
+
+ static public class Digest288
+ extends DigestKeccak
+ {
+ public Digest288()
+ {
+ super(288);
+ }
+ }
+
+ static public class Digest384
+ extends DigestKeccak
+ {
+ public Digest384()
+ {
+ super(384);
+ }
+ }
+
+ static public class Digest512
+ extends DigestKeccak
+ {
+ public Digest512()
+ {
+ super(512);
+ }
+ }
+
+ public static class HashMac224
+ extends BaseMac
+ {
+ public HashMac224()
+ {
+ super(new HMac(new KeccakDigest(224)));
+ }
+ }
+
+ public static class HashMac256
+ extends BaseMac
+ {
+ public HashMac256()
+ {
+ super(new HMac(new KeccakDigest(256)));
+ }
+ }
+
+ public static class HashMac288
+ extends BaseMac
+ {
+ public HashMac288()
+ {
+ super(new HMac(new KeccakDigest(288)));
+ }
+ }
+
+ public static class HashMac384
+ extends BaseMac
+ {
+ public HashMac384()
+ {
+ super(new HMac(new KeccakDigest(384)));
+ }
+ }
+
+ public static class HashMac512
+ extends BaseMac
+ {
+ public HashMac512()
+ {
+ super(new HMac(new KeccakDigest(512)));
+ }
+ }
+
+ public static class KeyGenerator224
+ extends BaseKeyGenerator
+ {
+ public KeyGenerator224()
+ {
+ super("HMACKECCAK224", 224, new CipherKeyGenerator());
+ }
+ }
+
+ public static class KeyGenerator256
+ extends BaseKeyGenerator
+ {
+ public KeyGenerator256()
+ {
+ super("HMACKECCAK256", 256, new CipherKeyGenerator());
+ }
+ }
+
+ public static class KeyGenerator288
+ extends BaseKeyGenerator
+ {
+ public KeyGenerator288()
+ {
+ super("HMACKECCAK288", 288, new CipherKeyGenerator());
+ }
+ }
+
+ public static class KeyGenerator384
+ extends BaseKeyGenerator
+ {
+ public KeyGenerator384()
+ {
+ super("HMACKECCAK384", 384, new CipherKeyGenerator());
+ }
+ }
+
+ public static class KeyGenerator512
+ extends BaseKeyGenerator
+ {
+ public KeyGenerator512()
+ {
+ super("HMACKECCAK512", 512, new CipherKeyGenerator());
+ }
+ }
+
+ public static class Mappings
+ extends DigestAlgorithmProvider
+ {
+ private static final String PREFIX = Keccak.class.getName();
+
+ public Mappings()
+ {
+ }
+
+ public void configure(ConfigurableProvider provider)
+ {
+ provider.addAlgorithm("MessageDigest.KECCAK-224", PREFIX + "$Digest224");
+ provider.addAlgorithm("MessageDigest.KECCAK-288", PREFIX + "$Digest288");
+ provider.addAlgorithm("MessageDigest.KECCAK-256", PREFIX + "$Digest256");
+ provider.addAlgorithm("MessageDigest.KECCAK-384", PREFIX + "$Digest384");
+ provider.addAlgorithm("MessageDigest.KECCAK-512", PREFIX + "$Digest512");
+
+ addHMACAlgorithm(provider, "KECCAK224", PREFIX + "$HashMac224", PREFIX + "$KeyGenerator224");
+ addHMACAlgorithm(provider, "KECCAK256", PREFIX + "$HashMac256", PREFIX + "$KeyGenerator256");
+ addHMACAlgorithm(provider, "KECCAK288", PREFIX + "$HashMac288", PREFIX + "$KeyGenerator288");
+ addHMACAlgorithm(provider, "KECCAK384", PREFIX + "$HashMac384", PREFIX + "$KeyGenerator384");
+ addHMACAlgorithm(provider, "KECCAK512", PREFIX + "$HashMac512", PREFIX + "$KeyGenerator512");
+ }
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/GcmSpecUtil.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/GcmSpecUtil.java
new file mode 100644
index 00000000..5ccc8ff0
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/GcmSpecUtil.java
@@ -0,0 +1,78 @@
+package org.bouncycastle.jcajce.provider.symmetric;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.InvalidParameterSpecException;
+
+import org.bouncycastle.asn1.ASN1Primitive;
+import org.bouncycastle.asn1.cms.GCMParameters;
+import org.bouncycastle.util.Integers;
+
+class GcmSpecUtil
+{
+ static final Class gcmSpecClass = lookup("javax.crypto.spec.GCMParameterSpec");
+
+ static boolean gcmSpecExists()
+ {
+ return gcmSpecClass != null;
+ }
+
+ static boolean isGcmSpec(AlgorithmParameterSpec paramSpec)
+ {
+ return gcmSpecClass != null && gcmSpecClass.isInstance(paramSpec);
+ }
+
+ static boolean isGcmSpec(Class paramSpecClass)
+ {
+ return gcmSpecClass == paramSpecClass;
+ }
+
+ static AlgorithmParameterSpec extractGcmSpec(ASN1Primitive spec)
+ throws InvalidParameterSpecException
+ {
+ try
+ {
+ GCMParameters gcmParams = GCMParameters.getInstance(spec);
+ Constructor constructor = gcmSpecClass.getConstructor(new Class[]{Integer.TYPE, byte[].class});
+
+ return (AlgorithmParameterSpec)constructor.newInstance(new Object[] { Integers.valueOf(gcmParams.getIcvLen() * 8), gcmParams.getNonce() });
+ }
+ catch (NoSuchMethodException e)
+ {
+ throw new InvalidParameterSpecException("No constructor found!"); // should never happen
+ }
+ catch (Exception e)
+ {
+ throw new InvalidParameterSpecException("Construction failed: " + e.getMessage()); // should never happen
+ }
+ }
+
+ static GCMParameters extractGcmParameters(AlgorithmParameterSpec paramSpec)
+ throws InvalidParameterSpecException
+ {
+ try
+ {
+ Method tLen = gcmSpecClass.getDeclaredMethod("getTLen", new Class[0]);
+ Method iv= gcmSpecClass.getDeclaredMethod("getIV", new Class[0]);
+
+ return new GCMParameters((byte[])iv.invoke(paramSpec, new Object[0]), ((Integer)tLen.invoke(paramSpec, new Object[0])).intValue() / 8);
+ }
+ catch (Exception e)
+ {
+ throw new InvalidParameterSpecException("Cannot process GCMParameterSpec");
+ }
+ }
+
+ private static Class lookup(String className)
+ {
+ try
+ {
+ return GcmSpecUtil.class.getClassLoader().loadClass(className);
+ }
+ catch (Exception e)
+ {
+ return null;
+ }
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/OpenSSLPBKDF.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/OpenSSLPBKDF.java
new file mode 100644
index 00000000..5888adfa
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/OpenSSLPBKDF.java
@@ -0,0 +1,86 @@
+package org.bouncycastle.jcajce.provider.symmetric;
+
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.KeySpec;
+
+import javax.crypto.SecretKey;
+import javax.crypto.spec.PBEKeySpec;
+import javax.crypto.spec.SecretKeySpec;
+
+import org.bouncycastle.crypto.generators.OpenSSLPBEParametersGenerator;
+import org.bouncycastle.crypto.params.KeyParameter;
+import org.bouncycastle.jcajce.provider.config.ConfigurableProvider;
+import org.bouncycastle.jcajce.provider.symmetric.util.BaseSecretKeyFactory;
+import org.bouncycastle.jcajce.provider.util.AlgorithmProvider;
+import org.bouncycastle.util.Strings;
+
+public final class OpenSSLPBKDF
+{
+ private OpenSSLPBKDF()
+ {
+ }
+
+ public static class PBKDF
+ extends BaseSecretKeyFactory
+ {
+ public PBKDF()
+ {
+ super("PBKDF-OpenSSL", null);
+ }
+
+ protected SecretKey engineGenerateSecret(
+ KeySpec keySpec)
+ throws InvalidKeySpecException
+ {
+ if (keySpec instanceof PBEKeySpec)
+ {
+ PBEKeySpec pbeSpec = (PBEKeySpec)keySpec;
+
+ if (pbeSpec.getSalt() == null)
+ {
+ throw new InvalidKeySpecException("missing required salt");
+ }
+
+ if (pbeSpec.getIterationCount() <= 0)
+ {
+ throw new InvalidKeySpecException("positive iteration count required: "
+ + pbeSpec.getIterationCount());
+ }
+
+ if (pbeSpec.getKeyLength() <= 0)
+ {
+ throw new InvalidKeySpecException("positive key length required: "
+ + pbeSpec.getKeyLength());
+ }
+
+ if (pbeSpec.getPassword().length == 0)
+ {
+ throw new IllegalArgumentException("password empty");
+ }
+
+ OpenSSLPBEParametersGenerator pGen = new OpenSSLPBEParametersGenerator();
+
+ pGen.init(Strings.toByteArray(pbeSpec.getPassword()), pbeSpec.getSalt());
+
+ return new SecretKeySpec(((KeyParameter)pGen.generateDerivedParameters(pbeSpec.getKeyLength())).getKey(), "OpenSSLPBKDF");
+ }
+
+ throw new InvalidKeySpecException("Invalid KeySpec");
+ }
+ }
+
+ public static class Mappings
+ extends AlgorithmProvider
+ {
+ private static final String PREFIX = OpenSSLPBKDF.class.getName();
+
+ public Mappings()
+ {
+ }
+
+ public void configure(ConfigurableProvider provider)
+ {
+ provider.addAlgorithm("SecretKeyFactory.PBKDF-OPENSSL", PREFIX + "$PBKDF");
+ }
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/SM4.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/SM4.java
new file mode 100644
index 00000000..05e037ab
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/SM4.java
@@ -0,0 +1,162 @@
+package org.bouncycastle.jcajce.provider.symmetric;
+
+import java.security.AlgorithmParameters;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.SecureRandom;
+import java.security.spec.AlgorithmParameterSpec;
+
+import javax.crypto.spec.IvParameterSpec;
+
+import org.bouncycastle.crypto.BlockCipher;
+import org.bouncycastle.crypto.CipherKeyGenerator;
+import org.bouncycastle.crypto.engines.SM4Engine;
+import org.bouncycastle.crypto.generators.Poly1305KeyGenerator;
+import org.bouncycastle.crypto.macs.CMac;
+import org.bouncycastle.crypto.macs.GMac;
+import org.bouncycastle.crypto.modes.GCMBlockCipher;
+import org.bouncycastle.jcajce.provider.config.ConfigurableProvider;
+import org.bouncycastle.jcajce.provider.symmetric.util.BaseAlgorithmParameterGenerator;
+import org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher;
+import org.bouncycastle.jcajce.provider.symmetric.util.BaseKeyGenerator;
+import org.bouncycastle.jcajce.provider.symmetric.util.BaseMac;
+import org.bouncycastle.jcajce.provider.symmetric.util.BlockCipherProvider;
+import org.bouncycastle.jcajce.provider.symmetric.util.IvAlgorithmParameters;
+
+public final class SM4
+{
+ private SM4()
+ {
+ }
+
+ public static class ECB
+ extends BaseBlockCipher
+ {
+ public ECB()
+ {
+ super(new BlockCipherProvider()
+ {
+ public BlockCipher get()
+ {
+ return new SM4Engine();
+ }
+ });
+ }
+ }
+
+ public static class KeyGen
+ extends BaseKeyGenerator
+ {
+ public KeyGen()
+ {
+ super("SM4", 128, new CipherKeyGenerator());
+ }
+ }
+
+ public static class CMAC
+ extends BaseMac
+ {
+ public CMAC()
+ {
+ super(new CMac(new SM4Engine()));
+ }
+ }
+
+ public static class GMAC
+ extends BaseMac
+ {
+ public GMAC()
+ {
+ super(new GMac(new GCMBlockCipher(new SM4Engine())));
+ }
+ }
+
+ public static class Poly1305
+ extends BaseMac
+ {
+ public Poly1305()
+ {
+ super(new org.bouncycastle.crypto.macs.Poly1305(new SM4Engine()));
+ }
+ }
+
+ public static class Poly1305KeyGen
+ extends BaseKeyGenerator
+ {
+ public Poly1305KeyGen()
+ {
+ super("Poly1305-SM4", 256, new Poly1305KeyGenerator());
+ }
+ }
+
+ public static class AlgParamGen
+ extends BaseAlgorithmParameterGenerator
+ {
+ protected void engineInit(
+ AlgorithmParameterSpec genParamSpec,
+ SecureRandom random)
+ throws InvalidAlgorithmParameterException
+ {
+ throw new InvalidAlgorithmParameterException("No supported AlgorithmParameterSpec for SM4 parameter generation.");
+ }
+
+ protected AlgorithmParameters engineGenerateParameters()
+ {
+ byte[] iv = new byte[16];
+
+ if (random == null)
+ {
+ random = new SecureRandom();
+ }
+
+ random.nextBytes(iv);
+
+ AlgorithmParameters params;
+
+ try
+ {
+ params = createParametersInstance("SM4");
+ params.init(new IvParameterSpec(iv));
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException(e.getMessage());
+ }
+
+ return params;
+ }
+ }
+
+ public static class AlgParams
+ extends IvAlgorithmParameters
+ {
+ protected String engineToString()
+ {
+ return "SM4 IV";
+ }
+ }
+
+ public static class Mappings
+ extends SymmetricAlgorithmProvider
+ {
+ private static final String PREFIX = SM4.class.getName();
+
+ public Mappings()
+ {
+ }
+
+ public void configure(ConfigurableProvider provider)
+ {
+ provider.addAlgorithm("AlgorithmParameters.SM4", PREFIX + "$AlgParams");
+
+ provider.addAlgorithm("AlgorithmParameterGenerator.SM4", PREFIX + "$AlgParamGen");
+
+ provider.addAlgorithm("Cipher.SM4", PREFIX + "$ECB");
+
+ provider.addAlgorithm("KeyGenerator.SM4", PREFIX + "$KeyGen");
+
+ addCMacAlgorithm(provider, "SM4", PREFIX + "$CMAC", PREFIX + "$KeyGen");
+ addGMacAlgorithm(provider, "SM4", PREFIX + "$GMAC", PREFIX + "$KeyGen");
+ addPoly1305Algorithm(provider, "SM4", PREFIX + "$Poly1305", PREFIX + "$Poly1305KeyGen");
+ }
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/spec/KTSParameterSpec.java b/bcprov/src/main/java/org/bouncycastle/jcajce/spec/KTSParameterSpec.java
new file mode 100644
index 00000000..a6d1a8d2
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/spec/KTSParameterSpec.java
@@ -0,0 +1,157 @@
+package org.bouncycastle.jcajce.spec;
+
+import java.security.spec.AlgorithmParameterSpec;
+
+import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
+import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
+import org.bouncycastle.util.Arrays;
+
+/**
+ * Parameter spec for doing KTS based wrapping via the Cipher API.
+ */
+public class KTSParameterSpec
+ implements AlgorithmParameterSpec
+{
+ private final String wrappingKeyAlgorithm;
+ private final int keySizeInBits;
+ private final AlgorithmParameterSpec parameterSpec;
+ private final AlgorithmIdentifier kdfAlgorithm;
+ private byte[] otherInfo;
+
+ /**
+ * Builder class for creating a KTSParameterSpec.
+ */
+ public static final class Builder
+ {
+ private final String algorithmName;
+ private final int keySizeInBits;
+
+ private AlgorithmParameterSpec parameterSpec;
+ private AlgorithmIdentifier kdfAlgorithm;
+ private byte[] otherInfo;
+
+ /**
+ * Basic builder.
+ *
+ * @param algorithmName the algorithm name for the secret key we use for wrapping.
+ * @param keySizeInBits the size of the wrapping key we want to produce in bits.
+ */
+ public Builder(String algorithmName, int keySizeInBits)
+ {
+ this(algorithmName, keySizeInBits, null);
+ }
+
+ /**
+ * Basic builder.
+ *
+ * @param algorithmName the algorithm name for the secret key we use for wrapping.
+ * @param keySizeInBits the size of the wrapping key we want to produce in bits.
+ * @param otherInfo the otherInfo/IV encoding to be applied to the KDF.
+ */
+ public Builder(String algorithmName, int keySizeInBits, byte[] otherInfo)
+ {
+ this.algorithmName = algorithmName;
+ this.keySizeInBits = keySizeInBits;
+ this.kdfAlgorithm = new AlgorithmIdentifier(X9ObjectIdentifiers.id_kdf_kdf3, new AlgorithmIdentifier(NISTObjectIdentifiers.id_sha256));
+ this.otherInfo = (otherInfo == null) ? new byte[0] : Arrays.clone(otherInfo);
+ }
+
+ /**
+ * Set the algorithm parameter spec to be used with the wrapper.
+ *
+ * @param parameterSpec the algorithm parameter spec to be used in wrapping/unwrapping.
+ * @return the current Builder instance.
+ */
+ public Builder withParameterSpec(AlgorithmParameterSpec parameterSpec)
+ {
+ this.parameterSpec = parameterSpec;
+
+ return this;
+ }
+
+ /**
+ * Set the KDF algorithm and digest algorithm for wrap key generation.
+ *
+ * @param kdfAlgorithm the KDF algorithm to apply.
+ * @return the current Builder instance.
+ */
+ public Builder withKdfAlgorithm(AlgorithmIdentifier kdfAlgorithm)
+ {
+ this.kdfAlgorithm = kdfAlgorithm;
+
+ return this;
+ }
+
+ /**
+ * Build the new parameter spec.
+ *
+ * @return a new parameter spec configured according to the builder state.
+ */
+ public KTSParameterSpec build()
+ {
+ return new KTSParameterSpec(algorithmName, keySizeInBits, parameterSpec, kdfAlgorithm, otherInfo);
+ }
+ }
+
+ private KTSParameterSpec(
+ String wrappingKeyAlgorithm, int keySizeInBits,
+ AlgorithmParameterSpec parameterSpec, AlgorithmIdentifier kdfAlgorithm, byte[] otherInfo)
+ {
+ this.wrappingKeyAlgorithm = wrappingKeyAlgorithm;
+ this.keySizeInBits = keySizeInBits;
+ this.parameterSpec = parameterSpec;
+ this.kdfAlgorithm = kdfAlgorithm;
+ this.otherInfo = otherInfo;
+ }
+
+ /**
+ * Return the name of the algorithm for the wrapping key this key spec should use.
+ *
+ * @return the key algorithm.
+ */
+ public String getKeyAlgorithmName()
+ {
+ return wrappingKeyAlgorithm;
+ }
+
+ /**
+ * Return the size of the key (in bits) for the wrapping key this key spec should use.
+ *
+ * @return length in bits of the key to be calculated.
+ */
+ public int getKeySize()
+ {
+ return keySizeInBits;
+ }
+
+ /**
+ * Return the algorithm parameter spec to be applied with the private key when the encapsulation is decrypted.
+ *
+ * @return the algorithm parameter spec to be used with the private key.
+ */
+ public AlgorithmParameterSpec getParameterSpec()
+ {
+ return parameterSpec;
+ }
+
+ /**
+ * Return the AlgorithmIdentifier for the KDF to do key derivation after extracting the secret.
+ *
+ * @return the AlgorithmIdentifier for the SecretKeyFactory's KDF.
+ */
+ public AlgorithmIdentifier getKdfAlgorithm()
+ {
+ return kdfAlgorithm;
+ }
+
+ /**
+ * Return the otherInfo data for initialising the KDF.
+ *
+ * @return the otherInfo data.
+ */
+ public byte[] getOtherInfo()
+ {
+ return Arrays.clone(otherInfo);
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/spec/MQVParameterSpec.java b/bcprov/src/main/java/org/bouncycastle/jcajce/spec/MQVParameterSpec.java
new file mode 100644
index 00000000..907abfb4
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/spec/MQVParameterSpec.java
@@ -0,0 +1,70 @@
+package org.bouncycastle.jcajce.spec;
+
+import java.security.KeyPair;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.spec.AlgorithmParameterSpec;
+
+import org.bouncycastle.util.Arrays;
+
+public class MQVParameterSpec
+ implements AlgorithmParameterSpec
+{
+ private final PublicKey ephemeralPublicKey;
+ private final PrivateKey ephemeralPrivateKey;
+ private final PublicKey otherPartyEphemeralKey;
+ private final byte[] userKeyingMaterial;
+
+ public MQVParameterSpec(PublicKey ephemeralPublicKey, PrivateKey ephemeralPrivateKey, PublicKey otherPartyEphemeralKey, byte[] userKeyingMaterial)
+ {
+ this.ephemeralPublicKey = ephemeralPublicKey;
+ this.ephemeralPrivateKey = ephemeralPrivateKey;
+ this.otherPartyEphemeralKey = otherPartyEphemeralKey;
+ this.userKeyingMaterial = Arrays.clone(userKeyingMaterial);
+ }
+
+ public MQVParameterSpec(PublicKey ephemeralPublicKey, PrivateKey ephemeralPrivateKey, PublicKey otherPartyEphemeralKey)
+ {
+ this(ephemeralPublicKey, ephemeralPrivateKey, otherPartyEphemeralKey, null);
+ }
+
+ public MQVParameterSpec(KeyPair ephemeralKeyPair, PublicKey otherPartyEphemeralKey, byte[] userKeyingMaterial)
+ {
+ this(ephemeralKeyPair.getPublic(), ephemeralKeyPair.getPrivate(), otherPartyEphemeralKey, userKeyingMaterial);
+ }
+
+ public MQVParameterSpec(PrivateKey ephemeralPrivateKey, PublicKey otherPartyEphemeralKey, byte[] userKeyingMaterial)
+ {
+ this(null, ephemeralPrivateKey, otherPartyEphemeralKey, userKeyingMaterial);
+ }
+
+ public MQVParameterSpec(KeyPair ephemeralKeyPair, PublicKey otherPartyEphemeralKey)
+ {
+ this(ephemeralKeyPair.getPublic(), ephemeralKeyPair.getPrivate(), otherPartyEphemeralKey, null);
+ }
+
+ public MQVParameterSpec(PrivateKey ephemeralPrivateKey, PublicKey otherPartyEphemeralKey)
+ {
+ this(null, ephemeralPrivateKey, otherPartyEphemeralKey, null);
+ }
+
+ public PrivateKey getEphemeralPrivateKey()
+ {
+ return ephemeralPrivateKey;
+ }
+
+ public PublicKey getEphemeralPublicKey()
+ {
+ return ephemeralPublicKey;
+ }
+
+ public PublicKey getOtherPartyEphemeralKey()
+ {
+ return otherPartyEphemeralKey;
+ }
+
+ public byte[] getUserKeyingMaterial()
+ {
+ return Arrays.clone(userKeyingMaterial);
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/spec/UserKeyingMaterialSpec.java b/bcprov/src/main/java/org/bouncycastle/jcajce/spec/UserKeyingMaterialSpec.java
new file mode 100644
index 00000000..d8135310
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/spec/UserKeyingMaterialSpec.java
@@ -0,0 +1,21 @@
+package org.bouncycastle.jcajce.spec;
+
+import java.security.spec.AlgorithmParameterSpec;
+
+import org.bouncycastle.util.Arrays;
+
+public class UserKeyingMaterialSpec
+ implements AlgorithmParameterSpec
+{
+ private final byte[] userKeyingMaterial;
+
+ public UserKeyingMaterialSpec(byte[] userKeyingMaterial)
+ {
+ this.userKeyingMaterial = Arrays.clone(userKeyingMaterial);
+ }
+
+ public byte[] getUserKeyingMaterial()
+ {
+ return Arrays.clone(userKeyingMaterial);
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/util/AlgorithmParametersUtils.java b/bcprov/src/main/java/org/bouncycastle/jcajce/util/AlgorithmParametersUtils.java
new file mode 100644
index 00000000..4a1a92a5
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/util/AlgorithmParametersUtils.java
@@ -0,0 +1,68 @@
+/***************************************************************/
+/****** DO NOT EDIT THIS CLASS bc-java SOURCE FILE ******/
+/***************************************************************/
+package org.bouncycastle.jcajce.util;
+
+import java.io.IOException;
+import java.security.AlgorithmParameters;
+
+import org.bouncycastle.asn1.ASN1Encodable;
+import org.bouncycastle.asn1.ASN1Primitive;
+
+/**
+ * General JCA/JCE utility methods.
+ */
+public class AlgorithmParametersUtils
+{
+
+
+ private AlgorithmParametersUtils()
+ {
+
+ }
+
+ /**
+ * Extract an ASN.1 encodable from an AlgorithmParameters object.
+ *
+ * @param params the object to get the encoding used to create the return value.
+ * @return an ASN.1 object representing the primitives making up the params parameter.
+ * @throws IOException if an encoding cannot be extracted.
+ */
+ public static ASN1Encodable extractParameters(AlgorithmParameters params)
+ throws IOException
+ {
+ // we try ASN.1 explicitly first just in case and then role back to the default.
+ ASN1Encodable asn1Params;
+ try
+ {
+ asn1Params = ASN1Primitive.fromByteArray(params.getEncoded("ASN.1"));
+ }
+ catch (Exception ex)
+ {
+ asn1Params = ASN1Primitive.fromByteArray(params.getEncoded());
+ }
+
+ return asn1Params;
+ }
+
+ /**
+ * Load an AlgorithmParameters object with the passed in ASN.1 encodable - if possible.
+ *
+ * @param params the AlgorithmParameters object to be initialised.
+ * @param sParams the ASN.1 encodable to initialise params with.
+ * @throws IOException if the parameters cannot be initialised.
+ */
+ public static void loadParameters(AlgorithmParameters params, ASN1Encodable sParams)
+ throws IOException
+ {
+ // we try ASN.1 explicitly first just in case and then role back to the default.
+ try
+ {
+ params.init(sParams.toASN1Primitive().getEncoded(), "ASN.1");
+ }
+ catch (Exception ex)
+ {
+ params.init(sParams.toASN1Primitive().getEncoded());
+ }
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/util/MessageDigestUtils.java b/bcprov/src/main/java/org/bouncycastle/jcajce/util/MessageDigestUtils.java
new file mode 100644
index 00000000..1bf8b31b
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/util/MessageDigestUtils.java
@@ -0,0 +1,55 @@
+package org.bouncycastle.jcajce.util;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
+import org.bouncycastle.asn1.gnu.GNUObjectIdentifiers;
+import org.bouncycastle.asn1.iso.ISOIECObjectIdentifiers;
+import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
+import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
+import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
+import org.bouncycastle.asn1.teletrust.TeleTrusTObjectIdentifiers;
+
+public class MessageDigestUtils
+{
+ private static Map<ASN1ObjectIdentifier, String> digestOidMap = new HashMap<ASN1ObjectIdentifier, String>();
+
+ static
+ {
+ digestOidMap.put(PKCSObjectIdentifiers.md2, "MD2");
+ digestOidMap.put(PKCSObjectIdentifiers.md4, "MD4");
+ digestOidMap.put(PKCSObjectIdentifiers.md5, "MD5");
+ digestOidMap.put(OIWObjectIdentifiers.idSHA1, "SHA-1");
+ digestOidMap.put(NISTObjectIdentifiers.id_sha224, "SHA-224");
+ digestOidMap.put(NISTObjectIdentifiers.id_sha256, "SHA-256");
+ digestOidMap.put(NISTObjectIdentifiers.id_sha384, "SHA-384");
+ digestOidMap.put(NISTObjectIdentifiers.id_sha512, "SHA-512");
+ digestOidMap.put(TeleTrusTObjectIdentifiers.ripemd128, "RIPEMD-128");
+ digestOidMap.put(TeleTrusTObjectIdentifiers.ripemd160, "RIPEMD-160");
+ digestOidMap.put(TeleTrusTObjectIdentifiers.ripemd256, "RIPEMD-128");
+ digestOidMap.put(ISOIECObjectIdentifiers.ripemd128, "RIPEMD-128");
+ digestOidMap.put(ISOIECObjectIdentifiers.ripemd160, "RIPEMD-160");
+ digestOidMap.put(CryptoProObjectIdentifiers.gostR3411, "GOST3411");
+ digestOidMap.put(GNUObjectIdentifiers.Tiger_192, "Tiger");
+ digestOidMap.put(ISOIECObjectIdentifiers.whirlpool, "Whirlpool");
+ }
+
+ /**
+ * Attempt to find a standard JCA name for the digest represented by the passed in OID.
+ *
+ * @param digestAlgOID the OID of the digest algorithm of interest.
+ * @return a string representing the standard name - the OID as a string if none available.
+ */
+ public static String getDigestName(ASN1ObjectIdentifier digestAlgOID)
+ {
+ String name = (String)digestOidMap.get(digestAlgOID); // for pre 1.5 JDK
+ if (name != null)
+ {
+ return name;
+ }
+
+ return digestAlgOID.getId();
+ }
+}