summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--crypto/src/crypto/signers/IDsaEncoding.cs6
-rw-r--r--crypto/src/crypto/signers/PlainDsaEncoding.cs29
-rw-r--r--crypto/src/crypto/signers/StandardDsaEncoding.cs17
3 files changed, 52 insertions, 0 deletions
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))