summary refs log tree commit diff
path: root/crypto/src
diff options
context:
space:
mode:
authorDavid Hook <dgh@cryptoworkshop.com>2019-01-20 11:19:37 +1100
committerDavid Hook <dgh@cryptoworkshop.com>2019-01-20 11:19:37 +1100
commita6cb039b7d6762c6e3116a95ab7239243531a665 (patch)
tree3b61bfe999c987146a1e125708f420a03f90d6af /crypto/src
parentrename (diff)
downloadBouncyCastle.NET-ed25519-a6cb039b7d6762c6e3116a95ab7239243531a665.tar.xz
fixed file name
Diffstat (limited to 'crypto/src')
-rw-r--r--crypto/src/crypto/signers/ECGost3410_2012Signer.cs153
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