summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2022-10-02 01:09:24 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2022-10-02 01:09:24 +0700
commitd18909ff1b1c4e671faeaf1ed1c174ad5401f7c9 (patch)
tree342bc379d5ba915b4f2197a6c7420ada023a9657
parentSpan-based constructor for BigInteger (diff)
downloadBouncyCastle.NET-ed25519-d18909ff1b1c4e671faeaf1ed1c174ad5401f7c9.tar.xz
Support encoding without allocation
-rw-r--r--crypto/src/math/ec/ECFieldElement.cs19
-rw-r--r--crypto/src/math/ec/ECPoint.cs71
2 files changed, 89 insertions, 1 deletions
diff --git a/crypto/src/math/ec/ECFieldElement.cs b/crypto/src/math/ec/ECFieldElement.cs
index a96556482..330708088 100644
--- a/crypto/src/math/ec/ECFieldElement.cs
+++ b/crypto/src/math/ec/ECFieldElement.cs
@@ -96,8 +96,25 @@ namespace Org.BouncyCastle.Math.EC
 
         public virtual byte[] GetEncoded()
         {
-            return BigIntegers.AsUnsignedByteArray((FieldSize + 7) / 8, ToBigInteger());
+            return BigIntegers.AsUnsignedByteArray(GetEncodedLength(), ToBigInteger());
         }
+
+        public virtual int GetEncodedLength()
+        {
+            return (FieldSize + 7) / 8;
+        }
+
+        public virtual void EncodeTo(byte[] buf, int off)
+        {
+            BigIntegers.AsUnsignedByteArray(ToBigInteger(), buf, off, GetEncodedLength());
+        }
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+        public virtual void EncodeTo(Span<byte> buf)
+        {
+            BigIntegers.AsUnsignedByteArray(ToBigInteger(), buf[..GetEncodedLength()]);
+        }
+#endif
     }
 
     public abstract class AbstractFpFieldElement
diff --git a/crypto/src/math/ec/ECPoint.cs b/crypto/src/math/ec/ECPoint.cs
index dcda5abfc..fc0ddf035 100644
--- a/crypto/src/math/ec/ECPoint.cs
+++ b/crypto/src/math/ec/ECPoint.cs
@@ -437,6 +437,14 @@ namespace Org.BouncyCastle.Math.EC
 
         public abstract byte[] GetEncoded(bool compressed);
 
+        public abstract int GetEncodedLength(bool compressed);
+
+        public abstract void EncodeTo(bool compressed, byte[] buf, int off);
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+        public abstract void EncodeTo(bool compressed, Span<byte> buf);
+#endif
+
         protected internal abstract bool CompressionYTilde { get; }
 
         public abstract ECPoint Add(ECPoint b);
@@ -560,6 +568,69 @@ namespace Org.BouncyCastle.Math.EC
             }
         }
 
+        public override int GetEncodedLength(bool compressed)
+        {
+            if (IsInfinity)
+                return 1;
+
+            if (compressed)
+                return 1 + XCoord.GetEncodedLength();
+
+            return 1 + XCoord.GetEncodedLength() + YCoord.GetEncodedLength();
+        }
+
+        public override void EncodeTo(bool compressed, byte[] buf, int off)
+        {
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+            EncodeTo(compressed, buf.AsSpan(off));
+#else
+            if (IsInfinity)
+            {
+                buf[off] = 0x00;
+                return;
+            }
+
+            ECPoint normed = Normalize();
+            ECFieldElement X = normed.XCoord, Y = normed.YCoord;
+
+            if (compressed)
+            {
+                buf[off] = (byte)(normed.CompressionYTilde ? 0x03 : 0x02);
+                X.EncodeTo(buf, off + 1);
+                return;
+            }
+
+            buf[off] = 0x04;
+            X.EncodeTo(buf, off + 1);
+            Y.EncodeTo(buf, off + 1 + X.GetEncodedLength());
+#endif
+        }
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+        public override void EncodeTo(bool compressed, Span<byte> buf)
+        {
+            if (IsInfinity)
+            {
+                buf[0] = 0x00;
+                return;
+            }
+
+            ECPoint normed = Normalize();
+            ECFieldElement X = normed.XCoord, Y = normed.YCoord;
+
+            if (compressed)
+            {
+                buf[0] = (byte)(normed.CompressionYTilde ? 0x03 : 0x02);
+                X.EncodeTo(buf[1..]);
+                return;
+            }
+
+            buf[0] = 0x04;
+            X.EncodeTo(buf[1..]);
+            Y.EncodeTo(buf[(1 + X.GetEncodedLength())..]);
+        }
+#endif
+
         /**
          * Multiplies this <code>ECPoint</code> by the given number.
          * @param k The multiplicator.