diff --git a/crypto/src/math/ec/rfc7748/X448Field.cs b/crypto/src/math/ec/rfc7748/X448Field.cs
index f1e89e520..14c9b4879 100644
--- a/crypto/src/math/ec/rfc7748/X448Field.cs
+++ b/crypto/src/math/ec/rfc7748/X448Field.cs
@@ -1009,6 +1009,14 @@ namespace Org.BouncyCastle.Math.EC.Rfc7748
z[15] = z15;
}
+ public static void SubOne(uint[] z)
+ {
+ uint[] one = Create();
+ one[0] = 1U;
+
+ Sub(z, one, z);
+ }
+
public static void Zero(uint[] z)
{
for (int i = 0; i < Size; ++i)
diff --git a/crypto/src/math/ec/rfc8032/Ed25519.cs b/crypto/src/math/ec/rfc8032/Ed25519.cs
index b798bdf2d..238256cf7 100644
--- a/crypto/src/math/ec/rfc8032/Ed25519.cs
+++ b/crypto/src/math/ec/rfc8032/Ed25519.cs
@@ -12,6 +12,8 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
{
public abstract class Ed25519
{
+ // -x^2 + y^2 == 1 + 0x52036CEE2B6FFE738CC740797779E89800700A4D4141D8AB75EB4DCA135978A3 * x^2 * y^2
+
public enum Algorithm
{
Ed25519 = 0,
@@ -112,6 +114,46 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
|| ctx != null && ctx.Length < 256;
}
+ private static int CheckPoint(int[] x, int[] y)
+ {
+ int[] t = X25519Field.Create();
+ int[] u = X25519Field.Create();
+ int[] v = X25519Field.Create();
+
+ X25519Field.Sqr(x, u);
+ X25519Field.Sqr(y, v);
+ X25519Field.Mul(u, v, t);
+ X25519Field.Sub(v, u, v);
+ X25519Field.Mul(t, C_d, t);
+ X25519Field.AddOne(t);
+ X25519Field.Sub(t, v, t);
+ X25519Field.Normalize(t);
+
+ return X25519Field.IsZero(t);
+ }
+
+ private static int CheckPoint(int[] x, int[] y, int[] z)
+ {
+ int[] t = X25519Field.Create();
+ int[] u = X25519Field.Create();
+ int[] v = X25519Field.Create();
+ int[] w = X25519Field.Create();
+
+ X25519Field.Sqr(x, u);
+ X25519Field.Sqr(y, v);
+ X25519Field.Sqr(z, w);
+ X25519Field.Mul(u, v, t);
+ X25519Field.Sub(v, u, v);
+ X25519Field.Mul(v, w, v);
+ X25519Field.Sqr(w, w);
+ X25519Field.Mul(t, C_d, t);
+ X25519Field.Add(t, w, t);
+ X25519Field.Sub(t, v, t);
+ X25519Field.Normalize(t);
+
+ return X25519Field.IsZero(t);
+ }
+
private static bool CheckPointVar(byte[] p)
{
uint[] t = new uint[8];
@@ -234,7 +276,7 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
Encode24((uint)(n >> 32), bs, off + 4);
}
- private static void EncodePoint(PointAccum p, byte[] r, int rOff)
+ private static int EncodePoint(PointAccum p, byte[] r, int rOff)
{
int[] x = X25519Field.Create();
int[] y = X25519Field.Create();
@@ -245,8 +287,12 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
X25519Field.Normalize(x);
X25519Field.Normalize(y);
+ int result = CheckPoint(x, y);
+
X25519Field.Encode(y, r, rOff);
r[rOff + PointBytes - 1] |= (byte)((x[0] & 1) << 7);
+
+ return result;
}
public static void GeneratePrivateKey(SecureRandom random, byte[] k)
@@ -426,9 +472,7 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
ScalarMultStrausVar(nS, nA, pA, pR);
byte[] check = new byte[PointBytes];
- EncodePoint(pR, check, 0);
-
- return Arrays.AreEqual(check, R);
+ return 0 != EncodePoint(pR, check, 0) && Arrays.AreEqual(check, R);
}
private static void PointAddVar(bool negate, PointExt p, PointAccum r)
@@ -931,7 +975,8 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
{
PointAccum p = new PointAccum();
ScalarMultBase(k, p);
- EncodePoint(p, r, rOff);
+ if (0 == EncodePoint(p, r, rOff))
+ throw new InvalidOperationException();
}
internal static void ScalarMultBaseYZ(byte[] k, int kOff, int[] y, int[] z)
@@ -941,6 +986,10 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
PointAccum p = new PointAccum();
ScalarMultBase(n, p);
+
+ if (0 == CheckPoint(p.x, p.y, p.z))
+ throw new InvalidOperationException();
+
X25519Field.Copy(p.y, 0, y, 0);
X25519Field.Copy(p.z, 0, z, 0);
}
diff --git a/crypto/src/math/ec/rfc8032/Ed448.cs b/crypto/src/math/ec/rfc8032/Ed448.cs
index 842839396..925f48eb1 100644
--- a/crypto/src/math/ec/rfc8032/Ed448.cs
+++ b/crypto/src/math/ec/rfc8032/Ed448.cs
@@ -12,6 +12,8 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
{
public abstract class Ed448
{
+ // x^2 + y^2 == 1 - 39081 * x^2 * y^2
+
public enum Algorithm
{
Ed448 = 0,
@@ -109,6 +111,46 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
return ctx != null && ctx.Length < 256;
}
+ private static int CheckPoint(uint[] x, uint[] y)
+ {
+ uint[] t = X448Field.Create();
+ uint[] u = X448Field.Create();
+ uint[] v = X448Field.Create();
+
+ X448Field.Sqr(x, u);
+ X448Field.Sqr(y, v);
+ X448Field.Mul(u, v, t);
+ X448Field.Add(u, v, u);
+ X448Field.Mul(t, -C_d, t);
+ X448Field.SubOne(t);
+ X448Field.Add(t, u, t);
+ X448Field.Normalize(t);
+
+ return X448Field.IsZero(t);
+ }
+
+ private static int CheckPoint(uint[] x, uint[] y, uint[] z)
+ {
+ uint[] t = X448Field.Create();
+ uint[] u = X448Field.Create();
+ uint[] v = X448Field.Create();
+ uint[] w = X448Field.Create();
+
+ X448Field.Sqr(x, u);
+ X448Field.Sqr(y, v);
+ X448Field.Sqr(z, w);
+ X448Field.Mul(u, v, t);
+ X448Field.Add(u, v, u);
+ X448Field.Mul(u, w, u);
+ X448Field.Sqr(w, w);
+ X448Field.Mul(t, -C_d, t);
+ X448Field.Sub(t, w, t);
+ X448Field.Add(t, u, t);
+ X448Field.Normalize(t);
+
+ return X448Field.IsZero(t);
+ }
+
private static bool CheckPointVar(byte[] p)
{
if ((p[PointBytes - 1] & 0x7F) != 0x00)
@@ -243,7 +285,7 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
Encode24((uint)(n >> 32), bs, off + 4);
}
- private static void EncodePoint(PointExt p, byte[] r, int rOff)
+ private static int EncodePoint(PointExt p, byte[] r, int rOff)
{
uint[] x = X448Field.Create();
uint[] y = X448Field.Create();
@@ -254,8 +296,12 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
X448Field.Normalize(x);
X448Field.Normalize(y);
+ int result = CheckPoint(x, y);
+
X448Field.Encode(y, r, rOff);
r[rOff + PointBytes - 1] = (byte)((x[0] & 1) << 7);
+
+ return result;
}
public static void GeneratePrivateKey(SecureRandom random, byte[] k)
@@ -435,9 +481,7 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
ScalarMultStrausVar(nS, nA, pA, pR);
byte[] check = new byte[PointBytes];
- EncodePoint(pR, check, 0);
-
- return Arrays.AreEqual(check, R);
+ return 0 != EncodePoint(pR, check, 0) && Arrays.AreEqual(check, R);
}
private static void PointAddVar(bool negate, PointExt p, PointExt r)
@@ -1018,7 +1062,8 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
{
PointExt p = new PointExt();
ScalarMultBase(k, p);
- EncodePoint(p, r, rOff);
+ if (0 == EncodePoint(p, r, rOff))
+ throw new InvalidOperationException();
}
internal static void ScalarMultBaseXY(byte[] k, int kOff, uint[] x, uint[] y)
@@ -1028,6 +1073,10 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
PointExt p = new PointExt();
ScalarMultBase(n, p);
+
+ if (0 == CheckPoint(p.x, p.y, p.z))
+ throw new InvalidOperationException();
+
X448Field.Copy(p.x, 0, x, 0);
X448Field.Copy(p.y, 0, y, 0);
}
|