diff options
author | Peter Dettman <peter.dettman@bouncycastle.org> | 2022-10-02 01:09:24 +0700 |
---|---|---|
committer | Peter Dettman <peter.dettman@bouncycastle.org> | 2022-10-02 01:09:24 +0700 |
commit | d18909ff1b1c4e671faeaf1ed1c174ad5401f7c9 (patch) | |
tree | 342bc379d5ba915b4f2197a6c7420ada023a9657 /crypto/src | |
parent | Span-based constructor for BigInteger (diff) | |
download | BouncyCastle.NET-ed25519-d18909ff1b1c4e671faeaf1ed1c174ad5401f7c9.tar.xz |
Support encoding without allocation
Diffstat (limited to 'crypto/src')
-rw-r--r-- | crypto/src/math/ec/ECFieldElement.cs | 19 | ||||
-rw-r--r-- | crypto/src/math/ec/ECPoint.cs | 71 |
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. |