summary refs log tree commit diff
path: root/crypto/src/openpgp/PgpV3SignatureGenerator.cs
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/src/openpgp/PgpV3SignatureGenerator.cs')
-rw-r--r--crypto/src/openpgp/PgpV3SignatureGenerator.cs105
1 files changed, 58 insertions, 47 deletions
diff --git a/crypto/src/openpgp/PgpV3SignatureGenerator.cs b/crypto/src/openpgp/PgpV3SignatureGenerator.cs
index c7113e0ae..324dbd768 100644
--- a/crypto/src/openpgp/PgpV3SignatureGenerator.cs
+++ b/crypto/src/openpgp/PgpV3SignatureGenerator.cs
@@ -1,3 +1,5 @@
+using System;
+
 using Org.BouncyCastle.Crypto;
 using Org.BouncyCastle.Crypto.Parameters;
 using Org.BouncyCastle.Security;
@@ -6,11 +8,11 @@ using Org.BouncyCastle.Utilities.Date;
 namespace Org.BouncyCastle.Bcpg.OpenPgp
 {
 	/// <remarks>Generator for old style PGP V3 Signatures.</remarks>
-	// TODO Should be able to implement ISigner?
 	public class PgpV3SignatureGenerator
     {
-        private PublicKeyAlgorithmTag keyAlgorithm;
-        private HashAlgorithmTag hashAlgorithm;
+        private readonly PublicKeyAlgorithmTag keyAlgorithm;
+        private readonly HashAlgorithmTag hashAlgorithm;
+
         private PgpPrivateKey privKey;
         private ISigner sig;
         private IDigest    dig;
@@ -22,36 +24,40 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
             PublicKeyAlgorithmTag	keyAlgorithm,
             HashAlgorithmTag		hashAlgorithm)
         {
+            if (keyAlgorithm == PublicKeyAlgorithmTag.EdDsa)
+                throw new ArgumentException("Invalid algorithm for V3 signature", nameof(keyAlgorithm));
+
             this.keyAlgorithm = keyAlgorithm;
             this.hashAlgorithm = hashAlgorithm;
 
-            dig = DigestUtilities.GetDigest(PgpUtilities.GetDigestName(hashAlgorithm));
-            sig = SignerUtilities.GetSigner(PgpUtilities.GetSignatureName(keyAlgorithm, hashAlgorithm));
+            dig = PgpUtilities.CreateDigest(hashAlgorithm);
         }
 
 		/// <summary>Initialise the generator for signing.</summary>
-		public void InitSign(
-			int				sigType,
-			PgpPrivateKey	key)
+		public void InitSign(int sigType, PgpPrivateKey privKey)
 		{
-			InitSign(sigType, key, null);
+			InitSign(sigType, privKey, null);
 		}
 
 		/// <summary>Initialise the generator for signing.</summary>
-        public void InitSign(
-            int				sigType,
-            PgpPrivateKey	key,
-			SecureRandom	random)
+        public void InitSign(int sigType, PgpPrivateKey privKey, SecureRandom random)
         {
-            this.privKey = key;
+            this.privKey = privKey;
             this.signatureType = sigType;
 
-			try
+            AsymmetricKeyParameter key = privKey.Key;
+
+            if (sig == null)
             {
-				ICipherParameters cp = key.Key;
+                this.sig = PgpUtilities.CreateSigner(keyAlgorithm, hashAlgorithm, key);
+            }
+
+            try
+            {
+				ICipherParameters cp = key;
 				if (random != null)
 				{
-					cp = new ParametersWithRandom(key.Key, random);
+					cp = new ParametersWithRandom(cp, random);
 				}
 
 				sig.Init(true, cp);
@@ -65,93 +71,98 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
             lastb = 0;
         }
 
-		public void Update(
-            byte b)
+		public void Update(byte b)
         {
             if (signatureType == PgpSignature.CanonicalTextDocument)
             {
-				doCanonicalUpdateByte(b);
+				DoCanonicalUpdateByte(b);
             }
             else
             {
-				doUpdateByte(b);
+				DoUpdateByte(b);
             }
         }
 
-		private void doCanonicalUpdateByte(
-			byte b)
+		private void DoCanonicalUpdateByte(byte b)
 		{
 			if (b == '\r')
 			{
-				doUpdateCRLF();
+				DoUpdateCRLF();
 			}
 			else if (b == '\n')
 			{
 				if (lastb != '\r')
 				{
-					doUpdateCRLF();
+					DoUpdateCRLF();
 				}
 			}
 			else
 			{
-				doUpdateByte(b);
+				DoUpdateByte(b);
 			}
 
 			lastb = b;
 		}
 
-		private void doUpdateCRLF()
+		private void DoUpdateCRLF()
 		{
-			doUpdateByte((byte)'\r');
-			doUpdateByte((byte)'\n');
+			DoUpdateByte((byte)'\r');
+			DoUpdateByte((byte)'\n');
 		}
 
-		private void doUpdateByte(
+		private void DoUpdateByte(
 			byte b)
 		{
 			sig.Update(b);
 			dig.Update(b);
 		}
 
-		public void Update(
-            byte[] b)
+		public void Update(params byte[] b)
+        {
+            Update(b, 0, b.Length);
+        }
+
+		public void Update(byte[] b, int off, int len)
         {
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+            Update(b.AsSpan(off, len));
+#else
             if (signatureType == PgpSignature.CanonicalTextDocument)
             {
-                for (int i = 0; i != b.Length; i++)
+                int finish = off + len;
+
+				for (int i = off; i != finish; i++)
                 {
-                    doCanonicalUpdateByte(b[i]);
+                    DoCanonicalUpdateByte(b[i]);
                 }
             }
             else
             {
-                sig.BlockUpdate(b, 0, b.Length);
-                dig.BlockUpdate(b, 0, b.Length);
+                sig.BlockUpdate(b, off, len);
+                dig.BlockUpdate(b, off, len);
             }
+#endif
         }
 
-		public void Update(
-            byte[]	b,
-            int		off,
-            int		len)
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+        public void Update(ReadOnlySpan<byte> input)
         {
             if (signatureType == PgpSignature.CanonicalTextDocument)
             {
-                int finish = off + len;
-
-				for (int i = off; i != finish; i++)
+                for (int i = 0; i < input.Length; ++i)
                 {
-                    doCanonicalUpdateByte(b[i]);
+                    DoCanonicalUpdateByte(input[i]);
                 }
             }
             else
             {
-                sig.BlockUpdate(b, off, len);
-                dig.BlockUpdate(b, off, len);
+                sig.BlockUpdate(input);
+                dig.BlockUpdate(input);
             }
         }
+#endif
 
-		/// <summary>Return the one pass header associated with the current signature.</summary>
+        /// <summary>Return the one pass header associated with the current signature.</summary>
         public PgpOnePassSignature GenerateOnePassVersion(
             bool isNested)
         {