<PackageReference Include="BouncyCastle.Cryptography" Version="2.6.1" />

Scalar25519

static class Scalar25519
using Org.BouncyCastle.Math.Raw; using Org.BouncyCastle.Utilities; using System; using System.Runtime.InteropServices; namespace Org.BouncyCastle.Math.EC.Rfc8032 { internal static class Scalar25519 { internal const int Size = 8; private const int ScalarBytes = 32; private const long M28L = 268435455; private const int TargetLength = 254; private static readonly uint[] L = new uint[8] { 1559614445, 1477600026, 2734136534, 350157278, 0, 0, 0, 268435456 }; private static readonly uint[] LSq = new uint[16] { 2870118761, 3807245957, 580428573, 1745064566, 3524785598, 1036971123, 461123738, 2712901953, 1268693629, 3405925475, 3562992538, 43769659, 0, 0, 0, 16777216 }; private const int L0 = -50998291; private const int L1 = 19280294; private const int L2 = 127719000; private const int L3 = -6428113; private const int L4 = 5343; internal static bool CheckVar(ReadOnlySpan<byte> s, Span<uint> n) { Decode(s, n); return !Nat256.Gte(n, L); } internal static void Decode(ReadOnlySpan<byte> k, Span<uint> n) { Codec.Decode32(k, n.Slice(0, 8)); } internal static void GetOrderWnafVar(int width, Span<sbyte> ws) { Wnaf.GetSignedVar(L, width, ws); } internal unsafe static void Multiply128Var(ReadOnlySpan<uint> x, ReadOnlySpan<uint> y128, Span<uint> z) { Span<uint> span = new Span<uint>(stackalloc byte[48], 12); Nat256.Mul128(x, y128, span); if ((int)y128[3] < 0) { Nat256.AddTo(L, span.Slice(4, span.Length - 4), 0); Nat256.SubFrom(x, span.Slice(4, span.Length - 4), 0); } if (BitConverter.IsLittleEndian) { Span<byte> span2 = MemoryMarshal.AsBytes(span); Reduce384(span2, span2); span.Slice(0, 8).CopyTo(z); } else { Span<byte> span3 = new Span<byte>(stackalloc byte[48], 48); Codec.Encode32(span, span3); Reduce384(span3, span3); Decode(span3, z); } } internal static byte[] Reduce384(byte[] n) { byte[] array = new byte[32]; Reduce384(n, array); return array; } internal static void Reduce384(ReadOnlySpan<byte> n, Span<byte> r) { long num = Codec.Decode32(n.Slice(0, n.Length)); long num2 = Codec.Decode24(n.Slice(4, n.Length - 4)) << 4; long num3 = Codec.Decode32(n.Slice(7, n.Length - 7)); long num4 = Codec.Decode24(n.Slice(11, n.Length - 11)) << 4; long num5 = Codec.Decode32(n.Slice(14, n.Length - 14)); long num6 = Codec.Decode24(n.Slice(18, n.Length - 18)) << 4; long num7 = Codec.Decode32(n.Slice(21, n.Length - 21)); long num8 = Codec.Decode24(n.Slice(25, n.Length - 25)) << 4; long num9 = Codec.Decode32(n.Slice(28, n.Length - 28)); long num10 = Codec.Decode24(n.Slice(32, n.Length - 32)) << 4; long num11 = Codec.Decode32(n.Slice(35, n.Length - 35)); long num12 = Codec.Decode24(n.Slice(39, n.Length - 39)) << 4; long num13 = Codec.Decode32(n.Slice(42, n.Length - 42)); long num14 = Codec.Decode16(n.Slice(46, n.Length - 46)) << 4; num14 += num13 >> 28; num13 &= 268435455; num5 -= num14 * -50998291; num6 -= num14 * 19280294; num7 -= num14 * 127719000; num8 -= num14 * -6428113; num9 -= num14 * 5343; num13 += num12 >> 28; num12 &= 268435455; num4 -= num13 * -50998291; num5 -= num13 * 19280294; num6 -= num13 * 127719000; num7 -= num13 * -6428113; num8 -= num13 * 5343; num12 += num11 >> 28; num11 &= 268435455; num3 -= num12 * -50998291; num4 -= num12 * 19280294; num5 -= num12 * 127719000; num6 -= num12 * -6428113; num7 -= num12 * 5343; num11 += num10 >> 28; num10 &= 268435455; num2 -= num11 * -50998291; num3 -= num11 * 19280294; num4 -= num11 * 127719000; num5 -= num11 * -6428113; num6 -= num11 * 5343; num9 += num8 >> 28; num8 &= 268435455; num10 += num9 >> 28; num9 &= 268435455; long num15 = (num9 >> 27) & 1; num10 += num15; num -= num10 * -50998291; num2 -= num10 * 19280294; num3 -= num10 * 127719000; num4 -= num10 * -6428113; num5 -= num10 * 5343; num2 += num >> 28; num &= 268435455; num3 += num2 >> 28; num2 &= 268435455; num4 += num3 >> 28; num3 &= 268435455; num5 += num4 >> 28; num4 &= 268435455; num6 += num5 >> 28; num5 &= 268435455; num7 += num6 >> 28; num6 &= 268435455; num8 += num7 >> 28; num7 &= 268435455; num9 += num8 >> 28; num8 &= 268435455; num10 = num9 >> 28; num9 &= 268435455; num10 -= num15; num += (num10 & -50998291); num2 += (num10 & 19280294); num3 += (num10 & 127719000); num4 += (num10 & -6428113); num5 += (num10 & 5343); num2 += num >> 28; num &= 268435455; num3 += num2 >> 28; num2 &= 268435455; num4 += num3 >> 28; num3 &= 268435455; num5 += num4 >> 28; num4 &= 268435455; num6 += num5 >> 28; num5 &= 268435455; num7 += num6 >> 28; num6 &= 268435455; num8 += num7 >> 28; num7 &= 268435455; num9 += num8 >> 28; num8 &= 268435455; Codec.Encode56((ulong)(num | (num2 << 28)), r); Codec.Encode56((ulong)(num3 | (num4 << 28)), r.Slice(7, r.Length - 7)); Codec.Encode56((ulong)(num5 | (num6 << 28)), r.Slice(14, r.Length - 14)); Codec.Encode56((ulong)(num7 | (num8 << 28)), r.Slice(21, r.Length - 21)); Codec.Encode32((uint)num9, r.Slice(28, r.Length - 28)); } internal static byte[] Reduce512(byte[] n) { byte[] array = new byte[32]; Reduce512(n, array); return array; } internal static void Reduce512(ReadOnlySpan<byte> n, Span<byte> r) { long num = Codec.Decode32(n.Slice(0, n.Length)); long num2 = Codec.Decode24(n.Slice(4, n.Length - 4)) << 4; long num3 = Codec.Decode32(n.Slice(7, n.Length - 7)); long num4 = Codec.Decode24(n.Slice(11, n.Length - 11)) << 4; long num5 = Codec.Decode32(n.Slice(14, n.Length - 14)); long num6 = Codec.Decode24(n.Slice(18, n.Length - 18)) << 4; long num7 = Codec.Decode32(n.Slice(21, n.Length - 21)); long num8 = Codec.Decode24(n.Slice(25, n.Length - 25)) << 4; long num9 = Codec.Decode32(n.Slice(28, n.Length - 28)); long num10 = Codec.Decode24(n.Slice(32, n.Length - 32)) << 4; long num11 = Codec.Decode32(n.Slice(35, n.Length - 35)); long num12 = Codec.Decode24(n.Slice(39, n.Length - 39)) << 4; long num13 = Codec.Decode32(n.Slice(42, n.Length - 42)); long num14 = Codec.Decode24(n.Slice(46, n.Length - 46)) << 4; long num15 = Codec.Decode32(n.Slice(49, n.Length - 49)); long num16 = Codec.Decode24(n.Slice(53, n.Length - 53)) << 4; long num17 = Codec.Decode32(n.Slice(56, n.Length - 56)); long num18 = Codec.Decode24(n.Slice(60, n.Length - 60)) << 4; long num19 = n[63]; num10 -= num19 * -50998291; num11 -= num19 * 19280294; num12 -= num19 * 127719000; num13 -= num19 * -6428113; num14 -= num19 * 5343; num18 += num17 >> 28; num17 &= 268435455; num9 -= num18 * -50998291; num10 -= num18 * 19280294; num11 -= num18 * 127719000; num12 -= num18 * -6428113; num13 -= num18 * 5343; num8 -= num17 * -50998291; num9 -= num17 * 19280294; num10 -= num17 * 127719000; num11 -= num17 * -6428113; num12 -= num17 * 5343; num16 += num15 >> 28; num15 &= 268435455; num7 -= num16 * -50998291; num8 -= num16 * 19280294; num9 -= num16 * 127719000; num10 -= num16 * -6428113; num11 -= num16 * 5343; num6 -= num15 * -50998291; num7 -= num15 * 19280294; num8 -= num15 * 127719000; num9 -= num15 * -6428113; num10 -= num15 * 5343; num14 += num13 >> 28; num13 &= 268435455; num5 -= num14 * -50998291; num6 -= num14 * 19280294; num7 -= num14 * 127719000; num8 -= num14 * -6428113; num9 -= num14 * 5343; num13 += num12 >> 28; num12 &= 268435455; num4 -= num13 * -50998291; num5 -= num13 * 19280294; num6 -= num13 * 127719000; num7 -= num13 * -6428113; num8 -= num13 * 5343; num12 += num11 >> 28; num11 &= 268435455; num3 -= num12 * -50998291; num4 -= num12 * 19280294; num5 -= num12 * 127719000; num6 -= num12 * -6428113; num7 -= num12 * 5343; num11 += num10 >> 28; num10 &= 268435455; num2 -= num11 * -50998291; num3 -= num11 * 19280294; num4 -= num11 * 127719000; num5 -= num11 * -6428113; num6 -= num11 * 5343; num9 += num8 >> 28; num8 &= 268435455; num10 += num9 >> 28; num9 &= 268435455; long num20 = (num9 >> 27) & 1; num10 += num20; num -= num10 * -50998291; num2 -= num10 * 19280294; num3 -= num10 * 127719000; num4 -= num10 * -6428113; num5 -= num10 * 5343; num2 += num >> 28; num &= 268435455; num3 += num2 >> 28; num2 &= 268435455; num4 += num3 >> 28; num3 &= 268435455; num5 += num4 >> 28; num4 &= 268435455; num6 += num5 >> 28; num5 &= 268435455; num7 += num6 >> 28; num6 &= 268435455; num8 += num7 >> 28; num7 &= 268435455; num9 += num8 >> 28; num8 &= 268435455; num10 = num9 >> 28; num9 &= 268435455; num10 -= num20; num += (num10 & -50998291); num2 += (num10 & 19280294); num3 += (num10 & 127719000); num4 += (num10 & -6428113); num5 += (num10 & 5343); num2 += num >> 28; num &= 268435455; num3 += num2 >> 28; num2 &= 268435455; num4 += num3 >> 28; num3 &= 268435455; num5 += num4 >> 28; num4 &= 268435455; num6 += num5 >> 28; num5 &= 268435455; num7 += num6 >> 28; num6 &= 268435455; num8 += num7 >> 28; num7 &= 268435455; num9 += num8 >> 28; num8 &= 268435455; Codec.Encode56((ulong)(num | (num2 << 28)), r); Codec.Encode56((ulong)(num3 | (num4 << 28)), r.Slice(7, r.Length - 7)); Codec.Encode56((ulong)(num5 | (num6 << 28)), r.Slice(14, r.Length - 14)); Codec.Encode56((ulong)(num7 | (num8 << 28)), r.Slice(21, r.Length - 21)); Codec.Encode32((uint)num9, r.Slice(28, r.Length - 28)); } internal unsafe static bool ReduceBasisVar(ReadOnlySpan<uint> k, Span<uint> z0, Span<uint> z1) { Span<uint> x = new Span<uint>(stackalloc byte[64], 16); LSq.CopyTo(x); Span<uint> y = new Span<uint>(stackalloc byte[64], 16); Nat256.Square(k, y); y[0]++; Span<uint> span = new Span<uint>(stackalloc byte[64], 16); Nat256.Mul(L, k, span); Span<uint> t = new Span<uint>(stackalloc byte[64], 16); Span<uint> x2 = new Span<uint>(stackalloc byte[16], 4); x2.CopyFrom(L); Span<uint> x3 = new Span<uint>(stackalloc byte[16], 4); Span<uint> y2 = new Span<uint>(stackalloc byte[16], 4); y2.CopyFrom(k); Span<uint> y3 = new Span<uint>(stackalloc byte[16], 4); y3[0] = 1; int num = 1016; int num2 = 15; int bitLengthPositive = ScalarUtilities.GetBitLengthPositive(num2, y); while (bitLengthPositive > 254) { if (--num < 0) return false; int num3 = ScalarUtilities.GetBitLength(num2, span) - bitLengthPositive; num3 &= ~(num3 >> 31); if ((int)span[num2] < 0) { ScalarUtilities.AddShifted_NP(num2, num3, x, y, span, t); ScalarUtilities.AddShifted_UV(3, num3, x2, x3, y2, y3); } else { ScalarUtilities.SubShifted_NP(num2, num3, x, y, span, t); ScalarUtilities.SubShifted_UV(3, num3, x2, x3, y2, y3); } if (ScalarUtilities.LessThan(num2, x, y)) { ScalarUtilities.Swap(ref x2, ref y2); ScalarUtilities.Swap(ref x3, ref y3); ScalarUtilities.Swap(ref x, ref y); num2 = bitLengthPositive >> 5; bitLengthPositive = ScalarUtilities.GetBitLengthPositive(num2, y); } } y2.CopyTo(z0); y3.CopyTo(z1); return true; } internal static void ToSignedDigits(int bits, Span<uint> z) { Nat.CAddTo(8, (int)(~z[0] & 1), L, z); Nat.ShiftDownBit(8, z, 1); } } }