diff --git a/crypto/src/math/ec/rfc8032/Ed25519.cs b/crypto/src/math/ec/rfc8032/Ed25519.cs
index 09cc9d433..766ccb393 100644
--- a/crypto/src/math/ec/rfc8032/Ed25519.cs
+++ b/crypto/src/math/ec/rfc8032/Ed25519.cs
@@ -1496,7 +1496,7 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
#endif
Scalar25519.Decode(k, n);
- Scalar25519.ToSignedDigits(256, n, n);
+ Scalar25519.ToSignedDigits(256, n);
Init(out PointPrecompZ q);
Init(out PointTemp t);
@@ -1541,7 +1541,7 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
#endif
Scalar25519.Decode(k, n);
- Scalar25519.ToSignedDigits(PrecompRange, n, n);
+ Scalar25519.ToSignedDigits(PrecompRange, n);
GroupCombBits(n);
Init(out PointPrecomp p);
diff --git a/crypto/src/math/ec/rfc8032/Scalar25519.cs b/crypto/src/math/ec/rfc8032/Scalar25519.cs
index 00dcd49a1..df31929cd 100644
--- a/crypto/src/math/ec/rfc8032/Scalar25519.cs
+++ b/crypto/src/math/ec/rfc8032/Scalar25519.cs
@@ -14,6 +14,8 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
{
internal const int Size = 8;
+ private const int ScalarBytes = Size * 4;
+
private const long M08L = 0x000000FFL;
private const long M28L = 0x0FFFFFFFL;
private const long M32L = 0xFFFFFFFFL;
@@ -105,7 +107,7 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
internal static byte[] Reduce(byte[] n)
{
- byte[] r = new byte[64];
+ byte[] r = new byte[ScalarBytes];
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
Reduce(n, r);
@@ -488,15 +490,15 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
#endif
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
- internal static void ToSignedDigits(int bits, ReadOnlySpan<uint> x, Span<uint> z)
+ internal static void ToSignedDigits(int bits, Span<uint> z)
#else
- internal static void ToSignedDigits(int bits, uint[] x, uint[] z)
+ internal static void ToSignedDigits(int bits, uint[] z)
#endif
{
Debug.Assert(bits == 256);
Debug.Assert(z.Length >= Size);
- uint c1 = Nat.CAdd(Size, ~(int)x[0] & 1, x, L, z); Debug.Assert(c1 == 0U);
+ uint c1 = Nat.CAddTo(Size, ~(int)z[0] & 1, L, z); Debug.Assert(c1 == 0U);
uint c2 = Nat.ShiftDownBit(Size, z, 1U); Debug.Assert(c2 == (1U << 31));
}
}
diff --git a/crypto/src/math/raw/Nat.cs b/crypto/src/math/raw/Nat.cs
index d748e04c5..0f53b1a8b 100644
--- a/crypto/src/math/raw/Nat.cs
+++ b/crypto/src/math/raw/Nat.cs
@@ -400,6 +400,36 @@ namespace Org.BouncyCastle.Math.Raw
}
#endif
+ public static uint CAddTo(int len, int mask, uint[] x, uint[] z)
+ {
+ uint MASK = (uint)-(mask & 1);
+
+ ulong c = 0;
+ for (int i = 0; i < len; ++i)
+ {
+ c += (ulong)z[i] + (x[i] & MASK);
+ z[i] = (uint)c;
+ c >>= 32;
+ }
+ return (uint)c;
+ }
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public static uint CAddTo(int len, int mask, ReadOnlySpan<uint> x, Span<uint> z)
+ {
+ uint MASK = (uint)-(mask & 1);
+
+ ulong c = 0;
+ for (int i = 0; i < len; ++i)
+ {
+ c += (ulong)z[i] + (x[i] & MASK);
+ z[i] = (uint)c;
+ c >>= 32;
+ }
+ return (uint)c;
+ }
+#endif
+
public static void CMov(int len, int mask, uint[] x, int xOff, uint[] z, int zOff)
{
uint MASK = (uint)-(mask & 1);
|