summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2022-10-02 01:12:28 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2022-10-02 01:12:28 +0700
commit9d24081e7690f4ec1ff898e3998e385d3486b226 (patch)
treea485ce0c43d41dd20db3c237ce97cd9b07b9af3a
parentGeneric ReverseInPlace method (diff)
downloadBouncyCastle.NET-ed25519-9d24081e7690f4ec1ff898e3998e385d3486b226.tar.xz
Span-based variant of ECCurve.DecodePoint
-rw-r--r--crypto/src/math/ec/ECCurve.cs163
1 files changed, 120 insertions, 43 deletions
diff --git a/crypto/src/math/ec/ECCurve.cs b/crypto/src/math/ec/ECCurve.cs
index 38e05991e..905ddb247 100644
--- a/crypto/src/math/ec/ECCurve.cs
+++ b/crypto/src/math/ec/ECCurve.cs
@@ -436,67 +436,143 @@ namespace Org.BouncyCastle.Math.EC
          */
         public virtual ECPoint DecodePoint(byte[] encoded)
         {
-            ECPoint p = null;
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+            return DecodePoint(encoded.AsSpan());
+#else
+            ECPoint p;
             int expectedLength = (FieldSize + 7) / 8;
 
             byte type = encoded[0];
             switch (type)
             {
-                case 0x00: // infinity
-                {
-                    if (encoded.Length != 1)
-                        throw new ArgumentException("Incorrect length for infinity encoding", "encoded");
+            case 0x00: // infinity
+            {
+                if (encoded.Length != 1)
+                    throw new ArgumentException("Incorrect length for infinity encoding", "encoded");
 
-                    p = Infinity;
-                    break;
-                }
+                p = Infinity;
+                break;
+            }
 
-                case 0x02: // compressed
-                case 0x03: // compressed
-                {
-                    if (encoded.Length != (expectedLength + 1))
-                        throw new ArgumentException("Incorrect length for compressed encoding", "encoded");
+            case 0x02: // compressed
+            case 0x03: // compressed
+            {
+                if (encoded.Length != (expectedLength + 1))
+                    throw new ArgumentException("Incorrect length for compressed encoding", "encoded");
 
-                    int yTilde = type & 1;
-                    BigInteger X = new BigInteger(1, encoded, 1, expectedLength);
+                int yTilde = type & 1;
+                BigInteger X = new BigInteger(1, encoded, 1, expectedLength);
 
-                    p = DecompressPoint(yTilde, X);
-                    if (!p.ImplIsValid(true, true))
-                        throw new ArgumentException("Invalid point");
+                p = DecompressPoint(yTilde, X);
+                if (!p.ImplIsValid(true, true))
+                    throw new ArgumentException("Invalid point");
 
-                    break;
-                }
+                break;
+            }
 
-                case 0x04: // uncompressed
-                {
-                    if (encoded.Length != (2 * expectedLength + 1))
-                        throw new ArgumentException("Incorrect length for uncompressed encoding", "encoded");
+            case 0x04: // uncompressed
+            {
+                if (encoded.Length != (2 * expectedLength + 1))
+                    throw new ArgumentException("Incorrect length for uncompressed encoding", "encoded");
 
-                    BigInteger X = new BigInteger(1, encoded, 1, expectedLength);
-                    BigInteger Y = new BigInteger(1, encoded, 1 + expectedLength, expectedLength);
+                BigInteger X = new BigInteger(1, encoded, 1, expectedLength);
+                BigInteger Y = new BigInteger(1, encoded, 1 + expectedLength, expectedLength);
 
-                    p = ValidatePoint(X, Y);
-                    break;
-                }
+                p = ValidatePoint(X, Y);
+                break;
+            }
 
-                case 0x06: // hybrid
-                case 0x07: // hybrid
-                {
-                    if (encoded.Length != (2 * expectedLength + 1))
-                        throw new ArgumentException("Incorrect length for hybrid encoding", "encoded");
+            case 0x06: // hybrid
+            case 0x07: // hybrid
+            {
+                if (encoded.Length != (2 * expectedLength + 1))
+                    throw new ArgumentException("Incorrect length for hybrid encoding", "encoded");
 
-                    BigInteger X = new BigInteger(1, encoded, 1, expectedLength);
-                    BigInteger Y = new BigInteger(1, encoded, 1 + expectedLength, expectedLength);
+                BigInteger X = new BigInteger(1, encoded, 1, expectedLength);
+                BigInteger Y = new BigInteger(1, encoded, 1 + expectedLength, expectedLength);
 
-                    if (Y.TestBit(0) != (type == 0x07))
-                        throw new ArgumentException("Inconsistent Y coordinate in hybrid encoding", "encoded");
+                if (Y.TestBit(0) != (type == 0x07))
+                    throw new ArgumentException("Inconsistent Y coordinate in hybrid encoding", "encoded");
 
-                    p = ValidatePoint(X, Y);
-                    break;
-                }
+                p = ValidatePoint(X, Y);
+                break;
+            }
 
-                default:
-                    throw new FormatException("Invalid point encoding " + type);
+            default:
+                throw new FormatException("Invalid point encoding " + type);
+            }
+
+            if (type != 0x00 && p.IsInfinity)
+                throw new ArgumentException("Invalid infinity encoding", "encoded");
+
+            return p;
+#endif
+        }
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+        public virtual ECPoint DecodePoint(ReadOnlySpan<byte> encodedX)
+        {
+            ECPoint p;
+            int expectedLength = (FieldSize + 7) / 8;
+
+            byte type = encodedX[0];
+            switch (type)
+            {
+            case 0x00: // infinity
+            {
+                if (encodedX.Length != 1)
+                    throw new ArgumentException("Incorrect length for infinity encoding", "encoded");
+
+                p = Infinity;
+                break;
+            }
+
+            case 0x02: // compressed
+            case 0x03: // compressed
+            {
+                if (encodedX.Length != (expectedLength + 1))
+                    throw new ArgumentException("Incorrect length for compressed encoding", "encoded");
+
+                int yTilde = type & 1;
+                BigInteger X = new BigInteger(1, encodedX[1..]);
+
+                p = DecompressPoint(yTilde, X);
+                if (!p.ImplIsValid(true, true))
+                    throw new ArgumentException("Invalid point");
+
+                break;
+            }
+
+            case 0x04: // uncompressed
+            {
+                if (encodedX.Length != (2 * expectedLength + 1))
+                    throw new ArgumentException("Incorrect length for uncompressed encoding", "encoded");
+
+                BigInteger X = new BigInteger(1, encodedX[1..(1 + expectedLength)]);
+                BigInteger Y = new BigInteger(1, encodedX[(1 + expectedLength)..]);
+
+                p = ValidatePoint(X, Y);
+                break;
+            }
+
+            case 0x06: // hybrid
+            case 0x07: // hybrid
+            {
+                if (encodedX.Length != (2 * expectedLength + 1))
+                    throw new ArgumentException("Incorrect length for hybrid encoding", "encoded");
+
+                BigInteger X = new BigInteger(1, encodedX[1..(1 + expectedLength)]);
+                BigInteger Y = new BigInteger(1, encodedX[(1 + expectedLength)..]);
+
+                if (Y.TestBit(0) != (type == 0x07))
+                    throw new ArgumentException("Inconsistent Y coordinate in hybrid encoding", "encoded");
+
+                p = ValidatePoint(X, Y);
+                break;
+            }
+
+            default:
+                throw new FormatException("Invalid point encoding " + type);
             }
 
             if (type != 0x00 && p.IsInfinity)
@@ -504,6 +580,7 @@ namespace Org.BouncyCastle.Math.EC
 
             return p;
         }
+#endif
 
         private class DefaultLookupTable
             : AbstractECLookupTable