diff --git a/crypto/src/asn1/cryptopro/ECGOST3410NamedCurves.cs b/crypto/src/asn1/cryptopro/ECGOST3410NamedCurves.cs
index b61da6b57..ccf3155cf 100644
--- a/crypto/src/asn1/cryptopro/ECGOST3410NamedCurves.cs
+++ b/crypto/src/asn1/cryptopro/ECGOST3410NamedCurves.cs
@@ -115,70 +115,70 @@ namespace Org.BouncyCastle.Asn1.CryptoPro
parameters[CryptoProObjectIdentifiers.GostR3410x2001CryptoProC] = ecParams;
//GOST34.10 2012
- mod_p = new BigInteger("115792089237316195423570985008687907853269984665640564039457584007913129639319"); //p
- mod_q = new BigInteger("115792089237316195423570985008687907853073762908499243225378155805079068850323"); //q
+ mod_p = new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD97", 16); //p
+ mod_q = new BigInteger("400000000000000000000000000000000FD8CDDFC87B6635C115AF556C360C67", 16); //q
curve = new FpCurve(
mod_p, // p
- new BigInteger("115792089237316195423570985008687907853269984665640564039457584007913129639316"), // a
- new BigInteger("166"), // b
+ new BigInteger("C2173F1513981673AF4892C23035A27CE25E2013BF95AA33B22C656F277E7335", 16), // a
+ new BigInteger("295F9BAE7428ED9CCC20E7C359A9D41A22FCCD9108E17BF7BA9337A6F8AE9513", 16), // b
mod_q, BigInteger.One);
ecParams = new ECDomainParameters(
curve,
curve.CreatePoint(
- new BigInteger("1"), // x
- new BigInteger("64033881142927202683649881450433473985931760268884941288852745803908878638612")), // y
+ new BigInteger("91E38443A5E82C0D880923425712B2BB658B9196932E02C78B2582FE742DAA28", 16), // x
+ new BigInteger("32879423AB1A0375895786C4BB46E9565FDE0B5344766740AF268ADB32322E5C", 16)), // y
mod_q, BigInteger.One);
parameters[RosstandartObjectIdentifiers.id_tc26_gost_3410_12_256_paramSetA] = ecParams;
- mod_p = new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDC7",16); //p
- mod_q = new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF27E69532F48D89116FF22B8D4E0560609B4B38ABFAD2B85DCACDB1411F10B275",16); //q
+ mod_p = new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDC7", 16); //p
+ mod_q = new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF27E69532F48D89116FF22B8D4E0560609B4B38ABFAD2B85DCACDB1411F10B275", 16); //q
curve = new FpCurve(
mod_p, // p
- new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDC4",16), // a
- new BigInteger("E8C2505DEDFC86DDC1BD0B2B6667F1DA34B82574761CB0E879BD081CFD0B6265EE3CB090F30D27614CB4574010DA90DD862EF9D4EBEE4761503190785A71C760",16), // b
+ new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDC4", 16), // a
+ new BigInteger("E8C2505DEDFC86DDC1BD0B2B6667F1DA34B82574761CB0E879BD081CFD0B6265EE3CB090F30D27614CB4574010DA90DD862EF9D4EBEE4761503190785A71C760", 16), // b
mod_q, BigInteger.One);
ecParams = new ECDomainParameters(
curve,
curve.CreatePoint(
new BigInteger("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003"), // x
- new BigInteger("7503CFE87A836AE3A61B8816E25450E6CE5E1C93ACF1ABC1778064FDCBEFA921DF1626BE4FD036E93D75E6A50E3A41E98028FE5FC235F5B889A589CB5215F2A4",16)), // y
+ new BigInteger("7503CFE87A836AE3A61B8816E25450E6CE5E1C93ACF1ABC1778064FDCBEFA921DF1626BE4FD036E93D75E6A50E3A41E98028FE5FC235F5B889A589CB5215F2A4", 16)), // y
mod_q, BigInteger.One);
parameters[RosstandartObjectIdentifiers.id_tc26_gost_3410_12_512_paramSetA] = ecParams;
- mod_p = new BigInteger("8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006F",16); //p
- mod_q = new BigInteger("800000000000000000000000000000000000000000000000000000000000000149A1EC142565A545ACFDB77BD9D40CFA8B996712101BEA0EC6346C54374F25BD",16); //q
+ mod_p = new BigInteger("8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006F", 16); //p
+ mod_q = new BigInteger("800000000000000000000000000000000000000000000000000000000000000149A1EC142565A545ACFDB77BD9D40CFA8B996712101BEA0EC6346C54374F25BD", 16); //q
curve = new FpCurve(
mod_p, // p
- new BigInteger("8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006C",16), // a
- new BigInteger("687D1B459DC841457E3E06CF6F5E2517B97C7D614AF138BCBF85DC806C4B289F3E965D2DB1416D217F8B276FAD1AB69C50F78BEE1FA3106EFB8CCBC7C5140116",16), // b
+ new BigInteger("8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006C", 16), // a
+ new BigInteger("687D1B459DC841457E3E06CF6F5E2517B97C7D614AF138BCBF85DC806C4B289F3E965D2DB1416D217F8B276FAD1AB69C50F78BEE1FA3106EFB8CCBC7C5140116", 16), // b
mod_q, BigInteger.One);
ecParams = new ECDomainParameters(
curve,
curve.CreatePoint(
new BigInteger("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002"), // x
- new BigInteger("1A8F7EDA389B094C2C071E3647A8940F3C123B697578C213BE6DD9E6C8EC7335DCB228FD1EDF4A39152CBCAAF8C0398828041055F94CEEEC7E21340780FE41BD",16)), // y
+ new BigInteger("1A8F7EDA389B094C2C071E3647A8940F3C123B697578C213BE6DD9E6C8EC7335DCB228FD1EDF4A39152CBCAAF8C0398828041055F94CEEEC7E21340780FE41BD", 16)), // y
mod_q, BigInteger.One);
parameters[RosstandartObjectIdentifiers.id_tc26_gost_3410_12_512_paramSetB] = ecParams;
- mod_p = new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDC7",16); //p
- mod_q = new BigInteger("3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC98CDBA46506AB004C33A9FF5147502CC8EDA9E7A769A12694623CEF47F023ED",16); //q
+ mod_p = new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDC7", 16); //p
+ mod_q = new BigInteger("3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC98CDBA46506AB004C33A9FF5147502CC8EDA9E7A769A12694623CEF47F023ED", 16); //q
curve = new FpCurve(
mod_p, // p
- new BigInteger("DC9203E514A721875485A529D2C722FB187BC8980EB866644DE41C68E143064546E861C0E2C9EDD92ADE71F46FCF50FF2AD97F951FDA9F2A2EB6546F39689BD3",16), // a
- new BigInteger("B4C4EE28CEBC6C2C8AC12952CF37F16AC7EFB6A9F69F4B57FFDA2E4F0DE5ADE038CBC2FFF719D2C18DE0284B8BFEF3B52B8CC7A5F5BF0A3C8D2319A5312557E1",16), // b
+ new BigInteger("DC9203E514A721875485A529D2C722FB187BC8980EB866644DE41C68E143064546E861C0E2C9EDD92ADE71F46FCF50FF2AD97F951FDA9F2A2EB6546F39689BD3", 16), // a
+ new BigInteger("B4C4EE28CEBC6C2C8AC12952CF37F16AC7EFB6A9F69F4B57FFDA2E4F0DE5ADE038CBC2FFF719D2C18DE0284B8BFEF3B52B8CC7A5F5BF0A3C8D2319A5312557E1", 16), // b
mod_q, BigInteger.One);
ecParams = new ECDomainParameters(
curve,
curve.CreatePoint(
new BigInteger("E2E31EDFC23DE7BDEBE241CE593EF5DE2295B7A9CBAEF021D385F7074CEA043AA27272A7AE602BF2A7B9033DB9ED3610C6FB85487EAE97AAC5BC7928C1950148", 16), // x
- new BigInteger("F5CE40D95B5EB899ABBCCFF5911CB8577939804D6527378B8C108C3D2090FF9BE18E2D33E3021ED2EF32D85822423B6304F726AA854BAE07D0396E9A9ADDC40F",16)), // y
+ new BigInteger("F5CE40D95B5EB899ABBCCFF5911CB8577939804D6527378B8C108C3D2090FF9BE18E2D33E3021ED2EF32D85822423B6304F726AA854BAE07D0396E9A9ADDC40F", 16)), // y
mod_q, BigInteger.One);
parameters[RosstandartObjectIdentifiers.id_tc26_gost_3410_12_512_paramSetC] = ecParams;
@@ -213,7 +213,7 @@ namespace Org.BouncyCastle.Asn1.CryptoPro
public static ECDomainParameters GetByOid(
DerObjectIdentifier oid)
{
- return (ECDomainParameters) parameters[oid];
+ return (ECDomainParameters)parameters[oid];
}
/**
@@ -228,11 +228,11 @@ namespace Org.BouncyCastle.Asn1.CryptoPro
public static ECDomainParameters GetByName(
string name)
{
- DerObjectIdentifier oid = (DerObjectIdentifier) objIds[name];
+ DerObjectIdentifier oid = (DerObjectIdentifier)objIds[name];
if (oid != null)
{
- return (ECDomainParameters) parameters[oid];
+ return (ECDomainParameters)parameters[oid];
}
return null;
@@ -244,13 +244,13 @@ namespace Org.BouncyCastle.Asn1.CryptoPro
public static string GetName(
DerObjectIdentifier oid)
{
- return (string) names[oid];
+ return (string)names[oid];
}
public static DerObjectIdentifier GetOid(
string name)
{
- return (DerObjectIdentifier) objIds[name];
+ return (DerObjectIdentifier)objIds[name];
}
}
}
diff --git a/crypto/src/crypto/parameters/ECGOST3410Parameters.cs b/crypto/src/crypto/parameters/ECGOST3410Parameters.cs
new file mode 100644
index 000000000..ede7433d6
--- /dev/null
+++ b/crypto/src/crypto/parameters/ECGOST3410Parameters.cs
@@ -0,0 +1,51 @@
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+ public class ECGOST3410Parameters : ECNamedDomainParameters
+ {
+
+ private readonly DerObjectIdentifier _publicKeyParamSet;
+ private readonly DerObjectIdentifier _digestParamSet;
+ private readonly DerObjectIdentifier _encryptionParamSet;
+
+ public DerObjectIdentifier PublicKeyParamSet
+ {
+ get { return _publicKeyParamSet; }
+ }
+
+ public DerObjectIdentifier DigestParamSet
+ {
+ get { return _digestParamSet; }
+ }
+
+ public DerObjectIdentifier EncryptionParamSet
+ {
+ get { return _encryptionParamSet; }
+ }
+
+ public ECGOST3410Parameters(
+ ECNamedDomainParameters dp,
+ DerObjectIdentifier publicKeyParamSet,
+ DerObjectIdentifier digestParamSet,
+ DerObjectIdentifier encryptionParamSet) : base(dp.Name, dp.Curve, dp.G, dp.N, dp.H, dp.GetSeed())
+ {
+ this._publicKeyParamSet = publicKeyParamSet;
+ this._digestParamSet = digestParamSet;
+ this._encryptionParamSet = encryptionParamSet;
+ }
+
+
+ public ECGOST3410Parameters(ECDomainParameters dp, DerObjectIdentifier publicKeyParamSet,
+ DerObjectIdentifier digestParamSet,
+ DerObjectIdentifier encryptionParamSet) : base(publicKeyParamSet, dp.Curve, dp.G, dp.N, dp.H, dp.GetSeed())
+ {
+ this._publicKeyParamSet = publicKeyParamSet;
+ this._digestParamSet = digestParamSet;
+ this._encryptionParamSet = encryptionParamSet;
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/crypto/src/crypto/parameters/ECNamedDomainParameters.cs b/crypto/src/crypto/parameters/ECNamedDomainParameters.cs
new file mode 100644
index 000000000..34e390a8f
--- /dev/null
+++ b/crypto/src/crypto/parameters/ECNamedDomainParameters.cs
@@ -0,0 +1,35 @@
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+ public class ECNamedDomainParameters : ECDomainParameters
+ {
+ private DerObjectIdentifier name;
+
+ public DerObjectIdentifier Name
+ {
+ get { return name; }
+ }
+
+ public ECNamedDomainParameters(DerObjectIdentifier name, ECDomainParameters dp) : this(name, dp.curve, dp.g, dp.n, dp.h, dp.seed)
+ { }
+
+
+ public ECNamedDomainParameters(DerObjectIdentifier name, ECCurve curve, ECPoint g, BigInteger n) : base(curve, g, n)
+ {
+ this.name = name;
+ }
+
+ public ECNamedDomainParameters(DerObjectIdentifier name, ECCurve curve, ECPoint g, BigInteger n, BigInteger h) : base(curve, g, n, h)
+ {
+ this.name = name;
+ }
+
+ public ECNamedDomainParameters(DerObjectIdentifier name, ECCurve curve, ECPoint g, BigInteger n, BigInteger h, byte[] seed) : base(curve, g, n, h, seed)
+ {
+ this.name = name;
+ }
+ }
+}
\ No newline at end of file
diff --git a/crypto/src/crypto/signers/EcGost3410_2012Signer.cs b/crypto/src/crypto/signers/EcGost3410_2012Signer.cs
new file mode 100644
index 000000000..cd50916dd
--- /dev/null
+++ b/crypto/src/crypto/signers/EcGost3410_2012Signer.cs
@@ -0,0 +1,151 @@
+using Org.BouncyCastle.Math;
+using System;
+using System.IO;
+using NUnit.Core;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Math.EC.Multiplier;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Signers
+{
+ public class ECGOST3410_2012Signer : IDsaExt
+ {
+ private ECKeyParameters key;
+ private SecureRandom secureRandom;
+ private bool forSigning;
+
+ public BigInteger Order
+ {
+ get { return key.Parameters.N; }
+ }
+
+ public string AlgorithmName
+ {
+ get { return key.AlgorithmName; }
+ }
+
+ public virtual void Init(bool forSigning, ICipherParameters parameters)
+ {
+ this.forSigning = forSigning;
+ if (forSigning)
+ {
+ if (parameters is ParametersWithRandom)
+ {
+ ParametersWithRandom rParam = (ParametersWithRandom)parameters;
+ this.secureRandom = rParam.Random;
+ this.key = (ECPrivateKeyParameters)rParam.Parameters;
+ }
+ else
+ {
+ this.secureRandom = new SecureRandom();
+ this.key = (ECPrivateKeyParameters)parameters;
+ }
+ }
+ else
+ {
+ this.key = (ECPublicKeyParameters)parameters;
+ }
+ }
+
+ public BigInteger[] GenerateSignature(byte[] message)
+ {
+ if (!forSigning)
+ {
+ throw new InvalidOperationException("not initialised for signing.");
+ }
+
+ byte[] mRev = new byte[message.Length]; // conversion is little-endian
+ for (int i = 0; i != mRev.Length; i++)
+ {
+ mRev[i] = message[mRev.Length - 1 - i];
+ }
+ BigInteger e = new BigInteger(1, mRev);
+
+ ECDomainParameters ec = key.Parameters;
+ BigInteger n = ec.N;
+ BigInteger d = ((ECPrivateKeyParameters)key).D;
+
+ BigInteger r, s;
+
+ ECMultiplier basePointMultiplier = CreateBasePointMultiplier();
+
+ do // generate s
+ {
+ BigInteger k;
+ do // generate r
+ {
+ do
+ {
+ k = BigIntegers.CreateRandomBigInteger(n.BitLength, secureRandom);
+ } while (k.Equals(BigInteger.Zero)); // ECConstants.ZERO));
+
+ ECPoint p = basePointMultiplier.Multiply(ec.G, k).Normalize();
+
+ r = p.AffineXCoord.ToBigInteger().Mod(n);
+ } while (r.Equals(BigInteger.Zero)); // ECConstants.ZERO));
+
+ s = (k.Multiply(e)).Add(d.Multiply(r)).Mod(n);
+ } while (s.Equals(BigInteger.Zero)); // ECConstants.ZERO));
+
+ return new BigInteger[] { r, s };
+ }
+
+
+ public bool VerifySignature(byte[] message, BigInteger r, BigInteger s)
+ {
+ if (forSigning)
+ {
+ throw new InvalidOperationException("not initialised for verification.");
+ }
+
+
+ byte[] mRev = new byte[message.Length]; // conversion is little-endian
+ for (int i = 0; i != mRev.Length; i++)
+ {
+ mRev[i] = message[mRev.Length - 1 - i];
+ }
+ BigInteger e = new BigInteger(1, mRev);
+ BigInteger n = key.Parameters.N;
+
+ // r in the range [1,n-1]
+ if (r.CompareTo(BigInteger.One) < 0 || r.CompareTo(n) >= 0)
+ {
+ return false;
+ }
+
+ // s in the range [1,n-1]
+ if (s.CompareTo(BigInteger.One) < 0 || s.CompareTo(n) >= 0)
+ {
+ return false;
+ }
+
+ BigInteger v = e.ModInverse(n);
+
+ BigInteger z1 = s.Multiply(v).Mod(n);
+ BigInteger z2 = (n.Subtract(r)).Multiply(v).Mod(n);
+
+ ECPoint G = key.Parameters.G; // P
+ ECPoint Q = ((ECPublicKeyParameters)key).Q;
+
+ ECPoint point = ECAlgorithms.SumOfTwoMultiplies(G, z1, Q, z2).Normalize();
+
+ // components must be bogus.
+ if (point.IsInfinity)
+ {
+ return false;
+ }
+
+ BigInteger R = point.AffineXCoord.ToBigInteger().Mod(n);
+
+ return R.Equals(r);
+ }
+
+ protected virtual ECMultiplier CreateBasePointMultiplier()
+ {
+ return new FixedPointCombMultiplier();
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/crypto/src/crypto/signers/GOST3410DigestSigner.cs b/crypto/src/crypto/signers/GOST3410DigestSigner.cs
index bc32808df..bff35869b 100644
--- a/crypto/src/crypto/signers/GOST3410DigestSigner.cs
+++ b/crypto/src/crypto/signers/GOST3410DigestSigner.cs
@@ -11,135 +11,144 @@ using Org.BouncyCastle.Security;
namespace Org.BouncyCastle.Crypto.Signers
{
- public class Gost3410DigestSigner
- : ISigner
- {
- private readonly IDigest digest;
- private readonly IDsa dsaSigner;
- private bool forSigning;
-
- public Gost3410DigestSigner(
- IDsa signer,
- IDigest digest)
- {
- this.dsaSigner = signer;
- this.digest = digest;
- }
+ public class Gost3410DigestSigner
+ : ISigner
+ {
+ private readonly IDigest digest;
+ private readonly IDsa dsaSigner;
+ private readonly int size;
+ private int halfSize;
+ private bool forSigning;
+
+
+
+ public Gost3410DigestSigner(
+ IDsa signer,
+ IDigest digest)
+ {
+ this.dsaSigner = signer;
+ this.digest = digest;
+
+ halfSize = digest.GetDigestSize();
+ this.size = halfSize * 2;
+
+ }
public virtual string AlgorithmName
- {
- get { return digest.AlgorithmName + "with" + dsaSigner.AlgorithmName; }
- }
+ {
+ get { return digest.AlgorithmName + "with" + dsaSigner.AlgorithmName; }
+ }
public virtual void Init(
- bool forSigning,
- ICipherParameters parameters)
- {
- this.forSigning = forSigning;
-
- AsymmetricKeyParameter k;
- if (parameters is ParametersWithRandom)
- {
- k = (AsymmetricKeyParameter)((ParametersWithRandom)parameters).Parameters;
- }
- else
- {
- k = (AsymmetricKeyParameter)parameters;
- }
-
- if (forSigning && !k.IsPrivate)
- {
- throw new InvalidKeyException("Signing Requires Private Key.");
- }
-
- if (!forSigning && k.IsPrivate)
- {
- throw new InvalidKeyException("Verification Requires Public Key.");
- }
-
- Reset();
-
- dsaSigner.Init(forSigning, parameters);
- }
-
- /**
+ bool forSigning,
+ ICipherParameters parameters)
+ {
+ this.forSigning = forSigning;
+
+ AsymmetricKeyParameter k;
+ if (parameters is ParametersWithRandom)
+ {
+ k = (AsymmetricKeyParameter)((ParametersWithRandom)parameters).Parameters;
+ }
+ else
+ {
+ k = (AsymmetricKeyParameter)parameters;
+ }
+
+ if (forSigning && !k.IsPrivate)
+ {
+ throw new InvalidKeyException("Signing Requires Private Key.");
+ }
+
+ if (!forSigning && k.IsPrivate)
+ {
+ throw new InvalidKeyException("Verification Requires Public Key.");
+ }
+
+
+ Reset();
+
+ dsaSigner.Init(forSigning, parameters);
+ }
+
+ /**
* update the internal digest with the byte b
*/
public virtual void Update(
- byte input)
- {
- digest.Update(input);
- }
+ byte input)
+ {
+ digest.Update(input);
+ }
- /**
+ /**
* update the internal digest with the byte array in
*/
public virtual void BlockUpdate(
- byte[] input,
- int inOff,
- int length)
- {
- digest.BlockUpdate(input, inOff, length);
- }
-
- /**
+ byte[] input,
+ int inOff,
+ int length)
+ {
+ digest.BlockUpdate(input, inOff, length);
+ }
+
+ /**
* Generate a signature for the message we've been loaded with using
* the key we were initialised with.
*/
public virtual byte[] GenerateSignature()
- {
- if (!forSigning)
- throw new InvalidOperationException("GOST3410DigestSigner not initialised for signature generation.");
-
- byte[] hash = new byte[digest.GetDigestSize()];
- digest.DoFinal(hash, 0);
-
- try
- {
- BigInteger[] sig = dsaSigner.GenerateSignature(hash);
- byte[] sigBytes = new byte[64];
-
- // TODO Add methods to allow writing BigInteger to existing byte array?
- byte[] r = sig[0].ToByteArrayUnsigned();
- byte[] s = sig[1].ToByteArrayUnsigned();
- s.CopyTo(sigBytes, 32 - s.Length);
- r.CopyTo(sigBytes, 64 - r.Length);
- return sigBytes;
- }
- catch (Exception e)
- {
- throw new SignatureException(e.Message, e);
- }
- }
-
- /// <returns>true if the internal state represents the signature described in the passed in array.</returns>
+ {
+ if (!forSigning)
+ throw new InvalidOperationException("GOST3410DigestSigner not initialised for signature generation.");
+
+ byte[] hash = new byte[digest.GetDigestSize()];
+ digest.DoFinal(hash, 0);
+
+ try
+ {
+ BigInteger[] sig = dsaSigner.GenerateSignature(hash);
+ byte[] sigBytes = new byte[size];
+
+ // TODO Add methods to allow writing BigInteger to existing byte array?
+ byte[] r = sig[0].ToByteArrayUnsigned();
+ byte[] s = sig[1].ToByteArrayUnsigned();
+ s.CopyTo(sigBytes, halfSize - s.Length);
+ r.CopyTo(sigBytes, size - r.Length);
+ return sigBytes;
+ }
+ catch (Exception e)
+ {
+ throw new SignatureException(e.Message, e);
+ }
+ }
+
+ /// <returns>true if the internal state represents the signature described in the passed in array.</returns>
public virtual bool VerifySignature(
- byte[] signature)
- {
- if (forSigning)
- throw new InvalidOperationException("DSADigestSigner not initialised for verification");
-
- byte[] hash = new byte[digest.GetDigestSize()];
- digest.DoFinal(hash, 0);
-
- BigInteger R, S;
- try
- {
- R = new BigInteger(1, signature, 32, 32);
- S = new BigInteger(1, signature, 0, 32);
- }
- catch (Exception e)
- {
- throw new SignatureException("error decoding signature bytes.", e);
- }
-
- return dsaSigner.VerifySignature(hash, R, S);
- }
-
- /// <summary>Reset the internal state</summary>
+ byte[] signature)
+ {
+ if (forSigning)
+ throw new InvalidOperationException("DSADigestSigner not initialised for verification");
+
+ byte[] hash = new byte[digest.GetDigestSize()];
+ digest.DoFinal(hash, 0);
+
+ BigInteger R, S;
+ try
+ {
+ R = new BigInteger(1, signature, halfSize, halfSize);
+ S = new BigInteger(1, signature, 0, halfSize);
+ }
+ catch (Exception e)
+ {
+ throw new SignatureException("error decoding signature bytes.", e);
+ }
+
+ return dsaSigner.VerifySignature(hash, R, S);
+ }
+
+ /// <summary>Reset the internal state</summary>
public virtual void Reset()
- {
- digest.Reset();
- }
- }
+ {
+ digest.Reset();
+ }
+ }
}
diff --git a/crypto/src/pkcs/PrivateKeyInfoFactory.cs b/crypto/src/pkcs/PrivateKeyInfoFactory.cs
index 3036dc8b6..75a56983a 100644
--- a/crypto/src/pkcs/PrivateKeyInfoFactory.cs
+++ b/crypto/src/pkcs/PrivateKeyInfoFactory.cs
@@ -5,6 +5,7 @@ using Org.BouncyCastle.Asn1.CryptoPro;
using Org.BouncyCastle.Asn1.EdEC;
using Org.BouncyCastle.Asn1.Oiw;
using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.Rosstandart;
using Org.BouncyCastle.Asn1.Sec;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Asn1.X9;
@@ -117,10 +118,35 @@ namespace Org.BouncyCastle.Pkcs
if (privateKey is ECPrivateKeyParameters)
{
- ECPrivateKeyParameters priv = (ECPrivateKeyParameters)privateKey;
+ ECPrivateKeyParameters priv = (ECPrivateKeyParameters) privateKey;
DerBitString publicKey = new DerBitString(ECKeyPairGenerator.GetCorrespondingPublicKey(priv).Q.GetEncoded(false));
ECDomainParameters dp = priv.Parameters;
+
+ // ECGOST3410
+ if (dp is ECGOST3410Parameters)
+ {
+ ECGOST3410Parameters domainParameters = (ECGOST3410Parameters) dp;
+
+ Gost3410PublicKeyAlgParameters gostParams = new Gost3410PublicKeyAlgParameters(
+ (domainParameters).PublicKeyParamSet,
+ (domainParameters).DigestParamSet,
+ (domainParameters).EncryptionParamSet);
+
+ bool is512 = priv.D.BitLength > 256;
+ DerObjectIdentifier identifier = (is512) ?
+ RosstandartObjectIdentifiers.id_tc26_gost_3410_12_512 :
+ RosstandartObjectIdentifiers.id_tc26_gost_3410_12_256;
+ int size = (is512) ? 64 : 32;
+
+ byte[] encKey = new byte[size];
+
+ ExtractBytes(encKey, size, 0, priv.D);
+
+ return new PrivateKeyInfo(new AlgorithmIdentifier(identifier, gostParams), new DerOctetString(encKey));
+ }
+
+
int orderBitLength = dp.N.BitLength;
AlgorithmIdentifier algID;
@@ -245,5 +271,21 @@ namespace Org.BouncyCastle.Pkcs
return PrivateKeyInfo.GetInstance(keyBytes);
}
+
+ private static void ExtractBytes(byte[] encKey, int size, int offSet, BigInteger bI)
+ {
+ byte[] val = bI.ToByteArray();
+ if (val.Length < size)
+ {
+ byte[] tmp = new byte[size];
+ Array.Copy(val, 0, tmp, tmp.Length - val.Length, val.Length);
+ val = tmp;
+ }
+
+ for (int i = 0; i != size; i++)
+ {
+ encKey[offSet + i] = val[val.Length - 1 - i];
+ }
+ }
}
}
diff --git a/crypto/src/security/PrivateKeyFactory.cs b/crypto/src/security/PrivateKeyFactory.cs
index 0b07d0659..9f2d2e9c1 100644
--- a/crypto/src/security/PrivateKeyFactory.cs
+++ b/crypto/src/security/PrivateKeyFactory.cs
@@ -8,6 +8,7 @@ using Org.BouncyCastle.Asn1.CryptoPro;
using Org.BouncyCastle.Asn1.EdEC;
using Org.BouncyCastle.Asn1.Oiw;
using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.Rosstandart;
using Org.BouncyCastle.Asn1.Sec;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Asn1.X9;
@@ -67,7 +68,7 @@ namespace Org.BouncyCastle.Security
keyStructure.Coefficient);
}
// TODO?
-// else if (algOid.Equals(X9ObjectIdentifiers.DHPublicNumber))
+ // else if (algOid.Equals(X9ObjectIdentifiers.DHPublicNumber))
else if (algOid.Equals(PkcsObjectIdentifiers.DhKeyAgreement))
{
DHParameter para = new DHParameter(
@@ -82,7 +83,7 @@ namespace Org.BouncyCastle.Security
}
else if (algOid.Equals(OiwObjectIdentifiers.ElGamalAlgorithm))
{
- ElGamalParameter para = new ElGamalParameter(
+ ElGamalParameter para = new ElGamalParameter(
Asn1Sequence.GetInstance(algID.Parameters.ToAsn1Object()));
DerInteger derX = (DerInteger)keyInfo.ParsePrivateKey();
@@ -126,7 +127,7 @@ namespace Org.BouncyCastle.Security
return new ECPrivateKeyParameters("EC", d, (DerObjectIdentifier)para.Parameters);
}
- ECDomainParameters dParams = new ECDomainParameters(x9.Curve, x9.G, x9.N, x9.H, x9.GetSeed());
+ ECDomainParameters dParams = new ECDomainParameters(x9.Curve, x9.G, x9.N, x9.H, x9.GetSeed());
return new ECPrivateKeyParameters(d, dParams);
}
else if (algOid.Equals(CryptoProObjectIdentifiers.GostR3410x2001))
@@ -163,14 +164,14 @@ namespace Org.BouncyCastle.Security
if (privKey is DerInteger)
{
x = DerInteger.GetInstance(privKey).PositiveValue;
- }
+ }
else
{
x = new BigInteger(1, Arrays.Reverse(Asn1OctetString.GetInstance(privKey).GetOctets()));
- }
+ }
- return new Gost3410PrivateKeyParameters(x, gostParams.PublicKeyParamSet);
- }
+ return new Gost3410PrivateKeyParameters(x, gostParams.PublicKeyParamSet);
+ }
else if (algOid.Equals(EdECObjectIdentifiers.id_X25519))
{
return new X25519PrivateKeyParameters(GetRawKey(keyInfo, X25519PrivateKeyParameters.KeySize), 0);
@@ -187,6 +188,117 @@ namespace Org.BouncyCastle.Security
{
return new Ed448PrivateKeyParameters(GetRawKey(keyInfo, Ed448PrivateKeyParameters.KeySize), 0);
}
+ else if (algOid.Equals(RosstandartObjectIdentifiers.id_tc26_gost_3410_12_512)
+ || algOid.Equals(RosstandartObjectIdentifiers.id_tc26_gost_3410_12_256))
+ {
+ Gost3410PublicKeyAlgParameters gostParams = Gost3410PublicKeyAlgParameters.GetInstance(keyInfo.PrivateKeyAlgorithm.Parameters);
+ ECGOST3410Parameters ecSpec = null;
+ BigInteger d = null;
+ Asn1Object p = keyInfo.PrivateKeyAlgorithm.Parameters.ToAsn1Object();
+ if (p is Asn1Sequence && (Asn1Sequence.GetInstance(p).Count == 2 || Asn1Sequence.GetInstance(p).Count == 3))
+ {
+
+ ECDomainParameters ecP = ECGost3410NamedCurves.GetByOid(gostParams.PublicKeyParamSet);
+
+ ecSpec = new ECGOST3410Parameters(
+ new ECNamedDomainParameters(
+ gostParams.PublicKeyParamSet, ecP),
+ gostParams.PublicKeyParamSet,
+ gostParams.DigestParamSet,
+ gostParams.EncryptionParamSet);
+ Asn1Encodable privKey = keyInfo.ParsePrivateKey();
+ if (privKey is DerInteger)
+ {
+ d = DerInteger.GetInstance(privKey).PositiveValue;
+ }
+ else
+ {
+ 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];
+ }
+
+ d = new BigInteger(1, dVal);
+ }
+
+
+ }
+ else
+ {
+ X962Parameters parameters = X962Parameters.GetInstance(keyInfo.PrivateKeyAlgorithm.Parameters);
+
+ if (parameters.IsNamedCurve)
+ {
+ DerObjectIdentifier oid = DerObjectIdentifier.GetInstance(parameters.Parameters);
+ X9ECParameters ecP = ECNamedCurveTable.GetByOid(oid);
+ if (ecP == null)
+ {
+ ECDomainParameters gParam = ECGost3410NamedCurves.GetByOid(oid);
+ ecSpec = new ECGOST3410Parameters(new ECNamedDomainParameters(
+ oid,
+ gParam.Curve,
+ gParam.G,
+ gParam.N,
+ gParam.H,
+ gParam.GetSeed()), gostParams.PublicKeyParamSet, gostParams.DigestParamSet,
+ gostParams.EncryptionParamSet);
+ }
+ else
+ {
+ ecSpec = new ECGOST3410Parameters(new ECNamedDomainParameters(
+ oid,
+ ecP.Curve,
+ ecP.G,
+ ecP.N,
+ ecP.H,
+ ecP.GetSeed()), gostParams.PublicKeyParamSet, gostParams.DigestParamSet,
+ gostParams.EncryptionParamSet);
+ }
+ }
+ else if (parameters.IsImplicitlyCA)
+ {
+ ecSpec = null;
+ }
+ else
+ {
+ X9ECParameters ecP = X9ECParameters.GetInstance(parameters.Parameters);
+ ecSpec = new ECGOST3410Parameters(new ECNamedDomainParameters(
+ algOid,
+ ecP.Curve,
+ ecP.G,
+ ecP.N,
+ ecP.H,
+ ecP.GetSeed()),
+ gostParams.PublicKeyParamSet,
+ gostParams.DigestParamSet,
+ gostParams.EncryptionParamSet);
+ }
+
+ Asn1Encodable privKey = keyInfo.ParsePrivateKey();
+ if (privKey is DerInteger)
+ {
+ DerInteger derD = DerInteger.GetInstance(privKey);
+ d = derD.Value;
+ }
+ else
+ {
+ ECPrivateKeyStructure ec = ECPrivateKeyStructure.GetInstance(privKey);
+ d = ec.GetKey();
+ }
+ }
+
+ return new ECPrivateKeyParameters(
+ d,
+ new ECGOST3410Parameters(
+ ecSpec,
+ gostParams.PublicKeyParamSet,
+ gostParams.DigestParamSet,
+ gostParams.EncryptionParamSet));
+
+ }
else
{
throw new SecurityUtilityException("algorithm identifier in private key not recognised");
@@ -203,50 +315,50 @@ namespace Org.BouncyCastle.Security
}
public static AsymmetricKeyParameter DecryptKey(
- char[] passPhrase,
- EncryptedPrivateKeyInfo encInfo)
+ char[] passPhrase,
+ EncryptedPrivateKeyInfo encInfo)
{
return CreateKey(PrivateKeyInfoFactory.CreatePrivateKeyInfo(passPhrase, encInfo));
}
public static AsymmetricKeyParameter DecryptKey(
- char[] passPhrase,
- byte[] encryptedPrivateKeyInfoData)
+ char[] passPhrase,
+ byte[] encryptedPrivateKeyInfoData)
{
return DecryptKey(passPhrase, Asn1Object.FromByteArray(encryptedPrivateKeyInfoData));
}
public static AsymmetricKeyParameter DecryptKey(
- char[] passPhrase,
- Stream encryptedPrivateKeyInfoStream)
+ char[] passPhrase,
+ Stream encryptedPrivateKeyInfoStream)
{
return DecryptKey(passPhrase, Asn1Object.FromStream(encryptedPrivateKeyInfoStream));
}
private static AsymmetricKeyParameter DecryptKey(
- char[] passPhrase,
- Asn1Object asn1Object)
+ char[] passPhrase,
+ Asn1Object asn1Object)
{
return DecryptKey(passPhrase, EncryptedPrivateKeyInfo.GetInstance(asn1Object));
}
public static byte[] EncryptKey(
- DerObjectIdentifier algorithm,
- char[] passPhrase,
- byte[] salt,
- int iterationCount,
- AsymmetricKeyParameter key)
+ DerObjectIdentifier algorithm,
+ char[] passPhrase,
+ byte[] salt,
+ int iterationCount,
+ AsymmetricKeyParameter key)
{
return EncryptedPrivateKeyInfoFactory.CreateEncryptedPrivateKeyInfo(
algorithm, passPhrase, salt, iterationCount, key).GetEncoded();
}
public static byte[] EncryptKey(
- string algorithm,
- char[] passPhrase,
- byte[] salt,
- int iterationCount,
- AsymmetricKeyParameter key)
+ string algorithm,
+ char[] passPhrase,
+ byte[] salt,
+ int iterationCount,
+ AsymmetricKeyParameter key)
{
return EncryptedPrivateKeyInfoFactory.CreateEncryptedPrivateKeyInfo(
algorithm, passPhrase, salt, iterationCount, key).GetEncoded();
diff --git a/crypto/src/security/PublicKeyFactory.cs b/crypto/src/security/PublicKeyFactory.cs
index e39748e45..3623c3ee2 100644
--- a/crypto/src/security/PublicKeyFactory.cs
+++ b/crypto/src/security/PublicKeyFactory.cs
@@ -8,6 +8,7 @@ using Org.BouncyCastle.Asn1.CryptoPro;
using Org.BouncyCastle.Asn1.EdEC;
using Org.BouncyCastle.Asn1.Oiw;
using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.Rosstandart;
using Org.BouncyCastle.Asn1.Sec;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Asn1.X9;
@@ -16,6 +17,7 @@ using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Utilities.Encoders;
namespace Org.BouncyCastle.Security
{
@@ -234,6 +236,40 @@ namespace Org.BouncyCastle.Security
else if (algOid.Equals(EdECObjectIdentifiers.id_Ed448))
{
return new Ed448PublicKeyParameters(GetRawKey(keyInfo, Ed448PublicKeyParameters.KeySize), 0);
+ } else if (
+ algOid.Equals(RosstandartObjectIdentifiers.id_tc26_gost_3410_12_256) ||
+ algOid.Equals(RosstandartObjectIdentifiers.id_tc26_gost_3410_12_512))
+ {
+
+ byte[] keyEnc = ((DerOctetString)Asn1Object.FromByteArray(keyInfo.PublicKeyData.GetOctets())).str;
+
+ int fieldSize = 32;
+ if (algOid.Equals(RosstandartObjectIdentifiers.id_tc26_gost_3410_12_512))
+ {
+ fieldSize = 64;
+ }
+
+ int keySize = 2 * fieldSize;
+
+ byte[] x9Encoding = new byte[1 + keySize];
+ x9Encoding[0] = 0x04;
+ for (int i = 1; i <= fieldSize; ++i)
+ {
+ x9Encoding[i] = keyEnc[fieldSize - i];
+ x9Encoding[i + fieldSize] = keyEnc[keySize - i];
+ }
+
+ Gost3410PublicKeyAlgParameters gostParams = Gost3410PublicKeyAlgParameters.GetInstance(keyInfo.AlgorithmID.Parameters);
+
+ ECGOST3410Parameters ecDomainParameters =
+ new ECGOST3410Parameters(
+ new ECNamedDomainParameters(gostParams.PublicKeyParamSet, ECGost3410NamedCurves.GetByOid(gostParams.PublicKeyParamSet)),
+ gostParams.PublicKeyParamSet,
+ gostParams.DigestParamSet,
+ gostParams.EncryptionParamSet);
+
+ return new ECPublicKeyParameters(ecDomainParameters.Curve.DecodePoint(x9Encoding), ecDomainParameters);
+
}
else
{
diff --git a/crypto/src/util/BigIntegers.cs b/crypto/src/util/BigIntegers.cs
index df78d1d86..6674750bb 100644
--- a/crypto/src/util/BigIntegers.cs
+++ b/crypto/src/util/BigIntegers.cs
@@ -46,6 +46,17 @@ namespace Org.BouncyCastle.Utilities
return tmp;
}
+ /// <summary>
+ /// Creates a Random BigInteger from the secure random of a given bit length.
+ /// </summary>
+ /// <param name="bitLength"></param>
+ /// <param name="secureRandom"></param>
+ /// <returns></returns>
+ public static BigInteger CreateRandomBigInteger(int bitLength, SecureRandom secureRandom)
+ {
+ return new BigInteger(bitLength, secureRandom);
+ }
+
/**
* Return a random BigInteger not less than 'min' and not greater than 'max'
*
diff --git a/crypto/src/x509/SubjectPublicKeyInfoFactory.cs b/crypto/src/x509/SubjectPublicKeyInfoFactory.cs
index 2fa8b7a28..234bcff34 100644
--- a/crypto/src/x509/SubjectPublicKeyInfoFactory.cs
+++ b/crypto/src/x509/SubjectPublicKeyInfoFactory.cs
@@ -6,12 +6,14 @@ using Org.BouncyCastle.Asn1.CryptoPro;
using Org.BouncyCastle.Asn1.EdEC;
using Org.BouncyCastle.Asn1.Oiw;
using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.Rosstandart;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Asn1.X9;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Math.EC;
using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
namespace Org.BouncyCastle.X509
{
@@ -91,9 +93,54 @@ namespace Org.BouncyCastle.X509
} // End of RSA.
if (publicKey is ECPublicKeyParameters)
- {
+ {
+
ECPublicKeyParameters _key = (ECPublicKeyParameters) publicKey;
+
+ if (_key.Parameters is ECGOST3410Parameters)
+ {
+ ECGOST3410Parameters gostParams = (ECGOST3410Parameters)_key.Parameters;
+
+ BigInteger bX = _key.Q.AffineXCoord.ToBigInteger();
+ BigInteger bY = _key.Q.AffineYCoord.ToBigInteger();
+ bool is512 = (bX.BitLength > 256);
+
+ Gost3410PublicKeyAlgParameters parameters = new Gost3410PublicKeyAlgParameters(
+ gostParams.PublicKeyParamSet,
+ gostParams.DigestParamSet,
+ gostParams.EncryptionParamSet);
+
+ int encKeySize;
+ int offset;
+ DerObjectIdentifier algIdentifier;
+ if (is512)
+ {
+ encKeySize = 128;
+ offset = 64;
+ algIdentifier = RosstandartObjectIdentifiers.id_tc26_gost_3410_12_512;
+ }
+ else
+ {
+ encKeySize = 64;
+ offset = 32;
+ algIdentifier = RosstandartObjectIdentifiers.id_tc26_gost_3410_12_256;
+ }
+
+ byte[] encKey = new byte[encKeySize];
+
+ ExtractBytes(encKey, encKeySize / 2, 0, bX);
+ ExtractBytes(encKey, encKeySize / 2, offset, bY);
+
+ return new SubjectPublicKeyInfo(new AlgorithmIdentifier(algIdentifier, parameters), new DerOctetString(encKey));
+
+
+ } // End of ECGOST3410_2012
+
+
+
+
+
if (_key.AlgorithmName == "ECGOST3410")
{
if (_key.PublicKeyParamSet == null)
@@ -209,5 +256,22 @@ namespace Org.BouncyCastle.X509
encKey[offset + i] = val[val.Length - 1 - i];
}
}
+
+
+ private static void ExtractBytes(byte[] encKey, int size, int offSet, BigInteger bI)
+ {
+ byte[] val = bI.ToByteArray();
+ if (val.Length < size)
+ {
+ byte[] tmp = new byte[size];
+ Array.Copy(val, 0, tmp, tmp.Length - val.Length, val.Length);
+ val = tmp;
+ }
+
+ for (int i = 0; i != size; i++)
+ {
+ encKey[offSet + i] = val[val.Length - 1 - i];
+ }
+ }
}
}
|