summary refs log tree commit diff
path: root/crypto/src/bcpg
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/src/bcpg')
-rw-r--r--crypto/src/bcpg/AeadAlgorithmTag.cs11
-rw-r--r--crypto/src/bcpg/AeadEncDataPacket.cs77
-rw-r--r--crypto/src/bcpg/ArmoredInputStream.cs2
-rw-r--r--crypto/src/bcpg/BcpgOutputStream.cs87
-rw-r--r--crypto/src/bcpg/ExperimentalPacket.cs30
-rw-r--r--crypto/src/bcpg/HashAlgorithmTags.cs10
-rw-r--r--crypto/src/bcpg/IBcpgKey.cs1
-rw-r--r--crypto/src/bcpg/IUserDataPacket.cs6
-rw-r--r--crypto/src/bcpg/InputStreamPacket.cs3
-rw-r--r--crypto/src/bcpg/MarkerPacket.cs10
-rw-r--r--crypto/src/bcpg/OnePassSignaturePacket.cs2
-rw-r--r--crypto/src/bcpg/PublicKeyEncSessionPacket.cs2
-rw-r--r--crypto/src/bcpg/PublicKeyPacket.cs5
-rw-r--r--crypto/src/bcpg/PublicSubkeyPacket.cs6
-rw-r--r--crypto/src/bcpg/SecretKeyPacket.cs5
-rw-r--r--crypto/src/bcpg/SecretSubkeyPacket.cs5
-rw-r--r--crypto/src/bcpg/SignaturePacket.cs2
-rw-r--r--crypto/src/bcpg/SignatureSubpacket.cs3
-rw-r--r--crypto/src/bcpg/SymmetricKeyEncSessionPacket.cs2
-rw-r--r--crypto/src/bcpg/TrustPacket.cs13
-rw-r--r--crypto/src/bcpg/UserAttributePacket.cs3
-rw-r--r--crypto/src/bcpg/UserIdPacket.cs37
-rw-r--r--crypto/src/bcpg/sig/SignerUserId.cs38
23 files changed, 210 insertions, 150 deletions
diff --git a/crypto/src/bcpg/AeadAlgorithmTag.cs b/crypto/src/bcpg/AeadAlgorithmTag.cs
new file mode 100644
index 000000000..632f88838
--- /dev/null
+++ b/crypto/src/bcpg/AeadAlgorithmTag.cs
@@ -0,0 +1,11 @@
+using System;
+
+namespace Org.BouncyCastle.Bcpg
+{
+    public enum AeadAlgorithmTag : byte
+    {
+        Eax = 1,    // EAX (IV len: 16 octets, Tag len: 16 octets)
+        Ocb = 2,    // OCB (IV len: 15 octets, Tag len: 16 octets)
+        Gcm = 3,    // GCM (IV len: 12 octets, Tag len: 16 octets)
+    }
+}
diff --git a/crypto/src/bcpg/AeadEncDataPacket.cs b/crypto/src/bcpg/AeadEncDataPacket.cs
new file mode 100644
index 000000000..2c7ec97f6
--- /dev/null
+++ b/crypto/src/bcpg/AeadEncDataPacket.cs
@@ -0,0 +1,77 @@
+using System;
+
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Bcpg
+{
+    /**
+     * Packet representing AEAD encrypted data. At the moment this appears to exist in the following
+     * expired draft only, but it's appearing despite this.
+     *
+     * @ref https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-rfc4880bis-04#section-5.16
+     */
+    public class AeadEncDataPacket
+        : InputStreamPacket
+    {
+        private readonly byte m_version;
+        private readonly SymmetricKeyAlgorithmTag m_algorithm;
+        private readonly AeadAlgorithmTag m_aeadAlgorithm;
+        private readonly byte m_chunkSize;
+        private readonly byte[] m_iv;
+
+        public AeadEncDataPacket(BcpgInputStream bcpgIn)
+            : base(bcpgIn)
+        {
+            m_version = (byte)bcpgIn.ReadByte();
+            if (m_version != 1)
+                throw new ArgumentException("wrong AEAD packet version: " + m_version);
+
+            m_algorithm = (SymmetricKeyAlgorithmTag)bcpgIn.ReadByte();
+            m_aeadAlgorithm = (AeadAlgorithmTag)bcpgIn.ReadByte();
+            m_chunkSize = (byte)bcpgIn.ReadByte();
+
+            m_iv = new byte[GetIVLength(m_aeadAlgorithm)];
+            bcpgIn.ReadFully(m_iv);
+        }
+
+        public AeadEncDataPacket(SymmetricKeyAlgorithmTag algorithm, AeadAlgorithmTag aeadAlgorithm, int chunkSize,
+            byte[] iv)
+            : base(null)
+        {
+            m_version = 1;
+            m_algorithm = algorithm;
+            m_aeadAlgorithm = aeadAlgorithm;
+            m_chunkSize = (byte)chunkSize;
+            m_iv = Arrays.Clone(iv);
+        }
+
+        public byte Version => m_version;
+
+        public SymmetricKeyAlgorithmTag Algorithm => m_algorithm;
+
+        public AeadAlgorithmTag AeadAlgorithm => m_aeadAlgorithm;
+
+        public int ChunkSize => m_chunkSize;
+
+        public byte[] GetIV()
+        {
+            return m_iv;
+        }
+
+        public static int GetIVLength(AeadAlgorithmTag aeadAlgorithm)
+        {
+            switch (aeadAlgorithm)
+            {
+            case AeadAlgorithmTag.Eax:
+                return 16;
+            case AeadAlgorithmTag.Ocb:
+                return 15;
+            case AeadAlgorithmTag.Gcm:
+                return 12;
+            default:
+                throw new ArgumentException("unknown mode: " + aeadAlgorithm);
+            }
+        }
+    }
+}
diff --git a/crypto/src/bcpg/ArmoredInputStream.cs b/crypto/src/bcpg/ArmoredInputStream.cs
index b493d04fc..eacba17dd 100644
--- a/crypto/src/bcpg/ArmoredInputStream.cs
+++ b/crypto/src/bcpg/ArmoredInputStream.cs
@@ -304,7 +304,7 @@ namespace Org.BouncyCastle.Bcpg
             {
                 c = input.ReadByte();
             }
-            while (c == ' ' || c == '\t' || c == '\f' || c == '\u000B'); // \u000B ~ \v
+            while (c == ' ' || c == '\t' || c == '\f' || c == '\v');
 
             if (c >= 128)
                 throw new IOException("invalid armor");
diff --git a/crypto/src/bcpg/BcpgOutputStream.cs b/crypto/src/bcpg/BcpgOutputStream.cs
index 3bae7e383..29ed9e22a 100644
--- a/crypto/src/bcpg/BcpgOutputStream.cs
+++ b/crypto/src/bcpg/BcpgOutputStream.cs
@@ -19,6 +19,7 @@ namespace Org.BouncyCastle.Bcpg
 		}
 
 		private Stream outStr;
+        private bool useOldFormat;
         private byte[] partialBuffer;
         private int partialBufferLength;
         private int partialPower;
@@ -27,26 +28,28 @@ namespace Org.BouncyCastle.Bcpg
 
 		/// <summary>Create a stream representing a general packet.</summary>
 		/// <param name="outStr">Output stream to write to.</param>
-		public BcpgOutputStream(
-            Stream outStr)
+		public BcpgOutputStream(Stream outStr)
+            : this(outStr, false)
         {
-			if (outStr == null)
-				throw new ArgumentNullException("outStr");
-
-			this.outStr = outStr;
         }
 
-		/// <summary>Create a stream representing an old style partial object.</summary>
+        /// <summary>Base constructor specifying whether or not to use packets in the new format wherever possible.
+        /// </summary>
 		/// <param name="outStr">Output stream to write to.</param>
-		/// <param name="tag">The packet tag for the object.</param>
-        public BcpgOutputStream(
-            Stream		outStr,
-            PacketTag	tag)
+        /// <param name="newFormatOnly"><c>true</c> if use new format packets, <c>false</c> if backwards compatible
+        /// preferred.</param>
+        public BcpgOutputStream(Stream outStr, bool newFormatOnly)
         {
-			if (outStr == null)
-				throw new ArgumentNullException("outStr");
+            this.outStr = outStr ?? throw new ArgumentNullException(nameof(outStr));
+            this.useOldFormat = !newFormatOnly;
+        }
 
-			this.outStr = outStr;
+        /// <summary>Create a stream representing an old style partial object.</summary>
+        /// <param name="outStr">Output stream to write to.</param>
+        /// <param name="tag">The packet tag for the object.</param>
+        public BcpgOutputStream(Stream outStr, PacketTag tag)
+        {
+            this.outStr = outStr ?? throw new ArgumentNullException(nameof(outStr));
             this.WriteHeader(tag, true, true, 0);
         }
 
@@ -55,16 +58,9 @@ namespace Org.BouncyCastle.Bcpg
 		/// <param name="tag">Packet tag.</param>
 		/// <param name="length">Size of chunks making up the packet.</param>
 		/// <param name="oldFormat">If true, the header is written out in old format.</param>
-		public BcpgOutputStream(
-            Stream		outStr,
-            PacketTag	tag,
-            long		length,
-            bool		oldFormat)
+		public BcpgOutputStream(Stream outStr, PacketTag tag, long length, bool oldFormat)
         {
-			if (outStr == null)
-				throw new ArgumentNullException("outStr");
-
-			this.outStr = outStr;
+            this.outStr = outStr ?? throw new ArgumentNullException(nameof(outStr));
 
             if (length > 0xFFFFFFFFL)
             {
@@ -84,15 +80,9 @@ namespace Org.BouncyCastle.Bcpg
 		/// <param name="outStr">Output stream to write to.</param>
 		/// <param name="tag">Packet tag.</param>
 		/// <param name="length">Size of chunks making up the packet.</param>
-		public BcpgOutputStream(
-            Stream		outStr,
-            PacketTag	tag,
-            long		length)
+		public BcpgOutputStream(Stream outStr, PacketTag tag, long length)
         {
-			if (outStr == null)
-				throw new ArgumentNullException("outStr");
-
-            this.outStr = outStr;
+            this.outStr = outStr ?? throw new ArgumentNullException(nameof(outStr));
             this.WriteHeader(tag, false, false, length);
         }
 
@@ -100,15 +90,9 @@ namespace Org.BouncyCastle.Bcpg
 		/// <param name="outStr">Output stream to write to.</param>
 		/// <param name="tag">Packet tag.</param>
 		/// <param name="buffer">Buffer to use for collecting chunks.</param>
-        public BcpgOutputStream(
-            Stream		outStr,
-            PacketTag	tag,
-            byte[]		buffer)
+        public BcpgOutputStream(Stream outStr, PacketTag tag, byte[] buffer)
         {
-			if (outStr == null)
-				throw new ArgumentNullException("outStr");
-
-            this.outStr = outStr;
+            this.outStr = outStr ?? throw new ArgumentNullException(nameof(outStr));
             this.WriteHeader(tag, false, true, 0);
 
 			this.partialBuffer = buffer;
@@ -120,15 +104,13 @@ namespace Org.BouncyCastle.Bcpg
             }
 
 			if (partialPower > 30)
-            {
                 throw new IOException("Buffer cannot be greater than 2^30 in length.");
-            }
+
             this.partialBufferLength = 1 << partialPower;
             this.partialOffset = 0;
         }
 
-		private void WriteNewPacketLength(
-            long bodyLen)
+		private void WriteNewPacketLength(long bodyLen)
         {
             if (bodyLen < 192)
             {
@@ -378,29 +360,28 @@ namespace Org.BouncyCastle.Bcpg
 				(byte)n);
 		}
 
-		public void WritePacket(
-            ContainedPacket p)
+		public void WritePacket(ContainedPacket p)
         {
             p.Encode(this);
         }
 
-        internal void WritePacket(
-            PacketTag	tag,
-            byte[]		body,
-            bool		oldFormat)
+        internal void WritePacket(PacketTag tag, byte[] body)
+        {
+            WritePacket(tag, body, useOldFormat);
+        }
+
+        internal void WritePacket(PacketTag tag, byte[] body, bool oldFormat)
         {
             this.WriteHeader(tag, oldFormat, false, body.Length);
             this.Write(body);
         }
 
-		public void WriteObject(
-            BcpgObject bcpgObject)
+		public void WriteObject(BcpgObject bcpgObject)
         {
             bcpgObject.Encode(this);
         }
 
-		public void WriteObjects(
-			params BcpgObject[] v)
+		public void WriteObjects(params BcpgObject[] v)
 		{
 			foreach (BcpgObject o in v)
 			{
diff --git a/crypto/src/bcpg/ExperimentalPacket.cs b/crypto/src/bcpg/ExperimentalPacket.cs
index 36a254be1..3d413db09 100644
--- a/crypto/src/bcpg/ExperimentalPacket.cs
+++ b/crypto/src/bcpg/ExperimentalPacket.cs
@@ -5,34 +5,24 @@ namespace Org.BouncyCastle.Bcpg
 {
 	/// <remarks>Basic packet for an experimental packet.</remarks>
     public class ExperimentalPacket
-        : ContainedPacket //, PublicKeyAlgorithmTag
+        : ContainedPacket
     {
-        private readonly PacketTag	tag;
-        private readonly byte[]		contents;
+        private readonly PacketTag m_tag;
+        private readonly byte[] m_contents;
 
-		internal ExperimentalPacket(
-            PacketTag		tag,
-            BcpgInputStream	bcpgIn)
+		internal ExperimentalPacket(PacketTag tag, BcpgInputStream bcpgIn)
         {
-            this.tag = tag;
-
-			this.contents = bcpgIn.ReadAll();
+            m_tag = tag;
+			m_contents = bcpgIn.ReadAll();
         }
 
-		public PacketTag Tag
-        {
-			get { return tag; }
-        }
+		public PacketTag Tag => m_tag;
 
-		public byte[] GetContents()
-        {
-			return (byte[]) contents.Clone();
-        }
+		public byte[] GetContents() => (byte[])m_contents.Clone();
 
-		public override void Encode(
-            BcpgOutputStream bcpgOut)
+		public override void Encode(BcpgOutputStream bcpgOut)
         {
-            bcpgOut.WritePacket(tag, contents, true);
+            bcpgOut.WritePacket(m_tag, m_contents);
         }
     }
 }
diff --git a/crypto/src/bcpg/HashAlgorithmTags.cs b/crypto/src/bcpg/HashAlgorithmTags.cs
index 96c009153..a13725de6 100644
--- a/crypto/src/bcpg/HashAlgorithmTags.cs
+++ b/crypto/src/bcpg/HashAlgorithmTags.cs
@@ -15,5 +15,15 @@ namespace Org.BouncyCastle.Bcpg
 		Sha384 = 9,			// SHA-384
 		Sha512 = 10,		// SHA-512
 		Sha224 = 11,		// SHA-224
+		Sha3_256 = 12,		// SHA3-256
+		Sha3_512 = 14,		// SHA3-512
+
+		MD4 = 301,
+		Sha3_224 = 312,		// SHA3-224
+		Sha3_256_Old = 313,	//SHA3-256
+		Sha3_384 = 314,		// SHA3-384
+		Sha3_512_Old = 315, // SHA3-512
+
+		SM3 = 326,			// SM3
 	}
 }
diff --git a/crypto/src/bcpg/IBcpgKey.cs b/crypto/src/bcpg/IBcpgKey.cs
index 275461772..86832eb8b 100644
--- a/crypto/src/bcpg/IBcpgKey.cs
+++ b/crypto/src/bcpg/IBcpgKey.cs
@@ -2,6 +2,7 @@ using System;
 
 namespace Org.BouncyCastle.Bcpg
 {
+	// TODO[api] Extend IEncodable
 	/// <remarks>Base interface for a PGP key.</remarks>
     public interface IBcpgKey
     {
diff --git a/crypto/src/bcpg/IUserDataPacket.cs b/crypto/src/bcpg/IUserDataPacket.cs
new file mode 100644
index 000000000..1519b5007
--- /dev/null
+++ b/crypto/src/bcpg/IUserDataPacket.cs
@@ -0,0 +1,6 @@
+namespace Org.BouncyCastle.Bcpg
+{
+    public interface IUserDataPacket
+    {
+    }
+}
diff --git a/crypto/src/bcpg/InputStreamPacket.cs b/crypto/src/bcpg/InputStreamPacket.cs
index c45efab7b..d4946ebf2 100644
--- a/crypto/src/bcpg/InputStreamPacket.cs
+++ b/crypto/src/bcpg/InputStreamPacket.cs
@@ -5,8 +5,7 @@ namespace Org.BouncyCastle.Bcpg
     {
         private readonly BcpgInputStream bcpgIn;
 
-		public InputStreamPacket(
-            BcpgInputStream bcpgIn)
+		public InputStreamPacket(BcpgInputStream bcpgIn)
         {
             this.bcpgIn = bcpgIn;
         }
diff --git a/crypto/src/bcpg/MarkerPacket.cs b/crypto/src/bcpg/MarkerPacket.cs
index 4dc4b5a83..f2c450793 100644
--- a/crypto/src/bcpg/MarkerPacket.cs
+++ b/crypto/src/bcpg/MarkerPacket.cs
@@ -7,18 +7,16 @@ namespace Org.BouncyCastle.Bcpg
         : ContainedPacket
     {
         // "PGP"
-        byte[] marker = { (byte)0x50, (byte)0x47, (byte)0x50 };
+        private readonly byte[] marker = { (byte)0x50, (byte)0x47, (byte)0x50 };
 
-        public MarkerPacket(
-            BcpgInputStream bcpgIn)
+        public MarkerPacket(BcpgInputStream bcpgIn)
         {
             bcpgIn.ReadFully(marker);
         }
 
-        public override void Encode(
-            BcpgOutputStream bcpgOut)
+        public override void Encode(BcpgOutputStream bcpgOut)
         {
-            bcpgOut.WritePacket(PacketTag.Marker, marker, true);
+            bcpgOut.WritePacket(PacketTag.Marker, marker);
         }
     }
 }
diff --git a/crypto/src/bcpg/OnePassSignaturePacket.cs b/crypto/src/bcpg/OnePassSignaturePacket.cs
index 70f0a2207..4efae1d63 100644
--- a/crypto/src/bcpg/OnePassSignaturePacket.cs
+++ b/crypto/src/bcpg/OnePassSignaturePacket.cs
@@ -81,7 +81,7 @@ namespace Org.BouncyCastle.Bcpg
 				pOut.WriteByte((byte)nested);
 			}
 
-			bcpgOut.WritePacket(PacketTag.OnePassSignature, bOut.ToArray(), true);
+			bcpgOut.WritePacket(PacketTag.OnePassSignature, bOut.ToArray());
 		}
 	}
 }
diff --git a/crypto/src/bcpg/PublicKeyEncSessionPacket.cs b/crypto/src/bcpg/PublicKeyEncSessionPacket.cs
index f0b1577ec..25d297890 100644
--- a/crypto/src/bcpg/PublicKeyEncSessionPacket.cs
+++ b/crypto/src/bcpg/PublicKeyEncSessionPacket.cs
@@ -105,7 +105,7 @@ namespace Org.BouncyCastle.Bcpg
 				}
 			}
 
-			bcpgOut.WritePacket(PacketTag.PublicKeyEncryptedSession, bOut.ToArray(), true);
+			bcpgOut.WritePacket(PacketTag.PublicKeyEncryptedSession, bOut.ToArray());
 		}
 	}
 }
diff --git a/crypto/src/bcpg/PublicKeyPacket.cs b/crypto/src/bcpg/PublicKeyPacket.cs
index 40c696a37..b3b5d1600 100644
--- a/crypto/src/bcpg/PublicKeyPacket.cs
+++ b/crypto/src/bcpg/PublicKeyPacket.cs
@@ -115,10 +115,9 @@ namespace Org.BouncyCastle.Bcpg
             return bOut.ToArray();
         }
 
-        public override void Encode(
-            BcpgOutputStream bcpgOut)
+        public override void Encode(BcpgOutputStream bcpgOut)
         {
-            bcpgOut.WritePacket(PacketTag.PublicKey, GetEncodedContents(), true);
+            bcpgOut.WritePacket(PacketTag.PublicKey, GetEncodedContents());
         }
     }
 }
diff --git a/crypto/src/bcpg/PublicSubkeyPacket.cs b/crypto/src/bcpg/PublicSubkeyPacket.cs
index 6e1aeda98..0e1065b72 100644
--- a/crypto/src/bcpg/PublicSubkeyPacket.cs
+++ b/crypto/src/bcpg/PublicSubkeyPacket.cs
@@ -1,5 +1,6 @@
 using System;
 using System.IO;
+
 namespace Org.BouncyCastle.Bcpg
 {
 	/// <remarks>Basic packet for a PGP public subkey</remarks>
@@ -21,10 +22,9 @@ namespace Org.BouncyCastle.Bcpg
         {
         }
 
-		public override void Encode(
-            BcpgOutputStream bcpgOut)
+		public override void Encode(BcpgOutputStream bcpgOut)
         {
-            bcpgOut.WritePacket(PacketTag.PublicSubkey, GetEncodedContents(), true);
+            bcpgOut.WritePacket(PacketTag.PublicSubkey, GetEncodedContents());
         }
     }
 }
diff --git a/crypto/src/bcpg/SecretKeyPacket.cs b/crypto/src/bcpg/SecretKeyPacket.cs
index d9ceab4f1..1bc684a69 100644
--- a/crypto/src/bcpg/SecretKeyPacket.cs
+++ b/crypto/src/bcpg/SecretKeyPacket.cs
@@ -161,10 +161,9 @@ namespace Org.BouncyCastle.Bcpg
             return bOut.ToArray();
         }
 
-        public override void Encode(
-            BcpgOutputStream bcpgOut)
+        public override void Encode(BcpgOutputStream bcpgOut)
         {
-            bcpgOut.WritePacket(PacketTag.SecretKey, GetEncodedContents(), true);
+            bcpgOut.WritePacket(PacketTag.SecretKey, GetEncodedContents());
         }
     }
 }
diff --git a/crypto/src/bcpg/SecretSubkeyPacket.cs b/crypto/src/bcpg/SecretSubkeyPacket.cs
index 8f1746942..2d405aec2 100644
--- a/crypto/src/bcpg/SecretSubkeyPacket.cs
+++ b/crypto/src/bcpg/SecretSubkeyPacket.cs
@@ -34,10 +34,9 @@ namespace Org.BouncyCastle.Bcpg
 		{
 		}
 
-		public override void Encode(
-			BcpgOutputStream bcpgOut)
+		public override void Encode(BcpgOutputStream bcpgOut)
         {
-            bcpgOut.WritePacket(PacketTag.SecretSubkey, GetEncodedContents(), true);
+            bcpgOut.WritePacket(PacketTag.SecretSubkey, GetEncodedContents());
         }
     }
 }
diff --git a/crypto/src/bcpg/SignaturePacket.cs b/crypto/src/bcpg/SignaturePacket.cs
index 09e6b059d..99ca7df40 100644
--- a/crypto/src/bcpg/SignaturePacket.cs
+++ b/crypto/src/bcpg/SignaturePacket.cs
@@ -392,7 +392,7 @@ namespace Org.BouncyCastle.Bcpg
                 }
             }
 
-			bcpgOut.WritePacket(PacketTag.Signature, bOut.ToArray(), true);
+			bcpgOut.WritePacket(PacketTag.Signature, bOut.ToArray());
         }
 
 		private static void EncodeLengthAndData(
diff --git a/crypto/src/bcpg/SignatureSubpacket.cs b/crypto/src/bcpg/SignatureSubpacket.cs
index c2186f373..f7f82b2a6 100644
--- a/crypto/src/bcpg/SignatureSubpacket.cs
+++ b/crypto/src/bcpg/SignatureSubpacket.cs
@@ -103,8 +103,7 @@ namespace Org.BouncyCastle.Bcpg
             if (obj == this)
                 return true;
 
-            SignatureSubpacket other = obj as SignatureSubpacket;
-            if (null == other)
+            if (!(obj is SignatureSubpacket other))
                 return false;
 
             return this.type == other.type
diff --git a/crypto/src/bcpg/SymmetricKeyEncSessionPacket.cs b/crypto/src/bcpg/SymmetricKeyEncSessionPacket.cs
index 85bcc2874..901088e33 100644
--- a/crypto/src/bcpg/SymmetricKeyEncSessionPacket.cs
+++ b/crypto/src/bcpg/SymmetricKeyEncSessionPacket.cs
@@ -82,7 +82,7 @@ namespace Org.BouncyCastle.Bcpg
                 }
             }
 
-			bcpgOut.WritePacket(PacketTag.SymmetricKeyEncryptedSessionKey, bOut.ToArray(), true);
+			bcpgOut.WritePacket(PacketTag.SymmetricKeyEncryptedSessionKey, bOut.ToArray());
         }
     }
 }
diff --git a/crypto/src/bcpg/TrustPacket.cs b/crypto/src/bcpg/TrustPacket.cs
index 6f1969c2a..a2a30177f 100644
--- a/crypto/src/bcpg/TrustPacket.cs
+++ b/crypto/src/bcpg/TrustPacket.cs
@@ -9,8 +9,7 @@ namespace Org.BouncyCastle.Bcpg
     {
         private readonly byte[] levelAndTrustAmount;
 
-		public TrustPacket(
-            BcpgInputStream bcpgIn)
+		public TrustPacket(BcpgInputStream bcpgIn)
         {
             MemoryStream bOut = new MemoryStream();
 
@@ -23,10 +22,9 @@ namespace Org.BouncyCastle.Bcpg
 			levelAndTrustAmount = bOut.ToArray();
         }
 
-		public TrustPacket(
-            int trustCode)
+		public TrustPacket(int trustCode)
         {
-			this.levelAndTrustAmount = new byte[]{ (byte) trustCode };
+			this.levelAndTrustAmount = new byte[]{ (byte)trustCode };
         }
 
 		public byte[] GetLevelAndTrustAmount()
@@ -34,10 +32,9 @@ namespace Org.BouncyCastle.Bcpg
 			return (byte[]) levelAndTrustAmount.Clone();
 		}
 
-		public override void Encode(
-            BcpgOutputStream bcpgOut)
+		public override void Encode(BcpgOutputStream bcpgOut)
         {
-            bcpgOut.WritePacket(PacketTag.Trust, levelAndTrustAmount, true);
+            bcpgOut.WritePacket(PacketTag.Trust, levelAndTrustAmount);
         }
     }
 }
diff --git a/crypto/src/bcpg/UserAttributePacket.cs b/crypto/src/bcpg/UserAttributePacket.cs
index 861f62f5d..0be24e006 100644
--- a/crypto/src/bcpg/UserAttributePacket.cs
+++ b/crypto/src/bcpg/UserAttributePacket.cs
@@ -37,8 +37,7 @@ namespace Org.BouncyCastle.Bcpg
             return subpackets;
         }
 
-        public override void Encode(
-            BcpgOutputStream bcpgOut)
+        public override void Encode(BcpgOutputStream bcpgOut)
         {
             MemoryStream bOut = new MemoryStream();
 
diff --git a/crypto/src/bcpg/UserIdPacket.cs b/crypto/src/bcpg/UserIdPacket.cs
index a175e74a6..7d3d3a846 100644
--- a/crypto/src/bcpg/UserIdPacket.cs
+++ b/crypto/src/bcpg/UserIdPacket.cs
@@ -1,37 +1,56 @@
 using System;
 using System.Text;
 
+using Org.BouncyCastle.Utilities;
+
 namespace Org.BouncyCastle.Bcpg
 {
     /**
     * Basic type for a user ID packet.
     */
     public class UserIdPacket
-        : ContainedPacket
+        : ContainedPacket, IUserDataPacket
     {
         private readonly byte[] idData;
 
-        public UserIdPacket(
-            BcpgInputStream bcpgIn)
+        public UserIdPacket(BcpgInputStream bcpgIn)
         {
             this.idData = bcpgIn.ReadAll();
         }
 
-		public UserIdPacket(
-			string id)
+		public UserIdPacket(string id)
         {
             this.idData = Encoding.UTF8.GetBytes(id);
         }
 
-		public string GetId()
+        public UserIdPacket(byte[] rawId)
+        {
+            this.idData = Arrays.Clone(rawId);
+        }
+
+        public string GetId()
         {
 			return Encoding.UTF8.GetString(idData, 0, idData.Length);
         }
 
-		public override void Encode(
-            BcpgOutputStream bcpgOut)
+        public byte[] GetRawId() => Arrays.Clone(idData);
+
+        public override bool Equals(object obj)
+        {
+            if (!(obj is UserIdPacket other))
+                return false;
+
+            return Arrays.AreEqual(this.idData, other.idData);
+        }
+
+        public override int GetHashCode()
+        {
+            return Arrays.GetHashCode(this.idData);
+        }
+
+        public override void Encode(BcpgOutputStream bcpgOut)
         {
-            bcpgOut.WritePacket(PacketTag.UserId, idData, true);
+            bcpgOut.WritePacket(PacketTag.UserId, idData);
         }
     }
 }
diff --git a/crypto/src/bcpg/sig/SignerUserId.cs b/crypto/src/bcpg/sig/SignerUserId.cs
index 6f812e210..bfa00d078 100644
--- a/crypto/src/bcpg/sig/SignerUserId.cs
+++ b/crypto/src/bcpg/sig/SignerUserId.cs
@@ -1,3 +1,5 @@
+using Org.BouncyCastle.Utilities;
+
 namespace Org.BouncyCastle.Bcpg.Sig
 {
     /**
@@ -6,44 +8,18 @@ namespace Org.BouncyCastle.Bcpg.Sig
     public class SignerUserId
         : SignatureSubpacket
     {
-        private static byte[] UserIdToBytes(
-            string id)
-        {
-            byte[] idData = new byte[id.Length];
-
-            for (int i = 0; i != id.Length; i++)
-            {
-                idData[i] = (byte)id[i];
-            }
-
-			return idData;
-        }
-
-        public SignerUserId(
-            bool    critical,
-            bool    isLongLength,
-            byte[]  data)
+        public SignerUserId(bool critical, bool isLongLength, byte[] data)
             : base(SignatureSubpacketTag.SignerUserId, critical, isLongLength, data)
 		{
 		}
 
-        public SignerUserId(
-            bool    critical,
-            string  userId)
-            : base(SignatureSubpacketTag.SignerUserId, critical, false, UserIdToBytes(userId))
+        public SignerUserId(bool critical, string userId)
+            : base(SignatureSubpacketTag.SignerUserId, critical, false, Strings.ToUtf8ByteArray(userId))
 		{
         }
 
-        public string GetId()
-        {
-            char[] chars = new char[data.Length];
-
-			for (int i = 0; i != chars.Length; i++)
-            {
-                chars[i] = (char)(data[i] & 0xff);
-            }
+        public string GetId() => Strings.FromUtf8ByteArray(data);
 
-			return new string(chars);
-        }
+        public byte[] GetRawId() => Arrays.Clone(data);
     }
 }