diff options
author | Oren Novotny <oren@novotny.org> | 2019-08-01 16:38:06 -0400 |
---|---|---|
committer | Oren Novotny <oren@novotny.org> | 2019-08-01 16:38:06 -0400 |
commit | fa5d0cc3ad1a1f25a9fc54c6904a7469a49935cb (patch) | |
tree | b3c5db1e7d83f557f86ee0cce3a676af00d4cacf /crypto | |
parent | Rename main (diff) | |
parent | Work on EC parameters classes (diff) | |
download | BouncyCastle.NET-ed25519-fa5d0cc3ad1a1f25a9fc54c6904a7469a49935cb.tar.xz |
merge from master
Diffstat (limited to 'crypto')
-rw-r--r-- | crypto/crypto.csproj | 5 | ||||
-rw-r--r-- | crypto/src/asn1/Asn1Set.cs | 37 | ||||
-rw-r--r-- | crypto/src/crypto/generators/ECKeyPairGenerator.cs | 2 | ||||
-rw-r--r-- | crypto/src/crypto/generators/SCrypt.cs | 28 | ||||
-rw-r--r-- | crypto/src/crypto/parameters/ECDomainParameters.cs | 51 | ||||
-rw-r--r-- | crypto/src/crypto/parameters/ECNamedDomainParameters.cs | 2 | ||||
-rw-r--r-- | crypto/src/crypto/parameters/ECPrivateKeyParameters.cs | 15 | ||||
-rw-r--r-- | crypto/src/crypto/parameters/ECPublicKeyParameters.cs | 15 | ||||
-rw-r--r-- | crypto/src/math/ec/custom/sec/SecP128R1Field.cs | 5 | ||||
-rw-r--r-- | crypto/src/math/raw/Nat.cs | 17 | ||||
-rw-r--r-- | crypto/test/src/math/ec/custom/sec/test/SecP128R1FieldTest.cs | 61 |
11 files changed, 168 insertions, 70 deletions
diff --git a/crypto/crypto.csproj b/crypto/crypto.csproj index 55fcf1704..1b4cccd52 100644 --- a/crypto/crypto.csproj +++ b/crypto/crypto.csproj @@ -12933,6 +12933,11 @@ BuildAction = "Compile" /> <File + RelPath = "test\src\math\ec\custom\sec\test\SecP128R1FieldTest.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File RelPath = "test\src\math\ec\custom\sec\test\SecP256R1FieldTest.cs" SubType = "Code" BuildAction = "Compile" diff --git a/crypto/src/asn1/Asn1Set.cs b/crypto/src/asn1/Asn1Set.cs index bf83dbdc1..7fa072c0d 100644 --- a/crypto/src/asn1/Asn1Set.cs +++ b/crypto/src/asn1/Asn1Set.cs @@ -1,5 +1,6 @@ using System; using System.Collections; +using System.Diagnostics; using System.IO; #if PORTABLE @@ -344,29 +345,35 @@ namespace Org.BouncyCastle.Asn1 { byte[] a = (byte[])x, b = (byte[])y; #endif + Debug.Assert(a.Length >= 2 && b.Length >= 2); + + /* + * NOTE: Set elements in DER encodings are ordered first according to their tags (class and + * number); the CONSTRUCTED bit is not part of the tag. + * + * For SET-OF, this is unimportant. All elements have the same tag and DER requires them to + * either all be in constructed form or all in primitive form, according to that tag. The + * elements are effectively ordered according to their content octets. + * + * For SET, the elements will have distinct tags, and each will be in constructed or + * primitive form accordingly. Failing to ignore the CONSTRUCTED bit could therefore lead to + * ordering inversions. + */ + int a0 = a[0] & ~Asn1Tags.Constructed; + int b0 = b[0] & ~Asn1Tags.Constructed; + if (a0 != b0) + return a0 < b0 ? -1 : 1; + int len = System.Math.Min(a.Length, b.Length); - for (int i = 0; i != len; ++i) + for (int i = 1; i < len; ++i) { byte ai = a[i], bi = b[i]; if (ai != bi) return ai < bi ? -1 : 1; } - if (a.Length > b.Length) - return AllZeroesFrom(a, len) ? 0 : 1; - if (a.Length < b.Length) - return AllZeroesFrom(b, len) ? 0 : -1; + Debug.Assert(a.Length == b.Length); return 0; } - - private bool AllZeroesFrom(byte[] bs, int pos) - { - while (pos < bs.Length) - { - if (bs[pos++] != 0) - return false; - } - return true; - } } } } diff --git a/crypto/src/crypto/generators/ECKeyPairGenerator.cs b/crypto/src/crypto/generators/ECKeyPairGenerator.cs index 26bc06e14..6a710c62e 100644 --- a/crypto/src/crypto/generators/ECKeyPairGenerator.cs +++ b/crypto/src/crypto/generators/ECKeyPairGenerator.cs @@ -105,7 +105,7 @@ namespace Org.BouncyCastle.Crypto.Generators { d = new BigInteger(n.BitLength, random); - if (d.CompareTo(BigInteger.Two) < 0 || d.CompareTo(n) >= 0) + if (d.CompareTo(BigInteger.One) < 0 || d.CompareTo(n) >= 0) continue; if (WNafUtilities.GetNafWeight(d) < minWeight) diff --git a/crypto/src/crypto/generators/SCrypt.cs b/crypto/src/crypto/generators/SCrypt.cs index 4d15bb3d7..51dc50b81 100644 --- a/crypto/src/crypto/generators/SCrypt.cs +++ b/crypto/src/crypto/generators/SCrypt.cs @@ -98,31 +98,37 @@ namespace Org.BouncyCastle.Crypto.Generators uint[] blockY = new uint[BCount]; uint[] X = new uint[BCount]; - uint[][] V = new uint[N][]; + uint[] V = new uint[N * BCount]; try { Array.Copy(B, BOff, X, 0, BCount); - for (int i = 0; i < N; ++i) - { - V[i] = (uint[])X.Clone(); - BlockMix(X, blockX1, blockX2, blockY, r); - } + int off = 0; + for (int i = 0; i < N; i += 2) + { + Array.Copy(X, 0, V, off, BCount); + off += BCount; + BlockMix(X, blockX1, blockX2, blockY, r); + Array.Copy(blockY, 0, V, off, BCount); + off += BCount; + BlockMix(blockY, blockX1, blockX2, X, r); + } uint mask = (uint)N - 1; for (int i = 0; i < N; ++i) { uint j = X[BCount - 16] & mask; - Xor(X, V[j], 0, X); - BlockMix(X, blockX1, blockX2, blockY, r); - } + Array.Copy(V, j * BCount, blockY, 0, BCount); + Xor(blockY, X, 0, blockY); + BlockMix(blockY, blockX1, blockX2, X, r); + } Array.Copy(X, 0, B, BOff, BCount); } finally { - ClearAll(V); + Clear(V); ClearAll(X, blockX1, blockX2, blockY); } } @@ -143,8 +149,6 @@ namespace Org.BouncyCastle.Crypto.Generators YOff = halfLen + BOff - YOff; BOff += 16; } - - Array.Copy(Y, 0, B, 0, Y.Length); } private static void Xor(uint[] a, uint[] b, int bOff, uint[] output) diff --git a/crypto/src/crypto/parameters/ECDomainParameters.cs b/crypto/src/crypto/parameters/ECDomainParameters.cs index e377f7760..3ff7d809f 100644 --- a/crypto/src/crypto/parameters/ECDomainParameters.cs +++ b/crypto/src/crypto/parameters/ECDomainParameters.cs @@ -8,12 +8,13 @@ namespace Org.BouncyCastle.Crypto.Parameters { public class ECDomainParameters { - internal ECCurve curve; - internal byte[] seed; - internal ECPoint g; - internal BigInteger n; - internal BigInteger h; - internal BigInteger hInv; + private readonly ECCurve curve; + private readonly byte[] seed; + private readonly ECPoint g; + private readonly BigInteger n; + private readonly BigInteger h; + + private BigInteger hInv; public ECDomainParameters( ECCurve curve, @@ -48,7 +49,7 @@ namespace Org.BouncyCastle.Crypto.Parameters // we can't check for h == null here as h is optional in X9.62 as it is not required for ECDSA this.curve = curve; - this.g = Validate(curve, g); + this.g = ValidatePublicPoint(curve, g); this.n = n; this.h = h; this.seed = Arrays.Clone(seed); @@ -113,26 +114,42 @@ namespace Org.BouncyCastle.Crypto.Parameters { return curve.Equals(other.curve) && g.Equals(other.g) - && n.Equals(other.n) - && h.Equals(other.h); + && n.Equals(other.n); } public override int GetHashCode() { - int hc = curve.GetHashCode(); - hc *= 37; + //return Arrays.GetHashCode(new object[]{ curve, g, n }); + int hc = 4; + hc *= 257; + hc ^= curve.GetHashCode(); + hc *= 257; hc ^= g.GetHashCode(); - hc *= 37; + hc *= 257; hc ^= n.GetHashCode(); - hc *= 37; - hc ^= h.GetHashCode(); return hc; } - internal static ECPoint Validate(ECCurve c, ECPoint q) + public BigInteger ValidatePrivateScalar(BigInteger d) + { + if (null == d) + throw new ArgumentNullException("d", "Scalar cannot be null"); + + if (d.CompareTo(BigInteger.One) < 0 || (d.CompareTo(N) >= 0)) + throw new ArgumentException("Scalar is not in the interval [1, n - 1]", "d"); + + return d; + } + + public ECPoint ValidatePublicPoint(ECPoint q) + { + return ValidatePublicPoint(Curve, q); + } + + internal static ECPoint ValidatePublicPoint(ECCurve c, ECPoint q) { - if (q == null) - throw new ArgumentException("Point has null value", "q"); + if (null == q) + throw new ArgumentNullException("q", "Point cannot be null"); q = ECAlgorithms.ImportPoint(c, q).Normalize(); diff --git a/crypto/src/crypto/parameters/ECNamedDomainParameters.cs b/crypto/src/crypto/parameters/ECNamedDomainParameters.cs index 4b8e2558f..2279c7dcc 100644 --- a/crypto/src/crypto/parameters/ECNamedDomainParameters.cs +++ b/crypto/src/crypto/parameters/ECNamedDomainParameters.cs @@ -17,7 +17,7 @@ namespace Org.BouncyCastle.Crypto.Parameters } public ECNamedDomainParameters(DerObjectIdentifier name, ECDomainParameters dp) - : this(name, dp.curve, dp.g, dp.n, dp.h, dp.seed) + : this(name, dp.Curve, dp.G, dp.N, dp.H, dp.GetSeed()) { } diff --git a/crypto/src/crypto/parameters/ECPrivateKeyParameters.cs b/crypto/src/crypto/parameters/ECPrivateKeyParameters.cs index 4d0fa1fc6..47e53ef2d 100644 --- a/crypto/src/crypto/parameters/ECPrivateKeyParameters.cs +++ b/crypto/src/crypto/parameters/ECPrivateKeyParameters.cs @@ -24,10 +24,7 @@ namespace Org.BouncyCastle.Crypto.Parameters DerObjectIdentifier publicKeyParamSet) : base("ECGOST3410", true, publicKeyParamSet) { - if (d == null) - throw new ArgumentNullException("d"); - - this.d = d; + this.d = Parameters.ValidatePrivateScalar(d); } public ECPrivateKeyParameters( @@ -36,10 +33,7 @@ namespace Org.BouncyCastle.Crypto.Parameters ECDomainParameters parameters) : base(algorithm, true, parameters) { - if (d == null) - throw new ArgumentNullException("d"); - - this.d = d; + this.d = Parameters.ValidatePrivateScalar(d); } public ECPrivateKeyParameters( @@ -48,10 +42,7 @@ namespace Org.BouncyCastle.Crypto.Parameters DerObjectIdentifier publicKeyParamSet) : base(algorithm, true, publicKeyParamSet) { - if (d == null) - throw new ArgumentNullException("d"); - - this.d = d; + this.d = Parameters.ValidatePrivateScalar(d); } public BigInteger D diff --git a/crypto/src/crypto/parameters/ECPublicKeyParameters.cs b/crypto/src/crypto/parameters/ECPublicKeyParameters.cs index 69916e525..d43ac7e0e 100644 --- a/crypto/src/crypto/parameters/ECPublicKeyParameters.cs +++ b/crypto/src/crypto/parameters/ECPublicKeyParameters.cs @@ -24,10 +24,7 @@ namespace Org.BouncyCastle.Crypto.Parameters DerObjectIdentifier publicKeyParamSet) : base("ECGOST3410", false, publicKeyParamSet) { - if (q == null) - throw new ArgumentNullException("q"); - - this.q = ECDomainParameters.Validate(Parameters.Curve, q); + this.q = ECDomainParameters.ValidatePublicPoint(Parameters.Curve, q); } public ECPublicKeyParameters( @@ -36,10 +33,7 @@ namespace Org.BouncyCastle.Crypto.Parameters ECDomainParameters parameters) : base(algorithm, false, parameters) { - if (q == null) - throw new ArgumentNullException("q"); - - this.q = ECDomainParameters.Validate(Parameters.Curve, q); + this.q = ECDomainParameters.ValidatePublicPoint(Parameters.Curve, q); } public ECPublicKeyParameters( @@ -48,10 +42,7 @@ namespace Org.BouncyCastle.Crypto.Parameters DerObjectIdentifier publicKeyParamSet) : base(algorithm, false, publicKeyParamSet) { - if (q == null) - throw new ArgumentNullException("q"); - - this.q = ECDomainParameters.Validate(Parameters.Curve, q); + this.q = ECDomainParameters.ValidatePublicPoint(Parameters.Curve, q); } public ECPoint Q diff --git a/crypto/src/math/ec/custom/sec/SecP128R1Field.cs b/crypto/src/math/ec/custom/sec/SecP128R1Field.cs index d1ac009b3..cf91c7e5d 100644 --- a/crypto/src/math/ec/custom/sec/SecP128R1Field.cs +++ b/crypto/src/math/ec/custom/sec/SecP128R1Field.cs @@ -134,6 +134,11 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec x = (uint)c; } + + if (z[3] >= P3 && Nat128.Gte(z, P)) + { + AddPInvTo(z); + } } public static void Square(uint[] x, uint[] z) diff --git a/crypto/src/math/raw/Nat.cs b/crypto/src/math/raw/Nat.cs index 040ade74f..f9e4e6714 100644 --- a/crypto/src/math/raw/Nat.cs +++ b/crypto/src/math/raw/Nat.cs @@ -270,6 +270,23 @@ namespace Org.BouncyCastle.Math.Raw Array.Copy(x, xOff, z, zOff, len); } + public static ulong[] Copy64(int len, ulong[] x) + { + ulong[] z = new ulong[len]; + Array.Copy(x, 0, z, 0, len); + return z; + } + + public static void Copy64(int len, ulong[] x, ulong[] z) + { + Array.Copy(x, 0, z, 0, len); + } + + public static void Copy64(int len, ulong[] x, int xOff, ulong[] z, int zOff) + { + Array.Copy(x, xOff, z, zOff, len); + } + public static uint[] Create(int len) { return new uint[len]; diff --git a/crypto/test/src/math/ec/custom/sec/test/SecP128R1FieldTest.cs b/crypto/test/src/math/ec/custom/sec/test/SecP128R1FieldTest.cs new file mode 100644 index 000000000..26b4060b0 --- /dev/null +++ b/crypto/test/src/math/ec/custom/sec/test/SecP128R1FieldTest.cs @@ -0,0 +1,61 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1.Sec; +using Org.BouncyCastle.Asn1.X9; +using Org.BouncyCastle.Crypto.EC; + +namespace Org.BouncyCastle.Math.EC.Custom.Sec.Tests +{ + [TestFixture] + public class SecP128R1FieldTest + { + private static readonly X9ECParameters DP = CustomNamedCurves + .GetByOid(SecObjectIdentifiers.SecP128r1); + + [Test] + public void Test_GitHub566() + { + uint[] x = new uint[]{ 0x4B1E2F5E, 0x09E29D21, 0xA58407ED, 0x6FC3C7CF }; + uint[] y = new uint[]{ 0x2FFE8892, 0x55CA61CA, 0x0AF780B5, 0x4BD7B797 }; + + ECFieldElement Z = FE(x).Multiply(FE(y)); + + uint[] expected = new uint[] { 0x01FFFF01, 0, 0, 0 }; + Assert.AreEqual(FE(expected), Z); + } + + private ECFieldElement FE(BigInteger x) + { + return DP.Curve.FromBigInteger(x); + } + + private ECFieldElement FE(uint[] x) + { + return FE(Nat128_ToBigInteger(x)); + } + + private static BigInteger Nat128_ToBigInteger(uint[] x) + { + byte[] bs = new byte[16]; + for (int i = 0; i < 4; ++i) + { + uint x_i = x[i]; + if (x_i != 0) + { + Pack_UInt32_To_BE(x_i, bs, (3 - i) << 2); + } + } + return new BigInteger(1, bs); + } + + private static void Pack_UInt32_To_BE(uint n, byte[] bs, int off) + { + bs[off] = (byte)(n >> 24); + bs[off + 1] = (byte)(n >> 16); + bs[off + 2] = (byte)(n >> 8); + bs[off + 3] = (byte)(n); + } + } +} |