summary refs log tree commit diff
path: root/crypto/src
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/src')
-rw-r--r--crypto/src/crypto/signers/DsaSigner.cs45
-rw-r--r--crypto/src/crypto/signers/ECDsaSigner.cs43
-rw-r--r--crypto/src/crypto/signers/HMacDsaKCalculator.cs150
-rw-r--r--crypto/src/crypto/signers/IDsaKCalculator.cs44
-rw-r--r--crypto/src/crypto/signers/RandomDsaKCalculator.cs44
5 files changed, 306 insertions, 20 deletions
diff --git a/crypto/src/crypto/signers/DsaSigner.cs b/crypto/src/crypto/signers/DsaSigner.cs

index fc0780a91..bb28addfc 100644 --- a/crypto/src/crypto/signers/DsaSigner.cs +++ b/crypto/src/crypto/signers/DsaSigner.cs
@@ -1,10 +1,9 @@ using System; -using Org.BouncyCastle.Math; -using Org.BouncyCastle.Math.EC; -using Org.BouncyCastle.Security; -using Org.BouncyCastle.Crypto; + using Org.BouncyCastle.Crypto.Digests; using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; namespace Org.BouncyCastle.Crypto.Signers { @@ -15,9 +14,29 @@ namespace Org.BouncyCastle.Crypto.Signers public class DsaSigner : IDsa { + protected readonly IDsaKCalculator kCalculator; + protected DsaKeyParameters key = null; protected SecureRandom random = null; + /** + * Default configuration, random K values. + */ + public DsaSigner() + { + this.kCalculator = new RandomDsaKCalculator(); + } + + /** + * Configuration with an alternate, possibly deterministic calculator of K. + * + * @param kCalculator a K value calculator. + */ + public DsaSigner(IDsaKCalculator kCalculator) + { + this.kCalculator = kCalculator; + } + public virtual string AlgorithmName { get { return "DSA"; } @@ -50,7 +69,7 @@ namespace Org.BouncyCastle.Crypto.Signers this.key = (DsaPublicKeyParameters)parameters; } - this.random = InitSecureRandom(forSigning, providedRandom); + this.random = InitSecureRandom(forSigning && !kCalculator.IsDeterministic, providedRandom); } /** @@ -65,18 +84,22 @@ namespace Org.BouncyCastle.Crypto.Signers DsaParameters parameters = key.Parameters; BigInteger q = parameters.Q; BigInteger m = CalculateE(q, message); - BigInteger k; + BigInteger x = ((DsaPrivateKeyParameters)key).X; - do + if (kCalculator.IsDeterministic) { - k = new BigInteger(q.BitLength, random); + kCalculator.Init(q, x, message); } - while (k.CompareTo(q) >= 0); + else + { + kCalculator.Init(q, random); + } + + BigInteger k = kCalculator.NextK(); BigInteger r = parameters.G.ModPow(k, parameters.P).Mod(q); - k = k.ModInverse(q).Multiply( - m.Add(((DsaPrivateKeyParameters)key).X.Multiply(r))); + k = k.ModInverse(q).Multiply(m.Add(x.Multiply(r))); BigInteger s = k.Mod(q); diff --git a/crypto/src/crypto/signers/ECDsaSigner.cs b/crypto/src/crypto/signers/ECDsaSigner.cs
index 867520535..9821732c2 100644 --- a/crypto/src/crypto/signers/ECDsaSigner.cs +++ b/crypto/src/crypto/signers/ECDsaSigner.cs
@@ -1,11 +1,11 @@ using System; + +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Math; using Org.BouncyCastle.Math.EC; using Org.BouncyCastle.Math.EC.Multiplier; using Org.BouncyCastle.Security; -using Org.BouncyCastle.Crypto; -using Org.BouncyCastle.Crypto.Digests; -using Org.BouncyCastle.Crypto.Parameters; namespace Org.BouncyCastle.Crypto.Signers { @@ -15,9 +15,29 @@ namespace Org.BouncyCastle.Crypto.Signers public class ECDsaSigner : IDsa { + protected readonly IDsaKCalculator kCalculator; + protected ECKeyParameters key = null; protected SecureRandom random = null; + /** + * Default configuration, random K values. + */ + public ECDsaSigner() + { + this.kCalculator = new RandomDsaKCalculator(); + } + + /** + * Configuration with an alternate, possibly deterministic calculator of K. + * + * @param kCalculator a K value calculator. + */ + public ECDsaSigner(IDsaKCalculator kCalculator) + { + this.kCalculator = kCalculator; + } + public virtual string AlgorithmName { get { return "ECDSA"; } @@ -50,7 +70,7 @@ namespace Org.BouncyCastle.Crypto.Signers this.key = (ECPublicKeyParameters)parameters; } - this.random = InitSecureRandom(forSigning, providedRandom); + this.random = InitSecureRandom(forSigning && !kCalculator.IsDeterministic, providedRandom); } // 5.3 pg 28 @@ -68,6 +88,15 @@ namespace Org.BouncyCastle.Crypto.Signers BigInteger e = CalculateE(n, message); BigInteger d = ((ECPrivateKeyParameters)key).D; + if (kCalculator.IsDeterministic) + { + kCalculator.Init(n, d, message); + } + else + { + kCalculator.Init(n, random); + } + BigInteger r, s; ECMultiplier basePointMultiplier = CreateBasePointMultiplier(); @@ -78,11 +107,7 @@ namespace Org.BouncyCastle.Crypto.Signers BigInteger k; do // Generate r { - do - { - k = new BigInteger(n.BitLength, random); - } - while (k.SignValue == 0 || k.CompareTo(n) >= 0); + k = kCalculator.NextK(); ECPoint p = basePointMultiplier.Multiply(ec.G, k).Normalize(); diff --git a/crypto/src/crypto/signers/HMacDsaKCalculator.cs b/crypto/src/crypto/signers/HMacDsaKCalculator.cs new file mode 100644
index 000000000..8231197b9 --- /dev/null +++ b/crypto/src/crypto/signers/HMacDsaKCalculator.cs
@@ -0,0 +1,150 @@ +using System; + +using Org.BouncyCastle.Crypto.Macs; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Signers +{ + /** + * A deterministic K calculator based on the algorithm in section 3.2 of RFC 6979. + */ + public class HMacDsaKCalculator + : IDsaKCalculator + { + private readonly HMac hMac; + private readonly byte[] K; + private readonly byte[] V; + + private BigInteger n; + + /** + * Base constructor. + * + * @param digest digest to build the HMAC on. + */ + public HMacDsaKCalculator(IDigest digest) + { + this.hMac = new HMac(digest); + this.V = new byte[hMac.GetMacSize()]; + this.K = new byte[hMac.GetMacSize()]; + } + + public virtual bool IsDeterministic + { + get { return true; } + } + + public virtual void Init(BigInteger n, SecureRandom random) + { + throw new InvalidOperationException("Operation not supported"); + } + + public void Init(BigInteger n, BigInteger d, byte[] message) + { + this.n = n; + + Arrays.Fill(V, (byte)0x01); + Arrays.Fill(K, (byte)0); + + byte[] x = new byte[(n.BitLength + 7) / 8]; + byte[] dVal = BigIntegers.AsUnsignedByteArray(d); + + Array.Copy(dVal, 0, x, x.Length - dVal.Length, dVal.Length); + + byte[] m = new byte[(n.BitLength + 7) / 8]; + + BigInteger mInt = BitsToInt(message); + + if (mInt.CompareTo(n) >= 0) + { + mInt = mInt.Subtract(n); + } + + byte[] mVal = BigIntegers.AsUnsignedByteArray(mInt); + + Array.Copy(mVal, 0, m, m.Length - mVal.Length, mVal.Length); + + hMac.Init(new KeyParameter(K)); + + hMac.BlockUpdate(V, 0, V.Length); + hMac.Update((byte)0x00); + hMac.BlockUpdate(x, 0, x.Length); + hMac.BlockUpdate(m, 0, m.Length); + + hMac.DoFinal(K, 0); + + hMac.Init(new KeyParameter(K)); + + hMac.BlockUpdate(V, 0, V.Length); + + hMac.DoFinal(V, 0); + + hMac.BlockUpdate(V, 0, V.Length); + hMac.Update((byte)0x01); + hMac.BlockUpdate(x, 0, x.Length); + hMac.BlockUpdate(m, 0, m.Length); + + hMac.DoFinal(K, 0); + + hMac.Init(new KeyParameter(K)); + + hMac.BlockUpdate(V, 0, V.Length); + + hMac.DoFinal(V, 0); + } + + public virtual BigInteger NextK() + { + byte[] t = new byte[((n.BitLength + 7) / 8)]; + + for (;;) + { + int tOff = 0; + + while (tOff < t.Length) + { + hMac.BlockUpdate(V, 0, V.Length); + + hMac.DoFinal(V, 0); + + int len = System.Math.Min(t.Length - tOff, V.Length); + Array.Copy(V, 0, t, tOff, len); + tOff += len; + } + + BigInteger k = BitsToInt(t); + + if (k.SignValue > 0 && k.CompareTo(n) < 0) + { + return k; + } + + hMac.BlockUpdate(V, 0, V.Length); + hMac.Update((byte)0x00); + + hMac.DoFinal(K, 0); + + hMac.Init(new KeyParameter(K)); + + hMac.BlockUpdate(V, 0, V.Length); + + hMac.DoFinal(V, 0); + } + } + + private BigInteger BitsToInt(byte[] t) + { + BigInteger v = new BigInteger(1, t); + + if (t.Length * 8 > n.BitLength) + { + v = v.ShiftRight(t.Length * 8 - n.BitLength); + } + + return v; + } + } +} diff --git a/crypto/src/crypto/signers/IDsaKCalculator.cs b/crypto/src/crypto/signers/IDsaKCalculator.cs new file mode 100644
index 000000000..645186d41 --- /dev/null +++ b/crypto/src/crypto/signers/IDsaKCalculator.cs
@@ -0,0 +1,44 @@ +using System; + +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto.Signers +{ + /** + * Interface define calculators of K values for DSA/ECDSA. + */ + public interface IDsaKCalculator + { + /** + * Return true if this calculator is deterministic, false otherwise. + * + * @return true if deterministic, otherwise false. + */ + bool IsDeterministic { get; } + + /** + * Non-deterministic initialiser. + * + * @param n the order of the DSA group. + * @param random a source of randomness. + */ + void Init(BigInteger n, SecureRandom random); + + /** + * Deterministic initialiser. + * + * @param n the order of the DSA group. + * @param d the DSA private value. + * @param message the message being signed. + */ + void Init(BigInteger n, BigInteger d, byte[] message); + + /** + * Return the next valid value of K. + * + * @return a K value. + */ + BigInteger NextK(); + } +} diff --git a/crypto/src/crypto/signers/RandomDsaKCalculator.cs b/crypto/src/crypto/signers/RandomDsaKCalculator.cs new file mode 100644
index 000000000..022cc268d --- /dev/null +++ b/crypto/src/crypto/signers/RandomDsaKCalculator.cs
@@ -0,0 +1,44 @@ +using System; + +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto.Signers +{ + public class RandomDsaKCalculator + : IDsaKCalculator + { + private BigInteger q; + private SecureRandom random; + + public virtual bool IsDeterministic + { + get { return false; } + } + + public virtual void Init(BigInteger n, SecureRandom random) + { + this.q = n; + this.random = random; + } + + public virtual void Init(BigInteger n, BigInteger d, byte[] message) + { + throw new InvalidOperationException("Operation not supported"); + } + + public virtual BigInteger NextK() + { + int qBitLength = q.BitLength; + + BigInteger k; + do + { + k = new BigInteger(qBitLength, random); + } + while (k.SignValue < 1 || k.CompareTo(q) >= 0); + + return k; + } + } +}