<PackageReference Include="BouncyCastle.Cryptography" Version="2.6.0" />

SignaturePacket

using Org.BouncyCastle.Bcpg.Sig; using Org.BouncyCastle.Crypto.Utilities; using Org.BouncyCastle.Utilities; using Org.BouncyCastle.Utilities.Date; using Org.BouncyCastle.Utilities.IO; using System; using System.Collections.Generic; using System.IO; namespace Org.BouncyCastle.Bcpg { public class SignaturePacket : ContainedPacket { private int version; private int signatureType; private long creationTime; private long keyId; private PublicKeyAlgorithmTag keyAlgorithm; private HashAlgorithmTag hashAlgorithm; private MPInteger[] signature; private byte[] fingerprint; private SignatureSubpacket[] hashedData; private SignatureSubpacket[] unhashedData; private byte[] signatureEncoding; public int Version => version; public int SignatureType => signatureType; public long KeyId => keyId; public PublicKeyAlgorithmTag KeyAlgorithm => keyAlgorithm; public HashAlgorithmTag HashAlgorithm => hashAlgorithm; public long CreationTime => creationTime; internal SignaturePacket(BcpgInputStream bcpgIn) { version = bcpgIn.RequireByte(); if (version == 3 || version == 2) { bcpgIn.RequireByte(); signatureType = bcpgIn.RequireByte(); creationTime = (long)StreamUtilities.RequireUInt32BE(bcpgIn) * 1000; keyId = (long)StreamUtilities.RequireUInt64BE(bcpgIn); keyAlgorithm = (PublicKeyAlgorithmTag)bcpgIn.RequireByte(); hashAlgorithm = (HashAlgorithmTag)bcpgIn.RequireByte(); } else { if (version != 4) { Streams.Drain(bcpgIn); throw new UnsupportedPacketVersionException("unsupported version: " + version.ToString()); } signatureType = bcpgIn.RequireByte(); keyAlgorithm = (PublicKeyAlgorithmTag)bcpgIn.RequireByte(); hashAlgorithm = (HashAlgorithmTag)bcpgIn.RequireByte(); byte[] buffer = new byte[StreamUtilities.RequireUInt16BE(bcpgIn)]; bcpgIn.ReadFully(buffer); SignatureSubpacketsParser signatureSubpacketsParser = new SignatureSubpacketsParser(new MemoryStream(buffer, false)); List<SignatureSubpacket> list = new List<SignatureSubpacket>(); SignatureSubpacket item; while ((item = signatureSubpacketsParser.ReadPacket()) != null) { list.Add(item); } hashedData = list.ToArray(); SignatureSubpacket[] array = hashedData; foreach (SignatureSubpacket signatureSubpacket in array) { IssuerKeyId issuerKeyId = signatureSubpacket as IssuerKeyId; if (issuerKeyId != null) keyId = issuerKeyId.KeyId; else { SignatureCreationTime signatureCreationTime = signatureSubpacket as SignatureCreationTime; if (signatureCreationTime != null) creationTime = DateTimeUtilities.DateTimeToUnixMs(signatureCreationTime.GetTime()); } } byte[] buffer2 = new byte[StreamUtilities.RequireUInt16BE(bcpgIn)]; bcpgIn.ReadFully(buffer2); signatureSubpacketsParser = new SignatureSubpacketsParser(new MemoryStream(buffer2, false)); list.Clear(); while ((item = signatureSubpacketsParser.ReadPacket()) != null) { list.Add(item); } unhashedData = list.ToArray(); array = unhashedData; for (int i = 0; i < array.Length; i++) { IssuerKeyId issuerKeyId2 = array[i] as IssuerKeyId; if (issuerKeyId2 != null) keyId = issuerKeyId2.KeyId; } } fingerprint = new byte[2]; bcpgIn.ReadFully(fingerprint); switch (keyAlgorithm) { case PublicKeyAlgorithmTag.RsaGeneral: case PublicKeyAlgorithmTag.RsaSign: { MPInteger mPInteger3 = new MPInteger(bcpgIn); signature = new MPInteger[1] { mPInteger3 }; break; } case PublicKeyAlgorithmTag.ElGamalEncrypt: case PublicKeyAlgorithmTag.Dsa: case PublicKeyAlgorithmTag.ElGamalGeneral: { MPInteger mPInteger = new MPInteger(bcpgIn); MPInteger mPInteger2 = new MPInteger(bcpgIn); signature = new MPInteger[2] { mPInteger, mPInteger2 }; break; } case PublicKeyAlgorithmTag.ECDsa: case PublicKeyAlgorithmTag.EdDsa: { MPInteger mPInteger4 = new MPInteger(bcpgIn); MPInteger mPInteger5 = new MPInteger(bcpgIn); signature = new MPInteger[2] { mPInteger4, mPInteger5 }; break; } default: if (keyAlgorithm < PublicKeyAlgorithmTag.Experimental_1 || keyAlgorithm > PublicKeyAlgorithmTag.Experimental_11) throw new IOException("unknown signature key algorithm: " + keyAlgorithm.ToString()); signature = null; signatureEncoding = Streams.ReadAll(bcpgIn); break; } } public SignaturePacket(int signatureType, long keyId, PublicKeyAlgorithmTag keyAlgorithm, HashAlgorithmTag hashAlgorithm, SignatureSubpacket[] hashedData, SignatureSubpacket[] unhashedData, byte[] fingerprint, MPInteger[] signature) : this(4, signatureType, keyId, keyAlgorithm, hashAlgorithm, hashedData, unhashedData, fingerprint, signature) { } public SignaturePacket(int version, int signatureType, long keyId, PublicKeyAlgorithmTag keyAlgorithm, HashAlgorithmTag hashAlgorithm, long creationTime, byte[] fingerprint, MPInteger[] signature) : this(version, signatureType, keyId, keyAlgorithm, hashAlgorithm, null, null, fingerprint, signature) { this.creationTime = creationTime; } public SignaturePacket(int version, int signatureType, long keyId, PublicKeyAlgorithmTag keyAlgorithm, HashAlgorithmTag hashAlgorithm, SignatureSubpacket[] hashedData, SignatureSubpacket[] unhashedData, byte[] fingerprint, MPInteger[] signature) { this.version = version; this.signatureType = signatureType; this.keyId = keyId; this.keyAlgorithm = keyAlgorithm; this.hashAlgorithm = hashAlgorithm; this.hashedData = hashedData; this.unhashedData = unhashedData; this.fingerprint = fingerprint; this.signature = signature; if (hashedData != null) SetCreationTime(); } public byte[] GetFingerprint() { return Arrays.Clone(fingerprint); } public byte[] GetSignatureTrailer() { if (version == 3) { long num = creationTime / 1000; byte[] array = new byte[5] { (byte)signatureType, 0, 0, 0, 0 }; Pack.UInt32_To_BE((uint)num, array, 1); return array; } MemoryStream memoryStream = new MemoryStream(); memoryStream.WriteByte((byte)Version); memoryStream.WriteByte((byte)SignatureType); memoryStream.WriteByte((byte)KeyAlgorithm); memoryStream.WriteByte((byte)HashAlgorithm); long position = memoryStream.Position; memoryStream.WriteByte(0); memoryStream.WriteByte(0); SignatureSubpacket[] hashedSubPackets = GetHashedSubPackets(); for (int i = 0; i != hashedSubPackets.Length; i++) { hashedSubPackets[i].Encode(memoryStream); } ushort num2 = Convert.ToUInt16(memoryStream.Position - position - 2); uint num3 = Convert.ToUInt32(memoryStream.Position); memoryStream.WriteByte((byte)Version); memoryStream.WriteByte(byte.MaxValue); memoryStream.WriteByte((byte)(num3 >> 24)); memoryStream.WriteByte((byte)(num3 >> 16)); memoryStream.WriteByte((byte)(num3 >> 8)); memoryStream.WriteByte((byte)num3); memoryStream.Position = position; memoryStream.WriteByte((byte)(num2 >> 8)); memoryStream.WriteByte((byte)num2); return memoryStream.ToArray(); } public MPInteger[] GetSignature() { return signature; } public byte[] GetSignatureBytes() { if (signatureEncoding != null) return (byte[])signatureEncoding.Clone(); MemoryStream memoryStream = new MemoryStream(); using (BcpgOutputStream bcpgOutputStream = new BcpgOutputStream(memoryStream)) { MPInteger[] array = signature; foreach (MPInteger bcpgObject in array) { try { bcpgOutputStream.WriteObject(bcpgObject); } catch (IOException ex) { throw new Exception("internal error: " + ex?.ToString()); } } } return memoryStream.ToArray(); } public SignatureSubpacket[] GetHashedSubPackets() { return hashedData; } public SignatureSubpacket[] GetUnhashedSubPackets() { return unhashedData; } public override void Encode(BcpgOutputStream bcpgOut) { MemoryStream memoryStream = new MemoryStream(); using (BcpgOutputStream bcpgOutputStream = new BcpgOutputStream(memoryStream)) { bcpgOutputStream.WriteByte((byte)version); if (version == 3 || version == 2) { byte b = 5; bcpgOutputStream.Write(b, (byte)signatureType); bcpgOutputStream.WriteInt((int)(creationTime / 1000)); bcpgOutputStream.WriteLong(keyId); bcpgOutputStream.Write((byte)keyAlgorithm, (byte)hashAlgorithm); } else { if (version != 4) throw new IOException("unknown version: " + version.ToString()); bcpgOutputStream.Write((byte)signatureType, (byte)keyAlgorithm, (byte)hashAlgorithm); EncodeLengthAndData(bcpgOutputStream, GetEncodedSubpackets(hashedData)); EncodeLengthAndData(bcpgOutputStream, GetEncodedSubpackets(unhashedData)); } bcpgOutputStream.Write(fingerprint); if (signature != null) { BcpgOutputStream bcpgOutputStream2 = bcpgOutputStream; BcpgObject[] v = signature; bcpgOutputStream2.WriteObjects(v); } else bcpgOutputStream.Write(signatureEncoding); } bcpgOut.WritePacket(PacketTag.Signature, memoryStream.ToArray()); } private static void EncodeLengthAndData(BcpgOutputStream pOut, byte[] data) { pOut.WriteShort((short)data.Length); pOut.Write(data); } private static byte[] GetEncodedSubpackets(SignatureSubpacket[] ps) { MemoryStream memoryStream = new MemoryStream(); for (int i = 0; i < ps.Length; i++) { ps[i].Encode(memoryStream); } return memoryStream.ToArray(); } private void SetCreationTime() { SignatureSubpacket[] array = hashedData; int num = 0; SignatureCreationTime signatureCreationTime; while (true) { if (num >= array.Length) return; signatureCreationTime = (array[num] as SignatureCreationTime); if (signatureCreationTime != null) break; num++; } creationTime = DateTimeUtilities.DateTimeToUnixMs(signatureCreationTime.GetTime()); } public static SignaturePacket FromByteArray(byte[] data) { return new SignaturePacket(BcpgInputStream.Wrap(new MemoryStream(data))); } } }