diff options
author | Peter Dettman <peter.dettman@bouncycastle.org> | 2022-10-04 19:44:44 +0700 |
---|---|---|
committer | Peter Dettman <peter.dettman@bouncycastle.org> | 2022-10-04 19:44:44 +0700 |
commit | 286b626903b2e3de5610b6cdff9ec196fcf2244e (patch) | |
tree | d1200531c206693630dc7edd0182cdee2342ecc4 /crypto/src/math/ec/rfc7748 | |
parent | Avoid some allocations around MPInteger (diff) | |
download | BouncyCastle.NET-ed25519-286b626903b2e3de5610b6cdff9ec196fcf2244e.tar.xz |
Span-based variants for XDH/EdDSA
Diffstat (limited to 'crypto/src/math/ec/rfc7748')
-rw-r--r-- | crypto/src/math/ec/rfc7748/X25519.cs | 42 | ||||
-rw-r--r-- | crypto/src/math/ec/rfc7748/X25519Field.cs | 21 | ||||
-rw-r--r-- | crypto/src/math/ec/rfc7748/X448.cs | 40 | ||||
-rw-r--r-- | crypto/src/math/ec/rfc7748/X448Field.cs | 23 |
4 files changed, 126 insertions, 0 deletions
diff --git a/crypto/src/math/ec/rfc7748/X25519.cs b/crypto/src/math/ec/rfc7748/X25519.cs index 2a471ae26..954b2dd90 100644 --- a/crypto/src/math/ec/rfc7748/X25519.cs +++ b/crypto/src/math/ec/rfc7748/X25519.cs @@ -80,18 +80,42 @@ namespace Org.BouncyCastle.Math.EC.Rfc7748 public static void GeneratePrivateKey(SecureRandom random, byte[] k) { + if (k.Length != ScalarSize) + throw new ArgumentException(nameof(k)); + + random.NextBytes(k); + + k[0] &= 0xF8; + k[ScalarSize - 1] &= 0x7F; + k[ScalarSize - 1] |= 0x40; + } + +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public static void GeneratePrivateKey(SecureRandom random, Span<byte> k) + { + if (k.Length != ScalarSize) + throw new ArgumentException(nameof(k)); + random.NextBytes(k); k[0] &= 0xF8; k[ScalarSize - 1] &= 0x7F; k[ScalarSize - 1] |= 0x40; } +#endif public static void GeneratePublicKey(byte[] k, int kOff, byte[] r, int rOff) { ScalarMultBase(k, kOff, r, rOff); } +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public static void GeneratePublicKey(ReadOnlySpan<byte> k, Span<byte> r) + { + ScalarMultBase(k, r); + } +#endif + private static void PointDouble(int[] x, int[] z) { int[] a = F.Create(); @@ -255,5 +279,23 @@ namespace Org.BouncyCastle.Math.EC.Rfc7748 F.Normalize(y); F.Encode(y, r, rOff); } + +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public static void ScalarMultBase(ReadOnlySpan<byte> k, Span<byte> r) + { + int[] y = F.Create(); + int[] z = F.Create(); + + Ed25519.ScalarMultBaseYZ(k, y, z); + + F.Apm(z, y, y, z); + + F.Inv(z, z); + F.Mul(y, z, y); + + F.Normalize(y); + F.Encode(y, r); + } +#endif } } diff --git a/crypto/src/math/ec/rfc7748/X25519Field.cs b/crypto/src/math/ec/rfc7748/X25519Field.cs index b4ea9a9ce..8365df03b 100644 --- a/crypto/src/math/ec/rfc7748/X25519Field.cs +++ b/crypto/src/math/ec/rfc7748/X25519Field.cs @@ -107,6 +107,20 @@ namespace Org.BouncyCastle.Math.EC.Rfc7748 } } +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public static void CMov(int cond, ReadOnlySpan<int> x, Span<int> z) + { + Debug.Assert(0 == cond || -1 == cond); + + for (int i = 0; i < Size; ++i) + { + int z_i = z[i], diff = z_i ^ x[i]; + z_i ^= (diff & cond); + z[i] = z_i; + } + } +#endif + public static void CNegate(int negate, int[] z) { Debug.Assert(negate >> 1 == 0); @@ -126,6 +140,13 @@ namespace Org.BouncyCastle.Math.EC.Rfc7748 } } +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public static void Copy(ReadOnlySpan<int> x, Span<int> z) + { + x[..Size].CopyTo(z); + } +#endif + public static int[] Create() { return new int[Size]; diff --git a/crypto/src/math/ec/rfc7748/X448.cs b/crypto/src/math/ec/rfc7748/X448.cs index ba2660f3c..2f6016a61 100644 --- a/crypto/src/math/ec/rfc7748/X448.cs +++ b/crypto/src/math/ec/rfc7748/X448.cs @@ -79,17 +79,40 @@ namespace Org.BouncyCastle.Math.EC.Rfc7748 public static void GeneratePrivateKey(SecureRandom random, byte[] k) { + if (k.Length != ScalarSize) + throw new ArgumentException(nameof(k)); + random.NextBytes(k); k[0] &= 0xFC; k[ScalarSize - 1] |= 0x80; } +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public static void GeneratePrivateKey(SecureRandom random, Span<byte> k) + { + if (k.Length != ScalarSize) + throw new ArgumentException(nameof(k)); + + random.NextBytes(k); + + k[0] &= 0xFC; + k[ScalarSize - 1] |= 0x80; + } +#endif + public static void GeneratePublicKey(byte[] k, int kOff, byte[] r, int rOff) { ScalarMultBase(k, kOff, r, rOff); } +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public static void GeneratePublicKey(ReadOnlySpan<byte> k, Span<byte> r) + { + ScalarMultBase(k, r); + } +#endif + private static void PointDouble(uint[] x, uint[] z) { uint[] a = F.Create(); @@ -268,5 +291,22 @@ namespace Org.BouncyCastle.Math.EC.Rfc7748 F.Normalize(x); F.Encode(x, r, rOff); } + +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public static void ScalarMultBase(ReadOnlySpan<byte> k, Span<byte> r) + { + uint[] x = F.Create(); + uint[] y = F.Create(); + + Ed448.ScalarMultBaseXY(k, x, y); + + F.Inv(x, x); + F.Mul(x, y, x); + F.Sqr(x, x); + + F.Normalize(x); + F.Encode(x, r); + } +#endif } } diff --git a/crypto/src/math/ec/rfc7748/X448Field.cs b/crypto/src/math/ec/rfc7748/X448Field.cs index a91ea0d5b..a1a86b61c 100644 --- a/crypto/src/math/ec/rfc7748/X448Field.cs +++ b/crypto/src/math/ec/rfc7748/X448Field.cs @@ -112,6 +112,22 @@ namespace Org.BouncyCastle.Math.EC.Rfc7748 } } +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public static void CMov(int cond, ReadOnlySpan<uint> x, Span<uint> z) + { + Debug.Assert(0 == cond || -1 == cond); + + uint MASK = (uint)cond; + + for (int i = 0; i < Size; ++i) + { + uint z_i = z[i], diff = z_i ^ x[i]; + z_i ^= (diff & MASK); + z[i] = z_i; + } + } +#endif + public static void CNegate(int negate, uint[] z) { Debug.Assert(negate >> 1 == 0); @@ -130,6 +146,13 @@ namespace Org.BouncyCastle.Math.EC.Rfc7748 } } +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public static void Copy(ReadOnlySpan<uint> x, Span<uint> z) + { + x[..Size].CopyTo(z); + } +#endif + public static uint[] Create() { return new uint[Size]; |