diff options
-rw-r--r-- | crypto/src/crypto/signers/ECGost3410_2012Signer.cs | 153 |
1 files changed, 153 insertions, 0 deletions
diff --git a/crypto/src/crypto/signers/ECGost3410_2012Signer.cs b/crypto/src/crypto/signers/ECGost3410_2012Signer.cs new file mode 100644 index 000000000..e7174ace6 --- /dev/null +++ b/crypto/src/crypto/signers/ECGost3410_2012Signer.cs @@ -0,0 +1,153 @@ +using Org.BouncyCastle.Math; +using System; +using System.IO; + +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 initialized 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 initialized 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 |