diff options
author | Peter Dettman <peter.dettman@bouncycastle.org> | 2022-10-01 19:46:15 +0700 |
---|---|---|
committer | Peter Dettman <peter.dettman@bouncycastle.org> | 2022-10-01 19:46:15 +0700 |
commit | 2f4de05c64ba6653bec38941ba1b66c6e16f05b2 (patch) | |
tree | fc27b837ffdd6e0b399c604db4ed88a035a1d936 /crypto/src/math/ec/rfc7748/X25519.cs | |
parent | Port Blake2xsDigest from bc-java (diff) | |
download | BouncyCastle.NET-ed25519-2f4de05c64ba6653bec38941ba1b66c6e16f05b2.tar.xz |
Span-based variant of IRawAgreement.CalculateAgreement
Diffstat (limited to 'crypto/src/math/ec/rfc7748/X25519.cs')
-rw-r--r-- | crypto/src/math/ec/rfc7748/X25519.cs | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/crypto/src/math/ec/rfc7748/X25519.cs b/crypto/src/math/ec/rfc7748/X25519.cs index 217ef8785..2a471ae26 100644 --- a/crypto/src/math/ec/rfc7748/X25519.cs +++ b/crypto/src/math/ec/rfc7748/X25519.cs @@ -26,6 +26,36 @@ namespace Org.BouncyCastle.Math.EC.Rfc7748 return !Arrays.AreAllZeroes(r, rOff, PointSize); } +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public static bool CalculateAgreement(ReadOnlySpan<byte> k, ReadOnlySpan<byte> u, Span<byte> r) + { + ScalarMult(k, u, r); + return !Arrays.AreAllZeroes(r[..PointSize]); + } +#endif + +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + private static uint Decode32(ReadOnlySpan<byte> bs) + { + uint n = bs[0]; + n |= (uint)bs[1] << 8; + n |= (uint)bs[2] << 16; + n |= (uint)bs[3] << 24; + return n; + } + + private static void DecodeScalar(ReadOnlySpan<byte> k, Span<uint> n) + { + for (int i = 0; i < 8; ++i) + { + n[i] = Decode32(k[(i * 4)..]); + } + + n[0] &= 0xFFFFFFF8U; + n[7] &= 0x7FFFFFFFU; + n[7] |= 0x40000000U; + } +#else private static uint Decode32(byte[] bs, int off) { uint n = bs[off]; @@ -46,6 +76,7 @@ namespace Org.BouncyCastle.Math.EC.Rfc7748 n[7] &= 0x7FFFFFFFU; n[7] |= 0x40000000U; } +#endif public static void GeneratePrivateKey(SecureRandom random, byte[] k) { @@ -83,6 +114,9 @@ namespace Org.BouncyCastle.Math.EC.Rfc7748 public static void ScalarMult(byte[] k, int kOff, byte[] u, int uOff, byte[] r, int rOff) { +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + ScalarMult(k.AsSpan(kOff), u.AsSpan(uOff), r.AsSpan(rOff)); +#else uint[] n = new uint[8]; DecodeScalar(k, kOff, n); int[] x1 = F.Create(); F.Decode(u, uOff, x1); @@ -140,7 +174,71 @@ namespace Org.BouncyCastle.Math.EC.Rfc7748 F.Normalize(x2); F.Encode(x2, r, rOff); +#endif + } + +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public static void ScalarMult(ReadOnlySpan<byte> k, ReadOnlySpan<byte> u, Span<byte> r) + { + uint[] n = new uint[8]; DecodeScalar(k, n); + + int[] x1 = F.Create(); F.Decode(u, x1); + int[] x2 = F.Create(); F.Copy(x1, 0, x2, 0); + int[] z2 = F.Create(); z2[0] = 1; + int[] x3 = F.Create(); x3[0] = 1; + int[] z3 = F.Create(); + + int[] t1 = F.Create(); + int[] t2 = F.Create(); + + Debug.Assert(n[7] >> 30 == 1U); + + int bit = 254, swap = 1; + do + { + F.Apm(x3, z3, t1, x3); + F.Apm(x2, z2, z3, x2); + F.Mul(t1, x2, t1); + F.Mul(x3, z3, x3); + F.Sqr(z3, z3); + F.Sqr(x2, x2); + + F.Sub(z3, x2, t2); + F.Mul(t2, C_A24, z2); + F.Add(z2, x2, z2); + F.Mul(z2, t2, z2); + F.Mul(x2, z3, x2); + + F.Apm(t1, x3, x3, z3); + F.Sqr(x3, x3); + F.Sqr(z3, z3); + F.Mul(z3, x1, z3); + + --bit; + + int word = bit >> 5, shift = bit & 0x1F; + int kt = (int)(n[word] >> shift) & 1; + swap ^= kt; + F.CSwap(swap, x2, x3); + F.CSwap(swap, z2, z3); + swap = kt; + } + while (bit >= 3); + + Debug.Assert(swap == 0); + + for (int i = 0; i < 3; ++i) + { + PointDouble(x2, z2); + } + + F.Inv(z2, z2); + F.Mul(x2, z2, x2); + + F.Normalize(x2); + F.Encode(x2, r); } +#endif public static void ScalarMultBase(byte[] k, int kOff, byte[] r, int rOff) { |