summary refs log tree commit diff
path: root/crypto/src/openpgp/PgpSignature.cs
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2023-02-28 18:49:21 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2023-02-28 18:49:21 +0700
commit5ac39b19f346e72005f41f13ff956f4fa7c97f86 (patch)
tree0ca4585a968a8b11044267b0268d3e65f29fa559 /crypto/src/openpgp/PgpSignature.cs
parentUpdate Asn1Tags (diff)
downloadBouncyCastle.NET-ed25519-5ac39b19f346e72005f41f13ff956f4fa7c97f86.tar.xz
OpenPGP updates from bc-java
Diffstat (limited to 'crypto/src/openpgp/PgpSignature.cs')
-rw-r--r--crypto/src/openpgp/PgpSignature.cs105
1 files changed, 76 insertions, 29 deletions
diff --git a/crypto/src/openpgp/PgpSignature.cs b/crypto/src/openpgp/PgpSignature.cs
index 9b596f279..d1146183a 100644
--- a/crypto/src/openpgp/PgpSignature.cs
+++ b/crypto/src/openpgp/PgpSignature.cs
@@ -1,4 +1,5 @@
 using System;
+using System.Collections.Generic;
 using System.IO;
 
 using Org.BouncyCastle.Asn1;
@@ -38,6 +39,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
         public const int SubkeyRevocation = 0x28;
         public const int CertificationRevocation = 0x30;
         public const int Timestamp = 0x40;
+        public const int ThirdPartyConfirmation = 0x50;
 
         private readonly SignaturePacket	sigPck;
         private readonly int				signatureType;
@@ -52,8 +54,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
         {
         }
 
-		internal PgpSignature(
-            SignaturePacket sigPacket)
+		internal PgpSignature(SignaturePacket sigPacket)
 			: this(sigPacket, null)
         {
         }
@@ -83,6 +84,12 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
 			get { return sigPck.HashAlgorithm; }
 		}
 
+        /// <summary>Return the digest prefix of the signature.</summary>
+        public byte[] GetDigestPrefix()
+        {
+            return sigPck.GetFingerprint();
+        }
+
         /// <summary>Return true if this signature represents a certification.</summary>
         public bool IsCertification()
         {
@@ -194,14 +201,13 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
         public bool Verify()
         {
             byte[] trailer = GetSignatureTrailer();
+
             sig.BlockUpdate(trailer, 0, trailer.Length);
 
 			return sig.VerifySignature(GetSignature());
         }
 
-		private void UpdateWithIdData(
-			int		header,
-			byte[]	idBytes)
+		private void UpdateWithIdData(int header, byte[] idBytes)
 		{
 			this.Update(
 				(byte) header,
@@ -212,8 +218,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
 			this.Update(idBytes);
 		}
 
-		private void UpdateWithPublicKey(
-			PgpPublicKey key)
+		private void UpdateWithPublicKey(PgpPublicKey key)
 		{
 			byte[] keyBytes = GetEncodedPublicKey(key);
 
@@ -231,9 +236,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
 		/// <param name="userAttributes">User attributes the key was stored under.</param>
 		/// <param name="key">The key to be verified.</param>
 		/// <returns>True, if the signature matches, false otherwise.</returns>
-		public bool VerifyCertification(
-			PgpUserAttributeSubpacketVector	userAttributes,
-			PgpPublicKey					key)
+		public bool VerifyCertification(PgpUserAttributeSubpacketVector	userAttributes, PgpPublicKey key)
 		{
 			UpdateWithPublicKey(key);
 
@@ -254,9 +257,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
 				throw new PgpException("cannot encode subpacket array", e);
 			}
 
-			this.Update(sigPck.GetSignatureTrailer());
-
-			return sig.VerifySignature(GetSignature());
+			return Verify();
 		}
 
 		/// <summary>
@@ -266,9 +267,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
 		/// <param name="id">ID the key was stored under.</param>
 		/// <param name="key">The key to be verified.</param>
 		/// <returns>True, if the signature matches, false otherwise.</returns>
-        public bool VerifyCertification(
-            string			id,
-            PgpPublicKey	key)
+        public bool VerifyCertification(string id, PgpPublicKey key)
         {
 			UpdateWithPublicKey(key);
 
@@ -277,9 +276,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
             //
             UpdateWithIdData(0xb4, Strings.ToUtf8ByteArray(id));
 
-			Update(sigPck.GetSignatureTrailer());
-
-			return sig.VerifySignature(GetSignature());
+            return Verify();
         }
 
 		/// <summary>Verify a certification for the passed in key against the passed in master key.</summary>
@@ -293,9 +290,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
 			UpdateWithPublicKey(masterKey);
 			UpdateWithPublicKey(pubKey);
 
-			Update(sigPck.GetSignatureTrailer());
-
-			return sig.VerifySignature(GetSignature());
+			return Verify();
         }
 
 		/// <summary>Verify a key certification, such as revocation, for the passed in key.</summary>
@@ -312,9 +307,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
 
 			UpdateWithPublicKey(pubKey);
 
-            Update(sigPck.GetSignatureTrailer());
-
-			return sig.VerifySignature(GetSignature());
+			return Verify();
         }
 
 		public int SignatureType
@@ -438,13 +431,28 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
 			return bOut.ToArray();
         }
 
-		public void Encode(Stream outStream)
+        public void Encode(Stream outStream)
         {
-            var bcpgOut = BcpgOutputStream.Wrap(outStream);
+            Encode(outStream, false);
+        }
 
-			bcpgOut.WritePacket(sigPck);
+        /**
+         * Encode the signature to outStream, with trust packets stripped out if forTransfer is true.
+         *
+         * @param outStream   stream to write the key encoding to.
+         * @param forTransfer if the purpose of encoding is to send key to other users.
+         * @throws IOException in case of encoding error.
+         */
+        public void Encode(Stream outStream, bool forTransfer)
+        {
+            // Exportable signatures MUST NOT be exported if forTransfer==true
+            if (forTransfer && (!GetHashedSubPackets().IsExportable() || !GetUnhashedSubPackets().IsExportable()))
+                return;
 
-			if (trustPck != null)
+            var bcpgOut = BcpgOutputStream.Wrap(outStream);
+
+            bcpgOut.WritePacket(sigPck);
+            if (!forTransfer && trustPck != null)
             {
                 bcpgOut.WritePacket(trustPck);
             }
@@ -480,5 +488,44 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
                 return false;
             }
         }
+
+        public static bool IsSignatureEncodingEqual(PgpSignature sig1, PgpSignature sig2)
+        {
+            return Arrays.AreEqual(sig1.sigPck.GetSignatureBytes(), sig2.sigPck.GetSignatureBytes());
+        }
+
+        public static PgpSignature Join(PgpSignature sig1, PgpSignature sig2)
+        {
+            if (!IsSignatureEncodingEqual(sig1, sig2))
+                throw new ArgumentException("These are different signatures.");
+
+            // merge unhashed subpackets
+            SignatureSubpacket[] sig1Unhashed = sig1.GetUnhashedSubPackets().ToSubpacketArray();
+            SignatureSubpacket[] sig2Unhashed = sig2.GetUnhashedSubPackets().ToSubpacketArray();
+
+            var merged = new List<SignatureSubpacket>(sig1Unhashed);
+
+            foreach (var subpacket in sig2Unhashed)
+            {
+                if (!merged.Contains(subpacket))
+                {
+                    merged.Add(subpacket);
+                }
+            }
+
+            SignatureSubpacket[] unhashed = merged.ToArray();
+            return new PgpSignature(
+                new SignaturePacket(
+                    sig1.SignatureType,
+                    sig1.KeyId,
+                    sig1.KeyAlgorithm,
+                    sig1.HashAlgorithm,
+                    sig1.GetHashedSubPackets().ToSubpacketArray(),
+                    unhashed,
+                    sig1.GetDigestPrefix(),
+                    sig1.sigPck.GetSignature()
+                )
+            );
+        }
     }
 }