diff --git a/crypto/src/crypto/signers/IDsaEncoding.cs b/crypto/src/crypto/signers/IDsaEncoding.cs
index cccc4f937..8960445cf 100644
--- a/crypto/src/crypto/signers/IDsaEncoding.cs
+++ b/crypto/src/crypto/signers/IDsaEncoding.cs
@@ -21,5 +21,11 @@ namespace Org.BouncyCastle.Crypto.Signers
/// <param name="s">The s value of a DSA signature.</param>
/// <returns>An encoding of the DSA signature given by the provided (r, s) pair.</returns>
byte[] Encode(BigInteger n, BigInteger r, BigInteger s);
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ int Encode(BigInteger n, BigInteger r, BigInteger s, Span<byte> output);
+#endif
+
+ int GetMaxEncodingSize(BigInteger n);
}
}
diff --git a/crypto/src/crypto/signers/PlainDsaEncoding.cs b/crypto/src/crypto/signers/PlainDsaEncoding.cs
index 2e1f65a1f..1563800ef 100644
--- a/crypto/src/crypto/signers/PlainDsaEncoding.cs
+++ b/crypto/src/crypto/signers/PlainDsaEncoding.cs
@@ -31,6 +31,22 @@ namespace Org.BouncyCastle.Crypto.Signers
return result;
}
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public virtual int Encode(BigInteger n, BigInteger r, BigInteger s, Span<byte> output)
+ {
+ int valueLength = BigIntegers.GetUnsignedByteLength(n);
+ int resultLength = valueLength * 2;
+ EncodeValue(n, r, output[..valueLength]);
+ EncodeValue(n, s, output[valueLength..resultLength]);
+ return resultLength;
+ }
+#endif
+
+ public virtual int GetMaxEncodingSize(BigInteger n)
+ {
+ return BigIntegers.GetUnsignedByteLength(n) * 2;
+ }
+
protected virtual BigInteger CheckValue(BigInteger n, BigInteger x)
{
if (x.SignValue < 0 || x.CompareTo(n) >= 0)
@@ -54,5 +70,18 @@ namespace Org.BouncyCastle.Crypto.Signers
Arrays.Fill(buf, off, off + pos, 0);
Array.Copy(bs, bsOff, buf, off + pos, bsLen);
}
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ protected virtual void EncodeValue(BigInteger n, BigInteger x, Span<byte> buffer)
+ {
+ byte[] bs = CheckValue(n, x).ToByteArrayUnsigned();
+ int bsOff = System.Math.Max(0, bs.Length - buffer.Length);
+ int bsLen = bs.Length - bsOff;
+
+ int pos = buffer.Length - bsLen;
+ buffer[..pos].Fill(0x00);
+ bs.AsSpan(bsOff, bsLen).CopyTo(buffer[pos..]);
+ }
+#endif
}
}
diff --git a/crypto/src/crypto/signers/StandardDsaEncoding.cs b/crypto/src/crypto/signers/StandardDsaEncoding.cs
index 75ac08411..77cd6124d 100644
--- a/crypto/src/crypto/signers/StandardDsaEncoding.cs
+++ b/crypto/src/crypto/signers/StandardDsaEncoding.cs
@@ -35,6 +35,23 @@ namespace Org.BouncyCastle.Crypto.Signers
).GetEncoded(Asn1Encodable.Der);
}
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public virtual int Encode(BigInteger n, BigInteger r, BigInteger s, Span<byte> output)
+ {
+ byte[] encoding = Encode(n, r, s);
+ encoding.CopyTo(output);
+ return encoding.Length;
+ }
+#endif
+
+ public virtual int GetMaxEncodingSize(BigInteger n)
+ {
+ int encodingLength = BigIntegers.GetByteLength(n);
+ int derIntegerLength = Asn1OutputStream.GetLengthOfDL(encodingLength) + encodingLength;
+ int seqContentsLength = 2 * derIntegerLength;
+ return Asn1OutputStream.GetLengthOfDL(seqContentsLength) + seqContentsLength;
+ }
+
protected virtual BigInteger CheckValue(BigInteger n, BigInteger x)
{
if (x.SignValue < 0 || (null != n && x.CompareTo(n) >= 0))
|