Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/quite/humla-spongycastle.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Hook <dgh@cryptoworkshop.com>2013-09-13 10:27:50 +0400
committerDavid Hook <dgh@cryptoworkshop.com>2013-09-13 10:27:50 +0400
commit1c67cdcb2d9d30487efee98979ee1646a89553de (patch)
tree6b2630bc78c2cf73ae9b8c857988330fba9e5d45
parent972c20edfaa73bf197b1665eb3c4818c01ac3934 (diff)
added support for GOST in conjunction with PBKDF2.
added support for keyMeshing with GOST block cipher (see GCFBBlockCipher). added correct encoding/decoding for GOST private keys.
-rw-r--r--core/src/main/j2me/java/util/AbstractList.java7
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cryptopro/CryptoProObjectIdentifiers.java2
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cryptopro/GOST3410PublicKeyAlgParameters.java3
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/pkcs/PBKDF2Params.java36
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/BufferedBlockCipher.java2
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/generators/PKCS5S2ParametersGenerator.java2
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/modes/CFBBlockCipher.java11
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/modes/GCFBBlockCipher.java81
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/GOST3411DigestTest.java47
-rw-r--r--pkix/src/main/java/org/bouncycastle/operator/DefaultSecretKeyProvider.java3
-rw-r--r--pkix/src/main/java/org/bouncycastle/pkcs/jcajce/JcePKCSPBEInputDecryptorProviderBuilder.java33
-rw-r--r--pkix/src/test/java/org/bouncycastle/pkcs/test/PfxPduTest.java153
-rw-r--r--prov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ecgost/BCECGOST3410PrivateKey.java300
-rw-r--r--prov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ecgost/BCECGOST3410PublicKey.java12
-rw-r--r--prov/src/main/java/org/bouncycastle/jcajce/provider/digest/GOST3411.java16
-rw-r--r--prov/src/main/java/org/bouncycastle/jcajce/provider/digest/SHA1.java1
-rw-r--r--prov/src/main/java/org/bouncycastle/jcajce/provider/keystore/pkcs12/PKCS12KeyStoreSpi.java156
-rw-r--r--prov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/GOST28147.java15
-rw-r--r--prov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/PBEPBKDF2.java106
-rw-r--r--prov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher.java23
-rw-r--r--prov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/PBE.java31
-rw-r--r--prov/src/main/java/org/bouncycastle/jce/spec/GOST28147ParameterSpec.java67
-rw-r--r--prov/src/main/java/org/bouncycastle/jce/spec/RepeatedSecretKeySpec.java23
-rw-r--r--prov/src/test/java/org/bouncycastle/jce/provider/test/AESSICTest.java2
-rw-r--r--prov/src/test/java/org/bouncycastle/jce/provider/test/GOST28147Test.java6
-rw-r--r--prov/src/test/java/org/bouncycastle/jce/provider/test/PKCS12StoreTest.java78
26 files changed, 972 insertions, 244 deletions
diff --git a/core/src/main/j2me/java/util/AbstractList.java b/core/src/main/j2me/java/util/AbstractList.java
index 42dda96e..dbb1dffc 100644
--- a/core/src/main/j2me/java/util/AbstractList.java
+++ b/core/src/main/j2me/java/util/AbstractList.java
@@ -57,7 +57,7 @@ public abstract class AbstractList
{
int index = li.nextIndex();
e = li.next();
- System.out.println(e);
+
if (o == null)
{
if (e == null)
@@ -217,14 +217,13 @@ public abstract class AbstractList
protected void removeRange(int fromIndex, int toIndex)
{
- System.out.println("breakpoint 1");
if (fromIndex == toIndex)
{
return;
}
- System.out.println("breakpoint 2");
+
ListIterator li = listIterator(fromIndex);
- System.out.println("breakpoint 3");
+
int i = fromIndex;
do
{
diff --git a/core/src/main/java/org/bouncycastle/asn1/cryptopro/CryptoProObjectIdentifiers.java b/core/src/main/java/org/bouncycastle/asn1/cryptopro/CryptoProObjectIdentifiers.java
index 108270e5..c6e8e0d1 100644
--- a/core/src/main/java/org/bouncycastle/asn1/cryptopro/CryptoProObjectIdentifiers.java
+++ b/core/src/main/java/org/bouncycastle/asn1/cryptopro/CryptoProObjectIdentifiers.java
@@ -19,7 +19,7 @@ public interface CryptoProObjectIdentifiers
static final ASN1ObjectIdentifier gostR3411Hmac = GOST_id.branch("10");
/** Gost R28147 OID: 1.2.643.2.2.21 */
- static final ASN1ObjectIdentifier gostR28147_cbc = GOST_id.branch("21");
+ static final ASN1ObjectIdentifier gostR28147_gcfb = GOST_id.branch("21");
/** Gost R28147-89-CryotoPro-A-ParamSet OID: 1.2.643.2.2.31.1 */
static final ASN1ObjectIdentifier id_Gost28147_89_CryptoPro_A_ParamSet = GOST_id.branch("31.1");
diff --git a/core/src/main/java/org/bouncycastle/asn1/cryptopro/GOST3410PublicKeyAlgParameters.java b/core/src/main/java/org/bouncycastle/asn1/cryptopro/GOST3410PublicKeyAlgParameters.java
index 0307f50f..45d78147 100644
--- a/core/src/main/java/org/bouncycastle/asn1/cryptopro/GOST3410PublicKeyAlgParameters.java
+++ b/core/src/main/java/org/bouncycastle/asn1/cryptopro/GOST3410PublicKeyAlgParameters.java
@@ -57,6 +57,9 @@ public class GOST3410PublicKeyAlgParameters
this.encryptionParamSet = encryptionParamSet;
}
+ /**
+ * @deprecated use getInstance()
+ */
public GOST3410PublicKeyAlgParameters(
ASN1Sequence seq)
{
diff --git a/core/src/main/java/org/bouncycastle/asn1/pkcs/PBKDF2Params.java b/core/src/main/java/org/bouncycastle/asn1/pkcs/PBKDF2Params.java
index c8e92dc9..92c4e8f1 100644
--- a/core/src/main/java/org/bouncycastle/asn1/pkcs/PBKDF2Params.java
+++ b/core/src/main/java/org/bouncycastle/asn1/pkcs/PBKDF2Params.java
@@ -89,6 +89,42 @@ public class PBKDF2Params
this.keyLength = new ASN1Integer(keyLength);
}
+ /**
+ * Create a PBKDF2Params with the specified salt, iteration count, keyLength, and a defined prf.
+ *
+ * @param salt input salt.
+ * @param iterationCount input iteration count.
+ * @param keyLength intended key length to be produced.
+ * @param prf the pseudo-random function to use.
+ */
+ public PBKDF2Params(
+ byte[] salt,
+ int iterationCount,
+ int keyLength,
+ AlgorithmIdentifier prf)
+ {
+ this(salt, iterationCount);
+
+ this.keyLength = new ASN1Integer(keyLength);
+ this.prf = prf;
+ }
+
+ /**
+ * Create a PBKDF2Params with the specified salt, iteration count, and a defined prf.
+ *
+ * @param salt input salt.
+ * @param iterationCount input iteration count.
+ * @param prf the pseudo-random function to use.
+ */
+ public PBKDF2Params(
+ byte[] salt,
+ int iterationCount,
+ AlgorithmIdentifier prf)
+ {
+ this(salt, iterationCount);
+ this.prf = prf;
+ }
+
private PBKDF2Params(
ASN1Sequence seq)
{
diff --git a/core/src/main/java/org/bouncycastle/crypto/BufferedBlockCipher.java b/core/src/main/java/org/bouncycastle/crypto/BufferedBlockCipher.java
index bdb694d4..dd056aca 100644
--- a/core/src/main/java/org/bouncycastle/crypto/BufferedBlockCipher.java
+++ b/core/src/main/java/org/bouncycastle/crypto/BufferedBlockCipher.java
@@ -54,7 +54,7 @@ public class BufferedBlockCipher
}
else
{
- partialBlockOkay = (idx > 0 && (name.startsWith("CFB", idx) || name.startsWith("OFB", idx) || name.startsWith("OpenPGP", idx) || name.startsWith("SIC", idx) || name.startsWith("GCTR", idx)));
+ partialBlockOkay = (idx > 0 && (name.startsWith("CFB", idx) || name.startsWith("GCFB", idx) ||name.startsWith("OFB", idx) || name.startsWith("OpenPGP", idx) || name.startsWith("SIC", idx) || name.startsWith("GCTR", idx)));
}
}
diff --git a/core/src/main/java/org/bouncycastle/crypto/generators/PKCS5S2ParametersGenerator.java b/core/src/main/java/org/bouncycastle/crypto/generators/PKCS5S2ParametersGenerator.java
index 640ead46..0954d481 100644
--- a/core/src/main/java/org/bouncycastle/crypto/generators/PKCS5S2ParametersGenerator.java
+++ b/core/src/main/java/org/bouncycastle/crypto/generators/PKCS5S2ParametersGenerator.java
@@ -58,7 +58,7 @@ public class PKCS5S2ParametersGenerator
hMac.doFinal(state, 0);
System.arraycopy(state, 0, out, outOff, state.length);
-
+
for (int count = 1; count < c; count++)
{
hMac.update(state, 0, state.length);
diff --git a/core/src/main/java/org/bouncycastle/crypto/modes/CFBBlockCipher.java b/core/src/main/java/org/bouncycastle/crypto/modes/CFBBlockCipher.java
index d0fb9bb6..a8851690 100644
--- a/core/src/main/java/org/bouncycastle/crypto/modes/CFBBlockCipher.java
+++ b/core/src/main/java/org/bouncycastle/crypto/modes/CFBBlockCipher.java
@@ -4,6 +4,7 @@ import org.bouncycastle.crypto.BlockCipher;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.DataLengthException;
import org.bouncycastle.crypto.params.ParametersWithIV;
+import org.bouncycastle.util.Arrays;
/**
* implements a Cipher-FeedBack (CFB) mode on top of a simple cipher.
@@ -246,6 +247,16 @@ public class CFBBlockCipher
}
/**
+ * Return the current state of the initialisation vector.
+ *
+ * @return current IV
+ */
+ public byte[] getCurrentIV()
+ {
+ return Arrays.clone(cfbV);
+ }
+
+ /**
* reset the chaining vector back to the IV and reset the underlying
* cipher.
*/
diff --git a/core/src/main/java/org/bouncycastle/crypto/modes/GCFBBlockCipher.java b/core/src/main/java/org/bouncycastle/crypto/modes/GCFBBlockCipher.java
index f441b89f..887c1697 100644
--- a/core/src/main/java/org/bouncycastle/crypto/modes/GCFBBlockCipher.java
+++ b/core/src/main/java/org/bouncycastle/crypto/modes/GCFBBlockCipher.java
@@ -3,38 +3,107 @@ package org.bouncycastle.crypto.modes;
import org.bouncycastle.crypto.BlockCipher;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.DataLengthException;
+import org.bouncycastle.crypto.params.KeyParameter;
+import org.bouncycastle.crypto.params.ParametersWithIV;
+import org.bouncycastle.crypto.params.ParametersWithRandom;
+import org.bouncycastle.crypto.params.ParametersWithSBox;
+/**
+ * An implementation of the GOST CFB mode with CryptoPro key meshing as described in RFC 4357.
+ */
public class GCFBBlockCipher
implements BlockCipher
{
+ private static final byte[] C =
+ {
+ 0x69, 0x00, 0x72, 0x22, 0x64, (byte)0xC9, 0x04, 0x23,
+ (byte)0x8D, 0x3A, (byte)0xDB, (byte)0x96, 0x46, (byte)0xE9, 0x2A, (byte)0xC4,
+ 0x18, (byte)0xFE, (byte)0xAC, (byte)0x94, 0x00, (byte)0xED, 0x07, 0x12,
+ (byte)0xC0, (byte)0x86, (byte)0xDC, (byte)0xC2, (byte)0xEF, 0x4C, (byte)0xA9, 0x2B
+ };
+
+ private final CFBBlockCipher cfbEngine;
+
+ private KeyParameter key;
+ private long counter = 0;
+ private boolean forEncryption;
+
public GCFBBlockCipher(BlockCipher engine)
{
-
+ this.cfbEngine = new CFBBlockCipher(engine, engine.getBlockSize() * 8);
}
+
public void init(boolean forEncryption, CipherParameters params)
throws IllegalArgumentException
{
- //To change body of implemented methods use File | Settings | File Templates.
+ counter = 0;
+ cfbEngine.init(forEncryption, params);
+
+ this.forEncryption = forEncryption;
+
+ if (params instanceof ParametersWithIV)
+ {
+ params = ((ParametersWithIV)params).getParameters();
+ }
+
+ if (params instanceof ParametersWithRandom)
+ {
+ params = ((ParametersWithRandom)params).getParameters();
+ }
+
+ if (params instanceof ParametersWithSBox)
+ {
+ params = ((ParametersWithSBox)params).getParameters();
+ }
+
+ key = (KeyParameter)params;
}
public String getAlgorithmName()
{
- return null; //To change body of implemented methods use File | Settings | File Templates.
+ return "G" + cfbEngine.getAlgorithmName();
}
public int getBlockSize()
{
- return 0; //To change body of implemented methods use File | Settings | File Templates.
+ return cfbEngine.getBlockSize();
}
public int processBlock(byte[] in, int inOff, byte[] out, int outOff)
throws DataLengthException, IllegalStateException
{
- return 0; //To change body of implemented methods use File | Settings | File Templates.
+ if (counter > 0 && counter % 1024 == 0)
+ {
+ BlockCipher base = cfbEngine.getUnderlyingCipher();
+
+ base.init(false, key);
+
+ byte[] nextKey = new byte[32];
+
+ base.processBlock(C, 0, nextKey, 0);
+ base.processBlock(C, 8, nextKey, 8);
+ base.processBlock(C, 16, nextKey, 16);
+ base.processBlock(C, 24, nextKey, 24);
+
+ key = new KeyParameter(nextKey);
+
+ byte[] iv = new byte[8];
+
+ base.init(true, key);
+
+ base.processBlock(cfbEngine.getCurrentIV(), 0, iv, 0);
+
+ cfbEngine.init(forEncryption, new ParametersWithIV(key, iv));
+ }
+
+ counter += cfbEngine.getBlockSize();
+
+ return cfbEngine.processBlock(in, inOff, out, outOff);
}
public void reset()
{
- //To change body of implemented methods use File | Settings | File Templates.
+ counter = 0;
+ cfbEngine.reset();
}
}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/GOST3411DigestTest.java b/core/src/test/java/org/bouncycastle/crypto/test/GOST3411DigestTest.java
index 9fb81a6c..7bf5be72 100644
--- a/core/src/test/java/org/bouncycastle/crypto/test/GOST3411DigestTest.java
+++ b/core/src/test/java/org/bouncycastle/crypto/test/GOST3411DigestTest.java
@@ -2,6 +2,12 @@ package org.bouncycastle.crypto.test;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.digests.GOST3411Digest;
+import org.bouncycastle.crypto.engines.GOST28147Engine;
+import org.bouncycastle.crypto.generators.PKCS5S1ParametersGenerator;
+import org.bouncycastle.crypto.generators.PKCS5S2ParametersGenerator;
+import org.bouncycastle.crypto.macs.HMac;
+import org.bouncycastle.crypto.params.KeyParameter;
+import org.bouncycastle.util.encoders.Hex;
public class GOST3411DigestTest
extends DigestTest
@@ -45,6 +51,19 @@ public class GOST3411DigestTest
super.performTest();
millionATest(million_a_digest);
+
+ HMac gMac = new HMac(new GOST3411Digest());
+
+ gMac.init(new KeyParameter(PKCS5S1ParametersGenerator.PKCS5PasswordToUTF8Bytes("1".toCharArray())));
+
+ byte[] data = "fred".getBytes();
+
+ gMac.update(data, 0, data.length);
+ byte[] mac = new byte[gMac.getMacSize()];
+
+ gMac.doFinal(mac, 0);
+ System.err.println("e080de3bde792327a6cccfa5dfd51e72b6829baa88d8130ed1a48822873fc7f6");
+ System.err.println(new String(Hex.encode(mac)));
}
protected Digest cloneDigest(Digest digest)
@@ -55,6 +74,34 @@ public class GOST3411DigestTest
public static void main(
String[] args)
{
+ HMac gMac = new HMac(new GOST3411Digest(GOST28147Engine.getSBox("D-Test")));
+
+ gMac.init(new KeyParameter(PKCS5S1ParametersGenerator.PKCS5PasswordToUTF8Bytes("Boss".toCharArray())));
+ byte[] iBuf = new byte[4];
+ byte[] data = Hex.decode("b5d78fa546ba645c");
+
+ gMac.update(data, 0, data.length);
+ byte[] mac = new byte[gMac.getMacSize()];
+
+ int pos = 3;
+ while (++iBuf[pos] == 0)
+ {
+ --pos;
+ }
+ gMac.update(iBuf, 0, iBuf.length);
+
+ gMac.doFinal(mac, 0);
+
+ System.err.println(mac.length + " " + new String(Hex.encode(mac)));
+
+ PKCS5S2ParametersGenerator pGen = new PKCS5S2ParametersGenerator(new GOST3411Digest());
+
+ pGen.init(PKCS5S1ParametersGenerator.PKCS5PasswordToUTF8Bytes("1".toCharArray()), data, 2048);
+
+ KeyParameter kp = (KeyParameter)pGen.generateDerivedMacParameters(256);
+
+ System.err.println(kp.getKey().length + " " + new String(Hex.encode(kp.getKey())));
+
runTest(new GOST3411DigestTest());
}
}
diff --git a/pkix/src/main/java/org/bouncycastle/operator/DefaultSecretKeyProvider.java b/pkix/src/main/java/org/bouncycastle/operator/DefaultSecretKeyProvider.java
index 234c38b1..8c419808 100644
--- a/pkix/src/main/java/org/bouncycastle/operator/DefaultSecretKeyProvider.java
+++ b/pkix/src/main/java/org/bouncycastle/operator/DefaultSecretKeyProvider.java
@@ -5,6 +5,7 @@ import java.util.HashMap;
import java.util.Map;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
import org.bouncycastle.asn1.ntt.NTTObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
@@ -34,6 +35,8 @@ public class DefaultSecretKeyProvider
keySizes.put(NTTObjectIdentifiers.id_camellia192_cbc, Integers.valueOf(192));
keySizes.put(NTTObjectIdentifiers.id_camellia256_cbc, Integers.valueOf(256));
+ keySizes.put(CryptoProObjectIdentifiers.gostR28147_gcfb, Integers.valueOf(256));
+
KEY_SIZES = Collections.unmodifiableMap(keySizes);
}
diff --git a/pkix/src/main/java/org/bouncycastle/pkcs/jcajce/JcePKCSPBEInputDecryptorProviderBuilder.java b/pkix/src/main/java/org/bouncycastle/pkcs/jcajce/JcePKCSPBEInputDecryptorProviderBuilder.java
index 79ab492f..eaddab4d 100644
--- a/pkix/src/main/java/org/bouncycastle/pkcs/jcajce/JcePKCSPBEInputDecryptorProviderBuilder.java
+++ b/pkix/src/main/java/org/bouncycastle/pkcs/jcajce/JcePKCSPBEInputDecryptorProviderBuilder.java
@@ -11,8 +11,10 @@ import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;
+import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1OctetString;
+import org.bouncycastle.asn1.cryptopro.GOST28147Parameters;
import org.bouncycastle.asn1.pkcs.PBES2Parameters;
import org.bouncycastle.asn1.pkcs.PBKDF2Params;
import org.bouncycastle.asn1.pkcs.PKCS12PBEParams;
@@ -23,13 +25,13 @@ import org.bouncycastle.jcajce.JcaJceHelper;
import org.bouncycastle.jcajce.NamedJcaJceHelper;
import org.bouncycastle.jcajce.ProviderJcaJceHelper;
import org.bouncycastle.jcajce.provider.symmetric.util.BCPBEKey;
+import org.bouncycastle.jcajce.spec.GOST28147ParameterSpec;
+import org.bouncycastle.jcajce.spec.PBKDF2KeySpec;
import org.bouncycastle.operator.DefaultSecretKeyProvider;
-import org.bouncycastle.operator.GenericKey;
import org.bouncycastle.operator.InputDecryptor;
import org.bouncycastle.operator.InputDecryptorProvider;
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.operator.SecretKeySizeProvider;
-import org.bouncycastle.operator.jcajce.JceGenericKey;
public class JcePKCSPBEInputDecryptorProviderBuilder
{
@@ -125,13 +127,31 @@ public class JcePKCSPBEInputDecryptorProviderBuilder
SecretKeyFactory keyFact = helper.createSecretKeyFactory(alg.getKeyDerivationFunc().getAlgorithm().getId());
- key = keyFact.generateSecret(new PBEKeySpec(password, func.getSalt(), func.getIterationCount().intValue(), keySizeProvider.getKeySize(encScheme)));
+ if (func.isDefaultPrf())
+ {
+ key = keyFact.generateSecret(new PBEKeySpec(password, func.getSalt(), func.getIterationCount().intValue(), keySizeProvider.getKeySize(encScheme)));
+ }
+ else
+ {
+ key = keyFact.generateSecret(new PBKDF2KeySpec(password, func.getSalt(), func.getIterationCount().intValue(), keySizeProvider.getKeySize(encScheme), func.getPrf()));
+ }
cipher = helper.createCipher(alg.getEncryptionScheme().getAlgorithm().getId());
encryptionAlg = AlgorithmIdentifier.getInstance(alg.getEncryptionScheme());
- cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(ASN1OctetString.getInstance(alg.getEncryptionScheme().getParameters()).getOctets()));
+ ASN1Encodable encParams = alg.getEncryptionScheme().getParameters();
+ if (encParams instanceof ASN1OctetString)
+ {
+ cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(ASN1OctetString.getInstance(encParams).getOctets()));
+ }
+ else
+ {
+ // TODO: at the moment it's just GOST, but...
+ GOST28147Parameters gParams = GOST28147Parameters.getInstance(encParams);
+
+ cipher.init(Cipher.DECRYPT_MODE, key, new GOST28147ParameterSpec(gParams.getEncryptionParamSet(), gParams.getIV()));
+ }
}
}
catch (Exception e)
@@ -150,11 +170,6 @@ public class JcePKCSPBEInputDecryptorProviderBuilder
{
return new CipherInputStream(input, cipher);
}
-
- public GenericKey getKey()
- {
- return new JceGenericKey(encryptionAlg, key);
- }
};
}
};
diff --git a/pkix/src/test/java/org/bouncycastle/pkcs/test/PfxPduTest.java b/pkix/src/test/java/org/bouncycastle/pkcs/test/PfxPduTest.java
index 9c4d138c..2bbf9eaa 100644
--- a/pkix/src/test/java/org/bouncycastle/pkcs/test/PfxPduTest.java
+++ b/pkix/src/test/java/org/bouncycastle/pkcs/test/PfxPduTest.java
@@ -19,6 +19,7 @@ import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1Encoding;
import org.bouncycastle.asn1.DERBMPString;
import org.bouncycastle.asn1.DERSequence;
+import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.Attribute;
import org.bouncycastle.asn1.pkcs.ContentInfo;
@@ -455,6 +456,74 @@ public class PfxPduTest
+ "LgBvAHIAZzAxMCEwCQYFKw4DAhoFAAQUc8hyg5aq/58lH3whwo66zJkWY28E"
+ "CKHZUIQsQX9hAgIIAA==");
+ private byte[] gostPfx = Base64.decode(
+ "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"
+ + "BAgY5sDtkrVeBQICCAA=");
+
+ private byte[] gostPfxFoo123 = Base64.decode(
+ "MIID6gIBAzCCA6MGCSqGSIb3DQEHAaCCA5QEggOQMIIDjDCCApQGCSqGSIb3"
+ + "DQEHBqCCAoUwggKBAgEAMIICegYJKoZIhvcNAQcBMFUGCSqGSIb3DQEFDTBI"
+ + "MCcGCSqGSIb3DQEFDDAaBAhIVrbUVNoQ2wICCAAwCgYGKoUDAgIKBQAwHQYG"
+ + "KoUDAgIVMBMECBLmAh+XCCYhBgcqhQMCAh8BgIICFP9hQLgDq5SORy2npOdo"
+ + "1bvoGl9Qdga1kV9s2c1/Y1kTGpuiYKfm5Il+PurzYdE5t/Wi2+SxoePm/AKA"
+ + "x1Ep5btK/002wnyRbUKdjgF1r7fMXRrd5Ioy8lYxB1v6qhHmzE5fz7FxY+iV"
+ + "Z70dSRS0JkTasI8MRsFLkJJfDb9twgoch8lYGFfYirHLcVy4xxA3JO9VSHm2"
+ + "8nuSWSnsmGN0ufPX14UpV2RFe3Rt0gZ0Jc8u2h2Mo0sIoVU6HVwdXzoe6LN7"
+ + "1NPZdRuhVtjxEvjDAvNJ8WHXQnBQMai2nVAj87uNr6OHLRs+foEccEY9WpPQ"
+ + "GPt4XbPt4MtmVctT2+Gsvf6Ws2UCx6hD4k8i28a6xS8lhTVam2g/2Z5cxtUV"
+ + "HxYt7j13HjuQVsuSNdgtrUnw3l43LnBxRZhlFz0r2zrvTB04ynenS+lGdVuG"
+ + "0TauIH+rdP1ubujw6lFdG9RNgUxWvS5IdwbFGX73a+ZrWiYJeERX11N/6r3g"
+ + "0EqVFNH9t/ROsdAtCCe2FycQoOSb+VxPU6I+SHjwe7Oa7R8Xxazh/eWTsV59"
+ + "QzPuLriUMbyYdQIf4xdclgcJoxFElopgl4orRfzH3XQsVbtTxN33lwjkE0j/"
+ + "686VtcO+b+dU7+BEB7O5yDcx1tupgre0ha/0KOlYfPvmbogGdDf0r6MOwrS7"
+ + "QFXxKlHfp8vn4mNwoy7pjrzjmjclkbkwgfEGCSqGSIb3DQEHAaCB4wSB4DCB"
+ + "3TCB2gYLKoZIhvcNAQwKAQKggaMwgaAwVQYJKoZIhvcNAQUNMEgwJwYJKoZI"
+ + "hvcNAQUMMBoECLD6Ld7TqurqAgIIADAKBgYqhQMCAgoFADAdBgYqhQMCAhUw"
+ + "EwQIoYXV7LETOEAGByqFAwICHwEERyBQK9LuYnOO0ELrge+a6JFeAVwPL85V"
+ + "ip2Kj/GfD3nzZR4tPzCwAt79RriKQklNqa3uCc9o0C9Zk5Qcj36SqiXxD1tz"
+ + "Ea63MSUwIwYJKoZIhvcNAQkVMRYEFKjg5gKM+i+vFhSwaga8YGaZ5thVMD4w"
+ + "LjAKBgYqhQMCAgkFAAQgIwD0CRCwva2Bjdlv5g970H2bCB1aafBNr/hxJLZE"
+ + "Ey4ECAW3VYXJzJpYAgIIAA==");
+
/**
* we generate the CA's certificate
*/
@@ -1042,6 +1111,90 @@ public class PfxPduTest
}
}
+ public void testGOST1()
+ throws Exception
+ {
+ char[] password = "1".toCharArray();
+
+ InputDecryptorProvider inputDecryptorProvider = new JcePKCSPBEInputDecryptorProviderBuilder()
+ .setProvider("BC").build(password);
+ PKCS12PfxPdu pfx = new PKCS12PfxPdu(gostPfx);
+
+ assertTrue(pfx.hasMac());
+ assertTrue(pfx.isMacValid(new JcePKCS12MacCalculatorBuilderProvider().setProvider("BC"), password));
+
+ ContentInfo[] infos = pfx.getContentInfos();
+
+ for (int i = 0; i != infos.length; i++)
+ {
+ if (infos[i].getContentType().equals(PKCSObjectIdentifiers.encryptedData))
+ {
+ PKCS12SafeBagFactory dataFact = new PKCS12SafeBagFactory(infos[i], inputDecryptorProvider);
+
+ PKCS12SafeBag[] bags = dataFact.getSafeBags();
+
+ // TODO: finish!
+// assertEquals(3, bags.length);
+// assertEquals(PKCSObjectIdentifiers.certBag, bags[0].getType());
+ }
+ else
+ {
+ PKCS12SafeBagFactory dataFact = new PKCS12SafeBagFactory(infos[i]);
+
+ PKCS12SafeBag[] bags = dataFact.getSafeBags();
+
+ assertEquals(1, bags.length);
+ assertEquals(PKCSObjectIdentifiers.pkcs8ShroudedKeyBag, bags[0].getType());
+
+ PKCS8EncryptedPrivateKeyInfo encInfo = (PKCS8EncryptedPrivateKeyInfo)bags[0].getBagValue();
+ PrivateKeyInfo info = encInfo.decryptPrivateKeyInfo(inputDecryptorProvider);
+ assertEquals(CryptoProObjectIdentifiers.gostR3410_2001, info.getPrivateKeyAlgorithm().getAlgorithm());
+ }
+ }
+ }
+
+ public void testGOST2()
+ throws Exception
+ {
+ char[] password = "foo123".toCharArray();
+
+ InputDecryptorProvider inputDecryptorProvider = new JcePKCSPBEInputDecryptorProviderBuilder()
+ .setProvider("BC").build(password);
+ PKCS12PfxPdu pfx = new PKCS12PfxPdu(gostPfxFoo123);
+
+ assertTrue(pfx.hasMac());
+ assertTrue(pfx.isMacValid(new JcePKCS12MacCalculatorBuilderProvider().setProvider("BC"), password));
+
+ ContentInfo[] infos = pfx.getContentInfos();
+
+ for (int i = 0; i != infos.length; i++)
+ {
+ if (infos[i].getContentType().equals(PKCSObjectIdentifiers.encryptedData))
+ {
+ PKCS12SafeBagFactory dataFact = new PKCS12SafeBagFactory(infos[i], inputDecryptorProvider);
+
+ PKCS12SafeBag[] bags = dataFact.getSafeBags();
+
+ // TODO: finish!
+// assertEquals(3, bags.length);
+// assertEquals(PKCSObjectIdentifiers.certBag, bags[0].getType());
+ }
+ else
+ {
+ PKCS12SafeBagFactory dataFact = new PKCS12SafeBagFactory(infos[i]);
+
+ PKCS12SafeBag[] bags = dataFact.getSafeBags();
+
+ assertEquals(1, bags.length);
+ assertEquals(PKCSObjectIdentifiers.pkcs8ShroudedKeyBag, bags[0].getType());
+
+ PKCS8EncryptedPrivateKeyInfo encInfo = (PKCS8EncryptedPrivateKeyInfo)bags[0].getBagValue();
+ PrivateKeyInfo info = encInfo.decryptPrivateKeyInfo(inputDecryptorProvider);
+ assertEquals(CryptoProObjectIdentifiers.gostR3410_2001, info.getPrivateKeyAlgorithm().getAlgorithm());
+ }
+ }
+ }
+
private X509Certificate[] createCertChain(KeyFactory fact, PublicKey pubKey)
throws Exception
{
diff --git a/prov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ecgost/BCECGOST3410PrivateKey.java b/prov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ecgost/BCECGOST3410PrivateKey.java
index 88d81c0a..02bf4533 100644
--- a/prov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ecgost/BCECGOST3410PrivateKey.java
+++ b/prov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ecgost/BCECGOST3410PrivateKey.java
@@ -14,27 +14,32 @@ import java.util.Enumeration;
import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1Encoding;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import org.bouncycastle.asn1.ASN1OctetString;
import org.bouncycastle.asn1.ASN1Primitive;
+import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.DERBitString;
import org.bouncycastle.asn1.DERInteger;
import org.bouncycastle.asn1.DERNull;
import org.bouncycastle.asn1.DERObjectIdentifier;
+import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
import org.bouncycastle.asn1.cryptopro.ECGOST3410NamedCurves;
+import org.bouncycastle.asn1.cryptopro.GOST3410PublicKeyAlgParameters;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.asn1.x9.X962Parameters;
import org.bouncycastle.asn1.x9.X9ECParameters;
-import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.jcajce.provider.asymmetric.util.EC5Util;
import org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil;
import org.bouncycastle.jcajce.provider.asymmetric.util.PKCS12BagAttributeCarrierImpl;
+import org.bouncycastle.jce.ECGOST3410NamedCurveTable;
import org.bouncycastle.jce.interfaces.ECPointEncoder;
import org.bouncycastle.jce.interfaces.PKCS12BagAttributeCarrier;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec;
import org.bouncycastle.jce.spec.ECNamedCurveSpec;
import org.bouncycastle.math.ec.ECCurve;
@@ -43,10 +48,11 @@ public class BCECGOST3410PrivateKey
{
static final long serialVersionUID = 7245981689601667138L;
- private String algorithm = "ECGOST3410";
- private boolean withCompression;
+ private String algorithm = "ECGOST3410";
+ private boolean withCompression;
- private transient BigInteger d;
+ private transient GOST3410PublicKeyAlgParameters gostParams;
+ private transient BigInteger d;
private transient ECParameterSpec ecSpec;
private transient DERBitString publicKey;
private transient PKCS12BagAttributeCarrierImpl attrCarrier = new PKCS12BagAttributeCarrierImpl();
@@ -99,6 +105,7 @@ public class BCECGOST3410PrivateKey
this.withCompression = key.withCompression;
this.attrCarrier = key.attrCarrier;
this.publicKey = key.publicKey;
+ this.gostParams = key.gostParams;
}
public BCECGOST3410PrivateKey(
@@ -107,7 +114,7 @@ public class BCECGOST3410PrivateKey
BCECGOST3410PublicKey pubKey,
ECParameterSpec spec)
{
- ECDomainParameters dp = params.getParameters();
+ ECDomainParameters dp = params.getParameters();
this.algorithm = algorithm;
this.d = params.getD();
@@ -117,18 +124,20 @@ public class BCECGOST3410PrivateKey
EllipticCurve ellipticCurve = EC5Util.convertCurve(dp.getCurve(), dp.getSeed());
this.ecSpec = new ECParameterSpec(
- ellipticCurve,
- new ECPoint(
- dp.getG().getX().toBigInteger(),
- dp.getG().getY().toBigInteger()),
- dp.getN(),
- dp.getH().intValue());
+ ellipticCurve,
+ new ECPoint(
+ dp.getG().getX().toBigInteger(),
+ dp.getG().getY().toBigInteger()),
+ dp.getN(),
+ dp.getH().intValue());
}
else
{
this.ecSpec = spec;
}
+ this.gostParams = pubKey.getGostParams();
+
publicKey = getPublicKeyDetails(pubKey);
}
@@ -138,7 +147,7 @@ public class BCECGOST3410PrivateKey
BCECGOST3410PublicKey pubKey,
org.bouncycastle.jce.spec.ECParameterSpec spec)
{
- ECDomainParameters dp = params.getParameters();
+ ECDomainParameters dp = params.getParameters();
this.algorithm = algorithm;
this.d = params.getD();
@@ -148,26 +157,28 @@ public class BCECGOST3410PrivateKey
EllipticCurve ellipticCurve = EC5Util.convertCurve(dp.getCurve(), dp.getSeed());
this.ecSpec = new ECParameterSpec(
- ellipticCurve,
- new ECPoint(
- dp.getG().getX().toBigInteger(),
- dp.getG().getY().toBigInteger()),
- dp.getN(),
- dp.getH().intValue());
+ ellipticCurve,
+ new ECPoint(
+ dp.getG().getX().toBigInteger(),
+ dp.getG().getY().toBigInteger()),
+ dp.getN(),
+ dp.getH().intValue());
}
else
{
EllipticCurve ellipticCurve = EC5Util.convertCurve(spec.getCurve(), spec.getSeed());
-
+
this.ecSpec = new ECParameterSpec(
- ellipticCurve,
- new ECPoint(
- spec.getG().getX().toBigInteger(),
- spec.getG().getY().toBigInteger()),
- spec.getN(),
- spec.getH().intValue());
+ ellipticCurve,
+ new ECPoint(
+ spec.getG().getX().toBigInteger(),
+ spec.getG().getY().toBigInteger()),
+ spec.getN(),
+ spec.getH().intValue());
}
+ this.gostParams = pubKey.getGostParams();
+
publicKey = getPublicKeyDetails(pubKey);
}
@@ -190,72 +201,107 @@ public class BCECGOST3410PrivateKey
private void populateFromPrivKeyInfo(PrivateKeyInfo info)
throws IOException
{
- X962Parameters params = new X962Parameters((ASN1Primitive)info.getPrivateKeyAlgorithm().getParameters());
+ ASN1Primitive p = info.getPrivateKeyAlgorithm().getParameters().toASN1Primitive();
+
+ if (p instanceof ASN1Sequence && (ASN1Sequence.getInstance(p).size() == 2 || ASN1Sequence.getInstance(p).size() == 3))
+ {
+ gostParams = GOST3410PublicKeyAlgParameters.getInstance(info.getPrivateKeyAlgorithm().getParameters());
+
+ ECNamedCurveParameterSpec spec = ECGOST3410NamedCurveTable.getParameterSpec(ECGOST3410NamedCurves.getName(gostParams.getPublicKeyParamSet()));
- if (params.isNamedCurve())
+ ECCurve curve = spec.getCurve();
+ EllipticCurve ellipticCurve = EC5Util.convertCurve(curve, spec.getSeed());
+
+ ecSpec = new ECNamedCurveSpec(
+ ECGOST3410NamedCurves.getName(gostParams.getPublicKeyParamSet()),
+ ellipticCurve,
+ new ECPoint(
+ spec.getG().getX().toBigInteger(),
+ spec.getG().getY().toBigInteger()),
+ spec.getN(), spec.getH());
+
+ ASN1Encodable privKey = info.parsePrivateKey();
+
+ byte[] encVal = ASN1OctetString.getInstance(privKey).getOctets();
+ byte[] dVal = new byte[encVal.length];
+
+ for (int i = 0; i != encVal.length; i++)
+ {
+ dVal[i] = encVal[encVal.length - 1 - i];
+ }
+
+ this.d = new BigInteger(1, dVal);
+ }
+ else
{
- ASN1ObjectIdentifier oid = ASN1ObjectIdentifier.getInstance(params.getParameters());
- X9ECParameters ecP = ECUtil.getNamedCurveByOid(oid);
+ // for backwards compatibility
+ X962Parameters params = X962Parameters.getInstance(info.getPrivateKeyAlgorithm().getParameters());
- if (ecP == null) // GOST Curve
+ if (params.isNamedCurve())
{
- ECDomainParameters gParam = ECGOST3410NamedCurves.getByOID(oid);
- EllipticCurve ellipticCurve = EC5Util.convertCurve(gParam.getCurve(), gParam.getSeed());
+ ASN1ObjectIdentifier oid = ASN1ObjectIdentifier.getInstance(params.getParameters());
+ X9ECParameters ecP = ECUtil.getNamedCurveByOid(oid);
- ecSpec = new ECNamedCurveSpec(
+ if (ecP == null) // GOST Curve
+ {
+ ECDomainParameters gParam = ECGOST3410NamedCurves.getByOID(oid);
+ EllipticCurve ellipticCurve = EC5Util.convertCurve(gParam.getCurve(), gParam.getSeed());
+
+ ecSpec = new ECNamedCurveSpec(
ECGOST3410NamedCurves.getName(oid),
ellipticCurve,
new ECPoint(
- gParam.getG().getX().toBigInteger(),
- gParam.getG().getY().toBigInteger()),
+ gParam.getG().getX().toBigInteger(),
+ gParam.getG().getY().toBigInteger()),
gParam.getN(),
gParam.getH());
- }
- else
- {
- EllipticCurve ellipticCurve = EC5Util.convertCurve(ecP.getCurve(), ecP.getSeed());
+ }
+ else
+ {
+ EllipticCurve ellipticCurve = EC5Util.convertCurve(ecP.getCurve(), ecP.getSeed());
- ecSpec = new ECNamedCurveSpec(
+ ecSpec = new ECNamedCurveSpec(
ECUtil.getCurveName(oid),
ellipticCurve,
new ECPoint(
- ecP.getG().getX().toBigInteger(),
- ecP.getG().getY().toBigInteger()),
+ ecP.getG().getX().toBigInteger(),
+ ecP.getG().getY().toBigInteger()),
ecP.getN(),
ecP.getH());
+ }
}
- }
- else if (params.isImplicitlyCA())
- {
- ecSpec = null;
- }
- else
- {
- X9ECParameters ecP = X9ECParameters.getInstance(params.getParameters());
- EllipticCurve ellipticCurve = EC5Util.convertCurve(ecP.getCurve(), ecP.getSeed());
+ else if (params.isImplicitlyCA())
+ {
+ ecSpec = null;
+ }
+ else
+ {
+ X9ECParameters ecP = X9ECParameters.getInstance(params.getParameters());
+ EllipticCurve ellipticCurve = EC5Util.convertCurve(ecP.getCurve(), ecP.getSeed());
- this.ecSpec = new ECParameterSpec(
- ellipticCurve,
- new ECPoint(
+ this.ecSpec = new ECParameterSpec(
+ ellipticCurve,
+ new ECPoint(
ecP.getG().getX().toBigInteger(),
ecP.getG().getY().toBigInteger()),
- ecP.getN(),
- ecP.getH().intValue());
- }
+ ecP.getN(),
+ ecP.getH().intValue());
+ }
- ASN1Encodable privKey = info.parsePrivateKey();
- if (privKey instanceof DERInteger)
- {
- DERInteger derD = DERInteger.getInstance(privKey);
+ ASN1Encodable privKey = info.parsePrivateKey();
+ if (privKey instanceof DERInteger)
+ {
+ DERInteger derD = DERInteger.getInstance(privKey);
- this.d = derD.getValue();
- }
- else
- {
- org.bouncycastle.asn1.sec.ECPrivateKey ec = org.bouncycastle.asn1.sec.ECPrivateKey.getInstance(privKey);
+ this.d = derD.getValue();
+ }
+ else
+ {
+ org.bouncycastle.asn1.sec.ECPrivateKey ec = org.bouncycastle.asn1.sec.ECPrivateKey.getInstance(privKey);
- this.d = ec.getKey();
- this.publicKey = ec.getPublicKey();
+ this.d = ec.getKey();
+ this.publicKey = ec.getPublicKey();
+ }
}
}
@@ -282,64 +328,92 @@ public class BCECGOST3410PrivateKey
*/
public byte[] getEncoded()
{
- X962Parameters params;
-
- if (ecSpec instanceof ECNamedCurveSpec)
+ if (gostParams != null)
{
- DERObjectIdentifier curveOid = ECUtil.getNamedCurveOid(((ECNamedCurveSpec)ecSpec).getName());
- if (curveOid == null) // guess it's the OID
+ byte[] encKey = new byte[32];
+
+ extractBytes(encKey, 0, this.getS());
+
+ try
{
- curveOid = new DERObjectIdentifier(((ECNamedCurveSpec)ecSpec).getName());
+ PrivateKeyInfo info = new PrivateKeyInfo(new AlgorithmIdentifier(CryptoProObjectIdentifiers.gostR3410_2001, gostParams), new DEROctetString(encKey));
+
+ return info.getEncoded(ASN1Encoding.DER);
+ }
+ catch (IOException e)
+ {
+ return null;
}
- params = new X962Parameters(curveOid);
- }
- else if (ecSpec == null)
- {
- params = new X962Parameters(DERNull.INSTANCE);
}
else
{
- ECCurve curve = EC5Util.convertCurve(ecSpec.getCurve());
+ X962Parameters params;
- X9ECParameters ecP = new X9ECParameters(
- curve,
- EC5Util.convertPoint(curve, ecSpec.getGenerator(), withCompression),
- ecSpec.getOrder(),
- BigInteger.valueOf(ecSpec.getCofactor()),
- ecSpec.getCurve().getSeed());
+ if (ecSpec instanceof ECNamedCurveSpec)
+ {
+ DERObjectIdentifier curveOid = ECUtil.getNamedCurveOid(((ECNamedCurveSpec)ecSpec).getName());
+ if (curveOid == null) // guess it's the OID
+ {
+ curveOid = new ASN1ObjectIdentifier(((ECNamedCurveSpec)ecSpec).getName());
+ }
+ params = new X962Parameters(curveOid);
+ }
+ else if (ecSpec == null)
+ {
+ params = new X962Parameters(DERNull.INSTANCE);
+ }
+ else
+ {
+ ECCurve curve = EC5Util.convertCurve(ecSpec.getCurve());
- params = new X962Parameters(ecP);
- }
-
- PrivateKeyInfo info;
- org.bouncycastle.asn1.sec.ECPrivateKey keyStructure;
+ X9ECParameters ecP = new X9ECParameters(
+ curve,
+ EC5Util.convertPoint(curve, ecSpec.getGenerator(), withCompression),
+ ecSpec.getOrder(),
+ BigInteger.valueOf(ecSpec.getCofactor()),
+ ecSpec.getCurve().getSeed());
- if (publicKey != null)
- {
- keyStructure = new org.bouncycastle.asn1.sec.ECPrivateKey(this.getS(), publicKey, params);
- }
- else
- {
- keyStructure = new org.bouncycastle.asn1.sec.ECPrivateKey(this.getS(), params);
- }
+ params = new X962Parameters(ecP);
+ }
- try
- {
- if (algorithm.equals("ECGOST3410"))
+ PrivateKeyInfo info;
+ org.bouncycastle.asn1.sec.ECPrivateKey keyStructure;
+
+ if (publicKey != null)
{
- info = new PrivateKeyInfo(new AlgorithmIdentifier(CryptoProObjectIdentifiers.gostR3410_2001, params.toASN1Primitive()), keyStructure.toASN1Primitive());
+ keyStructure = new org.bouncycastle.asn1.sec.ECPrivateKey(this.getS(), publicKey, params);
}
else
{
+ keyStructure = new org.bouncycastle.asn1.sec.ECPrivateKey(this.getS(), params);
+ }
+
+ try
+ {
+ info = new PrivateKeyInfo(new AlgorithmIdentifier(CryptoProObjectIdentifiers.gostR3410_2001, params.toASN1Primitive()), keyStructure.toASN1Primitive());
- info = new PrivateKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey, params.toASN1Primitive()), keyStructure.toASN1Primitive());
+ return info.getEncoded(ASN1Encoding.DER);
}
+ catch (IOException e)
+ {
+ return null;
+ }
+ }
+ }
- return info.getEncoded(ASN1Encoding.DER);
+ private void extractBytes(byte[] encKey, int offSet, BigInteger bI)
+ {
+ byte[] val = bI.toByteArray();
+ if (val.length < 32)
+ {
+ byte[] tmp = new byte[32];
+ System.arraycopy(val, 0, tmp, tmp.length - val.length, val.length);
+ val = tmp;
}
- catch (IOException e)
+
+ for (int i = 0; i != 32; i++)
{
- return null;
+ encKey[offSet + i] = val[val.length - 1 - i];
}
}
@@ -354,7 +428,7 @@ public class BCECGOST3410PrivateKey
{
return null;
}
-
+
return EC5Util.convertSpec(ecSpec, withCompression);
}
@@ -377,10 +451,10 @@ public class BCECGOST3410PrivateKey
{
return d;
}
-
+
public void setBagAttribute(
ASN1ObjectIdentifier oid,
- ASN1Encodable attribute)
+ ASN1Encodable attribute)
{
attrCarrier.setBagAttribute(oid, attribute);
}
@@ -398,7 +472,7 @@ public class BCECGOST3410PrivateKey
public void setPointFormat(String style)
{
- withCompression = !("UNCOMPRESSED".equalsIgnoreCase(style));
+ withCompression = !("UNCOMPRESSED".equalsIgnoreCase(style));
}
public boolean equals(Object o)
@@ -420,8 +494,8 @@ public class BCECGOST3410PrivateKey
public String toString()
{
- StringBuffer buf = new StringBuffer();
- String nl = System.getProperty("line.separator");
+ StringBuffer buf = new StringBuffer();
+ String nl = System.getProperty("line.separator");
buf.append("EC Private Key").append(nl);
buf.append(" S: ").append(this.d.toString(16)).append(nl);
diff --git a/prov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ecgost/BCECGOST3410PublicKey.java b/prov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ecgost/BCECGOST3410PublicKey.java
index 8d3ef79b..7fa9673f 100644
--- a/prov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ecgost/BCECGOST3410PublicKey.java
+++ b/prov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ecgost/BCECGOST3410PublicKey.java
@@ -13,7 +13,6 @@ import java.security.spec.EllipticCurve;
import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1OctetString;
import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.DERBitString;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
@@ -80,7 +79,7 @@ public class BCECGOST3410PublicKey
{
org.bouncycastle.jce.spec.ECParameterSpec s = BouncyCastleProvider.CONFIGURATION.getEcImplicitlyCa();
- q = s.getCurve().createPoint(q.getX().toBigInteger(), q.getY().toBigInteger(), false);
+ q = s.getCurve().createPoint(q.getX().toBigInteger(), q.getY().toBigInteger());
}
this.ecSpec = null;
}
@@ -198,14 +197,14 @@ public class BCECGOST3410PublicKey
y[i] = keyEnc[64 - 1 - i];
}
- gostParams = new GOST3410PublicKeyAlgParameters((ASN1Sequence)info.getAlgorithm().getParameters());
+ gostParams = GOST3410PublicKeyAlgParameters.getInstance(info.getAlgorithm().getParameters());
ECNamedCurveParameterSpec spec = ECGOST3410NamedCurveTable.getParameterSpec(ECGOST3410NamedCurves.getName(gostParams.getPublicKeyParamSet()));
ECCurve curve = spec.getCurve();
EllipticCurve ellipticCurve = EC5Util.convertCurve(curve, spec.getSeed());
- this.q = curve.createPoint(new BigInteger(1, x), new BigInteger(1, y), false);
+ this.q = curve.createPoint(new BigInteger(1, x), new BigInteger(1, y));
ecSpec = new ECNamedCurveSpec(
ECGOST3410NamedCurves.getName(gostParams.getPublicKeyParamSet()),
@@ -398,4 +397,9 @@ public class BCECGOST3410PublicKey
out.writeObject(this.getEncoded());
}
+
+ public GOST3410PublicKeyAlgParameters getGostParams()
+ {
+ return gostParams;
+ }
}
diff --git a/prov/src/main/java/org/bouncycastle/jcajce/provider/digest/GOST3411.java b/prov/src/main/java/org/bouncycastle/jcajce/provider/digest/GOST3411.java
index 7ff57d32..2112673e 100644
--- a/prov/src/main/java/org/bouncycastle/jcajce/provider/digest/GOST3411.java
+++ b/prov/src/main/java/org/bouncycastle/jcajce/provider/digest/GOST3411.java
@@ -7,6 +7,7 @@ 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;
+import org.bouncycastle.jcajce.provider.symmetric.util.PBESecretKeyFactory;
public class GOST3411
{
@@ -46,6 +47,18 @@ public class GOST3411
}
}
+ /**
+ * PBEWithHmacGOST3411
+ */
+ public static class PBEWithMacKeyFactory
+ extends PBESecretKeyFactory
+ {
+ public PBEWithMacKeyFactory()
+ {
+ super("PBEwithHmacGOST3411", null, false, PKCS12, GOST3411, 256, 0);
+ }
+ }
+
public static class KeyGenerator
extends BaseKeyGenerator
{
@@ -71,6 +84,9 @@ public class GOST3411
provider.addAlgorithm("Alg.Alias.MessageDigest.GOST-3411", "GOST3411");
provider.addAlgorithm("Alg.Alias.MessageDigest." + CryptoProObjectIdentifiers.gostR3411, "GOST3411");
+ provider.addAlgorithm("SecretKeyFactory.PBEWITHHMACGOST3411", PREFIX + "$PBEWithMacKeyFactory");
+ provider.addAlgorithm("Alg.Alias.SecretKeyFactory." + CryptoProObjectIdentifiers.gostR3411, "PBEWITHHMACGOST3411");
+
addHMACAlgorithm(provider, "GOST3411", PREFIX + "$HashMac", PREFIX + "$KeyGenerator");
addHMACAlias(provider, "GOST3411", CryptoProObjectIdentifiers.gostR3411);
}
diff --git a/prov/src/main/java/org/bouncycastle/jcajce/provider/digest/SHA1.java b/prov/src/main/java/org/bouncycastle/jcajce/provider/digest/SHA1.java
index df5d41aa..c7502c77 100644
--- a/prov/src/main/java/org/bouncycastle/jcajce/provider/digest/SHA1.java
+++ b/prov/src/main/java/org/bouncycastle/jcajce/provider/digest/SHA1.java
@@ -193,7 +193,6 @@ public class SHA1
provider.addAlgorithm("SecretKeyFactory.PBEWITHHMACSHA1", PREFIX + "$PBEWithMacKeyFactory");
provider.addAlgorithm("SecretKeyFactory.PBKDF2WithHmacSHA1", PREFIX + "$PBKDF2WithHmacSHA1UTF8");
- provider.addAlgorithm("Alg.Alias.SecretKeyFactory." + PKCSObjectIdentifiers.id_PBKDF2, "PBKDF2WithHmacSHA1");
provider.addAlgorithm("Alg.Alias.SecretKeyFactory.PBKDF2WithHmacSHA1AndUTF8", "PBKDF2WithHmacSHA1");
provider.addAlgorithm("SecretKeyFactory.PBKDF2WithHmacSHA1And8BIT", PREFIX + "$PBKDF2WithHmacSHA18BIT");
}
diff --git a/prov/src/main/java/org/bouncycastle/jcajce/provider/keystore/pkcs12/PKCS12KeyStoreSpi.java b/prov/src/main/java/org/bouncycastle/jcajce/provider/keystore/pkcs12/PKCS12KeyStoreSpi.java
index c2550027..9a62c98e 100644
--- a/prov/src/main/java/org/bouncycastle/jcajce/provider/keystore/pkcs12/PKCS12KeyStoreSpi.java
+++ b/prov/src/main/java/org/bouncycastle/jcajce/provider/keystore/pkcs12/PKCS12KeyStoreSpi.java
@@ -6,6 +6,8 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyStore;
import java.security.KeyStore.LoadStoreParameter;
@@ -24,13 +26,18 @@ import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
+import java.security.spec.InvalidKeySpecException;
+import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
+import java.util.HashMap;
import java.util.Hashtable;
+import java.util.Map;
import java.util.Vector;
import javax.crypto.Cipher;
import javax.crypto.Mac;
+import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
@@ -54,6 +61,10 @@ import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.DEROutputStream;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.DERSet;
+import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
+import org.bouncycastle.asn1.cryptopro.GOST28147Parameters;
+import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
+import org.bouncycastle.asn1.ntt.NTTObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.AuthenticatedSafe;
import org.bouncycastle.asn1.pkcs.CertBag;
import org.bouncycastle.asn1.pkcs.ContentInfo;
@@ -75,12 +86,14 @@ import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.asn1.x509.X509ObjectIdentifiers;
import org.bouncycastle.jcajce.provider.config.PKCS12StoreParameter;
import org.bouncycastle.jcajce.provider.symmetric.util.BCPBEKey;
-import org.bouncycastle.jcajce.provider.util.SecretKeyUtil;
+import org.bouncycastle.jcajce.spec.GOST28147ParameterSpec;
+import org.bouncycastle.jcajce.spec.PBKDF2KeySpec;
import org.bouncycastle.jce.interfaces.BCKeyStore;
import org.bouncycastle.jce.interfaces.PKCS12BagAttributeCarrier;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jce.provider.JDKPKCS12StoreParameter;
import org.bouncycastle.util.Arrays;
+import org.bouncycastle.util.Integers;
import org.bouncycastle.util.Strings;
import org.bouncycastle.util.encoders.Hex;
@@ -92,6 +105,7 @@ public class PKCS12KeyStoreSpi
private static final int MIN_ITERATIONS = 1024;
private static final Provider bcProvider = new BouncyCastleProvider();
+ private static final DefaultSecretKeyProvider keySizeProvider = new DefaultSecretKeyProvider();
private IgnoresCaseHashtable keys = new IgnoresCaseHashtable();
private Hashtable localIds = new Hashtable();
@@ -593,16 +607,8 @@ public class PKCS12KeyStoreSpi
}
else if (algorithm.equals(PKCSObjectIdentifiers.id_PBES2))
{
- PBES2Parameters alg = PBES2Parameters.getInstance(algId.getParameters());
- PBKDF2Params func = PBKDF2Params.getInstance(alg.getKeyDerivationFunc().getParameters());
- SecretKeyFactory keyFact = SecretKeyFactory.getInstance(alg.getKeyDerivationFunc().getAlgorithm().getId(), bcProvider);
-
- SecretKey k = keyFact.generateSecret(new PBEKeySpec(password, func.getSalt(), func.getIterationCount().intValue(), SecretKeyUtil.getKeySize(alg.getEncryptionScheme().getAlgorithm())));
-
- Cipher cipher = Cipher.getInstance(alg.getEncryptionScheme().getAlgorithm().getId(), bcProvider);
-
- cipher.init(Cipher.UNWRAP_MODE, k, new IvParameterSpec(ASN1OctetString.getInstance(alg.getEncryptionScheme().getParameters()).getOctets()));
+ Cipher cipher = createCipher(Cipher.UNWRAP_MODE, password, algId);
// we pass "" as the key algorithm type as it is unknown at this point
return (PrivateKey)cipher.unwrap(data, "", Cipher.PRIVATE_KEY);
@@ -656,29 +662,88 @@ public class PKCS12KeyStoreSpi
byte[] data)
throws IOException
{
- String algorithm = algId.getAlgorithm().getId();
- PKCS12PBEParams pbeParams = PKCS12PBEParams.getInstance(algId.getParameters());
- PBEKeySpec pbeSpec = new PBEKeySpec(password);
+ ASN1ObjectIdentifier algorithm = algId.getAlgorithm();
- try
+ if (algorithm.on(PKCSObjectIdentifiers.pkcs_12PbeIds))
{
- SecretKeyFactory keyFact = SecretKeyFactory.getInstance(algorithm, bcProvider);
- PBEParameterSpec defParams = new PBEParameterSpec(
- pbeParams.getIV(),
- pbeParams.getIterations().intValue());
- BCPBEKey key = (BCPBEKey)keyFact.generateSecret(pbeSpec);
+ PKCS12PBEParams pbeParams = PKCS12PBEParams.getInstance(algId.getParameters());
+ PBEKeySpec pbeSpec = new PBEKeySpec(password);
- key.setTryWrongPKCS12Zero(wrongPKCS12Zero);
+ try
+ {
+ SecretKeyFactory keyFact = SecretKeyFactory.getInstance(algorithm.getId(), bcProvider);
+ PBEParameterSpec defParams = new PBEParameterSpec(
+ pbeParams.getIV(),
+ pbeParams.getIterations().intValue());
+ BCPBEKey key = (BCPBEKey)keyFact.generateSecret(pbeSpec);
- Cipher cipher = Cipher.getInstance(algorithm, bcProvider);
- int mode = forEncryption ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE;
- cipher.init(mode, key, defParams);
- return cipher.doFinal(data);
+ key.setTryWrongPKCS12Zero(wrongPKCS12Zero);
+
+ Cipher cipher = Cipher.getInstance(algorithm.getId(), bcProvider);
+ int mode = forEncryption ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE;
+ cipher.init(mode, key, defParams);
+ return cipher.doFinal(data);
+ }
+ catch (Exception e)
+ {
+ throw new IOException("exception decrypting data - " + e.toString());
+ }
}
- catch (Exception e)
+ else if (algorithm.equals(PKCSObjectIdentifiers.id_PBES2))
+ {
+ try
+ {
+ Cipher cipher = createCipher(Cipher.DECRYPT_MODE, password, algId);
+
+ return cipher.doFinal(data);
+ }
+ catch (Exception e)
+ {
+ throw new IOException("exception decrypting data - " + e.toString());
+ }
+ }
+ else
+ {
+ throw new IOException("unknown PBE algorithm: " + algorithm);
+ }
+ }
+
+ private Cipher createCipher(int mode, char[] password, AlgorithmIdentifier algId)
+ throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException
+ {
+ PBES2Parameters alg = PBES2Parameters.getInstance(algId.getParameters());
+ PBKDF2Params func = PBKDF2Params.getInstance(alg.getKeyDerivationFunc().getParameters());
+ AlgorithmIdentifier encScheme = AlgorithmIdentifier.getInstance(alg.getEncryptionScheme());
+
+ SecretKeyFactory keyFact = SecretKeyFactory.getInstance(alg.getKeyDerivationFunc().getAlgorithm().getId(), bcProvider);
+ SecretKey key;
+
+ if (func.isDefaultPrf())
+ {
+ key = keyFact.generateSecret(new PBEKeySpec(password, func.getSalt(), func.getIterationCount().intValue(), keySizeProvider.getKeySize(encScheme)));
+ }
+ else
+ {
+ key = keyFact.generateSecret(new PBKDF2KeySpec(password, func.getSalt(), func.getIterationCount().intValue(), keySizeProvider.getKeySize(encScheme), func.getPrf()));
+ }
+
+ Cipher cipher = Cipher.getInstance(alg.getEncryptionScheme().getAlgorithm().getId());
+
+ AlgorithmIdentifier encryptionAlg = AlgorithmIdentifier.getInstance(alg.getEncryptionScheme());
+
+ ASN1Encodable encParams = alg.getEncryptionScheme().getParameters();
+ if (encParams instanceof ASN1OctetString)
{
- throw new IOException("exception decrypting data - " + e.toString());
+ cipher.init(mode, key, new IvParameterSpec(ASN1OctetString.getInstance(encParams).getOctets()));
}
+ else
+ {
+ // TODO: at the moment it's just GOST, but...
+ GOST28147Parameters gParams = GOST28147Parameters.getInstance(encParams);
+
+ cipher.init(mode, key, new GOST28147ParameterSpec(gParams.getEncryptionParamSet(), gParams.getIV()));
+ }
+ return cipher;
}
public void engineLoad(
@@ -1671,4 +1736,43 @@ public class PKCS12KeyStoreSpi
return orig.elements();
}
}
+
+ private static class DefaultSecretKeyProvider
+ {
+ private final Map KEY_SIZES;
+
+ DefaultSecretKeyProvider()
+ {
+ Map keySizes = new HashMap();
+
+ keySizes.put(new ASN1ObjectIdentifier("1.2.840.113533.7.66.10"), Integers.valueOf(128));
+
+ keySizes.put(PKCSObjectIdentifiers.des_EDE3_CBC.getId(), Integers.valueOf(192));
+
+ keySizes.put(NISTObjectIdentifiers.id_aes128_CBC, Integers.valueOf(128));
+ keySizes.put(NISTObjectIdentifiers.id_aes192_CBC, Integers.valueOf(192));
+ keySizes.put(NISTObjectIdentifiers.id_aes256_CBC, Integers.valueOf(256));
+
+ keySizes.put(NTTObjectIdentifiers.id_camellia128_cbc, Integers.valueOf(128));
+ keySizes.put(NTTObjectIdentifiers.id_camellia192_cbc, Integers.valueOf(192));
+ keySizes.put(NTTObjectIdentifiers.id_camellia256_cbc, Integers.valueOf(256));
+
+ keySizes.put(CryptoProObjectIdentifiers.gostR28147_gcfb, Integers.valueOf(256));
+
+ KEY_SIZES = Collections.unmodifiableMap(keySizes);
+ }
+
+ public int getKeySize(AlgorithmIdentifier algorithmIdentifier)
+ {
+ // TODO: not all ciphers/oid relationships are this simple.
+ Integer keySize = (Integer)KEY_SIZES.get(algorithmIdentifier.getAlgorithm());
+
+ if (keySize != null)
+ {
+ return keySize.intValue();
+ }
+
+ return -1;
+ }
+ }
}
diff --git a/prov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/GOST28147.java b/prov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/GOST28147.java
index 389b79a5..b3ff96b3 100644
--- a/prov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/GOST28147.java
+++ b/prov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/GOST28147.java
@@ -8,10 +8,12 @@ import java.security.spec.AlgorithmParameterSpec;
import javax.crypto.spec.IvParameterSpec;
import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
+import org.bouncycastle.crypto.BufferedBlockCipher;
import org.bouncycastle.crypto.CipherKeyGenerator;
import org.bouncycastle.crypto.engines.GOST28147Engine;
import org.bouncycastle.crypto.macs.GOST28147Mac;
import org.bouncycastle.crypto.modes.CBCBlockCipher;
+import org.bouncycastle.crypto.modes.GCFBBlockCipher;
import org.bouncycastle.jcajce.provider.config.ConfigurableProvider;
import org.bouncycastle.jcajce.provider.symmetric.util.BaseAlgorithmParameterGenerator;
import org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher;
@@ -45,6 +47,15 @@ public final class GOST28147
}
}
+ public static class GCFB
+ extends BaseBlockCipher
+ {
+ public GCFB()
+ {
+ super(new BufferedBlockCipher(new GCFBBlockCipher(new GOST28147Engine())), 64);
+ }
+ }
+
/**
* GOST28147
*/
@@ -132,12 +143,12 @@ public final class GOST28147
provider.addAlgorithm("Cipher.GOST28147", PREFIX + "$ECB");
provider.addAlgorithm("Alg.Alias.Cipher.GOST", "GOST28147");
provider.addAlgorithm("Alg.Alias.Cipher.GOST-28147", "GOST28147");
- provider.addAlgorithm("Cipher." + CryptoProObjectIdentifiers.gostR28147_cbc, PREFIX + "$CBC");
+ provider.addAlgorithm("Cipher." + CryptoProObjectIdentifiers.gostR28147_gcfb, PREFIX + "$GCFB");
provider.addAlgorithm("KeyGenerator.GOST28147", PREFIX + "$KeyGen");
provider.addAlgorithm("Alg.Alias.KeyGenerator.GOST", "GOST28147");
provider.addAlgorithm("Alg.Alias.KeyGenerator.GOST-28147", "GOST28147");
- provider.addAlgorithm("Alg.Alias.KeyGenerator." + CryptoProObjectIdentifiers.gostR28147_cbc, "GOST28147");
+ provider.addAlgorithm("Alg.Alias.KeyGenerator." + CryptoProObjectIdentifiers.gostR28147_gcfb, "GOST28147");
provider.addAlgorithm("Mac.GOST28147MAC", PREFIX + "$Mac");
provider.addAlgorithm("Alg.Alias.Mac.GOST28147", "GOST28147MAC");
diff --git a/prov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/PBEPBKDF2.java b/prov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/PBEPBKDF2.java
index ee3cac9e..4b0d8b97 100644
--- a/prov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/PBEPBKDF2.java
+++ b/prov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/PBEPBKDF2.java
@@ -2,17 +2,28 @@ package org.bouncycastle.jcajce.provider.symmetric;
import java.io.IOException;
import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.InvalidKeySpecException;
import java.security.spec.InvalidParameterSpecException;
+import java.security.spec.KeySpec;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;
import org.bouncycastle.asn1.ASN1Encoding;
+import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1Primitive;
+import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.PBKDF2Params;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
+import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.jcajce.provider.config.ConfigurableProvider;
+import org.bouncycastle.jcajce.provider.symmetric.util.BCPBEKey;
import org.bouncycastle.jcajce.provider.symmetric.util.BaseAlgorithmParameters;
+import org.bouncycastle.jcajce.provider.symmetric.util.BaseSecretKeyFactory;
+import org.bouncycastle.jcajce.provider.symmetric.util.PBE;
import org.bouncycastle.jcajce.provider.util.AlgorithmProvider;
+import org.bouncycastle.jcajce.spec.PBKDF2KeySpec;
public class PBEPBKDF2
{
@@ -104,6 +115,99 @@ public class PBEPBKDF2
}
}
+ public static class BasePBKDF2
+ extends BaseSecretKeyFactory
+ {
+ private int scheme;
+
+ public BasePBKDF2(String name, int scheme)
+ {
+ super(name, PKCSObjectIdentifiers.id_PBKDF2);
+
+ this.scheme = scheme;
+ }
+
+ 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");
+ }
+
+ if (pbeSpec instanceof PBKDF2KeySpec)
+ {
+ PBKDF2KeySpec spec = (PBKDF2KeySpec)pbeSpec;
+
+ int digest = getDigestCode(spec.getPrf().getAlgorithm());
+ int keySize = pbeSpec.getKeyLength();
+ int ivSize = -1; // JDK 1,2 and earlier does not understand simplified version.
+ CipherParameters param = PBE.Util.makePBEMacParameters(pbeSpec, scheme, digest, keySize);
+
+ return new BCPBEKey(this.algName, this.algOid, scheme, digest, keySize, ivSize, pbeSpec, param);
+ }
+ else
+ {
+ int digest = SHA1;
+ int keySize = pbeSpec.getKeyLength();
+ int ivSize = -1; // JDK 1,2 and earlier does not understand simplified version.
+ CipherParameters param = PBE.Util.makePBEMacParameters(pbeSpec, scheme, digest, keySize);
+
+ return new BCPBEKey(this.algName, this.algOid, scheme, digest, keySize, ivSize, pbeSpec, param);
+ }
+ }
+
+ throw new InvalidKeySpecException("Invalid KeySpec");
+ }
+
+
+ private int getDigestCode(ASN1ObjectIdentifier algorithm)
+ throws InvalidKeySpecException
+ {
+ if (algorithm.equals(CryptoProObjectIdentifiers.gostR3411Hmac))
+ {
+ return GOST3411;
+ }
+ else if (algorithm.equals(PKCSObjectIdentifiers.id_hmacWithSHA1))
+ {
+ return SHA1;
+ }
+
+ throw new InvalidKeySpecException("Invalid KeySpec: unknown PRF algorithm " + algorithm);
+ }
+ }
+
+ public static class PBKDF2withUTF8
+ extends BasePBKDF2
+ {
+ public PBKDF2withUTF8()
+ {
+ super("PBKDF2", PKCS5S2_UTF8);
+ }
+ }
+
public static class Mappings
extends AlgorithmProvider
{
@@ -117,6 +221,8 @@ public class PBEPBKDF2
{
provider.addAlgorithm("AlgorithmParameters.PBKDF2", PREFIX + "$AlgParams");
provider.addAlgorithm("Alg.Alias.AlgorithmParameters." + PKCSObjectIdentifiers.id_PBKDF2, "PBKDF2");
+ provider.addAlgorithm("SecretKeyFactory.PBKDF2", PREFIX + "$PBKDF2withUTF8");
+ provider.addAlgorithm("Alg.Alias.SecretKeyFactory." + PKCSObjectIdentifiers.id_PBKDF2, "PBKDF2");
}
}
}
diff --git a/prov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher.java b/prov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher.java
index 8379b55a..f73997fc 100644
--- a/prov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher.java
+++ b/prov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher.java
@@ -32,6 +32,7 @@ import org.bouncycastle.crypto.modes.CCMBlockCipher;
import org.bouncycastle.crypto.modes.CFBBlockCipher;
import org.bouncycastle.crypto.modes.CTSBlockCipher;
import org.bouncycastle.crypto.modes.EAXBlockCipher;
+import org.bouncycastle.crypto.modes.GCFBBlockCipher;
import org.bouncycastle.crypto.modes.GCMBlockCipher;
import org.bouncycastle.crypto.modes.GOFBBlockCipher;
import org.bouncycastle.crypto.modes.OCBBlockCipher;
@@ -52,9 +53,9 @@ import org.bouncycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.crypto.params.ParametersWithSBox;
import org.bouncycastle.crypto.params.RC2Parameters;
import org.bouncycastle.crypto.params.RC5Parameters;
+import org.bouncycastle.jcajce.spec.GOST28147ParameterSpec;
+import org.bouncycastle.jcajce.spec.RepeatedSecretKeySpec;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
-import org.bouncycastle.jce.spec.GOST28147ParameterSpec;
-import org.bouncycastle.jce.spec.RepeatedSecretKeySpec;
import org.bouncycastle.util.Strings;
public class BaseBlockCipher
@@ -271,6 +272,12 @@ public class BaseBlockCipher
cipher = new BufferedGenericBlockCipher(new BufferedBlockCipher(
new GOFBBlockCipher(baseEngine)));
}
+ else if (modeName.startsWith("GCFB"))
+ {
+ ivLength = baseEngine.getBlockSize();
+ cipher = new BufferedGenericBlockCipher(new BufferedBlockCipher(
+ new GCFBBlockCipher(baseEngine)));
+ }
else if (modeName.startsWith("CTS"))
{
ivLength = baseEngine.getBlockSize();
@@ -420,6 +427,18 @@ public class BaseBlockCipher
param = new ParametersWithIV(param, iv.getIV());
}
+ else if (params instanceof GOST28147ParameterSpec)
+ {
+ // need to pick up IV and SBox.
+ GOST28147ParameterSpec gost28147Param = (GOST28147ParameterSpec)params;
+
+ param = new ParametersWithSBox(param, gost28147Param.getSbox());
+
+ if (gost28147Param.getIV() != null && ivLength != 0)
+ {
+ param = new ParametersWithIV(param, gost28147Param.getIV());
+ }
+ }
}
else if (params instanceof PBEParameterSpec)
{
diff --git a/prov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/PBE.java b/prov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/PBE.java
index f16de3ca..fac3ead0 100644
--- a/prov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/PBE.java
+++ b/prov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/PBE.java
@@ -72,7 +72,32 @@ public interface PBE
}
else if (type == PKCS5S2 || type == PKCS5S2_UTF8)
{
- generator = new PKCS5S2ParametersGenerator();
+ switch (hash)
+ {
+ case MD2:
+ generator = new PKCS5S2ParametersGenerator(new MD2Digest());
+ break;
+ case MD5:
+ generator = new PKCS5S2ParametersGenerator(new MD5Digest());
+ break;
+ case SHA1:
+ generator = new PKCS5S2ParametersGenerator(new SHA1Digest());
+ break;
+ case RIPEMD160:
+ generator = new PKCS5S2ParametersGenerator(new RIPEMD160Digest());
+ break;
+ case TIGER:
+ generator = new PKCS5S2ParametersGenerator(new TigerDigest());
+ break;
+ case SHA256:
+ generator = new PKCS5S2ParametersGenerator(new SHA256Digest());
+ break;
+ case GOST3411:
+ generator = new PKCS5S2ParametersGenerator(new GOST3411Digest());
+ break;
+ default:
+ throw new IllegalStateException("unknown digest scheme for PBE PKCS5S2 encryption.");
+ }
}
else if (type == PKCS12)
{
@@ -261,9 +286,9 @@ public interface PBE
key = convertPassword(type, keySpec);
generator.init(key, keySpec.getSalt(), keySpec.getIterationCount());
-
+
param = generator.generateDerivedMacParameters(keySize);
-
+
for (int i = 0; i != key.length; i++)
{
key[i] = 0;
diff --git a/prov/src/main/java/org/bouncycastle/jce/spec/GOST28147ParameterSpec.java b/prov/src/main/java/org/bouncycastle/jce/spec/GOST28147ParameterSpec.java
index 384d871c..d03fbfe7 100644
--- a/prov/src/main/java/org/bouncycastle/jce/spec/GOST28147ParameterSpec.java
+++ b/prov/src/main/java/org/bouncycastle/jce/spec/GOST28147ParameterSpec.java
@@ -1,73 +1,48 @@
-package org.bouncycastle.jce.spec;
-
-import java.security.spec.AlgorithmParameterSpec;
-
-import org.bouncycastle.crypto.engines.GOST28147Engine;
+package org.bouncycastle.jce.spec;
/**
* A parameter spec for the GOST-28147 cipher.
+ * @deprecated use org.bouncycastle.jcajce.spec.GOST28147ParameterSpec
*/
public class GOST28147ParameterSpec
- implements AlgorithmParameterSpec
+ extends org.bouncycastle.jcajce.spec.GOST28147ParameterSpec
{
- private byte[] iv = null;
- private byte[] sBox = null;
-
+ /**
+ * @deprecated
+ */
public GOST28147ParameterSpec(
byte[] sBox)
{
- this.sBox = new byte[sBox.length];
-
- System.arraycopy(sBox, 0, this.sBox, 0, sBox.length);
+ super(sBox);
}
+ /**
+ * @deprecated
+ */
public GOST28147ParameterSpec(
byte[] sBox,
byte[] iv)
{
- this(sBox);
- this.iv = new byte[iv.length];
-
- System.arraycopy(iv, 0, this.iv, 0, iv.length);
+ super(sBox, iv);
+
}
-
+
+ /**
+ * @deprecated
+ */
public GOST28147ParameterSpec(
String sBoxName)
{
- this.sBox = GOST28147Engine.getSBox(sBoxName);
+ super(sBoxName);
}
+ /**
+ * @deprecated
+ */
public GOST28147ParameterSpec(
String sBoxName,
byte[] iv)
{
- this(sBoxName);
- this.iv = new byte[iv.length];
-
- System.arraycopy(iv, 0, this.iv, 0, iv.length);
- }
-
- public byte[] getSbox()
- {
- return sBox;
- }
-
- /**
- * Returns the IV or null if this parameter set does not contain an IV.
- *
- * @return the IV or null if this parameter set does not contain an IV.
- */
- public byte[] getIV()
- {
- if (iv == null)
- {
- return null;
- }
-
- byte[] tmp = new byte[iv.length];
-
- System.arraycopy(iv, 0, tmp, 0, tmp.length);
-
- return tmp;
+ super(sBoxName, iv);
}
} \ No newline at end of file
diff --git a/prov/src/main/java/org/bouncycastle/jce/spec/RepeatedSecretKeySpec.java b/prov/src/main/java/org/bouncycastle/jce/spec/RepeatedSecretKeySpec.java
index 2a7ceb53..41110728 100644
--- a/prov/src/main/java/org/bouncycastle/jce/spec/RepeatedSecretKeySpec.java
+++ b/prov/src/main/java/org/bouncycastle/jce/spec/RepeatedSecretKeySpec.java
@@ -1,34 +1,17 @@
package org.bouncycastle.jce.spec;
-
-import javax.crypto.SecretKey;
-
/**
* A simple object to indicate that a symmetric cipher should reuse the
* last key provided.
+ * @deprecated use super class org.bouncycastle.jcajce.spec.RepeatedSecretKeySpec
*/
public class RepeatedSecretKeySpec
- implements SecretKey
+ extends org.bouncycastle.jcajce.spec.RepeatedSecretKeySpec
{
private String algorithm;
public RepeatedSecretKeySpec(String algorithm)
{
- this.algorithm = algorithm;
- }
-
- public String getAlgorithm()
- {
- return algorithm;
- }
-
- public String getFormat()
- {
- return null;
- }
-
- public byte[] getEncoded()
- {
- return null;
+ super(algorithm);
}
}
diff --git a/prov/src/test/java/org/bouncycastle/jce/provider/test/AESSICTest.java b/prov/src/test/java/org/bouncycastle/jce/provider/test/AESSICTest.java
index 61f79959..ae6d7bce 100644
--- a/prov/src/test/java/org/bouncycastle/jce/provider/test/AESSICTest.java
+++ b/prov/src/test/java/org/bouncycastle/jce/provider/test/AESSICTest.java
@@ -7,8 +7,8 @@ import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
+import org.bouncycastle.jcajce.spec.RepeatedSecretKeySpec;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
-import org.bouncycastle.jce.spec.RepeatedSecretKeySpec;
import org.bouncycastle.util.encoders.Hex;
import org.bouncycastle.util.test.SimpleTest;
diff --git a/prov/src/test/java/org/bouncycastle/jce/provider/test/GOST28147Test.java b/prov/src/test/java/org/bouncycastle/jce/provider/test/GOST28147Test.java
index b7fecd09..93e3ad74 100644
--- a/prov/src/test/java/org/bouncycastle/jce/provider/test/GOST28147Test.java
+++ b/prov/src/test/java/org/bouncycastle/jce/provider/test/GOST28147Test.java
@@ -11,8 +11,8 @@ import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
-import javax.crypto.spec.SecretKeySpec;
import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
@@ -182,11 +182,11 @@ public class GOST28147Test
private void oidTest()
{
String[] oids = {
- CryptoProObjectIdentifiers.gostR28147_cbc.getId(),
+ CryptoProObjectIdentifiers.gostR28147_gcfb.getId(),
};
String[] names = {
- "GOST28147/CBC/PKCS7Padding"
+ "GOST28147/GCFB/NoPadding"
};
try
diff --git a/prov/src/test/java/org/bouncycastle/jce/provider/test/PKCS12StoreTest.java b/prov/src/test/java/org/bouncycastle/jce/provider/test/PKCS12StoreTest.java
index c35c5b88..0828440b 100644
--- a/prov/src/test/java/org/bouncycastle/jce/provider/test/PKCS12StoreTest.java
+++ b/prov/src/test/java/org/bouncycastle/jce/provider/test/PKCS12StoreTest.java
@@ -11,6 +11,7 @@ import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Security;
+import java.security.Signature;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPrivateKey;
@@ -426,6 +427,49 @@ public class PKCS12StoreTest
+ "AHoAeQB0AGsAbwB3AG4AaQBrAGEwMTAhMAkGBSsOAwIaBQAEFKJpUOIj0OtI"
+ "j2CPp38YIFBEqvjsBAi8G+yhJe3A/wICCAA=");
+ private byte[] gostPfx = Base64.decode(
+ "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"
+ + "BAgY5sDtkrVeBQICCAA=");
+
/**
* we generate a self signed certificate for the sake of testing - RSA
*/
@@ -482,6 +526,38 @@ public class PKCS12StoreTest
return certGen.generate(privKey);
}
+ private void testGOSTStore()
+ throws Exception
+ {
+ byte[] data = Hex.decode("deadbeef");
+
+ KeyStore pkcs12 = KeyStore.getInstance("PKCS12", "BC");
+
+ pkcs12.load(new ByteArrayInputStream(gostPfx), "1".toCharArray());
+
+ PrivateKey pk = (PrivateKey)pkcs12.getKey("cp_exported", null);
+ Certificate[] pubCerts = pkcs12.getCertificateChain("cp_exported");
+
+ Signature sig = Signature.getInstance("ECGOST3410", "BC");
+
+ sig.initSign(pk);
+
+ sig.update(data);
+
+ byte[] signature = sig.sign();
+
+ sig = Signature.getInstance("ECGOST3410", "BC");
+
+ sig.initVerify(pubCerts[0].getPublicKey());
+
+ sig.update(data);
+
+ if (!sig.verify(signature))
+ {
+ fail("key test failed in GOST store");
+ }
+ }
+
public void testPKCS12Store()
throws Exception
{
@@ -1080,7 +1156,7 @@ public class PKCS12StoreTest
throws Exception
{
testPKCS12Store();
-
+ testGOSTStore();
// converter tests