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);
}
}
}