summary refs log tree commit diff
path: root/crypto/src/math/ec/custom/sec/SecP256R1FieldElement.cs
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2014-01-30 15:15:14 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2014-01-30 15:15:14 +0700
commitd9501d9ea10c353e267142b94507e7a065ca75f7 (patch)
tree33c49d11ac65db2b78d3313c5e30a69f1f1bb160 /crypto/src/math/ec/custom/sec/SecP256R1FieldElement.cs
parentAdd SquareN to perform repeated modular squaring (diff)
downloadBouncyCastle.NET-ed25519-d9501d9ea10c353e267142b94507e7a065ca75f7.tar.xz
Take advantage of special prime modulus to optimize sqrt
Diffstat (limited to 'crypto/src/math/ec/custom/sec/SecP256R1FieldElement.cs')
-rw-r--r--crypto/src/math/ec/custom/sec/SecP256R1FieldElement.cs38
1 files changed, 36 insertions, 2 deletions
diff --git a/crypto/src/math/ec/custom/sec/SecP256R1FieldElement.cs b/crypto/src/math/ec/custom/sec/SecP256R1FieldElement.cs
index a4a7004c0..650f12aaf 100644
--- a/crypto/src/math/ec/custom/sec/SecP256R1FieldElement.cs
+++ b/crypto/src/math/ec/custom/sec/SecP256R1FieldElement.cs
@@ -126,8 +126,42 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
          */
         public override ECFieldElement Sqrt()
         {
-            ECFieldElement root = new FpFieldElement(Q, ToBigInteger()).Sqrt();
-            return root == null ? null : new SecP256R1FieldElement(root.ToBigInteger());
+            // Raise this element to the exponent 2^254 - 2^222 + 2^190 + 2^94
+
+            uint[] x1 = this.x;
+            if (Nat256.IsZero(x1) || Nat256.IsOne(x1))
+            {
+                return this;
+            }
+
+            uint[] t1 = Nat256.Create();
+            uint[] t2 = Nat256.Create();
+
+            SecP256R1Field.Square(x1, t1);
+            SecP256R1Field.Multiply(t1, x1, t1);
+
+            SecP256R1Field.SquareN(t1, 2, t2);
+            SecP256R1Field.Multiply(t2, t1, t2);
+
+            SecP256R1Field.SquareN(t2, 4, t1);
+            SecP256R1Field.Multiply(t1, t2, t1);
+
+            SecP256R1Field.SquareN(t1, 8, t2);
+            SecP256R1Field.Multiply(t2, t1, t2);
+
+            SecP256R1Field.SquareN(t2, 16, t1);
+            SecP256R1Field.Multiply(t1, t2, t1);
+
+            SecP256R1Field.SquareN(t1, 32, t1);
+            SecP256R1Field.Multiply(t1, x1, t1);
+
+            SecP256R1Field.SquareN(t1, 96, t1);
+            SecP256R1Field.Multiply(t1, x1, t1);
+
+            SecP256R1Field.SquareN(t1, 94, t1);
+            SecP256R1Field.Multiply(t1, t1, t2);
+
+            return Arrays.AreEqual(x1, t2) ? new SecP256R1FieldElement(t1) : null;
         }
 
         public override bool Equals(object obj)