339 lines
10 KiB
C#
339 lines
10 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.IO;
|
|
using Org.BouncyCastle.Bcpg.Sig;
|
|
using Org.BouncyCastle.Utilities;
|
|
using Org.BouncyCastle.Utilities.Date;
|
|
|
|
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.ReadByte();
|
|
if (version == 3 || version == 2)
|
|
{
|
|
bcpgIn.ReadByte();
|
|
signatureType = bcpgIn.ReadByte();
|
|
creationTime = (((long)bcpgIn.ReadByte() << 24) | ((long)bcpgIn.ReadByte() << 16) | ((long)bcpgIn.ReadByte() << 8) | (uint)bcpgIn.ReadByte()) * 1000;
|
|
keyId |= (long)bcpgIn.ReadByte() << 56;
|
|
keyId |= (long)bcpgIn.ReadByte() << 48;
|
|
keyId |= (long)bcpgIn.ReadByte() << 40;
|
|
keyId |= (long)bcpgIn.ReadByte() << 32;
|
|
keyId |= (long)bcpgIn.ReadByte() << 24;
|
|
keyId |= (long)bcpgIn.ReadByte() << 16;
|
|
keyId |= (long)bcpgIn.ReadByte() << 8;
|
|
keyId |= (uint)bcpgIn.ReadByte();
|
|
keyAlgorithm = (PublicKeyAlgorithmTag)bcpgIn.ReadByte();
|
|
hashAlgorithm = (HashAlgorithmTag)bcpgIn.ReadByte();
|
|
}
|
|
else
|
|
{
|
|
if (version != 4)
|
|
{
|
|
throw new Exception("unsupported version: " + version);
|
|
}
|
|
signatureType = bcpgIn.ReadByte();
|
|
keyAlgorithm = (PublicKeyAlgorithmTag)bcpgIn.ReadByte();
|
|
hashAlgorithm = (HashAlgorithmTag)bcpgIn.ReadByte();
|
|
int num = (bcpgIn.ReadByte() << 8) | bcpgIn.ReadByte();
|
|
byte[] buffer = new byte[num];
|
|
bcpgIn.ReadFully(buffer);
|
|
SignatureSubpacketsParser signatureSubpacketsParser = new SignatureSubpacketsParser(new MemoryStream(buffer, writable: false));
|
|
IList list = Platform.CreateArrayList();
|
|
SignatureSubpacket value;
|
|
while ((value = signatureSubpacketsParser.ReadPacket()) != null)
|
|
{
|
|
list.Add(value);
|
|
}
|
|
hashedData = new SignatureSubpacket[list.Count];
|
|
for (int i = 0; i != hashedData.Length; i++)
|
|
{
|
|
SignatureSubpacket signatureSubpacket = (SignatureSubpacket)list[i];
|
|
if (signatureSubpacket is IssuerKeyId)
|
|
{
|
|
keyId = ((IssuerKeyId)signatureSubpacket).KeyId;
|
|
}
|
|
else if (signatureSubpacket is SignatureCreationTime)
|
|
{
|
|
creationTime = DateTimeUtilities.DateTimeToUnixMs(((SignatureCreationTime)signatureSubpacket).GetTime());
|
|
}
|
|
hashedData[i] = signatureSubpacket;
|
|
}
|
|
int num2 = (bcpgIn.ReadByte() << 8) | bcpgIn.ReadByte();
|
|
byte[] buffer2 = new byte[num2];
|
|
bcpgIn.ReadFully(buffer2);
|
|
signatureSubpacketsParser = new SignatureSubpacketsParser(new MemoryStream(buffer2, writable: false));
|
|
list.Clear();
|
|
while ((value = signatureSubpacketsParser.ReadPacket()) != null)
|
|
{
|
|
list.Add(value);
|
|
}
|
|
unhashedData = new SignatureSubpacket[list.Count];
|
|
for (int j = 0; j != unhashedData.Length; j++)
|
|
{
|
|
SignatureSubpacket signatureSubpacket2 = (SignatureSubpacket)list[j];
|
|
if (signatureSubpacket2 is IssuerKeyId)
|
|
{
|
|
keyId = ((IssuerKeyId)signatureSubpacket2).KeyId;
|
|
}
|
|
unhashedData[j] = signatureSubpacket2;
|
|
}
|
|
}
|
|
fingerprint = new byte[2];
|
|
bcpgIn.ReadFully(fingerprint);
|
|
switch (keyAlgorithm)
|
|
{
|
|
case PublicKeyAlgorithmTag.RsaGeneral:
|
|
case PublicKeyAlgorithmTag.RsaSign:
|
|
{
|
|
MPInteger mPInteger8 = new MPInteger(bcpgIn);
|
|
signature = new MPInteger[1] { mPInteger8 };
|
|
return;
|
|
}
|
|
case PublicKeyAlgorithmTag.Dsa:
|
|
{
|
|
MPInteger mPInteger6 = new MPInteger(bcpgIn);
|
|
MPInteger mPInteger7 = new MPInteger(bcpgIn);
|
|
signature = new MPInteger[2] { mPInteger6, mPInteger7 };
|
|
return;
|
|
}
|
|
case PublicKeyAlgorithmTag.ElGamalEncrypt:
|
|
case PublicKeyAlgorithmTag.ElGamalGeneral:
|
|
{
|
|
MPInteger mPInteger3 = new MPInteger(bcpgIn);
|
|
MPInteger mPInteger4 = new MPInteger(bcpgIn);
|
|
MPInteger mPInteger5 = new MPInteger(bcpgIn);
|
|
signature = new MPInteger[3] { mPInteger3, mPInteger4, mPInteger5 };
|
|
return;
|
|
}
|
|
case PublicKeyAlgorithmTag.ECDsa:
|
|
{
|
|
MPInteger mPInteger = new MPInteger(bcpgIn);
|
|
MPInteger mPInteger2 = new MPInteger(bcpgIn);
|
|
signature = new MPInteger[2] { mPInteger, mPInteger2 };
|
|
return;
|
|
}
|
|
}
|
|
if (keyAlgorithm >= PublicKeyAlgorithmTag.Experimental_1 && keyAlgorithm <= PublicKeyAlgorithmTag.Experimental_11)
|
|
{
|
|
signature = null;
|
|
MemoryStream memoryStream = new MemoryStream();
|
|
int num3;
|
|
while ((num3 = bcpgIn.ReadByte()) >= 0)
|
|
{
|
|
memoryStream.WriteByte((byte)num3);
|
|
}
|
|
signatureEncoding = memoryStream.ToArray();
|
|
return;
|
|
}
|
|
throw new IOException("unknown signature key algorithm: " + keyAlgorithm);
|
|
}
|
|
|
|
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[] GetSignatureTrailer()
|
|
{
|
|
byte[] array = null;
|
|
if (version == 3)
|
|
{
|
|
array = new byte[5];
|
|
long num = creationTime / 1000;
|
|
array[0] = (byte)signatureType;
|
|
array[1] = (byte)(num >> 24);
|
|
array[2] = (byte)(num >> 16);
|
|
array[3] = (byte)(num >> 8);
|
|
array[4] = (byte)num;
|
|
}
|
|
else
|
|
{
|
|
MemoryStream memoryStream = new MemoryStream();
|
|
memoryStream.WriteByte((byte)Version);
|
|
memoryStream.WriteByte((byte)SignatureType);
|
|
memoryStream.WriteByte((byte)KeyAlgorithm);
|
|
memoryStream.WriteByte((byte)HashAlgorithm);
|
|
MemoryStream memoryStream2 = new MemoryStream();
|
|
SignatureSubpacket[] hashedSubPackets = GetHashedSubPackets();
|
|
for (int i = 0; i != hashedSubPackets.Length; i++)
|
|
{
|
|
hashedSubPackets[i].Encode(memoryStream2);
|
|
}
|
|
byte[] array2 = memoryStream2.ToArray();
|
|
memoryStream.WriteByte((byte)(array2.Length >> 8));
|
|
memoryStream.WriteByte((byte)array2.Length);
|
|
memoryStream.Write(array2, 0, array2.Length);
|
|
byte[] array3 = memoryStream.ToArray();
|
|
memoryStream.WriteByte((byte)Version);
|
|
memoryStream.WriteByte(byte.MaxValue);
|
|
memoryStream.WriteByte((byte)(array3.Length >> 24));
|
|
memoryStream.WriteByte((byte)(array3.Length >> 16));
|
|
memoryStream.WriteByte((byte)(array3.Length >> 8));
|
|
memoryStream.WriteByte((byte)array3.Length);
|
|
array = memoryStream.ToArray();
|
|
}
|
|
return array;
|
|
}
|
|
|
|
public MPInteger[] GetSignature()
|
|
{
|
|
return signature;
|
|
}
|
|
|
|
public byte[] GetSignatureBytes()
|
|
{
|
|
if (signatureEncoding != null)
|
|
{
|
|
return (byte[])signatureEncoding.Clone();
|
|
}
|
|
MemoryStream memoryStream = new MemoryStream();
|
|
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);
|
|
}
|
|
}
|
|
return memoryStream.ToArray();
|
|
}
|
|
|
|
public SignatureSubpacket[] GetHashedSubPackets()
|
|
{
|
|
return hashedData;
|
|
}
|
|
|
|
public SignatureSubpacket[] GetUnhashedSubPackets()
|
|
{
|
|
return unhashedData;
|
|
}
|
|
|
|
public override void Encode(BcpgOutputStream bcpgOut)
|
|
{
|
|
MemoryStream memoryStream = new MemoryStream();
|
|
BcpgOutputStream bcpgOutputStream = new BcpgOutputStream(memoryStream);
|
|
bcpgOutputStream.WriteByte((byte)version);
|
|
if (version == 3 || version == 2)
|
|
{
|
|
bcpgOutputStream.Write(5, (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);
|
|
}
|
|
bcpgOutputStream.Write((byte)signatureType, (byte)keyAlgorithm, (byte)hashAlgorithm);
|
|
EncodeLengthAndData(bcpgOutputStream, GetEncodedSubpackets(hashedData));
|
|
EncodeLengthAndData(bcpgOutputStream, GetEncodedSubpackets(unhashedData));
|
|
}
|
|
bcpgOutputStream.Write(fingerprint);
|
|
if (signature != null)
|
|
{
|
|
bcpgOutputStream.WriteObjects(signature);
|
|
}
|
|
else
|
|
{
|
|
bcpgOutputStream.Write(signatureEncoding);
|
|
}
|
|
bcpgOut.WritePacket(PacketTag.Signature, memoryStream.ToArray(), oldFormat: true);
|
|
}
|
|
|
|
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();
|
|
foreach (SignatureSubpacket signatureSubpacket in ps)
|
|
{
|
|
signatureSubpacket.Encode(memoryStream);
|
|
}
|
|
return memoryStream.ToArray();
|
|
}
|
|
|
|
private void setCreationTime()
|
|
{
|
|
SignatureSubpacket[] array = hashedData;
|
|
foreach (SignatureSubpacket signatureSubpacket in array)
|
|
{
|
|
if (signatureSubpacket is SignatureCreationTime)
|
|
{
|
|
creationTime = DateTimeUtilities.DateTimeToUnixMs(((SignatureCreationTime)signatureSubpacket).GetTime());
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|