From d18909ff1b1c4e671faeaf1ed1c174ad5401f7c9 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Sun, 2 Oct 2022 01:09:24 +0700 Subject: Support encoding without allocation --- crypto/src/math/ec/ECFieldElement.cs | 19 +++++++++- crypto/src/math/ec/ECPoint.cs | 71 ++++++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+), 1 deletion(-) 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 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 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 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 ECPoint by the given number. * @param k The multiplicator. -- cgit 1.4.1