init commit

This commit is contained in:
2025-10-09 09:57:24 +09:00
commit 4d551bd74f
6636 changed files with 1218703 additions and 0 deletions

View File

@@ -0,0 +1,418 @@
using System.Collections;
using System.IO;
using System.Text;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.IO;
namespace Org.BouncyCastle.Bcpg;
public class ArmoredInputStream : BaseInputStream
{
private static readonly byte[] decodingTable;
private Stream input;
private bool start = true;
private int[] outBuf = new int[3];
private int bufPtr = 3;
private Crc24 crc = new Crc24();
private bool crcFound = false;
private bool hasHeaders = true;
private string header = null;
private bool newLineFound = false;
private bool clearText = false;
private bool restart = false;
private IList headerList = Platform.CreateArrayList();
private int lastC = 0;
private bool isEndOfStream;
static ArmoredInputStream()
{
decodingTable = new byte[128];
for (int i = 65; i <= 90; i++)
{
decodingTable[i] = (byte)(i - 65);
}
for (int j = 97; j <= 122; j++)
{
decodingTable[j] = (byte)(j - 97 + 26);
}
for (int k = 48; k <= 57; k++)
{
decodingTable[k] = (byte)(k - 48 + 52);
}
decodingTable[43] = 62;
decodingTable[47] = 63;
}
private int Decode(int in0, int in1, int in2, int in3, int[] result)
{
if (in3 < 0)
{
throw new EndOfStreamException("unexpected end of file in armored stream.");
}
int num;
int num2;
if (in2 == 61)
{
num = decodingTable[in0] & 0xFF;
num2 = decodingTable[in1] & 0xFF;
result[2] = ((num << 2) | (num2 >> 4)) & 0xFF;
return 2;
}
int num3;
if (in3 == 61)
{
num = decodingTable[in0];
num2 = decodingTable[in1];
num3 = decodingTable[in2];
result[1] = ((num << 2) | (num2 >> 4)) & 0xFF;
result[2] = ((num2 << 4) | (num3 >> 2)) & 0xFF;
return 1;
}
num = decodingTable[in0];
num2 = decodingTable[in1];
num3 = decodingTable[in2];
int num4 = decodingTable[in3];
result[0] = ((num << 2) | (num2 >> 4)) & 0xFF;
result[1] = ((num2 << 4) | (num3 >> 2)) & 0xFF;
result[2] = ((num3 << 6) | num4) & 0xFF;
return 0;
}
public ArmoredInputStream(Stream input)
: this(input, hasHeaders: true)
{
}
public ArmoredInputStream(Stream input, bool hasHeaders)
{
this.input = input;
this.hasHeaders = hasHeaders;
if (hasHeaders)
{
ParseHeaders();
}
start = false;
}
private bool ParseHeaders()
{
header = null;
int num = 0;
bool flag = false;
headerList = Platform.CreateArrayList();
if (restart)
{
flag = true;
}
else
{
int num2;
while ((num2 = input.ReadByte()) >= 0)
{
if (num2 == 45 && (num == 0 || num == 10 || num == 13))
{
flag = true;
break;
}
num = num2;
}
}
if (flag)
{
StringBuilder stringBuilder = new StringBuilder("-");
bool flag2 = false;
bool flag3 = false;
if (restart)
{
stringBuilder.Append('-');
}
int num2;
while ((num2 = input.ReadByte()) >= 0)
{
if (num == 13 && num2 == 10)
{
flag3 = true;
}
if ((flag2 && num != 13 && num2 == 10) || (flag2 && num2 == 13))
{
break;
}
if (num2 == 13 || (num != 13 && num2 == 10))
{
string text = stringBuilder.ToString();
if (text.Trim().Length < 1)
{
break;
}
headerList.Add(text);
stringBuilder.Length = 0;
}
if (num2 != 10 && num2 != 13)
{
stringBuilder.Append((char)num2);
flag2 = false;
}
else if (num2 == 13 || (num != 13 && num2 == 10))
{
flag2 = true;
}
num = num2;
}
if (flag3)
{
input.ReadByte();
}
}
if (headerList.Count > 0)
{
header = (string)headerList[0];
}
clearText = "-----BEGIN PGP SIGNED MESSAGE-----".Equals(header);
newLineFound = true;
return flag;
}
public bool IsClearText()
{
return clearText;
}
public bool IsEndOfStream()
{
return isEndOfStream;
}
public string GetArmorHeaderLine()
{
return header;
}
public string[] GetArmorHeaders()
{
if (headerList.Count <= 1)
{
return null;
}
string[] array = new string[headerList.Count - 1];
for (int i = 0; i != array.Length; i++)
{
array[i] = (string)headerList[i + 1];
}
return array;
}
private int ReadIgnoreSpace()
{
int num;
do
{
num = input.ReadByte();
}
while (num == 32 || num == 9);
return num;
}
private int ReadIgnoreWhitespace()
{
int num;
do
{
num = input.ReadByte();
}
while (num == 32 || num == 9 || num == 13 || num == 10);
return num;
}
private int ReadByteClearText()
{
int num = input.ReadByte();
if (num == 13 || (num == 10 && lastC != 13))
{
newLineFound = true;
}
else if (newLineFound && num == 45)
{
num = input.ReadByte();
if (num == 45)
{
clearText = false;
start = true;
restart = true;
}
else
{
num = input.ReadByte();
}
newLineFound = false;
}
else if (num != 10 && lastC != 13)
{
newLineFound = false;
}
lastC = num;
if (num < 0)
{
isEndOfStream = true;
}
return num;
}
private int ReadClearText(byte[] buffer, int offset, int count)
{
int num = offset;
try
{
int num2 = offset + count;
while (num < num2)
{
int num3 = ReadByteClearText();
if (num3 != -1)
{
buffer[num++] = (byte)num3;
continue;
}
break;
}
}
catch (IOException ex)
{
if (num == offset)
{
throw ex;
}
}
return num - offset;
}
private int DoReadByte()
{
if (bufPtr > 2 || crcFound)
{
int num = ReadIgnoreSpace();
if (num == 10 || num == 13)
{
num = ReadIgnoreWhitespace();
if (num == 61)
{
bufPtr = Decode(ReadIgnoreSpace(), ReadIgnoreSpace(), ReadIgnoreSpace(), ReadIgnoreSpace(), outBuf);
if (bufPtr != 0)
{
throw new IOException("no crc found in armored message.");
}
crcFound = true;
int num2 = ((outBuf[0] & 0xFF) << 16) | ((outBuf[1] & 0xFF) << 8) | (outBuf[2] & 0xFF);
if (num2 != crc.Value)
{
throw new IOException("crc check failed in armored message.");
}
return ReadByte();
}
if (num == 45)
{
while ((num = input.ReadByte()) >= 0 && num != 10 && num != 13)
{
}
if (!crcFound)
{
throw new IOException("crc check not found.");
}
crcFound = false;
start = true;
bufPtr = 3;
if (num < 0)
{
isEndOfStream = true;
}
return -1;
}
}
if (num < 0)
{
isEndOfStream = true;
return -1;
}
bufPtr = Decode(num, ReadIgnoreSpace(), ReadIgnoreSpace(), ReadIgnoreSpace(), outBuf);
}
return outBuf[bufPtr++];
}
public override int ReadByte()
{
if (start)
{
if (hasHeaders)
{
ParseHeaders();
}
crc.Reset();
start = false;
}
if (clearText)
{
return ReadByteClearText();
}
int num = DoReadByte();
crc.Update(num);
return num;
}
public override int Read(byte[] buffer, int offset, int count)
{
if (start && count > 0)
{
if (hasHeaders)
{
ParseHeaders();
}
start = false;
}
if (clearText)
{
return ReadClearText(buffer, offset, count);
}
int num = offset;
try
{
int num2 = offset + count;
while (num < num2)
{
int num3 = DoReadByte();
crc.Update(num3);
if (num3 != -1)
{
buffer[num++] = (byte)num3;
continue;
}
break;
}
}
catch (IOException ex)
{
if (num == offset)
{
throw ex;
}
}
return num - offset;
}
public override void Close()
{
Platform.Dispose(input);
base.Close();
}
}

View File

@@ -0,0 +1,267 @@
using System.Collections;
using System.IO;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.IO;
namespace Org.BouncyCastle.Bcpg;
public class ArmoredOutputStream : BaseOutputStream
{
public static readonly string HeaderVersion = "Version";
private static readonly byte[] encodingTable = new byte[64]
{
65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
85, 86, 87, 88, 89, 90, 97, 98, 99, 100,
101, 102, 103, 104, 105, 106, 107, 108, 109, 110,
111, 112, 113, 114, 115, 116, 117, 118, 119, 120,
121, 122, 48, 49, 50, 51, 52, 53, 54, 55,
56, 57, 43, 47
};
private readonly Stream outStream;
private int[] buf = new int[3];
private int bufPtr = 0;
private Crc24 crc = new Crc24();
private int chunkCount = 0;
private int lastb;
private bool start = true;
private bool clearText = false;
private bool newLine = false;
private string type;
private static readonly string nl = Platform.NewLine;
private static readonly string headerStart = "-----BEGIN PGP ";
private static readonly string headerTail = "-----";
private static readonly string footerStart = "-----END PGP ";
private static readonly string footerTail = "-----";
private static readonly string Version = "BCPG C# v" + AssemblyInfo.Version;
private readonly IDictionary headers;
private static void Encode(Stream outStream, int[] data, int len)
{
byte[] array = new byte[4];
int num = data[0];
array[0] = encodingTable[(num >> 2) & 0x3F];
switch (len)
{
case 1:
array[1] = encodingTable[(num << 4) & 0x3F];
array[2] = 61;
array[3] = 61;
break;
case 2:
{
int num4 = data[1];
array[1] = encodingTable[((num << 4) | (num4 >> 4)) & 0x3F];
array[2] = encodingTable[(num4 << 2) & 0x3F];
array[3] = 61;
break;
}
case 3:
{
int num2 = data[1];
int num3 = data[2];
array[1] = encodingTable[((num << 4) | (num2 >> 4)) & 0x3F];
array[2] = encodingTable[((num2 << 2) | (num3 >> 6)) & 0x3F];
array[3] = encodingTable[num3 & 0x3F];
break;
}
}
outStream.Write(array, 0, array.Length);
}
public ArmoredOutputStream(Stream outStream)
{
this.outStream = outStream;
headers = Platform.CreateHashtable(1);
headers.Add(HeaderVersion, Version);
}
public ArmoredOutputStream(Stream outStream, IDictionary headers)
{
this.outStream = outStream;
this.headers = Platform.CreateHashtable(headers);
if (!this.headers.Contains(HeaderVersion))
{
this.headers.Add(HeaderVersion, Version);
}
}
public void SetHeader(string name, string v)
{
if (v == null)
{
headers.Remove(name);
}
else
{
headers[name] = v;
}
}
public void ResetHeaders()
{
string text = (string)headers[HeaderVersion];
headers.Clear();
if (text != null)
{
headers.Add(HeaderVersion, text);
}
}
public void BeginClearText(HashAlgorithmTag hashAlgorithm)
{
string text = hashAlgorithm switch
{
HashAlgorithmTag.Sha1 => "SHA1",
HashAlgorithmTag.Sha256 => "SHA256",
HashAlgorithmTag.Sha384 => "SHA384",
HashAlgorithmTag.Sha512 => "SHA512",
HashAlgorithmTag.MD2 => "MD2",
HashAlgorithmTag.MD5 => "MD5",
HashAlgorithmTag.RipeMD160 => "RIPEMD160",
_ => throw new IOException("unknown hash algorithm tag in beginClearText: " + hashAlgorithm),
};
DoWrite("-----BEGIN PGP SIGNED MESSAGE-----" + nl);
DoWrite("Hash: " + text + nl + nl);
clearText = true;
newLine = true;
lastb = 0;
}
public void EndClearText()
{
clearText = false;
}
public override void WriteByte(byte b)
{
if (clearText)
{
outStream.WriteByte(b);
if (newLine)
{
if (b != 10 || lastb != 13)
{
newLine = false;
}
if (b == 45)
{
outStream.WriteByte(32);
outStream.WriteByte(45);
}
}
if (b == 13 || (b == 10 && lastb != 13))
{
newLine = true;
}
lastb = b;
return;
}
if (start)
{
switch ((PacketTag)(((b & 0x40) == 0) ? ((b & 0x3F) >> 2) : (b & 0x3F)))
{
case PacketTag.PublicKey:
type = "PUBLIC KEY BLOCK";
break;
case PacketTag.SecretKey:
type = "PRIVATE KEY BLOCK";
break;
case PacketTag.Signature:
type = "SIGNATURE";
break;
default:
type = "MESSAGE";
break;
}
DoWrite(headerStart + type + headerTail + nl);
if (headers.Contains(HeaderVersion))
{
WriteHeaderEntry(HeaderVersion, (string)headers[HeaderVersion]);
}
foreach (object header in headers)
{
DictionaryEntry dictionaryEntry = (DictionaryEntry)header;
string text = (string)dictionaryEntry.Key;
if (text != HeaderVersion)
{
string v = (string)dictionaryEntry.Value;
WriteHeaderEntry(text, v);
}
}
DoWrite(nl);
start = false;
}
if (bufPtr == 3)
{
Encode(outStream, buf, bufPtr);
bufPtr = 0;
if ((++chunkCount & 0xF) == 0)
{
DoWrite(nl);
}
}
crc.Update(b);
buf[bufPtr++] = b & 0xFF;
}
public override void Close()
{
if (type != null)
{
DoClose();
type = null;
start = true;
base.Close();
}
}
private void DoClose()
{
if (bufPtr > 0)
{
Encode(outStream, buf, bufPtr);
}
DoWrite(nl + '=');
int value = crc.Value;
buf[0] = (value >> 16) & 0xFF;
buf[1] = (value >> 8) & 0xFF;
buf[2] = value & 0xFF;
Encode(outStream, buf, 3);
DoWrite(nl);
DoWrite(footerStart);
DoWrite(type);
DoWrite(footerTail);
DoWrite(nl);
outStream.Flush();
}
private void WriteHeaderEntry(string name, string v)
{
DoWrite(name + ": " + v + nl);
}
private void DoWrite(string s)
{
byte[] array = Strings.ToAsciiByteArray(s);
outStream.Write(array, 0, array.Length);
}
}

View File

@@ -0,0 +1,63 @@
using System;
using System.IO;
namespace Org.BouncyCastle.Bcpg.Attr;
public class ImageAttrib : UserAttributeSubpacket
{
public enum Format : byte
{
Jpeg = 1
}
private static readonly byte[] Zeroes = new byte[12];
private int hdrLength;
private int _version;
private int _encoding;
private byte[] imageData;
public virtual int Version => _version;
public virtual int Encoding => _encoding;
public ImageAttrib(byte[] data)
: this(forceLongLength: false, data)
{
}
public ImageAttrib(bool forceLongLength, byte[] data)
: base(UserAttributeSubpacketTag.ImageAttribute, forceLongLength, data)
{
hdrLength = ((data[1] & 0xFF) << 8) | (data[0] & 0xFF);
_version = data[2] & 0xFF;
_encoding = data[3] & 0xFF;
imageData = new byte[data.Length - hdrLength];
Array.Copy(data, hdrLength, imageData, 0, imageData.Length);
}
public ImageAttrib(Format imageType, byte[] imageData)
: this(ToByteArray(imageType, imageData))
{
}
private static byte[] ToByteArray(Format imageType, byte[] imageData)
{
MemoryStream memoryStream = new MemoryStream();
memoryStream.WriteByte(16);
memoryStream.WriteByte(0);
memoryStream.WriteByte(1);
memoryStream.WriteByte((byte)imageType);
memoryStream.Write(Zeroes, 0, Zeroes.Length);
memoryStream.Write(imageData, 0, imageData.Length);
return memoryStream.ToArray();
}
public virtual byte[] GetImageData()
{
return imageData;
}
}

View File

@@ -0,0 +1,309 @@
using System;
using System.IO;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.IO;
namespace Org.BouncyCastle.Bcpg;
public class BcpgInputStream : BaseInputStream
{
private class PartialInputStream : BaseInputStream
{
private BcpgInputStream m_in;
private bool partial;
private int dataLength;
internal PartialInputStream(BcpgInputStream bcpgIn, bool partial, int dataLength)
{
m_in = bcpgIn;
this.partial = partial;
this.dataLength = dataLength;
}
public override int ReadByte()
{
do
{
if (dataLength != 0)
{
int num = m_in.ReadByte();
if (num < 0)
{
throw new EndOfStreamException("Premature end of stream in PartialInputStream");
}
dataLength--;
return num;
}
}
while (partial && ReadPartialDataLength() >= 0);
return -1;
}
public override int Read(byte[] buffer, int offset, int count)
{
do
{
if (dataLength != 0)
{
int count2 = ((dataLength > count || dataLength < 0) ? count : dataLength);
int num = m_in.Read(buffer, offset, count2);
if (num < 1)
{
throw new EndOfStreamException("Premature end of stream in PartialInputStream");
}
dataLength -= num;
return num;
}
}
while (partial && ReadPartialDataLength() >= 0);
return 0;
}
private int ReadPartialDataLength()
{
int num = m_in.ReadByte();
if (num < 0)
{
return -1;
}
partial = false;
if (num < 192)
{
dataLength = num;
}
else if (num <= 223)
{
dataLength = (num - 192 << 8) + m_in.ReadByte() + 192;
}
else if (num == 255)
{
dataLength = (m_in.ReadByte() << 24) | (m_in.ReadByte() << 16) | (m_in.ReadByte() << 8) | m_in.ReadByte();
}
else
{
partial = true;
dataLength = 1 << (num & 0x1F);
}
return 0;
}
}
private Stream m_in;
private bool next = false;
private int nextB;
internal static BcpgInputStream Wrap(Stream inStr)
{
if (inStr is BcpgInputStream)
{
return (BcpgInputStream)inStr;
}
return new BcpgInputStream(inStr);
}
private BcpgInputStream(Stream inputStream)
{
m_in = inputStream;
}
public override int ReadByte()
{
if (next)
{
next = false;
return nextB;
}
return m_in.ReadByte();
}
public override int Read(byte[] buffer, int offset, int count)
{
if (!next)
{
return m_in.Read(buffer, offset, count);
}
if (nextB < 0)
{
return 0;
}
if (buffer == null)
{
throw new ArgumentNullException("buffer");
}
buffer[offset] = (byte)nextB;
next = false;
return 1;
}
public byte[] ReadAll()
{
return Streams.ReadAll(this);
}
public void ReadFully(byte[] buffer, int off, int len)
{
if (Streams.ReadFully(this, buffer, off, len) < len)
{
throw new EndOfStreamException();
}
}
public void ReadFully(byte[] buffer)
{
ReadFully(buffer, 0, buffer.Length);
}
public PacketTag NextPacketTag()
{
if (!next)
{
try
{
nextB = m_in.ReadByte();
}
catch (EndOfStreamException)
{
nextB = -1;
}
next = true;
}
if (nextB < 0)
{
return (PacketTag)nextB;
}
int num = nextB & 0x3F;
if ((nextB & 0x40) == 0)
{
num >>= 2;
}
return (PacketTag)num;
}
public Packet ReadPacket()
{
int num = ReadByte();
if (num < 0)
{
return null;
}
if ((num & 0x80) == 0)
{
throw new IOException("invalid header encountered");
}
bool flag = (num & 0x40) != 0;
PacketTag packetTag = PacketTag.Reserved;
int num2 = 0;
bool flag2 = false;
if (flag)
{
packetTag = (PacketTag)(num & 0x3F);
int num3 = ReadByte();
if (num3 < 192)
{
num2 = num3;
}
else if (num3 <= 223)
{
int num4 = m_in.ReadByte();
num2 = (num3 - 192 << 8) + num4 + 192;
}
else if (num3 == 255)
{
num2 = (m_in.ReadByte() << 24) | (m_in.ReadByte() << 16) | (m_in.ReadByte() << 8) | m_in.ReadByte();
}
else
{
flag2 = true;
num2 = 1 << (num3 & 0x1F);
}
}
else
{
int num5 = num & 3;
packetTag = (PacketTag)((num & 0x3F) >> 2);
switch (num5)
{
case 0:
num2 = ReadByte();
break;
case 1:
num2 = (ReadByte() << 8) | ReadByte();
break;
case 2:
num2 = (ReadByte() << 24) | (ReadByte() << 16) | (ReadByte() << 8) | ReadByte();
break;
case 3:
flag2 = true;
break;
default:
throw new IOException("unknown length type encountered");
}
}
BcpgInputStream bcpgIn;
if (num2 == 0 && flag2)
{
bcpgIn = this;
}
else
{
PartialInputStream inputStream = new PartialInputStream(this, flag2, num2);
bcpgIn = new BcpgInputStream(inputStream);
}
switch (packetTag)
{
case PacketTag.Reserved:
return new InputStreamPacket(bcpgIn);
case PacketTag.PublicKeyEncryptedSession:
return new PublicKeyEncSessionPacket(bcpgIn);
case PacketTag.Signature:
return new SignaturePacket(bcpgIn);
case PacketTag.SymmetricKeyEncryptedSessionKey:
return new SymmetricKeyEncSessionPacket(bcpgIn);
case PacketTag.OnePassSignature:
return new OnePassSignaturePacket(bcpgIn);
case PacketTag.SecretKey:
return new SecretKeyPacket(bcpgIn);
case PacketTag.PublicKey:
return new PublicKeyPacket(bcpgIn);
case PacketTag.SecretSubkey:
return new SecretSubkeyPacket(bcpgIn);
case PacketTag.CompressedData:
return new CompressedDataPacket(bcpgIn);
case PacketTag.SymmetricKeyEncrypted:
return new SymmetricEncDataPacket(bcpgIn);
case PacketTag.Marker:
return new MarkerPacket(bcpgIn);
case PacketTag.LiteralData:
return new LiteralDataPacket(bcpgIn);
case PacketTag.Trust:
return new TrustPacket(bcpgIn);
case PacketTag.UserId:
return new UserIdPacket(bcpgIn);
case PacketTag.UserAttribute:
return new UserAttributePacket(bcpgIn);
case PacketTag.PublicSubkey:
return new PublicSubkeyPacket(bcpgIn);
case PacketTag.SymmetricEncryptedIntegrityProtected:
return new SymmetricEncIntegrityPacket(bcpgIn);
case PacketTag.ModificationDetectionCode:
return new ModDetectionCodePacket(bcpgIn);
case PacketTag.Experimental1:
case PacketTag.Experimental2:
case PacketTag.Experimental3:
case PacketTag.Experimental4:
return new ExperimentalPacket(packetTag, bcpgIn);
default:
throw new IOException("unknown packet type encountered: " + packetTag);
}
}
public override void Close()
{
Platform.Dispose(m_in);
base.Close();
}
}

View File

@@ -0,0 +1,16 @@
using System.IO;
namespace Org.BouncyCastle.Bcpg;
public abstract class BcpgObject
{
public virtual byte[] GetEncoded()
{
MemoryStream memoryStream = new MemoryStream();
BcpgOutputStream bcpgOutputStream = new BcpgOutputStream(memoryStream);
bcpgOutputStream.WriteObject(this);
return memoryStream.ToArray();
}
public abstract void Encode(BcpgOutputStream bcpgOut);
}

View File

@@ -0,0 +1,314 @@
using System;
using System.IO;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.IO;
namespace Org.BouncyCastle.Bcpg;
public class BcpgOutputStream : BaseOutputStream
{
private const int BufferSizePower = 16;
private Stream outStr;
private byte[] partialBuffer;
private int partialBufferLength;
private int partialPower;
private int partialOffset;
internal static BcpgOutputStream Wrap(Stream outStr)
{
if (outStr is BcpgOutputStream)
{
return (BcpgOutputStream)outStr;
}
return new BcpgOutputStream(outStr);
}
public BcpgOutputStream(Stream outStr)
{
if (outStr == null)
{
throw new ArgumentNullException("outStr");
}
this.outStr = outStr;
}
public BcpgOutputStream(Stream outStr, PacketTag tag)
{
if (outStr == null)
{
throw new ArgumentNullException("outStr");
}
this.outStr = outStr;
WriteHeader(tag, oldPackets: true, partial: true, 0L);
}
public BcpgOutputStream(Stream outStr, PacketTag tag, long length, bool oldFormat)
{
if (outStr == null)
{
throw new ArgumentNullException("outStr");
}
this.outStr = outStr;
if (length > uint.MaxValue)
{
WriteHeader(tag, oldPackets: false, partial: true, 0L);
partialBufferLength = 65536;
partialBuffer = new byte[partialBufferLength];
partialPower = 16;
partialOffset = 0;
}
else
{
WriteHeader(tag, oldFormat, partial: false, length);
}
}
public BcpgOutputStream(Stream outStr, PacketTag tag, long length)
{
if (outStr == null)
{
throw new ArgumentNullException("outStr");
}
this.outStr = outStr;
WriteHeader(tag, oldPackets: false, partial: false, length);
}
public BcpgOutputStream(Stream outStr, PacketTag tag, byte[] buffer)
{
if (outStr == null)
{
throw new ArgumentNullException("outStr");
}
this.outStr = outStr;
WriteHeader(tag, oldPackets: false, partial: true, 0L);
partialBuffer = buffer;
uint num = (uint)partialBuffer.Length;
partialPower = 0;
while (num != 1)
{
num >>= 1;
partialPower++;
}
if (partialPower > 30)
{
throw new IOException("Buffer cannot be greater than 2^30 in length.");
}
partialBufferLength = 1 << partialPower;
partialOffset = 0;
}
private void WriteNewPacketLength(long bodyLen)
{
if (bodyLen < 192)
{
outStr.WriteByte((byte)bodyLen);
}
else if (bodyLen <= 8383)
{
bodyLen -= 192;
outStr.WriteByte((byte)(((bodyLen >> 8) & 0xFF) + 192));
outStr.WriteByte((byte)bodyLen);
}
else
{
outStr.WriteByte(byte.MaxValue);
outStr.WriteByte((byte)(bodyLen >> 24));
outStr.WriteByte((byte)(bodyLen >> 16));
outStr.WriteByte((byte)(bodyLen >> 8));
outStr.WriteByte((byte)bodyLen);
}
}
private void WriteHeader(PacketTag tag, bool oldPackets, bool partial, long bodyLen)
{
int num = 128;
if (partialBuffer != null)
{
PartialFlush(isLast: true);
partialBuffer = null;
}
if (oldPackets)
{
num |= (int)tag << 2;
if (partial)
{
WriteByte((byte)(num | 3));
}
else if (bodyLen <= 255)
{
WriteByte((byte)num);
WriteByte((byte)bodyLen);
}
else if (bodyLen <= 65535)
{
WriteByte((byte)(num | 1));
WriteByte((byte)(bodyLen >> 8));
WriteByte((byte)bodyLen);
}
else
{
WriteByte((byte)(num | 2));
WriteByte((byte)(bodyLen >> 24));
WriteByte((byte)(bodyLen >> 16));
WriteByte((byte)(bodyLen >> 8));
WriteByte((byte)bodyLen);
}
}
else
{
num |= (int)((PacketTag)64 | tag);
WriteByte((byte)num);
if (partial)
{
partialOffset = 0;
}
else
{
WriteNewPacketLength(bodyLen);
}
}
}
private void PartialFlush(bool isLast)
{
if (isLast)
{
WriteNewPacketLength(partialOffset);
outStr.Write(partialBuffer, 0, partialOffset);
}
else
{
outStr.WriteByte((byte)(0xE0 | partialPower));
outStr.Write(partialBuffer, 0, partialBufferLength);
}
partialOffset = 0;
}
private void WritePartial(byte b)
{
if (partialOffset == partialBufferLength)
{
PartialFlush(isLast: false);
}
partialBuffer[partialOffset++] = b;
}
private void WritePartial(byte[] buffer, int off, int len)
{
if (partialOffset == partialBufferLength)
{
PartialFlush(isLast: false);
}
if (len <= partialBufferLength - partialOffset)
{
Array.Copy(buffer, off, partialBuffer, partialOffset, len);
partialOffset += len;
return;
}
int num = partialBufferLength - partialOffset;
Array.Copy(buffer, off, partialBuffer, partialOffset, num);
off += num;
len -= num;
PartialFlush(isLast: false);
while (len > partialBufferLength)
{
Array.Copy(buffer, off, partialBuffer, 0, partialBufferLength);
off += partialBufferLength;
len -= partialBufferLength;
PartialFlush(isLast: false);
}
Array.Copy(buffer, off, partialBuffer, 0, len);
partialOffset += len;
}
public override void WriteByte(byte value)
{
if (partialBuffer != null)
{
WritePartial(value);
}
else
{
outStr.WriteByte(value);
}
}
public override void Write(byte[] buffer, int offset, int count)
{
if (partialBuffer != null)
{
WritePartial(buffer, offset, count);
}
else
{
outStr.Write(buffer, offset, count);
}
}
internal virtual void WriteShort(short n)
{
Write((byte)(n >> 8), (byte)n);
}
internal virtual void WriteInt(int n)
{
Write((byte)(n >> 24), (byte)(n >> 16), (byte)(n >> 8), (byte)n);
}
internal virtual void WriteLong(long n)
{
Write((byte)(n >> 56), (byte)(n >> 48), (byte)(n >> 40), (byte)(n >> 32), (byte)(n >> 24), (byte)(n >> 16), (byte)(n >> 8), (byte)n);
}
public void WritePacket(ContainedPacket p)
{
p.Encode(this);
}
internal void WritePacket(PacketTag tag, byte[] body, bool oldFormat)
{
WriteHeader(tag, oldFormat, partial: false, body.Length);
Write(body);
}
public void WriteObject(BcpgObject bcpgObject)
{
bcpgObject.Encode(this);
}
public void WriteObjects(params BcpgObject[] v)
{
foreach (BcpgObject bcpgObject in v)
{
bcpgObject.Encode(this);
}
}
public override void Flush()
{
outStr.Flush();
}
public void Finish()
{
if (partialBuffer != null)
{
PartialFlush(isLast: true);
Array.Clear(partialBuffer, 0, partialBuffer.Length);
partialBuffer = null;
}
}
public override void Close()
{
Finish();
outStr.Flush();
Platform.Dispose(outStr);
base.Close();
}
}

View File

@@ -0,0 +1,14 @@
namespace Org.BouncyCastle.Bcpg;
public class CompressedDataPacket : InputStreamPacket
{
private readonly CompressionAlgorithmTag algorithm;
public CompressionAlgorithmTag Algorithm => algorithm;
internal CompressedDataPacket(BcpgInputStream bcpgIn)
: base(bcpgIn)
{
algorithm = (CompressionAlgorithmTag)bcpgIn.ReadByte();
}
}

View File

@@ -0,0 +1,9 @@
namespace Org.BouncyCastle.Bcpg;
public enum CompressionAlgorithmTag
{
Uncompressed,
Zip,
ZLib,
BZip2
}

View File

@@ -0,0 +1,16 @@
using System.IO;
namespace Org.BouncyCastle.Bcpg;
public abstract class ContainedPacket : Packet
{
public byte[] GetEncoded()
{
MemoryStream memoryStream = new MemoryStream();
BcpgOutputStream bcpgOutputStream = new BcpgOutputStream(memoryStream);
bcpgOutputStream.WritePacket(this);
return memoryStream.ToArray();
}
public abstract void Encode(BcpgOutputStream bcpgOut);
}

View File

@@ -0,0 +1,38 @@
using System;
namespace Org.BouncyCastle.Bcpg;
public class Crc24
{
private const int Crc24Init = 11994318;
private const int Crc24Poly = 25578747;
private int crc = 11994318;
public int Value => crc;
public void Update(int b)
{
crc ^= b << 16;
for (int i = 0; i < 8; i++)
{
crc <<= 1;
if ((crc & 0x1000000) != 0)
{
crc ^= 25578747;
}
}
}
[Obsolete("Use 'Value' property instead")]
public int GetValue()
{
return crc;
}
public void Reset()
{
crc = 11994318;
}
}

View File

@@ -0,0 +1,58 @@
using System;
using Org.BouncyCastle.Math;
namespace Org.BouncyCastle.Bcpg;
public class DsaPublicBcpgKey : BcpgObject, IBcpgKey
{
private readonly MPInteger p;
private readonly MPInteger q;
private readonly MPInteger g;
private readonly MPInteger y;
public string Format => "PGP";
public BigInteger G => g.Value;
public BigInteger P => p.Value;
public BigInteger Q => q.Value;
public BigInteger Y => y.Value;
public DsaPublicBcpgKey(BcpgInputStream bcpgIn)
{
p = new MPInteger(bcpgIn);
q = new MPInteger(bcpgIn);
g = new MPInteger(bcpgIn);
y = new MPInteger(bcpgIn);
}
public DsaPublicBcpgKey(BigInteger p, BigInteger q, BigInteger g, BigInteger y)
{
this.p = new MPInteger(p);
this.q = new MPInteger(q);
this.g = new MPInteger(g);
this.y = new MPInteger(y);
}
public override byte[] GetEncoded()
{
try
{
return base.GetEncoded();
}
catch (Exception)
{
return null;
}
}
public override void Encode(BcpgOutputStream bcpgOut)
{
bcpgOut.WriteObjects(p, q, g, y);
}
}

View File

@@ -0,0 +1,40 @@
using System;
using Org.BouncyCastle.Math;
namespace Org.BouncyCastle.Bcpg;
public class DsaSecretBcpgKey : BcpgObject, IBcpgKey
{
internal MPInteger x;
public string Format => "PGP";
public BigInteger X => x.Value;
public DsaSecretBcpgKey(BcpgInputStream bcpgIn)
{
x = new MPInteger(bcpgIn);
}
public DsaSecretBcpgKey(BigInteger x)
{
this.x = new MPInteger(x);
}
public override byte[] GetEncoded()
{
try
{
return base.GetEncoded();
}
catch (Exception)
{
return null;
}
}
public override void Encode(BcpgOutputStream bcpgOut)
{
bcpgOut.WriteObject(x);
}
}

View File

@@ -0,0 +1,80 @@
using System;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Math.EC;
namespace Org.BouncyCastle.Bcpg;
public class ECDHPublicBcpgKey : ECPublicBcpgKey
{
private byte reserved;
private HashAlgorithmTag hashFunctionId;
private SymmetricKeyAlgorithmTag symAlgorithmId;
public virtual byte Reserved => reserved;
public virtual HashAlgorithmTag HashAlgorithm => hashFunctionId;
public virtual SymmetricKeyAlgorithmTag SymmetricKeyAlgorithm => symAlgorithmId;
public ECDHPublicBcpgKey(BcpgInputStream bcpgIn)
: base(bcpgIn)
{
int num = bcpgIn.ReadByte();
byte[] array = new byte[num];
if (array.Length != 3)
{
throw new InvalidOperationException("kdf parameters size of 3 expected.");
}
bcpgIn.ReadFully(array);
reserved = array[0];
hashFunctionId = (HashAlgorithmTag)array[1];
symAlgorithmId = (SymmetricKeyAlgorithmTag)array[2];
VerifyHashAlgorithm();
VerifySymmetricKeyAlgorithm();
}
public ECDHPublicBcpgKey(DerObjectIdentifier oid, ECPoint point, HashAlgorithmTag hashAlgorithm, SymmetricKeyAlgorithmTag symmetricKeyAlgorithm)
: base(oid, point)
{
reserved = 1;
hashFunctionId = hashAlgorithm;
symAlgorithmId = symmetricKeyAlgorithm;
VerifyHashAlgorithm();
VerifySymmetricKeyAlgorithm();
}
public override void Encode(BcpgOutputStream bcpgOut)
{
base.Encode(bcpgOut);
bcpgOut.WriteByte(3);
bcpgOut.WriteByte(reserved);
bcpgOut.WriteByte((byte)hashFunctionId);
bcpgOut.WriteByte((byte)symAlgorithmId);
}
private void VerifyHashAlgorithm()
{
switch (hashFunctionId)
{
case HashAlgorithmTag.Sha256:
case HashAlgorithmTag.Sha384:
case HashAlgorithmTag.Sha512:
return;
}
throw new InvalidOperationException("Hash algorithm must be SHA-256 or stronger.");
}
private void VerifySymmetricKeyAlgorithm()
{
switch (symAlgorithmId)
{
case SymmetricKeyAlgorithmTag.Aes128:
case SymmetricKeyAlgorithmTag.Aes192:
case SymmetricKeyAlgorithmTag.Aes256:
return;
}
throw new InvalidOperationException("Symmetric key algorithm must be AES-128 or stronger.");
}
}

View File

@@ -0,0 +1,23 @@
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Math.EC;
namespace Org.BouncyCastle.Bcpg;
public class ECDsaPublicBcpgKey : ECPublicBcpgKey
{
protected internal ECDsaPublicBcpgKey(BcpgInputStream bcpgIn)
: base(bcpgIn)
{
}
public ECDsaPublicBcpgKey(DerObjectIdentifier oid, ECPoint point)
: base(oid, point)
{
}
public ECDsaPublicBcpgKey(DerObjectIdentifier oid, BigInteger encodedPoint)
: base(oid, encodedPoint)
{
}
}

View File

@@ -0,0 +1,71 @@
using System.IO;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Math.EC;
namespace Org.BouncyCastle.Bcpg;
public abstract class ECPublicBcpgKey : BcpgObject, IBcpgKey
{
internal DerObjectIdentifier oid;
internal BigInteger point;
public string Format => "PGP";
public virtual BigInteger EncodedPoint => point;
public virtual DerObjectIdentifier CurveOid => oid;
protected ECPublicBcpgKey(BcpgInputStream bcpgIn)
{
oid = DerObjectIdentifier.GetInstance(Asn1Object.FromByteArray(ReadBytesOfEncodedLength(bcpgIn)));
point = new MPInteger(bcpgIn).Value;
}
protected ECPublicBcpgKey(DerObjectIdentifier oid, ECPoint point)
{
this.point = new BigInteger(1, point.GetEncoded(compressed: false));
this.oid = oid;
}
protected ECPublicBcpgKey(DerObjectIdentifier oid, BigInteger encodedPoint)
{
point = encodedPoint;
this.oid = oid;
}
public override byte[] GetEncoded()
{
try
{
return base.GetEncoded();
}
catch (IOException)
{
return null;
}
}
public override void Encode(BcpgOutputStream bcpgOut)
{
byte[] encoded = oid.GetEncoded();
bcpgOut.Write(encoded, 1, encoded.Length - 1);
MPInteger bcpgObject = new MPInteger(point);
bcpgOut.WriteObject(bcpgObject);
}
protected static byte[] ReadBytesOfEncodedLength(BcpgInputStream bcpgIn)
{
int num = bcpgIn.ReadByte();
if (num == 0 || num == 255)
{
throw new IOException("future extensions not yet implemented.");
}
byte[] array = new byte[num + 2];
bcpgIn.ReadFully(array, 2, array.Length - 2);
array[0] = 6;
array[1] = (byte)num;
return array;
}
}

View File

@@ -0,0 +1,40 @@
using System;
using Org.BouncyCastle.Math;
namespace Org.BouncyCastle.Bcpg;
public class ECSecretBcpgKey : BcpgObject, IBcpgKey
{
internal MPInteger x;
public string Format => "PGP";
public virtual BigInteger X => x.Value;
public ECSecretBcpgKey(BcpgInputStream bcpgIn)
{
x = new MPInteger(bcpgIn);
}
public ECSecretBcpgKey(BigInteger x)
{
this.x = new MPInteger(x);
}
public override byte[] GetEncoded()
{
try
{
return base.GetEncoded();
}
catch (Exception)
{
return null;
}
}
public override void Encode(BcpgOutputStream bcpgOut)
{
bcpgOut.WriteObject(x);
}
}

View File

@@ -0,0 +1,52 @@
using System;
using Org.BouncyCastle.Math;
namespace Org.BouncyCastle.Bcpg;
public class ElGamalPublicBcpgKey : BcpgObject, IBcpgKey
{
internal MPInteger p;
internal MPInteger g;
internal MPInteger y;
public string Format => "PGP";
public BigInteger P => p.Value;
public BigInteger G => g.Value;
public BigInteger Y => y.Value;
public ElGamalPublicBcpgKey(BcpgInputStream bcpgIn)
{
p = new MPInteger(bcpgIn);
g = new MPInteger(bcpgIn);
y = new MPInteger(bcpgIn);
}
public ElGamalPublicBcpgKey(BigInteger p, BigInteger g, BigInteger y)
{
this.p = new MPInteger(p);
this.g = new MPInteger(g);
this.y = new MPInteger(y);
}
public override byte[] GetEncoded()
{
try
{
return base.GetEncoded();
}
catch (Exception)
{
return null;
}
}
public override void Encode(BcpgOutputStream bcpgOut)
{
bcpgOut.WriteObjects(p, g, y);
}
}

View File

@@ -0,0 +1,40 @@
using System;
using Org.BouncyCastle.Math;
namespace Org.BouncyCastle.Bcpg;
public class ElGamalSecretBcpgKey : BcpgObject, IBcpgKey
{
internal MPInteger x;
public string Format => "PGP";
public BigInteger X => x.Value;
public ElGamalSecretBcpgKey(BcpgInputStream bcpgIn)
{
x = new MPInteger(bcpgIn);
}
public ElGamalSecretBcpgKey(BigInteger x)
{
this.x = new MPInteger(x);
}
public override byte[] GetEncoded()
{
try
{
return base.GetEncoded();
}
catch (Exception)
{
return null;
}
}
public override void Encode(BcpgOutputStream bcpgOut)
{
bcpgOut.WriteObject(x);
}
}

View File

@@ -0,0 +1,26 @@
namespace Org.BouncyCastle.Bcpg;
public class ExperimentalPacket : ContainedPacket
{
private readonly PacketTag tag;
private readonly byte[] contents;
public PacketTag Tag => tag;
internal ExperimentalPacket(PacketTag tag, BcpgInputStream bcpgIn)
{
this.tag = tag;
contents = bcpgIn.ReadAll();
}
public byte[] GetContents()
{
return (byte[])contents.Clone();
}
public override void Encode(BcpgOutputStream bcpgOut)
{
bcpgOut.WritePacket(tag, contents, oldFormat: true);
}
}

View File

@@ -0,0 +1,16 @@
namespace Org.BouncyCastle.Bcpg;
public enum HashAlgorithmTag
{
MD5 = 1,
Sha1,
RipeMD160,
DoubleSha,
MD2,
Tiger192,
Haval5pass160,
Sha256,
Sha384,
Sha512,
Sha224
}

View File

@@ -0,0 +1,6 @@
namespace Org.BouncyCastle.Bcpg;
public interface IBcpgKey
{
string Format { get; }
}

View File

@@ -0,0 +1,16 @@
namespace Org.BouncyCastle.Bcpg;
public class InputStreamPacket : Packet
{
private readonly BcpgInputStream bcpgIn;
public InputStreamPacket(BcpgInputStream bcpgIn)
{
this.bcpgIn = bcpgIn;
}
public BcpgInputStream GetInputStream()
{
return bcpgIn;
}
}

View File

@@ -0,0 +1,42 @@
using System.IO;
using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Bcpg;
public class LiteralDataPacket : InputStreamPacket
{
private int format;
private byte[] fileName;
private long modDate;
public int Format => format;
public long ModificationTime => modDate;
public string FileName => Strings.FromUtf8ByteArray(fileName);
internal LiteralDataPacket(BcpgInputStream bcpgIn)
: base(bcpgIn)
{
format = bcpgIn.ReadByte();
int num = bcpgIn.ReadByte();
fileName = new byte[num];
for (int i = 0; i != num; i++)
{
int num2 = bcpgIn.ReadByte();
if (num2 < 0)
{
throw new IOException("literal data truncated in header");
}
fileName[i] = (byte)num2;
}
modDate = (long)(uint)((bcpgIn.ReadByte() << 24) | (bcpgIn.ReadByte() << 16) | (bcpgIn.ReadByte() << 8) | bcpgIn.ReadByte()) * 1000L;
}
public byte[] GetRawFileName()
{
return Arrays.Clone(fileName);
}
}

View File

@@ -0,0 +1,48 @@
using System;
using Org.BouncyCastle.Math;
namespace Org.BouncyCastle.Bcpg;
public class MPInteger : BcpgObject
{
private readonly BigInteger val;
public BigInteger Value => val;
public MPInteger(BcpgInputStream bcpgIn)
{
if (bcpgIn == null)
{
throw new ArgumentNullException("bcpgIn");
}
int num = (bcpgIn.ReadByte() << 8) | bcpgIn.ReadByte();
byte[] array = new byte[(num + 7) / 8];
bcpgIn.ReadFully(array);
val = new BigInteger(1, array);
}
public MPInteger(BigInteger val)
{
if (val == null)
{
throw new ArgumentNullException("val");
}
if (val.SignValue < 0)
{
throw new ArgumentException("Values must be positive", "val");
}
this.val = val;
}
public override void Encode(BcpgOutputStream bcpgOut)
{
bcpgOut.WriteShort((short)val.BitLength);
bcpgOut.Write(val.ToByteArrayUnsigned());
}
internal static void Encode(BcpgOutputStream bcpgOut, BigInteger val)
{
bcpgOut.WriteShort((short)val.BitLength);
bcpgOut.Write(val.ToByteArrayUnsigned());
}
}

View File

@@ -0,0 +1,16 @@
namespace Org.BouncyCastle.Bcpg;
public class MarkerPacket : ContainedPacket
{
private byte[] marker = new byte[3] { 80, 71, 80 };
public MarkerPacket(BcpgInputStream bcpgIn)
{
bcpgIn.ReadFully(marker);
}
public override void Encode(BcpgOutputStream bcpgOut)
{
bcpgOut.WritePacket(PacketTag.Marker, marker, oldFormat: true);
}
}

View File

@@ -0,0 +1,37 @@
using System;
namespace Org.BouncyCastle.Bcpg;
public class ModDetectionCodePacket : ContainedPacket
{
private readonly byte[] digest;
internal ModDetectionCodePacket(BcpgInputStream bcpgIn)
{
if (bcpgIn == null)
{
throw new ArgumentNullException("bcpgIn");
}
digest = new byte[20];
bcpgIn.ReadFully(digest);
}
public ModDetectionCodePacket(byte[] digest)
{
if (digest == null)
{
throw new ArgumentNullException("digest");
}
this.digest = (byte[])digest.Clone();
}
public byte[] GetDigest()
{
return (byte[])digest.Clone();
}
public override void Encode(BcpgOutputStream bcpgOut)
{
bcpgOut.WritePacket(PacketTag.ModificationDetectionCode, digest, oldFormat: false);
}
}

View File

@@ -0,0 +1,63 @@
using System.IO;
namespace Org.BouncyCastle.Bcpg;
public class OnePassSignaturePacket : ContainedPacket
{
private int version;
private int sigType;
private HashAlgorithmTag hashAlgorithm;
private PublicKeyAlgorithmTag keyAlgorithm;
private long keyId;
private int nested;
public int SignatureType => sigType;
public PublicKeyAlgorithmTag KeyAlgorithm => keyAlgorithm;
public HashAlgorithmTag HashAlgorithm => hashAlgorithm;
public long KeyId => keyId;
internal OnePassSignaturePacket(BcpgInputStream bcpgIn)
{
version = bcpgIn.ReadByte();
sigType = bcpgIn.ReadByte();
hashAlgorithm = (HashAlgorithmTag)bcpgIn.ReadByte();
keyAlgorithm = (PublicKeyAlgorithmTag)bcpgIn.ReadByte();
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();
nested = bcpgIn.ReadByte();
}
public OnePassSignaturePacket(int sigType, HashAlgorithmTag hashAlgorithm, PublicKeyAlgorithmTag keyAlgorithm, long keyId, bool isNested)
{
version = 3;
this.sigType = sigType;
this.hashAlgorithm = hashAlgorithm;
this.keyAlgorithm = keyAlgorithm;
this.keyId = keyId;
nested = ((!isNested) ? 1 : 0);
}
public override void Encode(BcpgOutputStream bcpgOut)
{
MemoryStream memoryStream = new MemoryStream();
BcpgOutputStream bcpgOutputStream = new BcpgOutputStream(memoryStream);
bcpgOutputStream.Write((byte)version, (byte)sigType, (byte)hashAlgorithm, (byte)keyAlgorithm);
bcpgOutputStream.WriteLong(keyId);
bcpgOutputStream.WriteByte((byte)nested);
bcpgOut.WritePacket(PacketTag.OnePassSignature, memoryStream.ToArray(), oldFormat: true);
}
}

View File

@@ -0,0 +1,6 @@
namespace Org.BouncyCastle.Bcpg.OpenPgp;
public interface IStreamGenerator
{
void Close();
}

View File

@@ -0,0 +1,34 @@
using System.IO;
using Org.BouncyCastle.Apache.Bzip2;
using Org.BouncyCastle.Utilities.Zlib;
namespace Org.BouncyCastle.Bcpg.OpenPgp;
public class PgpCompressedData : PgpObject
{
private readonly CompressedDataPacket data;
public CompressionAlgorithmTag Algorithm => data.Algorithm;
public PgpCompressedData(BcpgInputStream bcpgInput)
{
data = (CompressedDataPacket)bcpgInput.ReadPacket();
}
public Stream GetInputStream()
{
return data.GetInputStream();
}
public Stream GetDataStream()
{
return Algorithm switch
{
CompressionAlgorithmTag.Uncompressed => GetInputStream(),
CompressionAlgorithmTag.Zip => new ZInputStream(GetInputStream(), nowrap: true),
CompressionAlgorithmTag.ZLib => new ZInputStream(GetInputStream()),
CompressionAlgorithmTag.BZip2 => new CBZip2InputStream(GetInputStream()),
_ => throw new PgpException("can't recognise compression algorithm: " + Algorithm),
};
}
}

View File

@@ -0,0 +1,154 @@
using System;
using System.IO;
using Org.BouncyCastle.Apache.Bzip2;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.Zlib;
namespace Org.BouncyCastle.Bcpg.OpenPgp;
public class PgpCompressedDataGenerator : IStreamGenerator
{
private class SafeCBZip2OutputStream : CBZip2OutputStream
{
public SafeCBZip2OutputStream(Stream output)
: base(output)
{
}
public override void Close()
{
Finish();
}
}
private class SafeZOutputStream : ZOutputStream
{
public SafeZOutputStream(Stream output, int level, bool nowrap)
: base(output, level, nowrap)
{
}
public override void Close()
{
Finish();
End();
}
}
private readonly CompressionAlgorithmTag algorithm;
private readonly int compression;
private Stream dOut;
private BcpgOutputStream pkOut;
public PgpCompressedDataGenerator(CompressionAlgorithmTag algorithm)
: this(algorithm, -1)
{
}
public PgpCompressedDataGenerator(CompressionAlgorithmTag algorithm, int compression)
{
switch (algorithm)
{
default:
throw new ArgumentException("unknown compression algorithm", "algorithm");
case CompressionAlgorithmTag.Uncompressed:
case CompressionAlgorithmTag.Zip:
case CompressionAlgorithmTag.ZLib:
case CompressionAlgorithmTag.BZip2:
switch (compression)
{
default:
throw new ArgumentException("unknown compression level: " + compression);
case -1:
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
this.algorithm = algorithm;
this.compression = compression;
break;
}
break;
}
}
public Stream Open(Stream outStr)
{
if (dOut != null)
{
throw new InvalidOperationException("generator already in open state");
}
if (outStr == null)
{
throw new ArgumentNullException("outStr");
}
pkOut = new BcpgOutputStream(outStr, PacketTag.CompressedData);
doOpen();
return new WrappedGeneratorStream(this, dOut);
}
public Stream Open(Stream outStr, byte[] buffer)
{
if (dOut != null)
{
throw new InvalidOperationException("generator already in open state");
}
if (outStr == null)
{
throw new ArgumentNullException("outStr");
}
if (buffer == null)
{
throw new ArgumentNullException("buffer");
}
pkOut = new BcpgOutputStream(outStr, PacketTag.CompressedData, buffer);
doOpen();
return new WrappedGeneratorStream(this, dOut);
}
private void doOpen()
{
pkOut.WriteByte((byte)algorithm);
switch (algorithm)
{
case CompressionAlgorithmTag.Uncompressed:
dOut = pkOut;
break;
case CompressionAlgorithmTag.Zip:
dOut = new SafeZOutputStream(pkOut, compression, nowrap: true);
break;
case CompressionAlgorithmTag.ZLib:
dOut = new SafeZOutputStream(pkOut, compression, nowrap: false);
break;
case CompressionAlgorithmTag.BZip2:
dOut = new SafeCBZip2OutputStream(pkOut);
break;
default:
throw new InvalidOperationException();
}
}
public void Close()
{
if (dOut != null)
{
if (dOut != pkOut)
{
Platform.Dispose(dOut);
}
dOut = null;
pkOut.Finish();
pkOut.Flush();
pkOut = null;
}
}
}

View File

@@ -0,0 +1,21 @@
using System;
namespace Org.BouncyCastle.Bcpg.OpenPgp;
[Serializable]
public class PgpDataValidationException : PgpException
{
public PgpDataValidationException()
{
}
public PgpDataValidationException(string message)
: base(message)
{
}
public PgpDataValidationException(string message, Exception exception)
: base(message, exception)
{
}
}

View File

@@ -0,0 +1,133 @@
using System;
using System.IO;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.IO;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.IO;
namespace Org.BouncyCastle.Bcpg.OpenPgp;
public abstract class PgpEncryptedData
{
internal class TruncatedStream : BaseInputStream
{
private const int LookAheadSize = 22;
private const int LookAheadBufSize = 512;
private const int LookAheadBufLimit = 490;
private readonly Stream inStr;
private readonly byte[] lookAhead = new byte[512];
private int bufStart;
private int bufEnd;
internal TruncatedStream(Stream inStr)
{
int num = Streams.ReadFully(inStr, lookAhead, 0, lookAhead.Length);
if (num < 22)
{
throw new EndOfStreamException();
}
this.inStr = inStr;
bufStart = 0;
bufEnd = num - 22;
}
private int FillBuffer()
{
if (bufEnd < 490)
{
return 0;
}
Array.Copy(lookAhead, 490, lookAhead, 0, 22);
bufEnd = Streams.ReadFully(inStr, lookAhead, 22, 490);
bufStart = 0;
return bufEnd;
}
public override int ReadByte()
{
if (bufStart < bufEnd)
{
return lookAhead[bufStart++];
}
if (FillBuffer() < 1)
{
return -1;
}
return lookAhead[bufStart++];
}
public override int Read(byte[] buf, int off, int len)
{
int num = bufEnd - bufStart;
int num2 = off;
while (len > num)
{
Array.Copy(lookAhead, bufStart, buf, num2, num);
bufStart += num;
num2 += num;
len -= num;
if ((num = FillBuffer()) < 1)
{
return num2 - off;
}
}
Array.Copy(lookAhead, bufStart, buf, num2, len);
bufStart += len;
return num2 + len - off;
}
internal byte[] GetLookAhead()
{
byte[] array = new byte[22];
Array.Copy(lookAhead, bufStart, array, 0, 22);
return array;
}
}
internal InputStreamPacket encData;
internal Stream encStream;
internal TruncatedStream truncStream;
internal PgpEncryptedData(InputStreamPacket encData)
{
this.encData = encData;
}
public virtual Stream GetInputStream()
{
return encData.GetInputStream();
}
public bool IsIntegrityProtected()
{
return encData is SymmetricEncIntegrityPacket;
}
public bool Verify()
{
if (!IsIntegrityProtected())
{
throw new PgpException("data not integrity protected.");
}
DigestStream digestStream = (DigestStream)encStream;
while (encStream.ReadByte() >= 0)
{
}
byte[] lookAhead = truncStream.GetLookAhead();
IDigest digest = digestStream.ReadDigest();
digest.BlockUpdate(lookAhead, 0, 2);
byte[] array = DigestUtilities.DoFinal(digest);
byte[] array2 = new byte[array.Length];
Array.Copy(lookAhead, 2, array2, 0, array2.Length);
return Arrays.ConstantTimeAreEqual(array, array2);
}
}

View File

@@ -0,0 +1,423 @@
using System;
using System.Collections;
using System.IO;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.IO;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Math.EC;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Bcpg.OpenPgp;
public class PgpEncryptedDataGenerator : IStreamGenerator
{
private abstract class EncMethod : ContainedPacket
{
protected byte[] sessionInfo;
protected SymmetricKeyAlgorithmTag encAlgorithm;
protected KeyParameter key;
public abstract void AddSessionInfo(byte[] si, SecureRandom random);
}
private class PbeMethod : EncMethod
{
private S2k s2k;
internal PbeMethod(SymmetricKeyAlgorithmTag encAlgorithm, S2k s2k, KeyParameter key)
{
base.encAlgorithm = encAlgorithm;
this.s2k = s2k;
base.key = key;
}
public KeyParameter GetKey()
{
return key;
}
public override void AddSessionInfo(byte[] si, SecureRandom random)
{
string symmetricCipherName = PgpUtilities.GetSymmetricCipherName(encAlgorithm);
IBufferedCipher cipher = CipherUtilities.GetCipher(symmetricCipherName + "/CFB/NoPadding");
byte[] iv = new byte[cipher.GetBlockSize()];
cipher.Init(forEncryption: true, new ParametersWithRandom(new ParametersWithIV(key, iv), random));
sessionInfo = cipher.DoFinal(si, 0, si.Length - 2);
}
public override void Encode(BcpgOutputStream pOut)
{
SymmetricKeyEncSessionPacket p = new SymmetricKeyEncSessionPacket(encAlgorithm, s2k, sessionInfo);
pOut.WritePacket(p);
}
}
private class PubMethod : EncMethod
{
internal PgpPublicKey pubKey;
internal byte[][] data;
internal PubMethod(PgpPublicKey pubKey)
{
this.pubKey = pubKey;
}
public override void AddSessionInfo(byte[] sessionInfo, SecureRandom random)
{
byte[] encryptedSessionInfo = EncryptSessionInfo(sessionInfo, random);
data = ProcessSessionInfo(encryptedSessionInfo);
}
private byte[] EncryptSessionInfo(byte[] sessionInfo, SecureRandom random)
{
if (pubKey.Algorithm != PublicKeyAlgorithmTag.EC)
{
IBufferedCipher cipher;
switch (pubKey.Algorithm)
{
case PublicKeyAlgorithmTag.RsaGeneral:
case PublicKeyAlgorithmTag.RsaEncrypt:
cipher = CipherUtilities.GetCipher("RSA//PKCS1Padding");
break;
case PublicKeyAlgorithmTag.ElGamalEncrypt:
case PublicKeyAlgorithmTag.ElGamalGeneral:
cipher = CipherUtilities.GetCipher("ElGamal/ECB/PKCS1Padding");
break;
case PublicKeyAlgorithmTag.Dsa:
throw new PgpException("Can't use DSA for encryption.");
case PublicKeyAlgorithmTag.ECDsa:
throw new PgpException("Can't use ECDSA for encryption.");
default:
throw new PgpException("unknown asymmetric algorithm: " + pubKey.Algorithm);
}
AsymmetricKeyParameter parameters = pubKey.GetKey();
cipher.Init(forEncryption: true, new ParametersWithRandom(parameters, random));
return cipher.DoFinal(sessionInfo);
}
ECDHPublicBcpgKey eCDHPublicBcpgKey = (ECDHPublicBcpgKey)pubKey.PublicKeyPacket.Key;
IAsymmetricCipherKeyPairGenerator keyPairGenerator = GeneratorUtilities.GetKeyPairGenerator("ECDH");
keyPairGenerator.Init(new ECKeyGenerationParameters(eCDHPublicBcpgKey.CurveOid, random));
AsymmetricCipherKeyPair asymmetricCipherKeyPair = keyPairGenerator.GenerateKeyPair();
ECPrivateKeyParameters eCPrivateKeyParameters = (ECPrivateKeyParameters)asymmetricCipherKeyPair.Private;
ECPublicKeyParameters eCPublicKeyParameters = (ECPublicKeyParameters)asymmetricCipherKeyPair.Public;
ECPublicKeyParameters eCPublicKeyParameters2 = (ECPublicKeyParameters)pubKey.GetKey();
ECPoint s = eCPublicKeyParameters2.Q.Multiply(eCPrivateKeyParameters.D).Normalize();
KeyParameter parameters2 = new KeyParameter(Rfc6637Utilities.CreateKey(pubKey.PublicKeyPacket, s));
IWrapper wrapper = PgpUtilities.CreateWrapper(eCDHPublicBcpgKey.SymmetricKeyAlgorithm);
wrapper.Init(forWrapping: true, new ParametersWithRandom(parameters2, random));
byte[] array = PgpPad.PadSessionData(sessionInfo);
byte[] array2 = wrapper.Wrap(array, 0, array.Length);
byte[] encoded = new MPInteger(new BigInteger(1, eCPublicKeyParameters.Q.GetEncoded(compressed: false))).GetEncoded();
byte[] array3 = new byte[encoded.Length + 1 + array2.Length];
Array.Copy(encoded, 0, array3, 0, encoded.Length);
array3[encoded.Length] = (byte)array2.Length;
Array.Copy(array2, 0, array3, encoded.Length + 1, array2.Length);
return array3;
}
private byte[][] ProcessSessionInfo(byte[] encryptedSessionInfo)
{
switch (pubKey.Algorithm)
{
case PublicKeyAlgorithmTag.RsaGeneral:
case PublicKeyAlgorithmTag.RsaEncrypt:
return new byte[1][] { ConvertToEncodedMpi(encryptedSessionInfo) };
case PublicKeyAlgorithmTag.ElGamalEncrypt:
case PublicKeyAlgorithmTag.ElGamalGeneral:
{
int num = encryptedSessionInfo.Length / 2;
byte[] array = new byte[num];
byte[] array2 = new byte[num];
Array.Copy(encryptedSessionInfo, 0, array, 0, num);
Array.Copy(encryptedSessionInfo, num, array2, 0, num);
return new byte[2][]
{
ConvertToEncodedMpi(array),
ConvertToEncodedMpi(array2)
};
}
case PublicKeyAlgorithmTag.EC:
return new byte[1][] { encryptedSessionInfo };
default:
throw new PgpException("unknown asymmetric algorithm: " + pubKey.Algorithm);
}
}
private byte[] ConvertToEncodedMpi(byte[] encryptedSessionInfo)
{
try
{
return new MPInteger(new BigInteger(1, encryptedSessionInfo)).GetEncoded();
}
catch (IOException ex)
{
throw new PgpException("Invalid MPI encoding: " + ex.Message, ex);
}
}
public override void Encode(BcpgOutputStream pOut)
{
PublicKeyEncSessionPacket p = new PublicKeyEncSessionPacket(pubKey.KeyId, pubKey.Algorithm, data);
pOut.WritePacket(p);
}
}
private BcpgOutputStream pOut;
private CipherStream cOut;
private IBufferedCipher c;
private bool withIntegrityPacket;
private bool oldFormat;
private DigestStream digestOut;
private readonly IList methods = Platform.CreateArrayList();
private readonly SymmetricKeyAlgorithmTag defAlgorithm;
private readonly SecureRandom rand;
public PgpEncryptedDataGenerator(SymmetricKeyAlgorithmTag encAlgorithm)
{
defAlgorithm = encAlgorithm;
rand = new SecureRandom();
}
public PgpEncryptedDataGenerator(SymmetricKeyAlgorithmTag encAlgorithm, bool withIntegrityPacket)
{
defAlgorithm = encAlgorithm;
this.withIntegrityPacket = withIntegrityPacket;
rand = new SecureRandom();
}
public PgpEncryptedDataGenerator(SymmetricKeyAlgorithmTag encAlgorithm, SecureRandom rand)
{
defAlgorithm = encAlgorithm;
this.rand = rand;
}
public PgpEncryptedDataGenerator(SymmetricKeyAlgorithmTag encAlgorithm, bool withIntegrityPacket, SecureRandom rand)
{
defAlgorithm = encAlgorithm;
this.rand = rand;
this.withIntegrityPacket = withIntegrityPacket;
}
public PgpEncryptedDataGenerator(SymmetricKeyAlgorithmTag encAlgorithm, SecureRandom rand, bool oldFormat)
{
defAlgorithm = encAlgorithm;
this.rand = rand;
this.oldFormat = oldFormat;
}
[Obsolete("Use version that takes an explicit s2kDigest parameter")]
public void AddMethod(char[] passPhrase)
{
AddMethod(passPhrase, HashAlgorithmTag.Sha1);
}
public void AddMethod(char[] passPhrase, HashAlgorithmTag s2kDigest)
{
DoAddMethod(PgpUtilities.EncodePassPhrase(passPhrase, utf8: false), clearPassPhrase: true, s2kDigest);
}
public void AddMethodUtf8(char[] passPhrase, HashAlgorithmTag s2kDigest)
{
DoAddMethod(PgpUtilities.EncodePassPhrase(passPhrase, utf8: true), clearPassPhrase: true, s2kDigest);
}
public void AddMethodRaw(byte[] rawPassPhrase, HashAlgorithmTag s2kDigest)
{
DoAddMethod(rawPassPhrase, clearPassPhrase: false, s2kDigest);
}
internal void DoAddMethod(byte[] rawPassPhrase, bool clearPassPhrase, HashAlgorithmTag s2kDigest)
{
S2k s2k = PgpUtilities.GenerateS2k(s2kDigest, 96, rand);
methods.Add(new PbeMethod(defAlgorithm, s2k, PgpUtilities.DoMakeKeyFromPassPhrase(defAlgorithm, s2k, rawPassPhrase, clearPassPhrase)));
}
public void AddMethod(PgpPublicKey key)
{
if (!key.IsEncryptionKey)
{
throw new ArgumentException("passed in key not an encryption key!");
}
methods.Add(new PubMethod(key));
}
private void AddCheckSum(byte[] sessionInfo)
{
int num = 0;
for (int i = 1; i < sessionInfo.Length - 2; i++)
{
num += sessionInfo[i];
}
sessionInfo[^2] = (byte)(num >> 8);
sessionInfo[^1] = (byte)num;
}
private byte[] CreateSessionInfo(SymmetricKeyAlgorithmTag algorithm, KeyParameter key)
{
byte[] key2 = key.GetKey();
byte[] array = new byte[key2.Length + 3];
array[0] = (byte)algorithm;
key2.CopyTo(array, 1);
AddCheckSum(array);
return array;
}
private Stream Open(Stream outStr, long length, byte[] buffer)
{
if (cOut != null)
{
throw new InvalidOperationException("generator already in open state");
}
if (methods.Count == 0)
{
throw new InvalidOperationException("No encryption methods specified");
}
if (outStr == null)
{
throw new ArgumentNullException("outStr");
}
pOut = new BcpgOutputStream(outStr);
KeyParameter keyParameter;
if (methods.Count == 1)
{
if (methods[0] is PbeMethod)
{
PbeMethod pbeMethod = (PbeMethod)methods[0];
keyParameter = pbeMethod.GetKey();
}
else
{
keyParameter = PgpUtilities.MakeRandomKey(defAlgorithm, rand);
byte[] si = CreateSessionInfo(defAlgorithm, keyParameter);
PubMethod pubMethod = (PubMethod)methods[0];
try
{
pubMethod.AddSessionInfo(si, rand);
}
catch (Exception exception)
{
throw new PgpException("exception encrypting session key", exception);
}
}
pOut.WritePacket((ContainedPacket)methods[0]);
}
else
{
keyParameter = PgpUtilities.MakeRandomKey(defAlgorithm, rand);
byte[] si2 = CreateSessionInfo(defAlgorithm, keyParameter);
for (int i = 0; i != methods.Count; i++)
{
EncMethod encMethod = (EncMethod)methods[i];
try
{
encMethod.AddSessionInfo(si2, rand);
}
catch (Exception exception2)
{
throw new PgpException("exception encrypting session key", exception2);
}
pOut.WritePacket(encMethod);
}
}
string symmetricCipherName = PgpUtilities.GetSymmetricCipherName(defAlgorithm);
if (symmetricCipherName == null)
{
throw new PgpException("null cipher specified");
}
try
{
symmetricCipherName = ((!withIntegrityPacket) ? (symmetricCipherName + "/OpenPGPCFB/NoPadding") : (symmetricCipherName + "/CFB/NoPadding"));
c = CipherUtilities.GetCipher(symmetricCipherName);
byte[] iv = new byte[c.GetBlockSize()];
c.Init(forEncryption: true, new ParametersWithRandom(new ParametersWithIV(keyParameter, iv), rand));
if (buffer == null)
{
if (withIntegrityPacket)
{
pOut = new BcpgOutputStream(outStr, PacketTag.SymmetricEncryptedIntegrityProtected, length + c.GetBlockSize() + 2 + 1 + 22);
pOut.WriteByte(1);
}
else
{
pOut = new BcpgOutputStream(outStr, PacketTag.SymmetricKeyEncrypted, length + c.GetBlockSize() + 2, oldFormat);
}
}
else if (withIntegrityPacket)
{
pOut = new BcpgOutputStream(outStr, PacketTag.SymmetricEncryptedIntegrityProtected, buffer);
pOut.WriteByte(1);
}
else
{
pOut = new BcpgOutputStream(outStr, PacketTag.SymmetricKeyEncrypted, buffer);
}
int blockSize = c.GetBlockSize();
byte[] array = new byte[blockSize + 2];
rand.NextBytes(array, 0, blockSize);
Array.Copy(array, array.Length - 4, array, array.Length - 2, 2);
Stream stream = (cOut = new CipherStream(pOut, null, c));
if (withIntegrityPacket)
{
string digestName = PgpUtilities.GetDigestName(HashAlgorithmTag.Sha1);
IDigest digest = DigestUtilities.GetDigest(digestName);
stream = (digestOut = new DigestStream(stream, null, digest));
}
stream.Write(array, 0, array.Length);
return new WrappedGeneratorStream(this, stream);
}
catch (Exception exception3)
{
throw new PgpException("Exception creating cipher", exception3);
}
}
public Stream Open(Stream outStr, long length)
{
return Open(outStr, length, null);
}
public Stream Open(Stream outStr, byte[] buffer)
{
return Open(outStr, 0L, buffer);
}
public void Close()
{
if (cOut != null)
{
if (digestOut != null)
{
BcpgOutputStream bcpgOutputStream = new BcpgOutputStream(digestOut, PacketTag.ModificationDetectionCode, 20L);
bcpgOutputStream.Flush();
digestOut.Flush();
byte[] array = DigestUtilities.DoFinal(digestOut.WriteDigest());
cOut.Write(array, 0, array.Length);
}
cOut.Flush();
try
{
pOut.Write(c.DoFinal());
pOut.Finish();
}
catch (Exception ex)
{
throw new IOException(ex.Message, ex);
}
cOut = null;
pOut = null;
}
}
}

View File

@@ -0,0 +1,53 @@
using System;
using System.Collections;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.Collections;
namespace Org.BouncyCastle.Bcpg.OpenPgp;
public class PgpEncryptedDataList : PgpObject
{
private IList list = Platform.CreateArrayList();
private InputStreamPacket data;
public PgpEncryptedData this[int index] => (PgpEncryptedData)list[index];
[Obsolete("Use 'Count' property instead")]
public int Size => list.Count;
public int Count => list.Count;
public bool IsEmpty => list.Count == 0;
public PgpEncryptedDataList(BcpgInputStream bcpgInput)
{
while (bcpgInput.NextPacketTag() == PacketTag.PublicKeyEncryptedSession || bcpgInput.NextPacketTag() == PacketTag.SymmetricKeyEncryptedSessionKey)
{
list.Add(bcpgInput.ReadPacket());
}
data = (InputStreamPacket)bcpgInput.ReadPacket();
for (int i = 0; i != list.Count; i++)
{
if (list[i] is SymmetricKeyEncSessionPacket)
{
list[i] = new PgpPbeEncryptedData((SymmetricKeyEncSessionPacket)list[i], data);
}
else
{
list[i] = new PgpPublicKeyEncryptedData((PublicKeyEncSessionPacket)list[i], data);
}
}
}
[Obsolete("Use 'object[index]' syntax instead")]
public object Get(int index)
{
return this[index];
}
public IEnumerable GetEncryptedDataObjects()
{
return new EnumerableProxy(list);
}
}

View File

@@ -0,0 +1,24 @@
using System;
namespace Org.BouncyCastle.Bcpg.OpenPgp;
[Serializable]
public class PgpException : Exception
{
[Obsolete("Use InnerException property")]
public Exception UnderlyingException => base.InnerException;
public PgpException()
{
}
public PgpException(string message)
: base(message)
{
}
public PgpException(string message, Exception exception)
: base(message, exception)
{
}
}

View File

@@ -0,0 +1,11 @@
namespace Org.BouncyCastle.Bcpg.OpenPgp;
public class PgpExperimental : PgpObject
{
private readonly ExperimentalPacket p;
public PgpExperimental(BcpgInputStream bcpgIn)
{
p = (ExperimentalPacket)bcpgIn.ReadPacket();
}
}

View File

@@ -0,0 +1,16 @@
namespace Org.BouncyCastle.Bcpg.OpenPgp;
public abstract class PgpKeyFlags
{
public const int CanCertify = 1;
public const int CanSign = 2;
public const int CanEncryptCommunications = 4;
public const int CanEncryptStorage = 8;
public const int MaybeSplit = 16;
public const int MaybeShared = 128;
}

View File

@@ -0,0 +1,34 @@
using System;
using Org.BouncyCastle.Crypto;
namespace Org.BouncyCastle.Bcpg.OpenPgp;
public class PgpKeyPair
{
private readonly PgpPublicKey pub;
private readonly PgpPrivateKey priv;
public long KeyId => pub.KeyId;
public PgpPublicKey PublicKey => pub;
public PgpPrivateKey PrivateKey => priv;
public PgpKeyPair(PublicKeyAlgorithmTag algorithm, AsymmetricCipherKeyPair keyPair, DateTime time)
: this(algorithm, keyPair.Public, keyPair.Private, time)
{
}
public PgpKeyPair(PublicKeyAlgorithmTag algorithm, AsymmetricKeyParameter pubKey, AsymmetricKeyParameter privKey, DateTime time)
{
pub = new PgpPublicKey(algorithm, pubKey, time);
priv = new PgpPrivateKey(pub.KeyId, pub.PublicKeyPacket, privKey);
}
public PgpKeyPair(PgpPublicKey pub, PgpPrivateKey priv)
{
this.pub = pub;
this.priv = priv;
}
}

View File

@@ -0,0 +1,63 @@
using System.Collections;
using System.IO;
using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Bcpg.OpenPgp;
public abstract class PgpKeyRing : PgpObject
{
internal PgpKeyRing()
{
}
internal static TrustPacket ReadOptionalTrustPacket(BcpgInputStream bcpgInput)
{
if (bcpgInput.NextPacketTag() != PacketTag.Trust)
{
return null;
}
return (TrustPacket)bcpgInput.ReadPacket();
}
internal static IList ReadSignaturesAndTrust(BcpgInputStream bcpgInput)
{
try
{
IList list = Platform.CreateArrayList();
while (bcpgInput.NextPacketTag() == PacketTag.Signature)
{
SignaturePacket sigPacket = (SignaturePacket)bcpgInput.ReadPacket();
TrustPacket trustPacket = ReadOptionalTrustPacket(bcpgInput);
list.Add(new PgpSignature(sigPacket, trustPacket));
}
return list;
}
catch (PgpException ex)
{
throw new IOException("can't create signature object: " + ex.Message, ex);
}
}
internal static void ReadUserIDs(BcpgInputStream bcpgInput, out IList ids, out IList idTrusts, out IList idSigs)
{
ids = Platform.CreateArrayList();
idTrusts = Platform.CreateArrayList();
idSigs = Platform.CreateArrayList();
while (bcpgInput.NextPacketTag() == PacketTag.UserId || bcpgInput.NextPacketTag() == PacketTag.UserAttribute)
{
Packet packet = bcpgInput.ReadPacket();
if (packet is UserIdPacket)
{
UserIdPacket userIdPacket = (UserIdPacket)packet;
ids.Add(userIdPacket.GetId());
}
else
{
UserAttributePacket userAttributePacket = (UserAttributePacket)packet;
ids.Add(new PgpUserAttributeSubpacketVector(userAttributePacket.GetSubpackets()));
}
idTrusts.Add(ReadOptionalTrustPacket(bcpgInput));
idSigs.Add(ReadSignaturesAndTrust(bcpgInput));
}
}
}

View File

@@ -0,0 +1,162 @@
using System;
using System.Collections;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Bcpg.OpenPgp;
public class PgpKeyRingGenerator
{
private IList keys = Platform.CreateArrayList();
private string id;
private SymmetricKeyAlgorithmTag encAlgorithm;
private HashAlgorithmTag hashAlgorithm;
private int certificationLevel;
private byte[] rawPassPhrase;
private bool useSha1;
private PgpKeyPair masterKey;
private PgpSignatureSubpacketVector hashedPacketVector;
private PgpSignatureSubpacketVector unhashedPacketVector;
private SecureRandom rand;
[Obsolete("Use version taking an explicit 'useSha1' parameter instead")]
public PgpKeyRingGenerator(int certificationLevel, PgpKeyPair masterKey, string id, SymmetricKeyAlgorithmTag encAlgorithm, char[] passPhrase, PgpSignatureSubpacketVector hashedPackets, PgpSignatureSubpacketVector unhashedPackets, SecureRandom rand)
: this(certificationLevel, masterKey, id, encAlgorithm, passPhrase, useSha1: false, hashedPackets, unhashedPackets, rand)
{
}
public PgpKeyRingGenerator(int certificationLevel, PgpKeyPair masterKey, string id, SymmetricKeyAlgorithmTag encAlgorithm, char[] passPhrase, bool useSha1, PgpSignatureSubpacketVector hashedPackets, PgpSignatureSubpacketVector unhashedPackets, SecureRandom rand)
: this(certificationLevel, masterKey, id, encAlgorithm, utf8PassPhrase: false, passPhrase, useSha1, hashedPackets, unhashedPackets, rand)
{
}
public PgpKeyRingGenerator(int certificationLevel, PgpKeyPair masterKey, string id, SymmetricKeyAlgorithmTag encAlgorithm, bool utf8PassPhrase, char[] passPhrase, bool useSha1, PgpSignatureSubpacketVector hashedPackets, PgpSignatureSubpacketVector unhashedPackets, SecureRandom rand)
: this(certificationLevel, masterKey, id, encAlgorithm, PgpUtilities.EncodePassPhrase(passPhrase, utf8PassPhrase), useSha1, hashedPackets, unhashedPackets, rand)
{
}
public PgpKeyRingGenerator(int certificationLevel, PgpKeyPair masterKey, string id, SymmetricKeyAlgorithmTag encAlgorithm, byte[] rawPassPhrase, bool useSha1, PgpSignatureSubpacketVector hashedPackets, PgpSignatureSubpacketVector unhashedPackets, SecureRandom rand)
{
this.certificationLevel = certificationLevel;
this.masterKey = masterKey;
this.id = id;
this.encAlgorithm = encAlgorithm;
this.rawPassPhrase = rawPassPhrase;
this.useSha1 = useSha1;
hashedPacketVector = hashedPackets;
unhashedPacketVector = unhashedPackets;
this.rand = rand;
keys.Add(new PgpSecretKey(certificationLevel, masterKey, id, encAlgorithm, rawPassPhrase, clearPassPhrase: false, useSha1, hashedPackets, unhashedPackets, rand));
}
public PgpKeyRingGenerator(int certificationLevel, PgpKeyPair masterKey, string id, SymmetricKeyAlgorithmTag encAlgorithm, HashAlgorithmTag hashAlgorithm, char[] passPhrase, bool useSha1, PgpSignatureSubpacketVector hashedPackets, PgpSignatureSubpacketVector unhashedPackets, SecureRandom rand)
: this(certificationLevel, masterKey, id, encAlgorithm, hashAlgorithm, utf8PassPhrase: false, passPhrase, useSha1, hashedPackets, unhashedPackets, rand)
{
}
public PgpKeyRingGenerator(int certificationLevel, PgpKeyPair masterKey, string id, SymmetricKeyAlgorithmTag encAlgorithm, HashAlgorithmTag hashAlgorithm, bool utf8PassPhrase, char[] passPhrase, bool useSha1, PgpSignatureSubpacketVector hashedPackets, PgpSignatureSubpacketVector unhashedPackets, SecureRandom rand)
: this(certificationLevel, masterKey, id, encAlgorithm, hashAlgorithm, PgpUtilities.EncodePassPhrase(passPhrase, utf8PassPhrase), useSha1, hashedPackets, unhashedPackets, rand)
{
}
public PgpKeyRingGenerator(int certificationLevel, PgpKeyPair masterKey, string id, SymmetricKeyAlgorithmTag encAlgorithm, HashAlgorithmTag hashAlgorithm, byte[] rawPassPhrase, bool useSha1, PgpSignatureSubpacketVector hashedPackets, PgpSignatureSubpacketVector unhashedPackets, SecureRandom rand)
{
this.certificationLevel = certificationLevel;
this.masterKey = masterKey;
this.id = id;
this.encAlgorithm = encAlgorithm;
this.rawPassPhrase = rawPassPhrase;
this.useSha1 = useSha1;
hashedPacketVector = hashedPackets;
unhashedPacketVector = unhashedPackets;
this.rand = rand;
this.hashAlgorithm = hashAlgorithm;
keys.Add(new PgpSecretKey(certificationLevel, masterKey, id, encAlgorithm, hashAlgorithm, rawPassPhrase, clearPassPhrase: false, useSha1, hashedPackets, unhashedPackets, rand));
}
public void AddSubKey(PgpKeyPair keyPair)
{
AddSubKey(keyPair, hashedPacketVector, unhashedPacketVector);
}
public void AddSubKey(PgpKeyPair keyPair, HashAlgorithmTag hashAlgorithm)
{
AddSubKey(keyPair, hashedPacketVector, unhashedPacketVector, hashAlgorithm);
}
public void AddSubKey(PgpKeyPair keyPair, PgpSignatureSubpacketVector hashedPackets, PgpSignatureSubpacketVector unhashedPackets)
{
try
{
PgpSignatureGenerator pgpSignatureGenerator = new PgpSignatureGenerator(masterKey.PublicKey.Algorithm, HashAlgorithmTag.Sha1);
pgpSignatureGenerator.InitSign(24, masterKey.PrivateKey);
pgpSignatureGenerator.SetHashedSubpackets(hashedPackets);
pgpSignatureGenerator.SetUnhashedSubpackets(unhashedPackets);
IList list = Platform.CreateArrayList();
list.Add(pgpSignatureGenerator.GenerateCertification(masterKey.PublicKey, keyPair.PublicKey));
keys.Add(new PgpSecretKey(keyPair.PrivateKey, new PgpPublicKey(keyPair.PublicKey, null, list), encAlgorithm, rawPassPhrase, clearPassPhrase: false, useSha1, rand, isMasterKey: false));
}
catch (PgpException ex)
{
throw ex;
}
catch (Exception exception)
{
throw new PgpException("exception adding subkey: ", exception);
}
}
public void AddSubKey(PgpKeyPair keyPair, PgpSignatureSubpacketVector hashedPackets, PgpSignatureSubpacketVector unhashedPackets, HashAlgorithmTag hashAlgorithm)
{
try
{
PgpSignatureGenerator pgpSignatureGenerator = new PgpSignatureGenerator(masterKey.PublicKey.Algorithm, hashAlgorithm);
pgpSignatureGenerator.InitSign(24, masterKey.PrivateKey);
pgpSignatureGenerator.SetHashedSubpackets(hashedPackets);
pgpSignatureGenerator.SetUnhashedSubpackets(unhashedPackets);
IList list = Platform.CreateArrayList();
list.Add(pgpSignatureGenerator.GenerateCertification(masterKey.PublicKey, keyPair.PublicKey));
keys.Add(new PgpSecretKey(keyPair.PrivateKey, new PgpPublicKey(keyPair.PublicKey, null, list), encAlgorithm, rawPassPhrase, clearPassPhrase: false, useSha1, rand, isMasterKey: false));
}
catch (PgpException)
{
throw;
}
catch (Exception exception)
{
throw new PgpException("exception adding subkey: ", exception);
}
}
public PgpSecretKeyRing GenerateSecretKeyRing()
{
return new PgpSecretKeyRing(keys);
}
public PgpPublicKeyRing GeneratePublicKeyRing()
{
IList list = Platform.CreateArrayList();
IEnumerator enumerator = keys.GetEnumerator();
enumerator.MoveNext();
PgpSecretKey pgpSecretKey = (PgpSecretKey)enumerator.Current;
list.Add(pgpSecretKey.PublicKey);
while (enumerator.MoveNext())
{
pgpSecretKey = (PgpSecretKey)enumerator.Current;
PgpPublicKey pgpPublicKey = new PgpPublicKey(pgpSecretKey.PublicKey);
pgpPublicKey.publicPk = new PublicSubkeyPacket(pgpPublicKey.Algorithm, pgpPublicKey.CreationTime, pgpPublicKey.publicPk.Key);
list.Add(pgpPublicKey);
}
return new PgpPublicKeyRing(list);
}
}

View File

@@ -0,0 +1,21 @@
using System;
namespace Org.BouncyCastle.Bcpg.OpenPgp;
[Serializable]
public class PgpKeyValidationException : PgpException
{
public PgpKeyValidationException()
{
}
public PgpKeyValidationException(string message)
: base(message)
{
}
public PgpKeyValidationException(string message, Exception exception)
: base(message, exception)
{
}
}

View File

@@ -0,0 +1,44 @@
using System;
using System.IO;
using Org.BouncyCastle.Utilities.Date;
namespace Org.BouncyCastle.Bcpg.OpenPgp;
public class PgpLiteralData : PgpObject
{
public const char Binary = 'b';
public const char Text = 't';
public const char Utf8 = 'u';
public const string Console = "_CONSOLE";
private LiteralDataPacket data;
public int Format => data.Format;
public string FileName => data.FileName;
public DateTime ModificationTime => DateTimeUtilities.UnixMsToDateTime(data.ModificationTime);
public PgpLiteralData(BcpgInputStream bcpgInput)
{
data = (LiteralDataPacket)bcpgInput.ReadPacket();
}
public byte[] GetRawFileName()
{
return data.GetRawFileName();
}
public Stream GetInputStream()
{
return data.GetInputStream();
}
public Stream GetDataStream()
{
return GetInputStream();
}
}

View File

@@ -0,0 +1,87 @@
using System;
using System.IO;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.Date;
namespace Org.BouncyCastle.Bcpg.OpenPgp;
public class PgpLiteralDataGenerator : IStreamGenerator
{
public const char Binary = 'b';
public const char Text = 't';
public const char Utf8 = 'u';
public const string Console = "_CONSOLE";
private BcpgOutputStream pkOut;
private bool oldFormat;
public PgpLiteralDataGenerator()
{
}
public PgpLiteralDataGenerator(bool oldFormat)
{
this.oldFormat = oldFormat;
}
private void WriteHeader(BcpgOutputStream outStr, char format, byte[] encName, long modificationTime)
{
outStr.Write((byte)format, (byte)encName.Length);
outStr.Write(encName);
long num = modificationTime / 1000;
outStr.Write((byte)(num >> 24), (byte)(num >> 16), (byte)(num >> 8), (byte)num);
}
public Stream Open(Stream outStr, char format, string name, long length, DateTime modificationTime)
{
if (pkOut != null)
{
throw new InvalidOperationException("generator already in open state");
}
if (outStr == null)
{
throw new ArgumentNullException("outStr");
}
long modificationTime2 = DateTimeUtilities.DateTimeToUnixMs(modificationTime);
byte[] array = Strings.ToUtf8ByteArray(name);
pkOut = new BcpgOutputStream(outStr, PacketTag.LiteralData, length + 2 + array.Length + 4, oldFormat);
WriteHeader(pkOut, format, array, modificationTime2);
return new WrappedGeneratorStream(this, pkOut);
}
public Stream Open(Stream outStr, char format, string name, DateTime modificationTime, byte[] buffer)
{
if (pkOut != null)
{
throw new InvalidOperationException("generator already in open state");
}
if (outStr == null)
{
throw new ArgumentNullException("outStr");
}
long modificationTime2 = DateTimeUtilities.DateTimeToUnixMs(modificationTime);
byte[] encName = Strings.ToUtf8ByteArray(name);
pkOut = new BcpgOutputStream(outStr, PacketTag.LiteralData, buffer);
WriteHeader(pkOut, format, encName, modificationTime2);
return new WrappedGeneratorStream(this, pkOut);
}
public Stream Open(Stream outStr, char format, FileInfo file)
{
return Open(outStr, format, file.Name, file.Length, file.LastWriteTime);
}
public void Close()
{
if (pkOut != null)
{
pkOut.Finish();
pkOut.Flush();
pkOut = null;
}
}
}

View File

@@ -0,0 +1,11 @@
namespace Org.BouncyCastle.Bcpg.OpenPgp;
public class PgpMarker : PgpObject
{
private readonly MarkerPacket p;
public PgpMarker(BcpgInputStream bcpgIn)
{
p = (MarkerPacket)bcpgIn.ReadPacket();
}
}

View File

@@ -0,0 +1,8 @@
namespace Org.BouncyCastle.Bcpg.OpenPgp;
public abstract class PgpObject
{
internal PgpObject()
{
}
}

View File

@@ -0,0 +1,119 @@
using System;
using System.Collections;
using System.IO;
using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Bcpg.OpenPgp;
public class PgpObjectFactory
{
private readonly BcpgInputStream bcpgIn;
public PgpObjectFactory(Stream inputStream)
{
bcpgIn = BcpgInputStream.Wrap(inputStream);
}
public PgpObjectFactory(byte[] bytes)
: this(new MemoryStream(bytes, writable: false))
{
}
public PgpObject NextPgpObject()
{
PacketTag packetTag = bcpgIn.NextPacketTag();
if (packetTag == (PacketTag)(-1))
{
return null;
}
switch (packetTag)
{
case PacketTag.Signature:
{
IList list2 = Platform.CreateArrayList();
while (bcpgIn.NextPacketTag() == PacketTag.Signature)
{
try
{
list2.Add(new PgpSignature(bcpgIn));
}
catch (PgpException ex3)
{
throw new IOException("can't create signature object: " + ex3);
}
}
PgpSignature[] array2 = new PgpSignature[list2.Count];
for (int j = 0; j < list2.Count; j++)
{
array2[j] = (PgpSignature)list2[j];
}
return new PgpSignatureList(array2);
}
case PacketTag.SecretKey:
try
{
return new PgpSecretKeyRing(bcpgIn);
}
catch (PgpException ex2)
{
throw new IOException("can't create secret key object: " + ex2);
}
case PacketTag.PublicKey:
return new PgpPublicKeyRing(bcpgIn);
case PacketTag.CompressedData:
return new PgpCompressedData(bcpgIn);
case PacketTag.LiteralData:
return new PgpLiteralData(bcpgIn);
case PacketTag.PublicKeyEncryptedSession:
case PacketTag.SymmetricKeyEncryptedSessionKey:
return new PgpEncryptedDataList(bcpgIn);
case PacketTag.OnePassSignature:
{
IList list = Platform.CreateArrayList();
while (bcpgIn.NextPacketTag() == PacketTag.OnePassSignature)
{
try
{
list.Add(new PgpOnePassSignature(bcpgIn));
}
catch (PgpException ex)
{
throw new IOException("can't create one pass signature object: " + ex);
}
}
PgpOnePassSignature[] array = new PgpOnePassSignature[list.Count];
for (int i = 0; i < list.Count; i++)
{
array[i] = (PgpOnePassSignature)list[i];
}
return new PgpOnePassSignatureList(array);
}
case PacketTag.Marker:
return new PgpMarker(bcpgIn);
case PacketTag.Experimental1:
case PacketTag.Experimental2:
case PacketTag.Experimental3:
case PacketTag.Experimental4:
return new PgpExperimental(bcpgIn);
default:
throw new IOException("unknown object in stream " + bcpgIn.NextPacketTag());
}
}
[Obsolete("Use NextPgpObject() instead")]
public object NextObject()
{
return NextPgpObject();
}
public IList AllPgpObjects()
{
IList list = Platform.CreateArrayList();
PgpObject value;
while ((value = NextPgpObject()) != null)
{
list.Add(value);
}
return list;
}
}

View File

@@ -0,0 +1,145 @@
using System;
using System.IO;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Security;
namespace Org.BouncyCastle.Bcpg.OpenPgp;
public class PgpOnePassSignature
{
private OnePassSignaturePacket sigPack;
private int signatureType;
private ISigner sig;
private byte lastb;
public long KeyId => sigPack.KeyId;
public int SignatureType => sigPack.SignatureType;
public HashAlgorithmTag HashAlgorithm => sigPack.HashAlgorithm;
public PublicKeyAlgorithmTag KeyAlgorithm => sigPack.KeyAlgorithm;
internal PgpOnePassSignature(BcpgInputStream bcpgInput)
: this((OnePassSignaturePacket)bcpgInput.ReadPacket())
{
}
internal PgpOnePassSignature(OnePassSignaturePacket sigPack)
{
this.sigPack = sigPack;
signatureType = sigPack.SignatureType;
}
public void InitVerify(PgpPublicKey pubKey)
{
lastb = 0;
try
{
sig = SignerUtilities.GetSigner(PgpUtilities.GetSignatureName(sigPack.KeyAlgorithm, sigPack.HashAlgorithm));
}
catch (Exception exception)
{
throw new PgpException("can't set up signature object.", exception);
}
try
{
sig.Init(forSigning: false, pubKey.GetKey());
}
catch (InvalidKeyException exception2)
{
throw new PgpException("invalid key.", exception2);
}
}
public void Update(byte b)
{
if (signatureType == 1)
{
doCanonicalUpdateByte(b);
}
else
{
sig.Update(b);
}
}
private void doCanonicalUpdateByte(byte b)
{
switch (b)
{
case 13:
doUpdateCRLF();
break;
case 10:
if (lastb != 13)
{
doUpdateCRLF();
}
break;
default:
sig.Update(b);
break;
}
lastb = b;
}
private void doUpdateCRLF()
{
sig.Update(13);
sig.Update(10);
}
public void Update(byte[] bytes)
{
if (signatureType == 1)
{
for (int i = 0; i != bytes.Length; i++)
{
doCanonicalUpdateByte(bytes[i]);
}
}
else
{
sig.BlockUpdate(bytes, 0, bytes.Length);
}
}
public void Update(byte[] bytes, int off, int length)
{
if (signatureType == 1)
{
int num = off + length;
for (int i = off; i != num; i++)
{
doCanonicalUpdateByte(bytes[i]);
}
}
else
{
sig.BlockUpdate(bytes, off, length);
}
}
public bool Verify(PgpSignature pgpSig)
{
byte[] signatureTrailer = pgpSig.GetSignatureTrailer();
sig.BlockUpdate(signatureTrailer, 0, signatureTrailer.Length);
return sig.VerifySignature(pgpSig.GetSignature());
}
public byte[] GetEncoded()
{
MemoryStream memoryStream = new MemoryStream();
Encode(memoryStream);
return memoryStream.ToArray();
}
public void Encode(Stream outStr)
{
BcpgOutputStream.Wrap(outStr).WritePacket(sigPack);
}
}

View File

@@ -0,0 +1,33 @@
using System;
namespace Org.BouncyCastle.Bcpg.OpenPgp;
public class PgpOnePassSignatureList : PgpObject
{
private readonly PgpOnePassSignature[] sigs;
public PgpOnePassSignature this[int index] => sigs[index];
[Obsolete("Use 'Count' property instead")]
public int Size => sigs.Length;
public int Count => sigs.Length;
public bool IsEmpty => sigs.Length == 0;
public PgpOnePassSignatureList(PgpOnePassSignature[] sigs)
{
this.sigs = (PgpOnePassSignature[])sigs.Clone();
}
public PgpOnePassSignatureList(PgpOnePassSignature sig)
{
sigs = new PgpOnePassSignature[1] { sig };
}
[Obsolete("Use 'object[index]' syntax instead")]
public PgpOnePassSignature Get(int index)
{
return this[index];
}
}

View File

@@ -0,0 +1,37 @@
using System;
namespace Org.BouncyCastle.Bcpg.OpenPgp;
public sealed class PgpPad
{
private PgpPad()
{
}
public static byte[] PadSessionData(byte[] sessionInfo)
{
byte[] array = new byte[40];
Array.Copy(sessionInfo, 0, array, 0, sessionInfo.Length);
byte b = (byte)(array.Length - sessionInfo.Length);
for (int i = sessionInfo.Length; i != array.Length; i++)
{
array[i] = b;
}
return array;
}
public static byte[] UnpadSessionData(byte[] encoded)
{
byte b = encoded[^1];
for (int i = encoded.Length - b; i != encoded.Length; i++)
{
if (encoded[i] != b)
{
throw new PgpException("bad padding found in session data");
}
}
byte[] array = new byte[encoded.Length - b];
Array.Copy(encoded, 0, array, 0, array.Length);
return array;
}
}

View File

@@ -0,0 +1,101 @@
using System;
using System.IO;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.IO;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities.IO;
namespace Org.BouncyCastle.Bcpg.OpenPgp;
public class PgpPbeEncryptedData : PgpEncryptedData
{
private readonly SymmetricKeyEncSessionPacket keyData;
internal PgpPbeEncryptedData(SymmetricKeyEncSessionPacket keyData, InputStreamPacket encData)
: base(encData)
{
this.keyData = keyData;
}
public override Stream GetInputStream()
{
return encData.GetInputStream();
}
public Stream GetDataStream(char[] passPhrase)
{
return DoGetDataStream(PgpUtilities.EncodePassPhrase(passPhrase, utf8: false), clearPassPhrase: true);
}
public Stream GetDataStreamUtf8(char[] passPhrase)
{
return DoGetDataStream(PgpUtilities.EncodePassPhrase(passPhrase, utf8: true), clearPassPhrase: true);
}
public Stream GetDataStreamRaw(byte[] rawPassPhrase)
{
return DoGetDataStream(rawPassPhrase, clearPassPhrase: false);
}
internal Stream DoGetDataStream(byte[] rawPassPhrase, bool clearPassPhrase)
{
try
{
SymmetricKeyAlgorithmTag symmetricKeyAlgorithmTag = keyData.EncAlgorithm;
KeyParameter parameters = PgpUtilities.DoMakeKeyFromPassPhrase(symmetricKeyAlgorithmTag, keyData.S2k, rawPassPhrase, clearPassPhrase);
byte[] secKeyData = keyData.GetSecKeyData();
if (secKeyData != null && secKeyData.Length > 0)
{
IBufferedCipher cipher = CipherUtilities.GetCipher(PgpUtilities.GetSymmetricCipherName(symmetricKeyAlgorithmTag) + "/CFB/NoPadding");
cipher.Init(forEncryption: false, new ParametersWithIV(parameters, new byte[cipher.GetBlockSize()]));
byte[] array = cipher.DoFinal(secKeyData);
symmetricKeyAlgorithmTag = (SymmetricKeyAlgorithmTag)array[0];
parameters = ParameterUtilities.CreateKeyParameter(PgpUtilities.GetSymmetricCipherName(symmetricKeyAlgorithmTag), array, 1, array.Length - 1);
}
IBufferedCipher bufferedCipher = CreateStreamCipher(symmetricKeyAlgorithmTag);
byte[] array2 = new byte[bufferedCipher.GetBlockSize()];
bufferedCipher.Init(forEncryption: false, new ParametersWithIV(parameters, array2));
encStream = BcpgInputStream.Wrap(new CipherStream(encData.GetInputStream(), bufferedCipher, null));
if (encData is SymmetricEncIntegrityPacket)
{
truncStream = new TruncatedStream(encStream);
string digestName = PgpUtilities.GetDigestName(HashAlgorithmTag.Sha1);
IDigest digest = DigestUtilities.GetDigest(digestName);
encStream = new DigestStream(truncStream, digest, null);
}
if (Streams.ReadFully(encStream, array2, 0, array2.Length) < array2.Length)
{
throw new EndOfStreamException("unexpected end of stream.");
}
int num = encStream.ReadByte();
int num2 = encStream.ReadByte();
if (num < 0 || num2 < 0)
{
throw new EndOfStreamException("unexpected end of stream.");
}
bool flag = array2[^2] == (byte)num && array2[^1] == (byte)num2;
bool flag2 = num == 0 && num2 == 0;
if (!flag && !flag2)
{
throw new PgpDataValidationException("quick check failed.");
}
return encStream;
}
catch (PgpException ex)
{
throw ex;
}
catch (Exception exception)
{
throw new PgpException("Exception creating cipher", exception);
}
}
private IBufferedCipher CreateStreamCipher(SymmetricKeyAlgorithmTag keyAlgorithm)
{
string text = ((encData is SymmetricEncIntegrityPacket) ? "CFB" : "OpenPGPCFB");
string algorithm = PgpUtilities.GetSymmetricCipherName(keyAlgorithm) + "/" + text + "/NoPadding";
return CipherUtilities.GetCipher(algorithm);
}
}

View File

@@ -0,0 +1,30 @@
using System;
using Org.BouncyCastle.Crypto;
namespace Org.BouncyCastle.Bcpg.OpenPgp;
public class PgpPrivateKey
{
private readonly long keyID;
private readonly PublicKeyPacket publicKeyPacket;
private readonly AsymmetricKeyParameter privateKey;
public long KeyId => keyID;
public PublicKeyPacket PublicKeyPacket => publicKeyPacket;
public AsymmetricKeyParameter Key => privateKey;
public PgpPrivateKey(long keyID, PublicKeyPacket publicKeyPacket, AsymmetricKeyParameter privateKey)
{
if (!privateKey.IsPrivate)
{
throw new ArgumentException("Expected a private key", "privateKey");
}
this.keyID = keyID;
this.publicKeyPacket = publicKeyPacket;
this.privateKey = privateKey;
}
}

View File

@@ -0,0 +1,738 @@
using System;
using System.Collections;
using System.IO;
using Org.BouncyCastle.Asn1.X9;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Math.EC;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.Collections;
namespace Org.BouncyCastle.Bcpg.OpenPgp;
public class PgpPublicKey
{
private static readonly int[] MasterKeyCertificationTypes = new int[4] { 19, 18, 17, 16 };
private long keyId;
private byte[] fingerprint;
private int keyStrength;
internal PublicKeyPacket publicPk;
internal TrustPacket trustPk;
internal IList keySigs = Platform.CreateArrayList();
internal IList ids = Platform.CreateArrayList();
internal IList idTrusts = Platform.CreateArrayList();
internal IList idSigs = Platform.CreateArrayList();
internal IList subSigs;
public int Version => publicPk.Version;
public DateTime CreationTime => publicPk.GetTime();
[Obsolete("Use 'GetValidSeconds' instead")]
public int ValidDays
{
get
{
if (publicPk.Version <= 3)
{
return publicPk.ValidDays;
}
long validSeconds = GetValidSeconds();
if (validSeconds <= 0)
{
return 0;
}
int val = (int)(validSeconds / 86400);
return System.Math.Max(1, val);
}
}
public long KeyId => keyId;
public bool IsEncryptionKey
{
get
{
switch (publicPk.Algorithm)
{
case PublicKeyAlgorithmTag.RsaGeneral:
case PublicKeyAlgorithmTag.RsaEncrypt:
case PublicKeyAlgorithmTag.ElGamalEncrypt:
case PublicKeyAlgorithmTag.EC:
case PublicKeyAlgorithmTag.ElGamalGeneral:
return true;
default:
return false;
}
}
}
public bool IsMasterKey => subSigs == null;
public PublicKeyAlgorithmTag Algorithm => publicPk.Algorithm;
public int BitStrength => keyStrength;
public PublicKeyPacket PublicKeyPacket => publicPk;
public static byte[] CalculateFingerprint(PublicKeyPacket publicPk)
{
IBcpgKey key = publicPk.Key;
IDigest digest;
if (publicPk.Version <= 3)
{
RsaPublicBcpgKey rsaPublicBcpgKey = (RsaPublicBcpgKey)key;
try
{
digest = DigestUtilities.GetDigest("MD5");
UpdateDigest(digest, rsaPublicBcpgKey.Modulus);
UpdateDigest(digest, rsaPublicBcpgKey.PublicExponent);
}
catch (Exception ex)
{
throw new PgpException("can't encode key components: " + ex.Message, ex);
}
}
else
{
try
{
byte[] encodedContents = publicPk.GetEncodedContents();
digest = DigestUtilities.GetDigest("SHA1");
digest.Update(153);
digest.Update((byte)(encodedContents.Length >> 8));
digest.Update((byte)encodedContents.Length);
digest.BlockUpdate(encodedContents, 0, encodedContents.Length);
}
catch (Exception ex2)
{
throw new PgpException("can't encode key components: " + ex2.Message, ex2);
}
}
return DigestUtilities.DoFinal(digest);
}
private static void UpdateDigest(IDigest d, BigInteger b)
{
byte[] array = b.ToByteArrayUnsigned();
d.BlockUpdate(array, 0, array.Length);
}
private void Init()
{
IBcpgKey key = publicPk.Key;
fingerprint = CalculateFingerprint(publicPk);
if (publicPk.Version <= 3)
{
RsaPublicBcpgKey rsaPublicBcpgKey = (RsaPublicBcpgKey)key;
keyId = rsaPublicBcpgKey.Modulus.LongValue;
keyStrength = rsaPublicBcpgKey.Modulus.BitLength;
return;
}
keyId = (long)(((ulong)fingerprint[fingerprint.Length - 8] << 56) | ((ulong)fingerprint[fingerprint.Length - 7] << 48) | ((ulong)fingerprint[fingerprint.Length - 6] << 40) | ((ulong)fingerprint[fingerprint.Length - 5] << 32) | ((ulong)fingerprint[fingerprint.Length - 4] << 24) | ((ulong)fingerprint[fingerprint.Length - 3] << 16) | ((ulong)fingerprint[fingerprint.Length - 2] << 8) | fingerprint[fingerprint.Length - 1]);
if (key is RsaPublicBcpgKey)
{
keyStrength = ((RsaPublicBcpgKey)key).Modulus.BitLength;
}
else if (key is DsaPublicBcpgKey)
{
keyStrength = ((DsaPublicBcpgKey)key).P.BitLength;
}
else if (key is ElGamalPublicBcpgKey)
{
keyStrength = ((ElGamalPublicBcpgKey)key).P.BitLength;
}
else if (key is ECPublicBcpgKey)
{
keyStrength = ECKeyPairGenerator.FindECCurveByOid(((ECPublicBcpgKey)key).CurveOid).Curve.FieldSize;
}
}
public PgpPublicKey(PublicKeyAlgorithmTag algorithm, AsymmetricKeyParameter pubKey, DateTime time)
{
if (pubKey.IsPrivate)
{
throw new ArgumentException("Expected a public key", "pubKey");
}
IBcpgKey key;
if (pubKey is RsaKeyParameters)
{
RsaKeyParameters rsaKeyParameters = (RsaKeyParameters)pubKey;
key = new RsaPublicBcpgKey(rsaKeyParameters.Modulus, rsaKeyParameters.Exponent);
}
else if (pubKey is DsaPublicKeyParameters)
{
DsaPublicKeyParameters dsaPublicKeyParameters = (DsaPublicKeyParameters)pubKey;
DsaParameters parameters = dsaPublicKeyParameters.Parameters;
key = new DsaPublicBcpgKey(parameters.P, parameters.Q, parameters.G, dsaPublicKeyParameters.Y);
}
else if (pubKey is ECPublicKeyParameters)
{
ECPublicKeyParameters eCPublicKeyParameters = (ECPublicKeyParameters)pubKey;
key = algorithm switch
{
PublicKeyAlgorithmTag.EC => new ECDHPublicBcpgKey(eCPublicKeyParameters.PublicKeyParamSet, eCPublicKeyParameters.Q, HashAlgorithmTag.Sha256, SymmetricKeyAlgorithmTag.Aes128),
PublicKeyAlgorithmTag.ECDsa => new ECDsaPublicBcpgKey(eCPublicKeyParameters.PublicKeyParamSet, eCPublicKeyParameters.Q),
_ => throw new PgpException("unknown EC algorithm"),
};
}
else
{
if (!(pubKey is ElGamalPublicKeyParameters))
{
throw new PgpException("unknown key class");
}
ElGamalPublicKeyParameters elGamalPublicKeyParameters = (ElGamalPublicKeyParameters)pubKey;
ElGamalParameters parameters2 = elGamalPublicKeyParameters.Parameters;
key = new ElGamalPublicBcpgKey(parameters2.P, parameters2.G, elGamalPublicKeyParameters.Y);
}
publicPk = new PublicKeyPacket(algorithm, time, key);
ids = Platform.CreateArrayList();
idSigs = Platform.CreateArrayList();
try
{
Init();
}
catch (IOException exception)
{
throw new PgpException("exception calculating keyId", exception);
}
}
public PgpPublicKey(PublicKeyPacket publicPk)
: this(publicPk, Platform.CreateArrayList(), Platform.CreateArrayList())
{
}
internal PgpPublicKey(PublicKeyPacket publicPk, TrustPacket trustPk, IList sigs)
{
this.publicPk = publicPk;
this.trustPk = trustPk;
subSigs = sigs;
Init();
}
internal PgpPublicKey(PgpPublicKey key, TrustPacket trust, IList subSigs)
{
publicPk = key.publicPk;
trustPk = trust;
this.subSigs = subSigs;
fingerprint = key.fingerprint;
keyId = key.keyId;
keyStrength = key.keyStrength;
}
internal PgpPublicKey(PgpPublicKey pubKey)
{
publicPk = pubKey.publicPk;
keySigs = Platform.CreateArrayList(pubKey.keySigs);
ids = Platform.CreateArrayList(pubKey.ids);
idTrusts = Platform.CreateArrayList(pubKey.idTrusts);
idSigs = Platform.CreateArrayList(pubKey.idSigs.Count);
for (int i = 0; i != pubKey.idSigs.Count; i++)
{
idSigs.Add(Platform.CreateArrayList((IList)pubKey.idSigs[i]));
}
if (pubKey.subSigs != null)
{
subSigs = Platform.CreateArrayList(pubKey.subSigs.Count);
for (int j = 0; j != pubKey.subSigs.Count; j++)
{
subSigs.Add(pubKey.subSigs[j]);
}
}
fingerprint = pubKey.fingerprint;
keyId = pubKey.keyId;
keyStrength = pubKey.keyStrength;
}
internal PgpPublicKey(PublicKeyPacket publicPk, TrustPacket trustPk, IList keySigs, IList ids, IList idTrusts, IList idSigs)
{
this.publicPk = publicPk;
this.trustPk = trustPk;
this.keySigs = keySigs;
this.ids = ids;
this.idTrusts = idTrusts;
this.idSigs = idSigs;
Init();
}
internal PgpPublicKey(PublicKeyPacket publicPk, IList ids, IList idSigs)
{
this.publicPk = publicPk;
this.ids = ids;
this.idSigs = idSigs;
Init();
}
public byte[] GetTrustData()
{
if (trustPk == null)
{
return null;
}
return Arrays.Clone(trustPk.GetLevelAndTrustAmount());
}
public long GetValidSeconds()
{
if (publicPk.Version <= 3)
{
return (long)publicPk.ValidDays * 86400L;
}
if (IsMasterKey)
{
for (int i = 0; i != MasterKeyCertificationTypes.Length; i++)
{
long expirationTimeFromSig = GetExpirationTimeFromSig(selfSigned: true, MasterKeyCertificationTypes[i]);
if (expirationTimeFromSig >= 0)
{
return expirationTimeFromSig;
}
}
}
else
{
long expirationTimeFromSig2 = GetExpirationTimeFromSig(selfSigned: false, 24);
if (expirationTimeFromSig2 >= 0)
{
return expirationTimeFromSig2;
}
}
return 0L;
}
private long GetExpirationTimeFromSig(bool selfSigned, int signatureType)
{
long num = -1L;
long num2 = -1L;
foreach (PgpSignature item in GetSignaturesOfType(signatureType))
{
if (selfSigned && item.KeyId != KeyId)
{
continue;
}
PgpSignatureSubpacketVector hashedSubPackets = item.GetHashedSubPackets();
if (hashedSubPackets == null)
{
continue;
}
long keyExpirationTime = hashedSubPackets.GetKeyExpirationTime();
if (item.KeyId == KeyId)
{
if (item.CreationTime.Ticks > num2)
{
num2 = item.CreationTime.Ticks;
num = keyExpirationTime;
}
}
else if (keyExpirationTime == 0 || keyExpirationTime > num)
{
num = keyExpirationTime;
}
}
return num;
}
public byte[] GetFingerprint()
{
return (byte[])fingerprint.Clone();
}
public AsymmetricKeyParameter GetKey()
{
try
{
switch (publicPk.Algorithm)
{
case PublicKeyAlgorithmTag.RsaGeneral:
case PublicKeyAlgorithmTag.RsaEncrypt:
case PublicKeyAlgorithmTag.RsaSign:
{
RsaPublicBcpgKey rsaPublicBcpgKey = (RsaPublicBcpgKey)publicPk.Key;
return new RsaKeyParameters(isPrivate: false, rsaPublicBcpgKey.Modulus, rsaPublicBcpgKey.PublicExponent);
}
case PublicKeyAlgorithmTag.Dsa:
{
DsaPublicBcpgKey dsaPublicBcpgKey = (DsaPublicBcpgKey)publicPk.Key;
return new DsaPublicKeyParameters(dsaPublicBcpgKey.Y, new DsaParameters(dsaPublicBcpgKey.P, dsaPublicBcpgKey.Q, dsaPublicBcpgKey.G));
}
case PublicKeyAlgorithmTag.ECDsa:
return GetECKey("ECDSA");
case PublicKeyAlgorithmTag.EC:
return GetECKey("ECDH");
case PublicKeyAlgorithmTag.ElGamalEncrypt:
case PublicKeyAlgorithmTag.ElGamalGeneral:
{
ElGamalPublicBcpgKey elGamalPublicBcpgKey = (ElGamalPublicBcpgKey)publicPk.Key;
return new ElGamalPublicKeyParameters(elGamalPublicBcpgKey.Y, new ElGamalParameters(elGamalPublicBcpgKey.P, elGamalPublicBcpgKey.G));
}
default:
throw new PgpException("unknown public key algorithm encountered");
}
}
catch (PgpException ex)
{
throw ex;
}
catch (Exception exception)
{
throw new PgpException("exception constructing public key", exception);
}
}
private ECPublicKeyParameters GetECKey(string algorithm)
{
ECPublicBcpgKey eCPublicBcpgKey = (ECPublicBcpgKey)publicPk.Key;
X9ECParameters x9ECParameters = ECKeyPairGenerator.FindECCurveByOid(eCPublicBcpgKey.CurveOid);
ECPoint q = x9ECParameters.Curve.DecodePoint(BigIntegers.AsUnsignedByteArray(eCPublicBcpgKey.EncodedPoint));
return new ECPublicKeyParameters(algorithm, q, eCPublicBcpgKey.CurveOid);
}
public IEnumerable GetUserIds()
{
IList list = Platform.CreateArrayList();
foreach (object id in ids)
{
if (id is string)
{
list.Add(id);
}
}
return new EnumerableProxy(list);
}
public IEnumerable GetUserAttributes()
{
IList list = Platform.CreateArrayList();
foreach (object id in ids)
{
if (id is PgpUserAttributeSubpacketVector)
{
list.Add(id);
}
}
return new EnumerableProxy(list);
}
public IEnumerable GetSignaturesForId(string id)
{
if (id == null)
{
throw new ArgumentNullException("id");
}
for (int i = 0; i != ids.Count; i++)
{
if (id.Equals(ids[i]))
{
return new EnumerableProxy((IList)idSigs[i]);
}
}
return null;
}
public IEnumerable GetSignaturesForUserAttribute(PgpUserAttributeSubpacketVector userAttributes)
{
for (int i = 0; i != ids.Count; i++)
{
if (userAttributes.Equals(ids[i]))
{
return new EnumerableProxy((IList)idSigs[i]);
}
}
return null;
}
public IEnumerable GetSignaturesOfType(int signatureType)
{
IList list = Platform.CreateArrayList();
foreach (PgpSignature signature in GetSignatures())
{
if (signature.SignatureType == signatureType)
{
list.Add(signature);
}
}
return new EnumerableProxy(list);
}
public IEnumerable GetSignatures()
{
IList list = subSigs;
if (list == null)
{
list = Platform.CreateArrayList(keySigs);
foreach (ICollection idSig in idSigs)
{
CollectionUtilities.AddRange(list, idSig);
}
}
return new EnumerableProxy(list);
}
public IEnumerable GetKeySignatures()
{
IList list = subSigs;
if (list == null)
{
list = Platform.CreateArrayList(keySigs);
}
return new EnumerableProxy(list);
}
public byte[] GetEncoded()
{
MemoryStream memoryStream = new MemoryStream();
Encode(memoryStream);
return memoryStream.ToArray();
}
public void Encode(Stream outStr)
{
BcpgOutputStream bcpgOutputStream = BcpgOutputStream.Wrap(outStr);
bcpgOutputStream.WritePacket(publicPk);
if (trustPk != null)
{
bcpgOutputStream.WritePacket(trustPk);
}
if (subSigs == null)
{
foreach (PgpSignature keySig in keySigs)
{
keySig.Encode(bcpgOutputStream);
}
for (int i = 0; i != ids.Count; i++)
{
if (ids[i] is string)
{
string id = (string)ids[i];
bcpgOutputStream.WritePacket(new UserIdPacket(id));
}
else
{
PgpUserAttributeSubpacketVector pgpUserAttributeSubpacketVector = (PgpUserAttributeSubpacketVector)ids[i];
bcpgOutputStream.WritePacket(new UserAttributePacket(pgpUserAttributeSubpacketVector.ToSubpacketArray()));
}
if (idTrusts[i] != null)
{
bcpgOutputStream.WritePacket((ContainedPacket)idTrusts[i]);
}
foreach (PgpSignature item in (IList)idSigs[i])
{
item.Encode(bcpgOutputStream);
}
}
return;
}
foreach (PgpSignature subSig in subSigs)
{
subSig.Encode(bcpgOutputStream);
}
}
public bool IsRevoked()
{
int num = 0;
bool flag = false;
if (IsMasterKey)
{
while (!flag && num < keySigs.Count)
{
if (((PgpSignature)keySigs[num++]).SignatureType == 32)
{
flag = true;
}
}
}
else
{
while (!flag && num < subSigs.Count)
{
if (((PgpSignature)subSigs[num++]).SignatureType == 40)
{
flag = true;
}
}
}
return flag;
}
public static PgpPublicKey AddCertification(PgpPublicKey key, string id, PgpSignature certification)
{
return AddCert(key, id, certification);
}
public static PgpPublicKey AddCertification(PgpPublicKey key, PgpUserAttributeSubpacketVector userAttributes, PgpSignature certification)
{
return AddCert(key, userAttributes, certification);
}
private static PgpPublicKey AddCert(PgpPublicKey key, object id, PgpSignature certification)
{
PgpPublicKey pgpPublicKey = new PgpPublicKey(key);
IList list = null;
for (int i = 0; i != pgpPublicKey.ids.Count; i++)
{
if (id.Equals(pgpPublicKey.ids[i]))
{
list = (IList)pgpPublicKey.idSigs[i];
}
}
if (list != null)
{
list.Add(certification);
}
else
{
list = Platform.CreateArrayList();
list.Add(certification);
pgpPublicKey.ids.Add(id);
pgpPublicKey.idTrusts.Add(null);
pgpPublicKey.idSigs.Add(list);
}
return pgpPublicKey;
}
public static PgpPublicKey RemoveCertification(PgpPublicKey key, PgpUserAttributeSubpacketVector userAttributes)
{
return RemoveCert(key, userAttributes);
}
public static PgpPublicKey RemoveCertification(PgpPublicKey key, string id)
{
return RemoveCert(key, id);
}
private static PgpPublicKey RemoveCert(PgpPublicKey key, object id)
{
PgpPublicKey pgpPublicKey = new PgpPublicKey(key);
bool flag = false;
for (int i = 0; i < pgpPublicKey.ids.Count; i++)
{
if (id.Equals(pgpPublicKey.ids[i]))
{
flag = true;
pgpPublicKey.ids.RemoveAt(i);
pgpPublicKey.idTrusts.RemoveAt(i);
pgpPublicKey.idSigs.RemoveAt(i);
}
}
if (!flag)
{
return null;
}
return pgpPublicKey;
}
public static PgpPublicKey RemoveCertification(PgpPublicKey key, string id, PgpSignature certification)
{
return RemoveCert(key, id, certification);
}
public static PgpPublicKey RemoveCertification(PgpPublicKey key, PgpUserAttributeSubpacketVector userAttributes, PgpSignature certification)
{
return RemoveCert(key, userAttributes, certification);
}
private static PgpPublicKey RemoveCert(PgpPublicKey key, object id, PgpSignature certification)
{
PgpPublicKey pgpPublicKey = new PgpPublicKey(key);
bool flag = false;
for (int i = 0; i < pgpPublicKey.ids.Count; i++)
{
if (id.Equals(pgpPublicKey.ids[i]))
{
IList list = (IList)pgpPublicKey.idSigs[i];
flag = list.Contains(certification);
if (flag)
{
list.Remove(certification);
}
}
}
if (!flag)
{
return null;
}
return pgpPublicKey;
}
public static PgpPublicKey AddCertification(PgpPublicKey key, PgpSignature certification)
{
if (key.IsMasterKey)
{
if (certification.SignatureType == 40)
{
throw new ArgumentException("signature type incorrect for master key revocation.");
}
}
else if (certification.SignatureType == 32)
{
throw new ArgumentException("signature type incorrect for sub-key revocation.");
}
PgpPublicKey pgpPublicKey = new PgpPublicKey(key);
if (pgpPublicKey.subSigs != null)
{
pgpPublicKey.subSigs.Add(certification);
}
else
{
pgpPublicKey.keySigs.Add(certification);
}
return pgpPublicKey;
}
public static PgpPublicKey RemoveCertification(PgpPublicKey key, PgpSignature certification)
{
PgpPublicKey pgpPublicKey = new PgpPublicKey(key);
IList list = ((pgpPublicKey.subSigs != null) ? pgpPublicKey.subSigs : pgpPublicKey.keySigs);
int num = list.IndexOf(certification);
bool flag = num >= 0;
if (flag)
{
list.RemoveAt(num);
}
else
{
foreach (string userId in key.GetUserIds())
{
foreach (object item in key.GetSignaturesForId(userId))
{
if (certification == item)
{
flag = true;
pgpPublicKey = RemoveCertification(pgpPublicKey, userId, certification);
}
}
}
if (!flag)
{
foreach (PgpUserAttributeSubpacketVector userAttribute in key.GetUserAttributes())
{
foreach (object item2 in key.GetSignaturesForUserAttribute(userAttribute))
{
if (certification == item2)
{
flag = true;
pgpPublicKey = RemoveCertification(pgpPublicKey, userAttribute, certification);
}
}
}
}
}
return pgpPublicKey;
}
}

View File

@@ -0,0 +1,198 @@
using System;
using System.IO;
using Org.BouncyCastle.Asn1.X9;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.IO;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math.EC;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities.IO;
namespace Org.BouncyCastle.Bcpg.OpenPgp;
public class PgpPublicKeyEncryptedData : PgpEncryptedData
{
private PublicKeyEncSessionPacket keyData;
public long KeyId => keyData.KeyId;
internal PgpPublicKeyEncryptedData(PublicKeyEncSessionPacket keyData, InputStreamPacket encData)
: base(encData)
{
this.keyData = keyData;
}
private static IBufferedCipher GetKeyCipher(PublicKeyAlgorithmTag algorithm)
{
try
{
switch (algorithm)
{
case PublicKeyAlgorithmTag.RsaGeneral:
case PublicKeyAlgorithmTag.RsaEncrypt:
return CipherUtilities.GetCipher("RSA//PKCS1Padding");
case PublicKeyAlgorithmTag.ElGamalEncrypt:
case PublicKeyAlgorithmTag.ElGamalGeneral:
return CipherUtilities.GetCipher("ElGamal/ECB/PKCS1Padding");
default:
throw new PgpException("unknown asymmetric algorithm: " + algorithm);
}
}
catch (PgpException ex)
{
throw ex;
}
catch (Exception exception)
{
throw new PgpException("Exception creating cipher", exception);
}
}
private bool ConfirmCheckSum(byte[] sessionInfo)
{
int num = 0;
for (int i = 1; i != sessionInfo.Length - 2; i++)
{
num += sessionInfo[i] & 0xFF;
}
if (sessionInfo[^2] == (byte)(num >> 8))
{
return sessionInfo[^1] == (byte)num;
}
return false;
}
public SymmetricKeyAlgorithmTag GetSymmetricAlgorithm(PgpPrivateKey privKey)
{
byte[] array = RecoverSessionData(privKey);
return (SymmetricKeyAlgorithmTag)array[0];
}
public Stream GetDataStream(PgpPrivateKey privKey)
{
byte[] array = RecoverSessionData(privKey);
if (!ConfirmCheckSum(array))
{
throw new PgpKeyValidationException("key checksum failed");
}
SymmetricKeyAlgorithmTag symmetricKeyAlgorithmTag = (SymmetricKeyAlgorithmTag)array[0];
if (symmetricKeyAlgorithmTag == SymmetricKeyAlgorithmTag.Null)
{
return encData.GetInputStream();
}
string symmetricCipherName = PgpUtilities.GetSymmetricCipherName(symmetricKeyAlgorithmTag);
string text = symmetricCipherName;
IBufferedCipher cipher;
try
{
text = ((!(encData is SymmetricEncIntegrityPacket)) ? (text + "/OpenPGPCFB/NoPadding") : (text + "/CFB/NoPadding"));
cipher = CipherUtilities.GetCipher(text);
}
catch (PgpException ex)
{
throw ex;
}
catch (Exception exception)
{
throw new PgpException("exception creating cipher", exception);
}
try
{
KeyParameter parameters = ParameterUtilities.CreateKeyParameter(symmetricCipherName, array, 1, array.Length - 3);
byte[] array2 = new byte[cipher.GetBlockSize()];
cipher.Init(forEncryption: false, new ParametersWithIV(parameters, array2));
encStream = BcpgInputStream.Wrap(new CipherStream(encData.GetInputStream(), cipher, null));
if (encData is SymmetricEncIntegrityPacket)
{
truncStream = new TruncatedStream(encStream);
string digestName = PgpUtilities.GetDigestName(HashAlgorithmTag.Sha1);
IDigest digest = DigestUtilities.GetDigest(digestName);
encStream = new DigestStream(truncStream, digest, null);
}
if (Streams.ReadFully(encStream, array2, 0, array2.Length) < array2.Length)
{
throw new EndOfStreamException("unexpected end of stream.");
}
int num = encStream.ReadByte();
int num2 = encStream.ReadByte();
if (num < 0 || num2 < 0)
{
throw new EndOfStreamException("unexpected end of stream.");
}
return encStream;
}
catch (PgpException ex2)
{
throw ex2;
}
catch (Exception exception2)
{
throw new PgpException("Exception starting decryption", exception2);
}
}
private byte[] RecoverSessionData(PgpPrivateKey privKey)
{
byte[][] encSessionKey = keyData.GetEncSessionKey();
if (keyData.Algorithm == PublicKeyAlgorithmTag.EC)
{
ECDHPublicBcpgKey eCDHPublicBcpgKey = (ECDHPublicBcpgKey)privKey.PublicKeyPacket.Key;
X9ECParameters x9ECParameters = ECKeyPairGenerator.FindECCurveByOid(eCDHPublicBcpgKey.CurveOid);
byte[] array = encSessionKey[0];
int num = (((array[0] & 0xFF) << 8) + (array[1] & 0xFF) + 7) / 8;
byte[] array2 = new byte[num];
Array.Copy(array, 2, array2, 0, num);
byte[] array3 = new byte[array[num + 2]];
Array.Copy(array, 2 + num + 1, array3, 0, array3.Length);
ECPoint eCPoint = x9ECParameters.Curve.DecodePoint(array2);
ECPrivateKeyParameters eCPrivateKeyParameters = (ECPrivateKeyParameters)privKey.Key;
ECPoint s = eCPoint.Multiply(eCPrivateKeyParameters.D).Normalize();
KeyParameter parameters = new KeyParameter(Rfc6637Utilities.CreateKey(privKey.PublicKeyPacket, s));
IWrapper wrapper = PgpUtilities.CreateWrapper(eCDHPublicBcpgKey.SymmetricKeyAlgorithm);
wrapper.Init(forWrapping: false, parameters);
return PgpPad.UnpadSessionData(wrapper.Unwrap(array3, 0, array3.Length));
}
IBufferedCipher keyCipher = GetKeyCipher(keyData.Algorithm);
try
{
keyCipher.Init(forEncryption: false, privKey.Key);
}
catch (InvalidKeyException exception)
{
throw new PgpException("error setting asymmetric cipher", exception);
}
if (keyData.Algorithm == PublicKeyAlgorithmTag.RsaEncrypt || keyData.Algorithm == PublicKeyAlgorithmTag.RsaGeneral)
{
byte[] array4 = encSessionKey[0];
keyCipher.ProcessBytes(array4, 2, array4.Length - 2);
}
else
{
ElGamalPrivateKeyParameters elGamalPrivateKeyParameters = (ElGamalPrivateKeyParameters)privKey.Key;
int size = (elGamalPrivateKeyParameters.Parameters.P.BitLength + 7) / 8;
ProcessEncodedMpi(keyCipher, size, encSessionKey[0]);
ProcessEncodedMpi(keyCipher, size, encSessionKey[1]);
}
try
{
return keyCipher.DoFinal();
}
catch (Exception exception2)
{
throw new PgpException("exception decrypting secret key", exception2);
}
}
private static void ProcessEncodedMpi(IBufferedCipher cipher, int size, byte[] mpiEnc)
{
if (mpiEnc.Length - 2 > size)
{
cipher.ProcessBytes(mpiEnc, 3, mpiEnc.Length - 3);
return;
}
byte[] array = new byte[size];
Array.Copy(mpiEnc, 2, array, array.Length - (mpiEnc.Length - 2), mpiEnc.Length - 2);
cipher.ProcessBytes(array, 0, array.Length);
}
}

View File

@@ -0,0 +1,148 @@
using System;
using System.Collections;
using System.IO;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.Collections;
namespace Org.BouncyCastle.Bcpg.OpenPgp;
public class PgpPublicKeyRing : PgpKeyRing
{
private readonly IList keys;
public PgpPublicKeyRing(byte[] encoding)
: this(new MemoryStream(encoding, writable: false))
{
}
internal PgpPublicKeyRing(IList pubKeys)
{
keys = pubKeys;
}
public PgpPublicKeyRing(Stream inputStream)
{
keys = Platform.CreateArrayList();
BcpgInputStream bcpgInputStream = BcpgInputStream.Wrap(inputStream);
PacketTag packetTag = bcpgInputStream.NextPacketTag();
if (packetTag != PacketTag.PublicKey && packetTag != PacketTag.PublicSubkey)
{
int num = (int)packetTag;
throw new IOException("public key ring doesn't start with public key tag: tag 0x" + num.ToString("X"));
}
PublicKeyPacket publicPk = (PublicKeyPacket)bcpgInputStream.ReadPacket();
TrustPacket trustPk = PgpKeyRing.ReadOptionalTrustPacket(bcpgInputStream);
IList keySigs = PgpKeyRing.ReadSignaturesAndTrust(bcpgInputStream);
PgpKeyRing.ReadUserIDs(bcpgInputStream, out var ids, out var idTrusts, out var idSigs);
keys.Add(new PgpPublicKey(publicPk, trustPk, keySigs, ids, idTrusts, idSigs));
while (bcpgInputStream.NextPacketTag() == PacketTag.PublicSubkey)
{
keys.Add(ReadSubkey(bcpgInputStream));
}
}
public virtual PgpPublicKey GetPublicKey()
{
return (PgpPublicKey)keys[0];
}
public virtual PgpPublicKey GetPublicKey(long keyId)
{
foreach (PgpPublicKey key in keys)
{
if (keyId == key.KeyId)
{
return key;
}
}
return null;
}
public virtual IEnumerable GetPublicKeys()
{
return new EnumerableProxy(keys);
}
public virtual byte[] GetEncoded()
{
MemoryStream memoryStream = new MemoryStream();
Encode(memoryStream);
return memoryStream.ToArray();
}
public virtual void Encode(Stream outStr)
{
if (outStr == null)
{
throw new ArgumentNullException("outStr");
}
foreach (PgpPublicKey key in keys)
{
key.Encode(outStr);
}
}
public static PgpPublicKeyRing InsertPublicKey(PgpPublicKeyRing pubRing, PgpPublicKey pubKey)
{
IList list = Platform.CreateArrayList(pubRing.keys);
bool flag = false;
bool flag2 = false;
for (int i = 0; i != list.Count; i++)
{
PgpPublicKey pgpPublicKey = (PgpPublicKey)list[i];
if (pgpPublicKey.KeyId == pubKey.KeyId)
{
flag = true;
list[i] = pubKey;
}
if (pgpPublicKey.IsMasterKey)
{
flag2 = true;
}
}
if (!flag)
{
if (pubKey.IsMasterKey)
{
if (flag2)
{
throw new ArgumentException("cannot add a master key to a ring that already has one");
}
list.Insert(0, pubKey);
}
else
{
list.Add(pubKey);
}
}
return new PgpPublicKeyRing(list);
}
public static PgpPublicKeyRing RemovePublicKey(PgpPublicKeyRing pubRing, PgpPublicKey pubKey)
{
IList list = Platform.CreateArrayList(pubRing.keys);
bool flag = false;
for (int i = 0; i < list.Count; i++)
{
PgpPublicKey pgpPublicKey = (PgpPublicKey)list[i];
if (pgpPublicKey.KeyId == pubKey.KeyId)
{
flag = true;
list.RemoveAt(i);
}
}
if (!flag)
{
return null;
}
return new PgpPublicKeyRing(list);
}
internal static PgpPublicKey ReadSubkey(BcpgInputStream bcpgInput)
{
PublicKeyPacket publicPk = (PublicKeyPacket)bcpgInput.ReadPacket();
TrustPacket trustPk = PgpKeyRing.ReadOptionalTrustPacket(bcpgInput);
IList sigs = PgpKeyRing.ReadSignaturesAndTrust(bcpgInput);
return new PgpPublicKey(publicPk, trustPk, sigs);
}
}

View File

@@ -0,0 +1,179 @@
using System;
using System.Collections;
using System.IO;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.Collections;
namespace Org.BouncyCastle.Bcpg.OpenPgp;
public class PgpPublicKeyRingBundle
{
private readonly IDictionary pubRings;
private readonly IList order;
[Obsolete("Use 'Count' property instead")]
public int Size => order.Count;
public int Count => order.Count;
private PgpPublicKeyRingBundle(IDictionary pubRings, IList order)
{
this.pubRings = pubRings;
this.order = order;
}
public PgpPublicKeyRingBundle(byte[] encoding)
: this(new MemoryStream(encoding, writable: false))
{
}
public PgpPublicKeyRingBundle(Stream inputStream)
: this(new PgpObjectFactory(inputStream).AllPgpObjects())
{
}
public PgpPublicKeyRingBundle(IEnumerable e)
{
pubRings = Platform.CreateHashtable();
order = Platform.CreateArrayList();
foreach (object item in e)
{
if (!(item is PgpPublicKeyRing pgpPublicKeyRing))
{
throw new PgpException(Platform.GetTypeName(item) + " found where PgpPublicKeyRing expected");
}
long keyId = pgpPublicKeyRing.GetPublicKey().KeyId;
pubRings.Add(keyId, pgpPublicKeyRing);
order.Add(keyId);
}
}
public IEnumerable GetKeyRings()
{
return new EnumerableProxy(pubRings.Values);
}
public IEnumerable GetKeyRings(string userId)
{
return GetKeyRings(userId, matchPartial: false, ignoreCase: false);
}
public IEnumerable GetKeyRings(string userId, bool matchPartial)
{
return GetKeyRings(userId, matchPartial, ignoreCase: false);
}
public IEnumerable GetKeyRings(string userId, bool matchPartial, bool ignoreCase)
{
IList list = Platform.CreateArrayList();
if (ignoreCase)
{
userId = Platform.ToUpperInvariant(userId);
}
foreach (PgpPublicKeyRing keyRing in GetKeyRings())
{
foreach (string userId2 in keyRing.GetPublicKey().GetUserIds())
{
string text2 = userId2;
if (ignoreCase)
{
text2 = Platform.ToUpperInvariant(text2);
}
if (matchPartial)
{
if (Platform.IndexOf(text2, userId) > -1)
{
list.Add(keyRing);
}
}
else if (text2.Equals(userId))
{
list.Add(keyRing);
}
}
}
return new EnumerableProxy(list);
}
public PgpPublicKey GetPublicKey(long keyId)
{
foreach (PgpPublicKeyRing keyRing in GetKeyRings())
{
PgpPublicKey publicKey = keyRing.GetPublicKey(keyId);
if (publicKey != null)
{
return publicKey;
}
}
return null;
}
public PgpPublicKeyRing GetPublicKeyRing(long keyId)
{
if (pubRings.Contains(keyId))
{
return (PgpPublicKeyRing)pubRings[keyId];
}
foreach (PgpPublicKeyRing keyRing in GetKeyRings())
{
PgpPublicKey publicKey = keyRing.GetPublicKey(keyId);
if (publicKey != null)
{
return keyRing;
}
}
return null;
}
public bool Contains(long keyID)
{
return GetPublicKey(keyID) != null;
}
public byte[] GetEncoded()
{
MemoryStream memoryStream = new MemoryStream();
Encode(memoryStream);
return memoryStream.ToArray();
}
public void Encode(Stream outStr)
{
BcpgOutputStream outStr2 = BcpgOutputStream.Wrap(outStr);
foreach (object item in order)
{
long num = (long)item;
PgpPublicKeyRing pgpPublicKeyRing = (PgpPublicKeyRing)pubRings[num];
pgpPublicKeyRing.Encode(outStr2);
}
}
public static PgpPublicKeyRingBundle AddPublicKeyRing(PgpPublicKeyRingBundle bundle, PgpPublicKeyRing publicKeyRing)
{
long keyId = publicKeyRing.GetPublicKey().KeyId;
if (bundle.pubRings.Contains(keyId))
{
throw new ArgumentException("Bundle already contains a key with a keyId for the passed in ring.");
}
IDictionary dictionary = Platform.CreateHashtable(bundle.pubRings);
IList list = Platform.CreateArrayList(bundle.order);
dictionary[keyId] = publicKeyRing;
list.Add(keyId);
return new PgpPublicKeyRingBundle(dictionary, list);
}
public static PgpPublicKeyRingBundle RemovePublicKeyRing(PgpPublicKeyRingBundle bundle, PgpPublicKeyRing publicKeyRing)
{
long keyId = publicKeyRing.GetPublicKey().KeyId;
if (!bundle.pubRings.Contains(keyId))
{
throw new ArgumentException("Bundle does not contain a key with a keyId for the passed in ring.");
}
IDictionary dictionary = Platform.CreateHashtable(bundle.pubRings);
IList list = Platform.CreateArrayList(bundle.order);
dictionary.Remove(keyId);
list.Remove(keyId);
return new PgpPublicKeyRingBundle(dictionary, list);
}
}

View File

@@ -0,0 +1,758 @@
using System;
using System.Collections;
using System.IO;
using Org.BouncyCastle.Asn1.X9;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Bcpg.OpenPgp;
public class PgpSecretKey
{
private readonly SecretKeyPacket secret;
private readonly PgpPublicKey pub;
public bool IsSigningKey
{
get
{
switch (pub.Algorithm)
{
case PublicKeyAlgorithmTag.RsaGeneral:
case PublicKeyAlgorithmTag.RsaSign:
case PublicKeyAlgorithmTag.Dsa:
case PublicKeyAlgorithmTag.ECDsa:
case PublicKeyAlgorithmTag.ElGamalGeneral:
return true;
default:
return false;
}
}
}
public bool IsMasterKey => pub.IsMasterKey;
public bool IsPrivateKeyEmpty
{
get
{
byte[] secretKeyData = secret.GetSecretKeyData();
if (secretKeyData != null)
{
return secretKeyData.Length < 1;
}
return true;
}
}
public SymmetricKeyAlgorithmTag KeyEncryptionAlgorithm => secret.EncAlgorithm;
public long KeyId => pub.KeyId;
public int S2kUsage => secret.S2kUsage;
public S2k S2k => secret.S2k;
public PgpPublicKey PublicKey => pub;
public IEnumerable UserIds => pub.GetUserIds();
public IEnumerable UserAttributes => pub.GetUserAttributes();
internal PgpSecretKey(SecretKeyPacket secret, PgpPublicKey pub)
{
this.secret = secret;
this.pub = pub;
}
internal PgpSecretKey(PgpPrivateKey privKey, PgpPublicKey pubKey, SymmetricKeyAlgorithmTag encAlgorithm, byte[] rawPassPhrase, bool clearPassPhrase, bool useSha1, SecureRandom rand, bool isMasterKey)
{
pub = pubKey;
BcpgObject bcpgObject;
switch (pubKey.Algorithm)
{
case PublicKeyAlgorithmTag.RsaGeneral:
case PublicKeyAlgorithmTag.RsaEncrypt:
case PublicKeyAlgorithmTag.RsaSign:
{
RsaPrivateCrtKeyParameters rsaPrivateCrtKeyParameters = (RsaPrivateCrtKeyParameters)privKey.Key;
bcpgObject = new RsaSecretBcpgKey(rsaPrivateCrtKeyParameters.Exponent, rsaPrivateCrtKeyParameters.P, rsaPrivateCrtKeyParameters.Q);
break;
}
case PublicKeyAlgorithmTag.Dsa:
{
DsaPrivateKeyParameters dsaPrivateKeyParameters = (DsaPrivateKeyParameters)privKey.Key;
bcpgObject = new DsaSecretBcpgKey(dsaPrivateKeyParameters.X);
break;
}
case PublicKeyAlgorithmTag.EC:
case PublicKeyAlgorithmTag.ECDsa:
{
ECPrivateKeyParameters eCPrivateKeyParameters = (ECPrivateKeyParameters)privKey.Key;
bcpgObject = new ECSecretBcpgKey(eCPrivateKeyParameters.D);
break;
}
case PublicKeyAlgorithmTag.ElGamalEncrypt:
case PublicKeyAlgorithmTag.ElGamalGeneral:
{
ElGamalPrivateKeyParameters elGamalPrivateKeyParameters = (ElGamalPrivateKeyParameters)privKey.Key;
bcpgObject = new ElGamalSecretBcpgKey(elGamalPrivateKeyParameters.X);
break;
}
default:
throw new PgpException("unknown key class");
}
try
{
MemoryStream memoryStream = new MemoryStream();
BcpgOutputStream bcpgOutputStream = new BcpgOutputStream(memoryStream);
bcpgOutputStream.WriteObject(bcpgObject);
byte[] array = memoryStream.ToArray();
byte[] b = Checksum(useSha1, array, array.Length);
array = Arrays.Concatenate(array, b);
if (encAlgorithm == SymmetricKeyAlgorithmTag.Null)
{
if (isMasterKey)
{
secret = new SecretKeyPacket(pub.publicPk, encAlgorithm, null, null, array);
}
else
{
secret = new SecretSubkeyPacket(pub.publicPk, encAlgorithm, null, null, array);
}
return;
}
S2k s2k;
byte[] iv;
byte[] secKeyData = ((pub.Version < 4) ? EncryptKeyDataV3(array, encAlgorithm, rawPassPhrase, clearPassPhrase, rand, out s2k, out iv) : EncryptKeyDataV4(array, encAlgorithm, HashAlgorithmTag.Sha1, rawPassPhrase, clearPassPhrase, rand, out s2k, out iv));
int s2kUsage = (useSha1 ? 254 : 255);
if (isMasterKey)
{
secret = new SecretKeyPacket(pub.publicPk, encAlgorithm, s2kUsage, s2k, iv, secKeyData);
}
else
{
secret = new SecretSubkeyPacket(pub.publicPk, encAlgorithm, s2kUsage, s2k, iv, secKeyData);
}
}
catch (PgpException ex)
{
throw ex;
}
catch (Exception exception)
{
throw new PgpException("Exception encrypting key", exception);
}
}
[Obsolete("Use the constructor taking an explicit 'useSha1' parameter instead")]
public PgpSecretKey(int certificationLevel, PgpKeyPair keyPair, string id, SymmetricKeyAlgorithmTag encAlgorithm, char[] passPhrase, PgpSignatureSubpacketVector hashedPackets, PgpSignatureSubpacketVector unhashedPackets, SecureRandom rand)
: this(certificationLevel, keyPair, id, encAlgorithm, passPhrase, useSha1: false, hashedPackets, unhashedPackets, rand)
{
}
public PgpSecretKey(int certificationLevel, PgpKeyPair keyPair, string id, SymmetricKeyAlgorithmTag encAlgorithm, char[] passPhrase, bool useSha1, PgpSignatureSubpacketVector hashedPackets, PgpSignatureSubpacketVector unhashedPackets, SecureRandom rand)
: this(certificationLevel, keyPair, id, encAlgorithm, utf8PassPhrase: false, passPhrase, useSha1, hashedPackets, unhashedPackets, rand)
{
}
public PgpSecretKey(int certificationLevel, PgpKeyPair keyPair, string id, SymmetricKeyAlgorithmTag encAlgorithm, bool utf8PassPhrase, char[] passPhrase, bool useSha1, PgpSignatureSubpacketVector hashedPackets, PgpSignatureSubpacketVector unhashedPackets, SecureRandom rand)
: this(certificationLevel, keyPair, id, encAlgorithm, PgpUtilities.EncodePassPhrase(passPhrase, utf8PassPhrase), clearPassPhrase: true, useSha1, hashedPackets, unhashedPackets, rand)
{
}
public PgpSecretKey(int certificationLevel, PgpKeyPair keyPair, string id, SymmetricKeyAlgorithmTag encAlgorithm, byte[] rawPassPhrase, bool useSha1, PgpSignatureSubpacketVector hashedPackets, PgpSignatureSubpacketVector unhashedPackets, SecureRandom rand)
: this(certificationLevel, keyPair, id, encAlgorithm, rawPassPhrase, clearPassPhrase: false, useSha1, hashedPackets, unhashedPackets, rand)
{
}
internal PgpSecretKey(int certificationLevel, PgpKeyPair keyPair, string id, SymmetricKeyAlgorithmTag encAlgorithm, byte[] rawPassPhrase, bool clearPassPhrase, bool useSha1, PgpSignatureSubpacketVector hashedPackets, PgpSignatureSubpacketVector unhashedPackets, SecureRandom rand)
: this(keyPair.PrivateKey, CertifiedPublicKey(certificationLevel, keyPair, id, hashedPackets, unhashedPackets), encAlgorithm, rawPassPhrase, clearPassPhrase, useSha1, rand, isMasterKey: true)
{
}
public PgpSecretKey(int certificationLevel, PgpKeyPair keyPair, string id, SymmetricKeyAlgorithmTag encAlgorithm, HashAlgorithmTag hashAlgorithm, char[] passPhrase, bool useSha1, PgpSignatureSubpacketVector hashedPackets, PgpSignatureSubpacketVector unhashedPackets, SecureRandom rand)
: this(certificationLevel, keyPair, id, encAlgorithm, hashAlgorithm, utf8PassPhrase: false, passPhrase, useSha1, hashedPackets, unhashedPackets, rand)
{
}
public PgpSecretKey(int certificationLevel, PgpKeyPair keyPair, string id, SymmetricKeyAlgorithmTag encAlgorithm, HashAlgorithmTag hashAlgorithm, bool utf8PassPhrase, char[] passPhrase, bool useSha1, PgpSignatureSubpacketVector hashedPackets, PgpSignatureSubpacketVector unhashedPackets, SecureRandom rand)
: this(certificationLevel, keyPair, id, encAlgorithm, hashAlgorithm, PgpUtilities.EncodePassPhrase(passPhrase, utf8PassPhrase), clearPassPhrase: true, useSha1, hashedPackets, unhashedPackets, rand)
{
}
public PgpSecretKey(int certificationLevel, PgpKeyPair keyPair, string id, SymmetricKeyAlgorithmTag encAlgorithm, HashAlgorithmTag hashAlgorithm, byte[] rawPassPhrase, bool useSha1, PgpSignatureSubpacketVector hashedPackets, PgpSignatureSubpacketVector unhashedPackets, SecureRandom rand)
: this(certificationLevel, keyPair, id, encAlgorithm, hashAlgorithm, rawPassPhrase, clearPassPhrase: false, useSha1, hashedPackets, unhashedPackets, rand)
{
}
internal PgpSecretKey(int certificationLevel, PgpKeyPair keyPair, string id, SymmetricKeyAlgorithmTag encAlgorithm, HashAlgorithmTag hashAlgorithm, byte[] rawPassPhrase, bool clearPassPhrase, bool useSha1, PgpSignatureSubpacketVector hashedPackets, PgpSignatureSubpacketVector unhashedPackets, SecureRandom rand)
: this(keyPair.PrivateKey, CertifiedPublicKey(certificationLevel, keyPair, id, hashedPackets, unhashedPackets, hashAlgorithm), encAlgorithm, rawPassPhrase, clearPassPhrase, useSha1, rand, isMasterKey: true)
{
}
private static PgpPublicKey CertifiedPublicKey(int certificationLevel, PgpKeyPair keyPair, string id, PgpSignatureSubpacketVector hashedPackets, PgpSignatureSubpacketVector unhashedPackets)
{
PgpSignatureGenerator pgpSignatureGenerator;
try
{
pgpSignatureGenerator = new PgpSignatureGenerator(keyPair.PublicKey.Algorithm, HashAlgorithmTag.Sha1);
}
catch (Exception ex)
{
throw new PgpException("Creating signature generator: " + ex.Message, ex);
}
pgpSignatureGenerator.InitSign(certificationLevel, keyPair.PrivateKey);
pgpSignatureGenerator.SetHashedSubpackets(hashedPackets);
pgpSignatureGenerator.SetUnhashedSubpackets(unhashedPackets);
try
{
PgpSignature certification = pgpSignatureGenerator.GenerateCertification(id, keyPair.PublicKey);
return PgpPublicKey.AddCertification(keyPair.PublicKey, id, certification);
}
catch (Exception ex2)
{
throw new PgpException("Exception doing certification: " + ex2.Message, ex2);
}
}
private static PgpPublicKey CertifiedPublicKey(int certificationLevel, PgpKeyPair keyPair, string id, PgpSignatureSubpacketVector hashedPackets, PgpSignatureSubpacketVector unhashedPackets, HashAlgorithmTag hashAlgorithm)
{
PgpSignatureGenerator pgpSignatureGenerator;
try
{
pgpSignatureGenerator = new PgpSignatureGenerator(keyPair.PublicKey.Algorithm, hashAlgorithm);
}
catch (Exception ex)
{
throw new PgpException("Creating signature generator: " + ex.Message, ex);
}
pgpSignatureGenerator.InitSign(certificationLevel, keyPair.PrivateKey);
pgpSignatureGenerator.SetHashedSubpackets(hashedPackets);
pgpSignatureGenerator.SetUnhashedSubpackets(unhashedPackets);
try
{
PgpSignature certification = pgpSignatureGenerator.GenerateCertification(id, keyPair.PublicKey);
return PgpPublicKey.AddCertification(keyPair.PublicKey, id, certification);
}
catch (Exception ex2)
{
throw new PgpException("Exception doing certification: " + ex2.Message, ex2);
}
}
public PgpSecretKey(int certificationLevel, PublicKeyAlgorithmTag algorithm, AsymmetricKeyParameter pubKey, AsymmetricKeyParameter privKey, DateTime time, string id, SymmetricKeyAlgorithmTag encAlgorithm, char[] passPhrase, PgpSignatureSubpacketVector hashedPackets, PgpSignatureSubpacketVector unhashedPackets, SecureRandom rand)
: this(certificationLevel, new PgpKeyPair(algorithm, pubKey, privKey, time), id, encAlgorithm, passPhrase, useSha1: false, hashedPackets, unhashedPackets, rand)
{
}
public PgpSecretKey(int certificationLevel, PublicKeyAlgorithmTag algorithm, AsymmetricKeyParameter pubKey, AsymmetricKeyParameter privKey, DateTime time, string id, SymmetricKeyAlgorithmTag encAlgorithm, char[] passPhrase, bool useSha1, PgpSignatureSubpacketVector hashedPackets, PgpSignatureSubpacketVector unhashedPackets, SecureRandom rand)
: this(certificationLevel, new PgpKeyPair(algorithm, pubKey, privKey, time), id, encAlgorithm, passPhrase, useSha1, hashedPackets, unhashedPackets, rand)
{
}
private byte[] ExtractKeyData(byte[] rawPassPhrase, bool clearPassPhrase)
{
SymmetricKeyAlgorithmTag encAlgorithm = secret.EncAlgorithm;
byte[] secretKeyData = secret.GetSecretKeyData();
if (encAlgorithm == SymmetricKeyAlgorithmTag.Null)
{
return secretKeyData;
}
try
{
KeyParameter key = PgpUtilities.DoMakeKeyFromPassPhrase(secret.EncAlgorithm, secret.S2k, rawPassPhrase, clearPassPhrase);
byte[] iV = secret.GetIV();
byte[] array;
if (secret.PublicKeyPacket.Version >= 4)
{
array = RecoverKeyData(encAlgorithm, "/CFB/NoPadding", key, iV, secretKeyData, 0, secretKeyData.Length);
bool flag = secret.S2kUsage == 254;
byte[] array2 = Checksum(flag, array, flag ? (array.Length - 20) : (array.Length - 2));
for (int i = 0; i != array2.Length; i++)
{
if (array2[i] != array[array.Length - array2.Length + i])
{
throw new PgpException("Checksum mismatch at " + i + " of " + array2.Length);
}
}
}
else
{
array = new byte[secretKeyData.Length];
iV = Arrays.Clone(iV);
int num = 0;
for (int j = 0; j != 4; j++)
{
int num2 = (((secretKeyData[num] << 8) | (secretKeyData[num + 1] & 0xFF)) + 7) / 8;
array[num] = secretKeyData[num];
array[num + 1] = secretKeyData[num + 1];
num += 2;
byte[] sourceArray = RecoverKeyData(encAlgorithm, "/CFB/NoPadding", key, iV, secretKeyData, num, num2);
Array.Copy(sourceArray, 0, array, num, num2);
num += num2;
if (j != 3)
{
Array.Copy(secretKeyData, num - iV.Length, iV, 0, iV.Length);
}
}
array[num] = secretKeyData[num];
array[num + 1] = secretKeyData[num + 1];
int num3 = ((secretKeyData[num] << 8) & 0xFF00) | (secretKeyData[num + 1] & 0xFF);
int num4 = 0;
for (int k = 0; k < num; k++)
{
num4 += array[k] & 0xFF;
}
num4 &= 0xFFFF;
if (num4 != num3)
{
throw new PgpException("Checksum mismatch: passphrase wrong, expected " + num3.ToString("X") + " found " + num4.ToString("X"));
}
}
return array;
}
catch (PgpException ex)
{
throw ex;
}
catch (Exception exception)
{
throw new PgpException("Exception decrypting key", exception);
}
}
private static byte[] RecoverKeyData(SymmetricKeyAlgorithmTag encAlgorithm, string modeAndPadding, KeyParameter key, byte[] iv, byte[] keyData, int keyOff, int keyLen)
{
IBufferedCipher cipher;
try
{
string symmetricCipherName = PgpUtilities.GetSymmetricCipherName(encAlgorithm);
cipher = CipherUtilities.GetCipher(symmetricCipherName + modeAndPadding);
}
catch (Exception exception)
{
throw new PgpException("Exception creating cipher", exception);
}
cipher.Init(forEncryption: false, new ParametersWithIV(key, iv));
return cipher.DoFinal(keyData, keyOff, keyLen);
}
public PgpPrivateKey ExtractPrivateKey(char[] passPhrase)
{
return DoExtractPrivateKey(PgpUtilities.EncodePassPhrase(passPhrase, utf8: false), clearPassPhrase: true);
}
public PgpPrivateKey ExtractPrivateKeyUtf8(char[] passPhrase)
{
return DoExtractPrivateKey(PgpUtilities.EncodePassPhrase(passPhrase, utf8: true), clearPassPhrase: true);
}
public PgpPrivateKey ExtractPrivateKeyRaw(byte[] rawPassPhrase)
{
return DoExtractPrivateKey(rawPassPhrase, clearPassPhrase: false);
}
internal PgpPrivateKey DoExtractPrivateKey(byte[] rawPassPhrase, bool clearPassPhrase)
{
if (IsPrivateKeyEmpty)
{
return null;
}
PublicKeyPacket publicKeyPacket = secret.PublicKeyPacket;
try
{
byte[] buffer = ExtractKeyData(rawPassPhrase, clearPassPhrase);
BcpgInputStream bcpgIn = BcpgInputStream.Wrap(new MemoryStream(buffer, writable: false));
AsymmetricKeyParameter privateKey;
switch (publicKeyPacket.Algorithm)
{
case PublicKeyAlgorithmTag.RsaGeneral:
case PublicKeyAlgorithmTag.RsaEncrypt:
case PublicKeyAlgorithmTag.RsaSign:
{
RsaPublicBcpgKey rsaPublicBcpgKey = (RsaPublicBcpgKey)publicKeyPacket.Key;
RsaSecretBcpgKey rsaSecretBcpgKey = new RsaSecretBcpgKey(bcpgIn);
RsaPrivateCrtKeyParameters rsaPrivateCrtKeyParameters = new RsaPrivateCrtKeyParameters(rsaSecretBcpgKey.Modulus, rsaPublicBcpgKey.PublicExponent, rsaSecretBcpgKey.PrivateExponent, rsaSecretBcpgKey.PrimeP, rsaSecretBcpgKey.PrimeQ, rsaSecretBcpgKey.PrimeExponentP, rsaSecretBcpgKey.PrimeExponentQ, rsaSecretBcpgKey.CrtCoefficient);
privateKey = rsaPrivateCrtKeyParameters;
break;
}
case PublicKeyAlgorithmTag.Dsa:
{
DsaPublicBcpgKey dsaPublicBcpgKey = (DsaPublicBcpgKey)publicKeyPacket.Key;
DsaSecretBcpgKey dsaSecretBcpgKey = new DsaSecretBcpgKey(bcpgIn);
DsaParameters parameters2 = new DsaParameters(dsaPublicBcpgKey.P, dsaPublicBcpgKey.Q, dsaPublicBcpgKey.G);
privateKey = new DsaPrivateKeyParameters(dsaSecretBcpgKey.X, parameters2);
break;
}
case PublicKeyAlgorithmTag.EC:
privateKey = GetECKey("ECDH", bcpgIn);
break;
case PublicKeyAlgorithmTag.ECDsa:
privateKey = GetECKey("ECDSA", bcpgIn);
break;
case PublicKeyAlgorithmTag.ElGamalEncrypt:
case PublicKeyAlgorithmTag.ElGamalGeneral:
{
ElGamalPublicBcpgKey elGamalPublicBcpgKey = (ElGamalPublicBcpgKey)publicKeyPacket.Key;
ElGamalSecretBcpgKey elGamalSecretBcpgKey = new ElGamalSecretBcpgKey(bcpgIn);
ElGamalParameters parameters = new ElGamalParameters(elGamalPublicBcpgKey.P, elGamalPublicBcpgKey.G);
privateKey = new ElGamalPrivateKeyParameters(elGamalSecretBcpgKey.X, parameters);
break;
}
default:
throw new PgpException("unknown public key algorithm encountered");
}
return new PgpPrivateKey(KeyId, publicKeyPacket, privateKey);
}
catch (PgpException ex)
{
throw ex;
}
catch (Exception exception)
{
throw new PgpException("Exception constructing key", exception);
}
}
private ECPrivateKeyParameters GetECKey(string algorithm, BcpgInputStream bcpgIn)
{
ECPublicBcpgKey eCPublicBcpgKey = (ECPublicBcpgKey)secret.PublicKeyPacket.Key;
ECSecretBcpgKey eCSecretBcpgKey = new ECSecretBcpgKey(bcpgIn);
return new ECPrivateKeyParameters(algorithm, eCSecretBcpgKey.X, eCPublicBcpgKey.CurveOid);
}
private static byte[] Checksum(bool useSha1, byte[] bytes, int length)
{
if (useSha1)
{
try
{
IDigest digest = DigestUtilities.GetDigest("SHA1");
digest.BlockUpdate(bytes, 0, length);
return DigestUtilities.DoFinal(digest);
}
catch (Exception exception)
{
throw new PgpException("Can't find SHA-1", exception);
}
}
int num = 0;
for (int i = 0; i != length; i++)
{
num += bytes[i];
}
return new byte[2]
{
(byte)(num >> 8),
(byte)num
};
}
public byte[] GetEncoded()
{
MemoryStream memoryStream = new MemoryStream();
Encode(memoryStream);
return memoryStream.ToArray();
}
public void Encode(Stream outStr)
{
BcpgOutputStream bcpgOutputStream = BcpgOutputStream.Wrap(outStr);
bcpgOutputStream.WritePacket(secret);
if (pub.trustPk != null)
{
bcpgOutputStream.WritePacket(pub.trustPk);
}
if (pub.subSigs == null)
{
foreach (PgpSignature keySig in pub.keySigs)
{
keySig.Encode(bcpgOutputStream);
}
for (int i = 0; i != pub.ids.Count; i++)
{
object obj = pub.ids[i];
if (obj is string)
{
string id = (string)obj;
bcpgOutputStream.WritePacket(new UserIdPacket(id));
}
else
{
PgpUserAttributeSubpacketVector pgpUserAttributeSubpacketVector = (PgpUserAttributeSubpacketVector)obj;
bcpgOutputStream.WritePacket(new UserAttributePacket(pgpUserAttributeSubpacketVector.ToSubpacketArray()));
}
if (pub.idTrusts[i] != null)
{
bcpgOutputStream.WritePacket((ContainedPacket)pub.idTrusts[i]);
}
foreach (PgpSignature item in (IList)pub.idSigs[i])
{
item.Encode(bcpgOutputStream);
}
}
return;
}
foreach (PgpSignature subSig in pub.subSigs)
{
subSig.Encode(bcpgOutputStream);
}
}
public static PgpSecretKey CopyWithNewPassword(PgpSecretKey key, char[] oldPassPhrase, char[] newPassPhrase, SymmetricKeyAlgorithmTag newEncAlgorithm, SecureRandom rand)
{
return DoCopyWithNewPassword(key, PgpUtilities.EncodePassPhrase(oldPassPhrase, utf8: false), PgpUtilities.EncodePassPhrase(newPassPhrase, utf8: false), clearPassPhrase: true, newEncAlgorithm, rand);
}
public static PgpSecretKey CopyWithNewPasswordUtf8(PgpSecretKey key, char[] oldPassPhrase, char[] newPassPhrase, SymmetricKeyAlgorithmTag newEncAlgorithm, SecureRandom rand)
{
return DoCopyWithNewPassword(key, PgpUtilities.EncodePassPhrase(oldPassPhrase, utf8: true), PgpUtilities.EncodePassPhrase(newPassPhrase, utf8: true), clearPassPhrase: true, newEncAlgorithm, rand);
}
public static PgpSecretKey CopyWithNewPasswordRaw(PgpSecretKey key, byte[] rawOldPassPhrase, byte[] rawNewPassPhrase, SymmetricKeyAlgorithmTag newEncAlgorithm, SecureRandom rand)
{
return DoCopyWithNewPassword(key, rawOldPassPhrase, rawNewPassPhrase, clearPassPhrase: false, newEncAlgorithm, rand);
}
internal static PgpSecretKey DoCopyWithNewPassword(PgpSecretKey key, byte[] rawOldPassPhrase, byte[] rawNewPassPhrase, bool clearPassPhrase, SymmetricKeyAlgorithmTag newEncAlgorithm, SecureRandom rand)
{
if (key.IsPrivateKeyEmpty)
{
throw new PgpException("no private key in this SecretKey - public key present only.");
}
byte[] array = key.ExtractKeyData(rawOldPassPhrase, clearPassPhrase);
int num = key.secret.S2kUsage;
byte[] iv = null;
S2k s2k = null;
PublicKeyPacket publicKeyPacket = key.secret.PublicKeyPacket;
byte[] array2;
if (newEncAlgorithm == SymmetricKeyAlgorithmTag.Null)
{
num = 0;
if (key.secret.S2kUsage == 254)
{
array2 = new byte[array.Length - 18];
Array.Copy(array, 0, array2, 0, array2.Length - 2);
byte[] array3 = Checksum(useSha1: false, array2, array2.Length - 2);
array2[^2] = array3[0];
array2[^1] = array3[1];
}
else
{
array2 = array;
}
}
else
{
if (num == 0)
{
num = 255;
}
try
{
array2 = ((publicKeyPacket.Version < 4) ? EncryptKeyDataV3(array, newEncAlgorithm, rawNewPassPhrase, clearPassPhrase, rand, out s2k, out iv) : EncryptKeyDataV4(array, newEncAlgorithm, HashAlgorithmTag.Sha1, rawNewPassPhrase, clearPassPhrase, rand, out s2k, out iv));
}
catch (PgpException ex)
{
throw ex;
}
catch (Exception exception)
{
throw new PgpException("Exception encrypting key", exception);
}
}
SecretKeyPacket secretKeyPacket = ((!(key.secret is SecretSubkeyPacket)) ? new SecretKeyPacket(publicKeyPacket, newEncAlgorithm, num, s2k, iv, array2) : new SecretSubkeyPacket(publicKeyPacket, newEncAlgorithm, num, s2k, iv, array2));
return new PgpSecretKey(secretKeyPacket, key.pub);
}
public static PgpSecretKey ReplacePublicKey(PgpSecretKey secretKey, PgpPublicKey publicKey)
{
if (publicKey.KeyId != secretKey.KeyId)
{
throw new ArgumentException("KeyId's do not match");
}
return new PgpSecretKey(secretKey.secret, publicKey);
}
private static byte[] EncryptKeyDataV3(byte[] rawKeyData, SymmetricKeyAlgorithmTag encAlgorithm, byte[] rawPassPhrase, bool clearPassPhrase, SecureRandom random, out S2k s2k, out byte[] iv)
{
s2k = null;
iv = null;
KeyParameter key = PgpUtilities.DoMakeKeyFromPassPhrase(encAlgorithm, s2k, rawPassPhrase, clearPassPhrase);
byte[] array = new byte[rawKeyData.Length];
int num = 0;
for (int i = 0; i != 4; i++)
{
int num2 = (((rawKeyData[num] << 8) | (rawKeyData[num + 1] & 0xFF)) + 7) / 8;
array[num] = rawKeyData[num];
array[num + 1] = rawKeyData[num + 1];
byte[] array2;
if (i == 0)
{
array2 = EncryptData(encAlgorithm, key, rawKeyData, num + 2, num2, random, ref iv);
}
else
{
byte[] iv2 = Arrays.CopyOfRange(array, num - iv.Length, num);
array2 = EncryptData(encAlgorithm, key, rawKeyData, num + 2, num2, random, ref iv2);
}
Array.Copy(array2, 0, array, num + 2, array2.Length);
num += 2 + num2;
}
array[num] = rawKeyData[num];
array[num + 1] = rawKeyData[num + 1];
return array;
}
private static byte[] EncryptKeyDataV4(byte[] rawKeyData, SymmetricKeyAlgorithmTag encAlgorithm, HashAlgorithmTag hashAlgorithm, byte[] rawPassPhrase, bool clearPassPhrase, SecureRandom random, out S2k s2k, out byte[] iv)
{
s2k = PgpUtilities.GenerateS2k(hashAlgorithm, 96, random);
KeyParameter key = PgpUtilities.DoMakeKeyFromPassPhrase(encAlgorithm, s2k, rawPassPhrase, clearPassPhrase);
iv = null;
return EncryptData(encAlgorithm, key, rawKeyData, 0, rawKeyData.Length, random, ref iv);
}
private static byte[] EncryptData(SymmetricKeyAlgorithmTag encAlgorithm, KeyParameter key, byte[] data, int dataOff, int dataLen, SecureRandom random, ref byte[] iv)
{
IBufferedCipher cipher;
try
{
string symmetricCipherName = PgpUtilities.GetSymmetricCipherName(encAlgorithm);
cipher = CipherUtilities.GetCipher(symmetricCipherName + "/CFB/NoPadding");
}
catch (Exception exception)
{
throw new PgpException("Exception creating cipher", exception);
}
if (iv == null)
{
iv = PgpUtilities.GenerateIV(cipher.GetBlockSize(), random);
}
cipher.Init(forEncryption: true, new ParametersWithRandom(new ParametersWithIV(key, iv), random));
return cipher.DoFinal(data, dataOff, dataLen);
}
public static PgpSecretKey ParseSecretKeyFromSExpr(Stream inputStream, char[] passPhrase, PgpPublicKey pubKey)
{
return DoParseSecretKeyFromSExpr(inputStream, PgpUtilities.EncodePassPhrase(passPhrase, utf8: false), clearPassPhrase: true, pubKey);
}
public static PgpSecretKey ParseSecretKeyFromSExprUtf8(Stream inputStream, char[] passPhrase, PgpPublicKey pubKey)
{
return DoParseSecretKeyFromSExpr(inputStream, PgpUtilities.EncodePassPhrase(passPhrase, utf8: true), clearPassPhrase: true, pubKey);
}
public static PgpSecretKey ParseSecretKeyFromSExprRaw(Stream inputStream, byte[] rawPassPhrase, PgpPublicKey pubKey)
{
return DoParseSecretKeyFromSExpr(inputStream, rawPassPhrase, clearPassPhrase: false, pubKey);
}
internal static PgpSecretKey DoParseSecretKeyFromSExpr(Stream inputStream, byte[] rawPassPhrase, bool clearPassPhrase, PgpPublicKey pubKey)
{
SXprUtilities.SkipOpenParenthesis(inputStream);
string text = SXprUtilities.ReadString(inputStream, inputStream.ReadByte());
if (text.Equals("protected-private-key"))
{
SXprUtilities.SkipOpenParenthesis(inputStream);
string text2 = SXprUtilities.ReadString(inputStream, inputStream.ReadByte());
if (text2.Equals("ecc"))
{
SXprUtilities.SkipOpenParenthesis(inputStream);
SXprUtilities.ReadString(inputStream, inputStream.ReadByte());
string curveName = SXprUtilities.ReadString(inputStream, inputStream.ReadByte());
SXprUtilities.SkipCloseParenthesis(inputStream);
SXprUtilities.SkipOpenParenthesis(inputStream);
text = SXprUtilities.ReadString(inputStream, inputStream.ReadByte());
if (text.Equals("q"))
{
SXprUtilities.ReadBytes(inputStream, inputStream.ReadByte());
SXprUtilities.SkipCloseParenthesis(inputStream);
byte[] dValue = GetDValue(inputStream, rawPassPhrase, clearPassPhrase, curveName);
return new PgpSecretKey(new SecretKeyPacket(pubKey.PublicKeyPacket, SymmetricKeyAlgorithmTag.Null, null, null, new ECSecretBcpgKey(new BigInteger(1, dValue)).GetEncoded()), pubKey);
}
throw new PgpException("no q value found");
}
throw new PgpException("no curve details found");
}
throw new PgpException("unknown key type found");
}
public static PgpSecretKey ParseSecretKeyFromSExpr(Stream inputStream, char[] passPhrase)
{
return DoParseSecretKeyFromSExpr(inputStream, PgpUtilities.EncodePassPhrase(passPhrase, utf8: false), clearPassPhrase: true);
}
public static PgpSecretKey ParseSecretKeyFromSExprUtf8(Stream inputStream, char[] passPhrase)
{
return DoParseSecretKeyFromSExpr(inputStream, PgpUtilities.EncodePassPhrase(passPhrase, utf8: true), clearPassPhrase: true);
}
public static PgpSecretKey ParseSecretKeyFromSExprRaw(Stream inputStream, byte[] rawPassPhrase)
{
return DoParseSecretKeyFromSExpr(inputStream, rawPassPhrase, clearPassPhrase: false);
}
internal static PgpSecretKey DoParseSecretKeyFromSExpr(Stream inputStream, byte[] rawPassPhrase, bool clearPassPhrase)
{
SXprUtilities.SkipOpenParenthesis(inputStream);
string text = SXprUtilities.ReadString(inputStream, inputStream.ReadByte());
if (text.Equals("protected-private-key"))
{
SXprUtilities.SkipOpenParenthesis(inputStream);
string text2 = SXprUtilities.ReadString(inputStream, inputStream.ReadByte());
if (text2.Equals("ecc"))
{
SXprUtilities.SkipOpenParenthesis(inputStream);
SXprUtilities.ReadString(inputStream, inputStream.ReadByte());
string text3 = SXprUtilities.ReadString(inputStream, inputStream.ReadByte());
if (Platform.StartsWith(text3, "NIST "))
{
text3 = text3.Substring("NIST ".Length);
}
SXprUtilities.SkipCloseParenthesis(inputStream);
SXprUtilities.SkipOpenParenthesis(inputStream);
text = SXprUtilities.ReadString(inputStream, inputStream.ReadByte());
if (text.Equals("q"))
{
byte[] bytes = SXprUtilities.ReadBytes(inputStream, inputStream.ReadByte());
PublicKeyPacket publicKeyPacket = new PublicKeyPacket(PublicKeyAlgorithmTag.ECDsa, DateTime.UtcNow, new ECDsaPublicBcpgKey(ECNamedCurveTable.GetOid(text3), new BigInteger(1, bytes)));
SXprUtilities.SkipCloseParenthesis(inputStream);
byte[] dValue = GetDValue(inputStream, rawPassPhrase, clearPassPhrase, text3);
return new PgpSecretKey(new SecretKeyPacket(publicKeyPacket, SymmetricKeyAlgorithmTag.Null, null, null, new ECSecretBcpgKey(new BigInteger(1, dValue)).GetEncoded()), new PgpPublicKey(publicKeyPacket));
}
throw new PgpException("no q value found");
}
throw new PgpException("no curve details found");
}
throw new PgpException("unknown key type found");
}
private static byte[] GetDValue(Stream inputStream, byte[] rawPassPhrase, bool clearPassPhrase, string curveName)
{
SXprUtilities.SkipOpenParenthesis(inputStream);
string text = SXprUtilities.ReadString(inputStream, inputStream.ReadByte());
if (text.Equals("protected"))
{
SXprUtilities.ReadString(inputStream, inputStream.ReadByte());
SXprUtilities.SkipOpenParenthesis(inputStream);
S2k s2k = SXprUtilities.ParseS2k(inputStream);
byte[] iv = SXprUtilities.ReadBytes(inputStream, inputStream.ReadByte());
SXprUtilities.SkipCloseParenthesis(inputStream);
byte[] array = SXprUtilities.ReadBytes(inputStream, inputStream.ReadByte());
KeyParameter key = PgpUtilities.DoMakeKeyFromPassPhrase(SymmetricKeyAlgorithmTag.Aes128, s2k, rawPassPhrase, clearPassPhrase);
byte[] buffer = RecoverKeyData(SymmetricKeyAlgorithmTag.Aes128, "/CBC/NoPadding", key, iv, array, 0, array.Length);
Stream stream = new MemoryStream(buffer, writable: false);
SXprUtilities.SkipOpenParenthesis(stream);
SXprUtilities.SkipOpenParenthesis(stream);
SXprUtilities.SkipOpenParenthesis(stream);
SXprUtilities.ReadString(stream, stream.ReadByte());
return SXprUtilities.ReadBytes(stream, stream.ReadByte());
}
throw new PgpException("protected block not found");
}
}

View File

@@ -0,0 +1,213 @@
using System;
using System.Collections;
using System.IO;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.Collections;
namespace Org.BouncyCastle.Bcpg.OpenPgp;
public class PgpSecretKeyRing : PgpKeyRing
{
private readonly IList keys;
private readonly IList extraPubKeys;
internal PgpSecretKeyRing(IList keys)
: this(keys, Platform.CreateArrayList())
{
}
private PgpSecretKeyRing(IList keys, IList extraPubKeys)
{
this.keys = keys;
this.extraPubKeys = extraPubKeys;
}
public PgpSecretKeyRing(byte[] encoding)
: this(new MemoryStream(encoding))
{
}
public PgpSecretKeyRing(Stream inputStream)
{
keys = Platform.CreateArrayList();
extraPubKeys = Platform.CreateArrayList();
BcpgInputStream bcpgInputStream = BcpgInputStream.Wrap(inputStream);
PacketTag packetTag = bcpgInputStream.NextPacketTag();
if (packetTag != PacketTag.SecretKey && packetTag != PacketTag.SecretSubkey)
{
int num = (int)packetTag;
throw new IOException("secret key ring doesn't start with secret key tag: tag 0x" + num.ToString("X"));
}
SecretKeyPacket secretKeyPacket = (SecretKeyPacket)bcpgInputStream.ReadPacket();
while (bcpgInputStream.NextPacketTag() == PacketTag.Experimental2)
{
bcpgInputStream.ReadPacket();
}
TrustPacket trustPk = PgpKeyRing.ReadOptionalTrustPacket(bcpgInputStream);
IList keySigs = PgpKeyRing.ReadSignaturesAndTrust(bcpgInputStream);
PgpKeyRing.ReadUserIDs(bcpgInputStream, out var ids, out var idTrusts, out var idSigs);
keys.Add(new PgpSecretKey(secretKeyPacket, new PgpPublicKey(secretKeyPacket.PublicKeyPacket, trustPk, keySigs, ids, idTrusts, idSigs)));
while (bcpgInputStream.NextPacketTag() == PacketTag.SecretSubkey || bcpgInputStream.NextPacketTag() == PacketTag.PublicSubkey)
{
if (bcpgInputStream.NextPacketTag() == PacketTag.SecretSubkey)
{
SecretSubkeyPacket secretSubkeyPacket = (SecretSubkeyPacket)bcpgInputStream.ReadPacket();
while (bcpgInputStream.NextPacketTag() == PacketTag.Experimental2)
{
bcpgInputStream.ReadPacket();
}
TrustPacket trustPk2 = PgpKeyRing.ReadOptionalTrustPacket(bcpgInputStream);
IList sigs = PgpKeyRing.ReadSignaturesAndTrust(bcpgInputStream);
keys.Add(new PgpSecretKey(secretSubkeyPacket, new PgpPublicKey(secretSubkeyPacket.PublicKeyPacket, trustPk2, sigs)));
}
else
{
PublicSubkeyPacket publicPk = (PublicSubkeyPacket)bcpgInputStream.ReadPacket();
TrustPacket trustPk3 = PgpKeyRing.ReadOptionalTrustPacket(bcpgInputStream);
IList sigs2 = PgpKeyRing.ReadSignaturesAndTrust(bcpgInputStream);
extraPubKeys.Add(new PgpPublicKey(publicPk, trustPk3, sigs2));
}
}
}
public PgpPublicKey GetPublicKey()
{
return ((PgpSecretKey)keys[0]).PublicKey;
}
public PgpSecretKey GetSecretKey()
{
return (PgpSecretKey)keys[0];
}
public IEnumerable GetSecretKeys()
{
return new EnumerableProxy(keys);
}
public PgpSecretKey GetSecretKey(long keyId)
{
foreach (PgpSecretKey key in keys)
{
if (keyId == key.KeyId)
{
return key;
}
}
return null;
}
public IEnumerable GetExtraPublicKeys()
{
return new EnumerableProxy(extraPubKeys);
}
public byte[] GetEncoded()
{
MemoryStream memoryStream = new MemoryStream();
Encode(memoryStream);
return memoryStream.ToArray();
}
public void Encode(Stream outStr)
{
if (outStr == null)
{
throw new ArgumentNullException("outStr");
}
foreach (PgpSecretKey key in keys)
{
key.Encode(outStr);
}
foreach (PgpPublicKey extraPubKey in extraPubKeys)
{
extraPubKey.Encode(outStr);
}
}
public static PgpSecretKeyRing ReplacePublicKeys(PgpSecretKeyRing secretRing, PgpPublicKeyRing publicRing)
{
IList list = Platform.CreateArrayList(secretRing.keys.Count);
foreach (PgpSecretKey key in secretRing.keys)
{
PgpPublicKey publicKey = publicRing.GetPublicKey(key.KeyId);
list.Add(PgpSecretKey.ReplacePublicKey(key, publicKey));
}
return new PgpSecretKeyRing(list);
}
public static PgpSecretKeyRing CopyWithNewPassword(PgpSecretKeyRing ring, char[] oldPassPhrase, char[] newPassPhrase, SymmetricKeyAlgorithmTag newEncAlgorithm, SecureRandom rand)
{
IList list = Platform.CreateArrayList(ring.keys.Count);
foreach (PgpSecretKey secretKey in ring.GetSecretKeys())
{
if (secretKey.IsPrivateKeyEmpty)
{
list.Add(secretKey);
}
else
{
list.Add(PgpSecretKey.CopyWithNewPassword(secretKey, oldPassPhrase, newPassPhrase, newEncAlgorithm, rand));
}
}
return new PgpSecretKeyRing(list, ring.extraPubKeys);
}
public static PgpSecretKeyRing InsertSecretKey(PgpSecretKeyRing secRing, PgpSecretKey secKey)
{
IList list = Platform.CreateArrayList(secRing.keys);
bool flag = false;
bool flag2 = false;
for (int i = 0; i != list.Count; i++)
{
PgpSecretKey pgpSecretKey = (PgpSecretKey)list[i];
if (pgpSecretKey.KeyId == secKey.KeyId)
{
flag = true;
list[i] = secKey;
}
if (pgpSecretKey.IsMasterKey)
{
flag2 = true;
}
}
if (!flag)
{
if (secKey.IsMasterKey)
{
if (flag2)
{
throw new ArgumentException("cannot add a master key to a ring that already has one");
}
list.Insert(0, secKey);
}
else
{
list.Add(secKey);
}
}
return new PgpSecretKeyRing(list, secRing.extraPubKeys);
}
public static PgpSecretKeyRing RemoveSecretKey(PgpSecretKeyRing secRing, PgpSecretKey secKey)
{
IList list = Platform.CreateArrayList(secRing.keys);
bool flag = false;
for (int i = 0; i < list.Count; i++)
{
PgpSecretKey pgpSecretKey = (PgpSecretKey)list[i];
if (pgpSecretKey.KeyId == secKey.KeyId)
{
flag = true;
list.RemoveAt(i);
}
}
if (!flag)
{
return null;
}
return new PgpSecretKeyRing(list, secRing.extraPubKeys);
}
}

View File

@@ -0,0 +1,179 @@
using System;
using System.Collections;
using System.IO;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.Collections;
namespace Org.BouncyCastle.Bcpg.OpenPgp;
public class PgpSecretKeyRingBundle
{
private readonly IDictionary secretRings;
private readonly IList order;
[Obsolete("Use 'Count' property instead")]
public int Size => order.Count;
public int Count => order.Count;
private PgpSecretKeyRingBundle(IDictionary secretRings, IList order)
{
this.secretRings = secretRings;
this.order = order;
}
public PgpSecretKeyRingBundle(byte[] encoding)
: this(new MemoryStream(encoding, writable: false))
{
}
public PgpSecretKeyRingBundle(Stream inputStream)
: this(new PgpObjectFactory(inputStream).AllPgpObjects())
{
}
public PgpSecretKeyRingBundle(IEnumerable e)
{
secretRings = Platform.CreateHashtable();
order = Platform.CreateArrayList();
foreach (object item in e)
{
if (!(item is PgpSecretKeyRing pgpSecretKeyRing))
{
throw new PgpException(Platform.GetTypeName(item) + " found where PgpSecretKeyRing expected");
}
long keyId = pgpSecretKeyRing.GetPublicKey().KeyId;
secretRings.Add(keyId, pgpSecretKeyRing);
order.Add(keyId);
}
}
public IEnumerable GetKeyRings()
{
return new EnumerableProxy(secretRings.Values);
}
public IEnumerable GetKeyRings(string userId)
{
return GetKeyRings(userId, matchPartial: false, ignoreCase: false);
}
public IEnumerable GetKeyRings(string userId, bool matchPartial)
{
return GetKeyRings(userId, matchPartial, ignoreCase: false);
}
public IEnumerable GetKeyRings(string userId, bool matchPartial, bool ignoreCase)
{
IList list = Platform.CreateArrayList();
if (ignoreCase)
{
userId = Platform.ToUpperInvariant(userId);
}
foreach (PgpSecretKeyRing keyRing in GetKeyRings())
{
foreach (string userId2 in keyRing.GetSecretKey().UserIds)
{
string text2 = userId2;
if (ignoreCase)
{
text2 = Platform.ToUpperInvariant(text2);
}
if (matchPartial)
{
if (Platform.IndexOf(text2, userId) > -1)
{
list.Add(keyRing);
}
}
else if (text2.Equals(userId))
{
list.Add(keyRing);
}
}
}
return new EnumerableProxy(list);
}
public PgpSecretKey GetSecretKey(long keyId)
{
foreach (PgpSecretKeyRing keyRing in GetKeyRings())
{
PgpSecretKey secretKey = keyRing.GetSecretKey(keyId);
if (secretKey != null)
{
return secretKey;
}
}
return null;
}
public PgpSecretKeyRing GetSecretKeyRing(long keyId)
{
if (secretRings.Contains(keyId))
{
return (PgpSecretKeyRing)secretRings[keyId];
}
foreach (PgpSecretKeyRing keyRing in GetKeyRings())
{
PgpSecretKey secretKey = keyRing.GetSecretKey(keyId);
if (secretKey != null)
{
return keyRing;
}
}
return null;
}
public bool Contains(long keyID)
{
return GetSecretKey(keyID) != null;
}
public byte[] GetEncoded()
{
MemoryStream memoryStream = new MemoryStream();
Encode(memoryStream);
return memoryStream.ToArray();
}
public void Encode(Stream outStr)
{
BcpgOutputStream outStr2 = BcpgOutputStream.Wrap(outStr);
foreach (object item in order)
{
long num = (long)item;
PgpSecretKeyRing pgpSecretKeyRing = (PgpSecretKeyRing)secretRings[num];
pgpSecretKeyRing.Encode(outStr2);
}
}
public static PgpSecretKeyRingBundle AddSecretKeyRing(PgpSecretKeyRingBundle bundle, PgpSecretKeyRing secretKeyRing)
{
long keyId = secretKeyRing.GetPublicKey().KeyId;
if (bundle.secretRings.Contains(keyId))
{
throw new ArgumentException("Collection already contains a key with a keyId for the passed in ring.");
}
IDictionary dictionary = Platform.CreateHashtable(bundle.secretRings);
IList list = Platform.CreateArrayList(bundle.order);
dictionary[keyId] = secretKeyRing;
list.Add(keyId);
return new PgpSecretKeyRingBundle(dictionary, list);
}
public static PgpSecretKeyRingBundle RemoveSecretKeyRing(PgpSecretKeyRingBundle bundle, PgpSecretKeyRing secretKeyRing)
{
long keyId = secretKeyRing.GetPublicKey().KeyId;
if (!bundle.secretRings.Contains(keyId))
{
throw new ArgumentException("Collection does not contain a key with a keyId for the passed in ring.");
}
IDictionary dictionary = Platform.CreateHashtable(bundle.secretRings);
IList list = Platform.CreateArrayList(bundle.order);
dictionary.Remove(keyId);
list.Remove(keyId);
return new PgpSecretKeyRingBundle(dictionary, list);
}
}

View File

@@ -0,0 +1,343 @@
using System;
using System.IO;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.Date;
namespace Org.BouncyCastle.Bcpg.OpenPgp;
public class PgpSignature
{
public const int BinaryDocument = 0;
public const int CanonicalTextDocument = 1;
public const int StandAlone = 2;
public const int DefaultCertification = 16;
public const int NoCertification = 17;
public const int CasualCertification = 18;
public const int PositiveCertification = 19;
public const int SubkeyBinding = 24;
public const int PrimaryKeyBinding = 25;
public const int DirectKey = 31;
public const int KeyRevocation = 32;
public const int SubkeyRevocation = 40;
public const int CertificationRevocation = 48;
public const int Timestamp = 64;
private readonly SignaturePacket sigPck;
private readonly int signatureType;
private readonly TrustPacket trustPck;
private ISigner sig;
private byte lastb;
public int Version => sigPck.Version;
public PublicKeyAlgorithmTag KeyAlgorithm => sigPck.KeyAlgorithm;
public HashAlgorithmTag HashAlgorithm => sigPck.HashAlgorithm;
public int SignatureType => sigPck.SignatureType;
public long KeyId => sigPck.KeyId;
public DateTime CreationTime => DateTimeUtilities.UnixMsToDateTime(sigPck.CreationTime);
public bool HasSubpackets
{
get
{
if (sigPck.GetHashedSubPackets() == null)
{
return sigPck.GetUnhashedSubPackets() != null;
}
return true;
}
}
internal PgpSignature(BcpgInputStream bcpgInput)
: this((SignaturePacket)bcpgInput.ReadPacket())
{
}
internal PgpSignature(SignaturePacket sigPacket)
: this(sigPacket, null)
{
}
internal PgpSignature(SignaturePacket sigPacket, TrustPacket trustPacket)
{
if (sigPacket == null)
{
throw new ArgumentNullException("sigPacket");
}
sigPck = sigPacket;
signatureType = sigPck.SignatureType;
trustPck = trustPacket;
}
private void GetSig()
{
sig = SignerUtilities.GetSigner(PgpUtilities.GetSignatureName(sigPck.KeyAlgorithm, sigPck.HashAlgorithm));
}
public bool IsCertification()
{
return IsCertification(SignatureType);
}
public void InitVerify(PgpPublicKey pubKey)
{
lastb = 0;
if (sig == null)
{
GetSig();
}
try
{
sig.Init(forSigning: false, pubKey.GetKey());
}
catch (InvalidKeyException exception)
{
throw new PgpException("invalid key.", exception);
}
}
public void Update(byte b)
{
if (signatureType == 1)
{
doCanonicalUpdateByte(b);
}
else
{
sig.Update(b);
}
}
private void doCanonicalUpdateByte(byte b)
{
switch (b)
{
case 13:
doUpdateCRLF();
break;
case 10:
if (lastb != 13)
{
doUpdateCRLF();
}
break;
default:
sig.Update(b);
break;
}
lastb = b;
}
private void doUpdateCRLF()
{
sig.Update(13);
sig.Update(10);
}
public void Update(params byte[] bytes)
{
Update(bytes, 0, bytes.Length);
}
public void Update(byte[] bytes, int off, int length)
{
if (signatureType == 1)
{
int num = off + length;
for (int i = off; i != num; i++)
{
doCanonicalUpdateByte(bytes[i]);
}
}
else
{
sig.BlockUpdate(bytes, off, length);
}
}
public bool Verify()
{
byte[] signatureTrailer = GetSignatureTrailer();
sig.BlockUpdate(signatureTrailer, 0, signatureTrailer.Length);
return sig.VerifySignature(GetSignature());
}
private void UpdateWithIdData(int header, byte[] idBytes)
{
Update((byte)header, (byte)(idBytes.Length >> 24), (byte)(idBytes.Length >> 16), (byte)(idBytes.Length >> 8), (byte)idBytes.Length);
Update(idBytes);
}
private void UpdateWithPublicKey(PgpPublicKey key)
{
byte[] encodedPublicKey = GetEncodedPublicKey(key);
Update(153, (byte)(encodedPublicKey.Length >> 8), (byte)encodedPublicKey.Length);
Update(encodedPublicKey);
}
public bool VerifyCertification(PgpUserAttributeSubpacketVector userAttributes, PgpPublicKey key)
{
UpdateWithPublicKey(key);
try
{
MemoryStream memoryStream = new MemoryStream();
UserAttributeSubpacket[] array = userAttributes.ToSubpacketArray();
foreach (UserAttributeSubpacket userAttributeSubpacket in array)
{
userAttributeSubpacket.Encode(memoryStream);
}
UpdateWithIdData(209, memoryStream.ToArray());
}
catch (IOException exception)
{
throw new PgpException("cannot encode subpacket array", exception);
}
Update(sigPck.GetSignatureTrailer());
return sig.VerifySignature(GetSignature());
}
public bool VerifyCertification(string id, PgpPublicKey key)
{
UpdateWithPublicKey(key);
UpdateWithIdData(180, Strings.ToUtf8ByteArray(id));
Update(sigPck.GetSignatureTrailer());
return sig.VerifySignature(GetSignature());
}
public bool VerifyCertification(PgpPublicKey masterKey, PgpPublicKey pubKey)
{
UpdateWithPublicKey(masterKey);
UpdateWithPublicKey(pubKey);
Update(sigPck.GetSignatureTrailer());
return sig.VerifySignature(GetSignature());
}
public bool VerifyCertification(PgpPublicKey pubKey)
{
if (SignatureType != 32 && SignatureType != 40)
{
throw new InvalidOperationException("signature is not a key signature");
}
UpdateWithPublicKey(pubKey);
Update(sigPck.GetSignatureTrailer());
return sig.VerifySignature(GetSignature());
}
[Obsolete("Use 'CreationTime' property instead")]
public DateTime GetCreationTime()
{
return CreationTime;
}
public byte[] GetSignatureTrailer()
{
return sigPck.GetSignatureTrailer();
}
public PgpSignatureSubpacketVector GetHashedSubPackets()
{
return createSubpacketVector(sigPck.GetHashedSubPackets());
}
public PgpSignatureSubpacketVector GetUnhashedSubPackets()
{
return createSubpacketVector(sigPck.GetUnhashedSubPackets());
}
private PgpSignatureSubpacketVector createSubpacketVector(SignatureSubpacket[] pcks)
{
if (pcks != null)
{
return new PgpSignatureSubpacketVector(pcks);
}
return null;
}
public byte[] GetSignature()
{
MPInteger[] signature = sigPck.GetSignature();
if (signature != null)
{
if (signature.Length == 1)
{
return signature[0].Value.ToByteArrayUnsigned();
}
try
{
return new DerSequence(new DerInteger(signature[0].Value), new DerInteger(signature[1].Value)).GetEncoded();
}
catch (IOException exception)
{
throw new PgpException("exception encoding DSA sig.", exception);
}
}
return sigPck.GetSignatureBytes();
}
public byte[] GetEncoded()
{
MemoryStream memoryStream = new MemoryStream();
Encode(memoryStream);
return memoryStream.ToArray();
}
public void Encode(Stream outStream)
{
BcpgOutputStream bcpgOutputStream = BcpgOutputStream.Wrap(outStream);
bcpgOutputStream.WritePacket(sigPck);
if (trustPck != null)
{
bcpgOutputStream.WritePacket(trustPck);
}
}
private byte[] GetEncodedPublicKey(PgpPublicKey pubKey)
{
try
{
return pubKey.publicPk.GetEncodedContents();
}
catch (IOException exception)
{
throw new PgpException("exception preparing key.", exception);
}
}
public static bool IsCertification(int signatureType)
{
switch (signatureType)
{
case 16:
case 17:
case 18:
case 19:
return true;
default:
return false;
}
}
}

View File

@@ -0,0 +1,292 @@
using System;
using System.IO;
using Org.BouncyCastle.Bcpg.Sig;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Bcpg.OpenPgp;
public class PgpSignatureGenerator
{
private static readonly SignatureSubpacket[] EmptySignatureSubpackets = new SignatureSubpacket[0];
private PublicKeyAlgorithmTag keyAlgorithm;
private HashAlgorithmTag hashAlgorithm;
private PgpPrivateKey privKey;
private ISigner sig;
private IDigest dig;
private int signatureType;
private byte lastb;
private SignatureSubpacket[] unhashed = EmptySignatureSubpackets;
private SignatureSubpacket[] hashed = EmptySignatureSubpackets;
public PgpSignatureGenerator(PublicKeyAlgorithmTag keyAlgorithm, HashAlgorithmTag hashAlgorithm)
{
this.keyAlgorithm = keyAlgorithm;
this.hashAlgorithm = hashAlgorithm;
dig = DigestUtilities.GetDigest(PgpUtilities.GetDigestName(hashAlgorithm));
sig = SignerUtilities.GetSigner(PgpUtilities.GetSignatureName(keyAlgorithm, hashAlgorithm));
}
public void InitSign(int sigType, PgpPrivateKey key)
{
InitSign(sigType, key, null);
}
public void InitSign(int sigType, PgpPrivateKey key, SecureRandom random)
{
privKey = key;
signatureType = sigType;
try
{
ICipherParameters parameters = key.Key;
if (random != null)
{
parameters = new ParametersWithRandom(key.Key, random);
}
sig.Init(forSigning: true, parameters);
}
catch (InvalidKeyException exception)
{
throw new PgpException("invalid key.", exception);
}
dig.Reset();
lastb = 0;
}
public void Update(byte b)
{
if (signatureType == 1)
{
doCanonicalUpdateByte(b);
}
else
{
doUpdateByte(b);
}
}
private void doCanonicalUpdateByte(byte b)
{
switch (b)
{
case 13:
doUpdateCRLF();
break;
case 10:
if (lastb != 13)
{
doUpdateCRLF();
}
break;
default:
doUpdateByte(b);
break;
}
lastb = b;
}
private void doUpdateCRLF()
{
doUpdateByte(13);
doUpdateByte(10);
}
private void doUpdateByte(byte b)
{
sig.Update(b);
dig.Update(b);
}
public void Update(params byte[] b)
{
Update(b, 0, b.Length);
}
public void Update(byte[] b, int off, int len)
{
if (signatureType == 1)
{
int num = off + len;
for (int i = off; i != num; i++)
{
doCanonicalUpdateByte(b[i]);
}
}
else
{
sig.BlockUpdate(b, off, len);
dig.BlockUpdate(b, off, len);
}
}
public void SetHashedSubpackets(PgpSignatureSubpacketVector hashedPackets)
{
hashed = ((hashedPackets == null) ? EmptySignatureSubpackets : hashedPackets.ToSubpacketArray());
}
public void SetUnhashedSubpackets(PgpSignatureSubpacketVector unhashedPackets)
{
unhashed = ((unhashedPackets == null) ? EmptySignatureSubpackets : unhashedPackets.ToSubpacketArray());
}
public PgpOnePassSignature GenerateOnePassVersion(bool isNested)
{
return new PgpOnePassSignature(new OnePassSignaturePacket(signatureType, hashAlgorithm, keyAlgorithm, privKey.KeyId, isNested));
}
public PgpSignature Generate()
{
SignatureSubpacket[] array = hashed;
SignatureSubpacket[] array2 = unhashed;
if (!packetPresent(hashed, SignatureSubpacketTag.CreationTime))
{
array = insertSubpacket(array, new SignatureCreationTime(critical: false, DateTime.UtcNow));
}
if (!packetPresent(hashed, SignatureSubpacketTag.IssuerKeyId) && !packetPresent(unhashed, SignatureSubpacketTag.IssuerKeyId))
{
array2 = insertSubpacket(array2, new IssuerKeyId(critical: false, privKey.KeyId));
}
int num = 4;
byte[] array4;
try
{
MemoryStream memoryStream = new MemoryStream();
for (int i = 0; i != array.Length; i++)
{
array[i].Encode(memoryStream);
}
byte[] array3 = memoryStream.ToArray();
MemoryStream memoryStream2 = new MemoryStream(array3.Length + 6);
memoryStream2.WriteByte((byte)num);
memoryStream2.WriteByte((byte)signatureType);
memoryStream2.WriteByte((byte)keyAlgorithm);
memoryStream2.WriteByte((byte)hashAlgorithm);
memoryStream2.WriteByte((byte)(array3.Length >> 8));
memoryStream2.WriteByte((byte)array3.Length);
memoryStream2.Write(array3, 0, array3.Length);
array4 = memoryStream2.ToArray();
}
catch (IOException exception)
{
throw new PgpException("exception encoding hashed data.", exception);
}
sig.BlockUpdate(array4, 0, array4.Length);
dig.BlockUpdate(array4, 0, array4.Length);
array4 = new byte[6]
{
(byte)num,
255,
(byte)(array4.Length >> 24),
(byte)(array4.Length >> 16),
(byte)(array4.Length >> 8),
(byte)array4.Length
};
sig.BlockUpdate(array4, 0, array4.Length);
dig.BlockUpdate(array4, 0, array4.Length);
byte[] encoding = sig.GenerateSignature();
byte[] array5 = DigestUtilities.DoFinal(dig);
byte[] fingerprint = new byte[2]
{
array5[0],
array5[1]
};
MPInteger[] signature = ((keyAlgorithm == PublicKeyAlgorithmTag.RsaSign || keyAlgorithm == PublicKeyAlgorithmTag.RsaGeneral) ? PgpUtilities.RsaSigToMpi(encoding) : PgpUtilities.DsaSigToMpi(encoding));
return new PgpSignature(new SignaturePacket(signatureType, privKey.KeyId, keyAlgorithm, hashAlgorithm, array, array2, fingerprint, signature));
}
public PgpSignature GenerateCertification(string id, PgpPublicKey pubKey)
{
UpdateWithPublicKey(pubKey);
UpdateWithIdData(180, Strings.ToUtf8ByteArray(id));
return Generate();
}
public PgpSignature GenerateCertification(PgpUserAttributeSubpacketVector userAttributes, PgpPublicKey pubKey)
{
UpdateWithPublicKey(pubKey);
try
{
MemoryStream memoryStream = new MemoryStream();
UserAttributeSubpacket[] array = userAttributes.ToSubpacketArray();
foreach (UserAttributeSubpacket userAttributeSubpacket in array)
{
userAttributeSubpacket.Encode(memoryStream);
}
UpdateWithIdData(209, memoryStream.ToArray());
}
catch (IOException exception)
{
throw new PgpException("cannot encode subpacket array", exception);
}
return Generate();
}
public PgpSignature GenerateCertification(PgpPublicKey masterKey, PgpPublicKey pubKey)
{
UpdateWithPublicKey(masterKey);
UpdateWithPublicKey(pubKey);
return Generate();
}
public PgpSignature GenerateCertification(PgpPublicKey pubKey)
{
UpdateWithPublicKey(pubKey);
return Generate();
}
private byte[] GetEncodedPublicKey(PgpPublicKey pubKey)
{
try
{
return pubKey.publicPk.GetEncodedContents();
}
catch (IOException exception)
{
throw new PgpException("exception preparing key.", exception);
}
}
private bool packetPresent(SignatureSubpacket[] packets, SignatureSubpacketTag type)
{
for (int i = 0; i != packets.Length; i++)
{
if (packets[i].SubpacketType == type)
{
return true;
}
}
return false;
}
private SignatureSubpacket[] insertSubpacket(SignatureSubpacket[] packets, SignatureSubpacket subpacket)
{
SignatureSubpacket[] array = new SignatureSubpacket[packets.Length + 1];
array[0] = subpacket;
packets.CopyTo(array, 1);
return array;
}
private void UpdateWithIdData(int header, byte[] idBytes)
{
Update((byte)header, (byte)(idBytes.Length >> 24), (byte)(idBytes.Length >> 16), (byte)(idBytes.Length >> 8), (byte)idBytes.Length);
Update(idBytes);
}
private void UpdateWithPublicKey(PgpPublicKey key)
{
byte[] encodedPublicKey = GetEncodedPublicKey(key);
Update(153, (byte)(encodedPublicKey.Length >> 8), (byte)encodedPublicKey.Length);
Update(encodedPublicKey);
}
}

View File

@@ -0,0 +1,33 @@
using System;
namespace Org.BouncyCastle.Bcpg.OpenPgp;
public class PgpSignatureList : PgpObject
{
private PgpSignature[] sigs;
public PgpSignature this[int index] => sigs[index];
[Obsolete("Use 'Count' property instead")]
public int Size => sigs.Length;
public int Count => sigs.Length;
public bool IsEmpty => sigs.Length == 0;
public PgpSignatureList(PgpSignature[] sigs)
{
this.sigs = (PgpSignature[])sigs.Clone();
}
public PgpSignatureList(PgpSignature sig)
{
sigs = new PgpSignature[1] { sig };
}
[Obsolete("Use 'object[index]' syntax instead")]
public PgpSignature Get(int index)
{
return this[index];
}
}

View File

@@ -0,0 +1,127 @@
using System;
using System.Collections;
using Org.BouncyCastle.Bcpg.Sig;
using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Bcpg.OpenPgp;
public class PgpSignatureSubpacketGenerator
{
private IList list = Platform.CreateArrayList();
public void SetRevocable(bool isCritical, bool isRevocable)
{
list.Add(new Revocable(isCritical, isRevocable));
}
public void SetExportable(bool isCritical, bool isExportable)
{
list.Add(new Exportable(isCritical, isExportable));
}
public void SetFeature(bool isCritical, byte feature)
{
list.Add(new Features(isCritical, feature));
}
public void SetTrust(bool isCritical, int depth, int trustAmount)
{
list.Add(new TrustSignature(isCritical, depth, trustAmount));
}
public void SetKeyExpirationTime(bool isCritical, long seconds)
{
list.Add(new KeyExpirationTime(isCritical, seconds));
}
public void SetSignatureExpirationTime(bool isCritical, long seconds)
{
list.Add(new SignatureExpirationTime(isCritical, seconds));
}
public void SetSignatureCreationTime(bool isCritical, DateTime date)
{
list.Add(new SignatureCreationTime(isCritical, date));
}
public void SetPreferredHashAlgorithms(bool isCritical, int[] algorithms)
{
list.Add(new PreferredAlgorithms(SignatureSubpacketTag.PreferredHashAlgorithms, isCritical, algorithms));
}
public void SetPreferredSymmetricAlgorithms(bool isCritical, int[] algorithms)
{
list.Add(new PreferredAlgorithms(SignatureSubpacketTag.PreferredSymmetricAlgorithms, isCritical, algorithms));
}
public void SetPreferredCompressionAlgorithms(bool isCritical, int[] algorithms)
{
list.Add(new PreferredAlgorithms(SignatureSubpacketTag.PreferredCompressionAlgorithms, isCritical, algorithms));
}
public void SetKeyFlags(bool isCritical, int flags)
{
list.Add(new KeyFlags(isCritical, flags));
}
public void SetSignerUserId(bool isCritical, string userId)
{
if (userId == null)
{
throw new ArgumentNullException("userId");
}
list.Add(new SignerUserId(isCritical, userId));
}
public void SetSignerUserId(bool isCritical, byte[] rawUserId)
{
if (rawUserId == null)
{
throw new ArgumentNullException("rawUserId");
}
list.Add(new SignerUserId(isCritical, isLongLength: false, rawUserId));
}
public void SetEmbeddedSignature(bool isCritical, PgpSignature pgpSignature)
{
byte[] encoded = pgpSignature.GetEncoded();
byte[] array = ((encoded.Length - 1 <= 256) ? new byte[encoded.Length - 2] : new byte[encoded.Length - 3]);
Array.Copy(encoded, encoded.Length - array.Length, array, 0, array.Length);
list.Add(new EmbeddedSignature(isCritical, isLongLength: false, array));
}
public void SetPrimaryUserId(bool isCritical, bool isPrimaryUserId)
{
list.Add(new PrimaryUserId(isCritical, isPrimaryUserId));
}
public void SetNotationData(bool isCritical, bool isHumanReadable, string notationName, string notationValue)
{
list.Add(new NotationData(isCritical, isHumanReadable, notationName, notationValue));
}
public void SetRevocationReason(bool isCritical, RevocationReasonTag reason, string description)
{
list.Add(new RevocationReason(isCritical, reason, description));
}
public void SetRevocationKey(bool isCritical, PublicKeyAlgorithmTag keyAlgorithm, byte[] fingerprint)
{
list.Add(new RevocationKey(isCritical, RevocationKeyTag.ClassDefault, keyAlgorithm, fingerprint));
}
public void SetIssuerKeyID(bool isCritical, long keyID)
{
list.Add(new IssuerKeyId(isCritical, keyID));
}
public PgpSignatureSubpacketVector Generate()
{
SignatureSubpacket[] array = new SignatureSubpacket[list.Count];
for (int i = 0; i < list.Count; i++)
{
array[i] = (SignatureSubpacket)list[i];
}
return new PgpSignatureSubpacketVector(array);
}
}

View File

@@ -0,0 +1,212 @@
using System;
using Org.BouncyCastle.Bcpg.Sig;
namespace Org.BouncyCastle.Bcpg.OpenPgp;
public class PgpSignatureSubpacketVector
{
private readonly SignatureSubpacket[] packets;
[Obsolete("Use 'Count' property instead")]
public int Size => packets.Length;
public int Count => packets.Length;
internal PgpSignatureSubpacketVector(SignatureSubpacket[] packets)
{
this.packets = packets;
}
public SignatureSubpacket GetSubpacket(SignatureSubpacketTag type)
{
for (int i = 0; i != packets.Length; i++)
{
if (packets[i].SubpacketType == type)
{
return packets[i];
}
}
return null;
}
public bool HasSubpacket(SignatureSubpacketTag type)
{
return GetSubpacket(type) != null;
}
public SignatureSubpacket[] GetSubpackets(SignatureSubpacketTag type)
{
int num = 0;
for (int i = 0; i < packets.Length; i++)
{
if (packets[i].SubpacketType == type)
{
num++;
}
}
SignatureSubpacket[] array = new SignatureSubpacket[num];
int num2 = 0;
for (int j = 0; j < packets.Length; j++)
{
if (packets[j].SubpacketType == type)
{
array[num2++] = packets[j];
}
}
return array;
}
public NotationData[] GetNotationDataOccurrences()
{
SignatureSubpacket[] subpackets = GetSubpackets(SignatureSubpacketTag.NotationData);
NotationData[] array = new NotationData[subpackets.Length];
for (int i = 0; i < subpackets.Length; i++)
{
array[i] = (NotationData)subpackets[i];
}
return array;
}
[Obsolete("Use 'GetNotationDataOccurrences' instead")]
public NotationData[] GetNotationDataOccurences()
{
return GetNotationDataOccurrences();
}
public long GetIssuerKeyId()
{
SignatureSubpacket subpacket = GetSubpacket(SignatureSubpacketTag.IssuerKeyId);
if (subpacket != null)
{
return ((IssuerKeyId)subpacket).KeyId;
}
return 0L;
}
public bool HasSignatureCreationTime()
{
return GetSubpacket(SignatureSubpacketTag.CreationTime) != null;
}
public DateTime GetSignatureCreationTime()
{
SignatureSubpacket subpacket = GetSubpacket(SignatureSubpacketTag.CreationTime);
if (subpacket == null)
{
throw new PgpException("SignatureCreationTime not available");
}
return ((SignatureCreationTime)subpacket).GetTime();
}
public long GetSignatureExpirationTime()
{
SignatureSubpacket subpacket = GetSubpacket(SignatureSubpacketTag.ExpireTime);
if (subpacket != null)
{
return ((SignatureExpirationTime)subpacket).Time;
}
return 0L;
}
public long GetKeyExpirationTime()
{
SignatureSubpacket subpacket = GetSubpacket(SignatureSubpacketTag.KeyExpireTime);
if (subpacket != null)
{
return ((KeyExpirationTime)subpacket).Time;
}
return 0L;
}
public int[] GetPreferredHashAlgorithms()
{
SignatureSubpacket subpacket = GetSubpacket(SignatureSubpacketTag.PreferredHashAlgorithms);
if (subpacket != null)
{
return ((PreferredAlgorithms)subpacket).GetPreferences();
}
return null;
}
public int[] GetPreferredSymmetricAlgorithms()
{
SignatureSubpacket subpacket = GetSubpacket(SignatureSubpacketTag.PreferredSymmetricAlgorithms);
if (subpacket != null)
{
return ((PreferredAlgorithms)subpacket).GetPreferences();
}
return null;
}
public int[] GetPreferredCompressionAlgorithms()
{
SignatureSubpacket subpacket = GetSubpacket(SignatureSubpacketTag.PreferredCompressionAlgorithms);
if (subpacket != null)
{
return ((PreferredAlgorithms)subpacket).GetPreferences();
}
return null;
}
public int GetKeyFlags()
{
SignatureSubpacket subpacket = GetSubpacket(SignatureSubpacketTag.KeyFlags);
if (subpacket != null)
{
return ((KeyFlags)subpacket).Flags;
}
return 0;
}
public string GetSignerUserId()
{
SignatureSubpacket subpacket = GetSubpacket(SignatureSubpacketTag.SignerUserId);
if (subpacket != null)
{
return ((SignerUserId)subpacket).GetId();
}
return null;
}
public bool IsPrimaryUserId()
{
return ((PrimaryUserId)GetSubpacket(SignatureSubpacketTag.PrimaryUserId))?.IsPrimaryUserId() ?? false;
}
public SignatureSubpacketTag[] GetCriticalTags()
{
int num = 0;
for (int i = 0; i != packets.Length; i++)
{
if (packets[i].IsCritical())
{
num++;
}
}
SignatureSubpacketTag[] array = new SignatureSubpacketTag[num];
num = 0;
for (int j = 0; j != packets.Length; j++)
{
if (packets[j].IsCritical())
{
array[num++] = packets[j].SubpacketType;
}
}
return array;
}
public Features GetFeatures()
{
SignatureSubpacket subpacket = GetSubpacket(SignatureSubpacketTag.Features);
if (subpacket == null)
{
return null;
}
return new Features(subpacket.IsCritical(), subpacket.IsLongLength(), subpacket.GetData());
}
internal SignatureSubpacket[] ToSubpacketArray()
{
return packets;
}
}

View File

@@ -0,0 +1,75 @@
using Org.BouncyCastle.Bcpg.Attr;
namespace Org.BouncyCastle.Bcpg.OpenPgp;
public class PgpUserAttributeSubpacketVector
{
private readonly UserAttributeSubpacket[] packets;
internal PgpUserAttributeSubpacketVector(UserAttributeSubpacket[] packets)
{
this.packets = packets;
}
public UserAttributeSubpacket GetSubpacket(UserAttributeSubpacketTag type)
{
for (int i = 0; i != packets.Length; i++)
{
if (packets[i].SubpacketType == type)
{
return packets[i];
}
}
return null;
}
public ImageAttrib GetImageAttribute()
{
UserAttributeSubpacket subpacket = GetSubpacket(UserAttributeSubpacketTag.ImageAttribute);
if (subpacket != null)
{
return (ImageAttrib)subpacket;
}
return null;
}
internal UserAttributeSubpacket[] ToSubpacketArray()
{
return packets;
}
public override bool Equals(object obj)
{
if (obj == this)
{
return true;
}
if (!(obj is PgpUserAttributeSubpacketVector pgpUserAttributeSubpacketVector))
{
return false;
}
if (pgpUserAttributeSubpacketVector.packets.Length != packets.Length)
{
return false;
}
for (int i = 0; i != packets.Length; i++)
{
if (!pgpUserAttributeSubpacketVector.packets[i].Equals(packets[i]))
{
return false;
}
}
return true;
}
public override int GetHashCode()
{
int num = 0;
UserAttributeSubpacket[] array = packets;
foreach (object obj in array)
{
num ^= obj.GetHashCode();
}
return num;
}
}

View File

@@ -0,0 +1,30 @@
using System;
using System.Collections;
using Org.BouncyCastle.Bcpg.Attr;
using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Bcpg.OpenPgp;
public class PgpUserAttributeSubpacketVectorGenerator
{
private IList list = Platform.CreateArrayList();
public virtual void SetImageAttribute(ImageAttrib.Format imageType, byte[] imageData)
{
if (imageData == null)
{
throw new ArgumentException("attempt to set null image", "imageData");
}
list.Add(new ImageAttrib(imageType, imageData));
}
public virtual PgpUserAttributeSubpacketVector Generate()
{
UserAttributeSubpacket[] array = new UserAttributeSubpacket[list.Count];
for (int i = 0; i < list.Count; i++)
{
array[i] = (UserAttributeSubpacket)list[i];
}
return new PgpUserAttributeSubpacketVector(array);
}
}

View File

@@ -0,0 +1,419 @@
using System;
using System.IO;
using System.Text;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.Encoders;
namespace Org.BouncyCastle.Bcpg.OpenPgp;
public sealed class PgpUtilities
{
private const int ReadAhead = 60;
private PgpUtilities()
{
}
public static MPInteger[] DsaSigToMpi(byte[] encoding)
{
DerInteger derInteger;
DerInteger derInteger2;
try
{
Asn1Sequence asn1Sequence = (Asn1Sequence)Asn1Object.FromByteArray(encoding);
derInteger = (DerInteger)asn1Sequence[0];
derInteger2 = (DerInteger)asn1Sequence[1];
}
catch (IOException exception)
{
throw new PgpException("exception encoding signature", exception);
}
return new MPInteger[2]
{
new MPInteger(derInteger.Value),
new MPInteger(derInteger2.Value)
};
}
public static MPInteger[] RsaSigToMpi(byte[] encoding)
{
return new MPInteger[1]
{
new MPInteger(new BigInteger(1, encoding))
};
}
public static string GetDigestName(HashAlgorithmTag hashAlgorithm)
{
return hashAlgorithm switch
{
HashAlgorithmTag.Sha1 => "SHA1",
HashAlgorithmTag.MD2 => "MD2",
HashAlgorithmTag.MD5 => "MD5",
HashAlgorithmTag.RipeMD160 => "RIPEMD160",
HashAlgorithmTag.Sha224 => "SHA224",
HashAlgorithmTag.Sha256 => "SHA256",
HashAlgorithmTag.Sha384 => "SHA384",
HashAlgorithmTag.Sha512 => "SHA512",
_ => throw new PgpException("unknown hash algorithm tag in GetDigestName: " + hashAlgorithm),
};
}
public static string GetSignatureName(PublicKeyAlgorithmTag keyAlgorithm, HashAlgorithmTag hashAlgorithm)
{
string text;
switch (keyAlgorithm)
{
case PublicKeyAlgorithmTag.RsaGeneral:
case PublicKeyAlgorithmTag.RsaSign:
text = "RSA";
break;
case PublicKeyAlgorithmTag.Dsa:
text = "DSA";
break;
case PublicKeyAlgorithmTag.EC:
text = "ECDH";
break;
case PublicKeyAlgorithmTag.ECDsa:
text = "ECDSA";
break;
case PublicKeyAlgorithmTag.ElGamalEncrypt:
case PublicKeyAlgorithmTag.ElGamalGeneral:
text = "ElGamal";
break;
default:
throw new PgpException("unknown algorithm tag in signature:" + keyAlgorithm);
}
return GetDigestName(hashAlgorithm) + "with" + text;
}
public static string GetSymmetricCipherName(SymmetricKeyAlgorithmTag algorithm)
{
return algorithm switch
{
SymmetricKeyAlgorithmTag.Null => null,
SymmetricKeyAlgorithmTag.TripleDes => "DESEDE",
SymmetricKeyAlgorithmTag.Idea => "IDEA",
SymmetricKeyAlgorithmTag.Cast5 => "CAST5",
SymmetricKeyAlgorithmTag.Blowfish => "Blowfish",
SymmetricKeyAlgorithmTag.Safer => "SAFER",
SymmetricKeyAlgorithmTag.Des => "DES",
SymmetricKeyAlgorithmTag.Aes128 => "AES",
SymmetricKeyAlgorithmTag.Aes192 => "AES",
SymmetricKeyAlgorithmTag.Aes256 => "AES",
SymmetricKeyAlgorithmTag.Twofish => "Twofish",
SymmetricKeyAlgorithmTag.Camellia128 => "Camellia",
SymmetricKeyAlgorithmTag.Camellia192 => "Camellia",
SymmetricKeyAlgorithmTag.Camellia256 => "Camellia",
_ => throw new PgpException("unknown symmetric algorithm: " + algorithm),
};
}
public static int GetKeySize(SymmetricKeyAlgorithmTag algorithm)
{
switch (algorithm)
{
case SymmetricKeyAlgorithmTag.Des:
return 64;
case SymmetricKeyAlgorithmTag.Idea:
case SymmetricKeyAlgorithmTag.Cast5:
case SymmetricKeyAlgorithmTag.Blowfish:
case SymmetricKeyAlgorithmTag.Safer:
case SymmetricKeyAlgorithmTag.Aes128:
case SymmetricKeyAlgorithmTag.Camellia128:
return 128;
case SymmetricKeyAlgorithmTag.TripleDes:
case SymmetricKeyAlgorithmTag.Aes192:
case SymmetricKeyAlgorithmTag.Camellia192:
return 192;
case SymmetricKeyAlgorithmTag.Aes256:
case SymmetricKeyAlgorithmTag.Twofish:
case SymmetricKeyAlgorithmTag.Camellia256:
return 256;
default:
throw new PgpException("unknown symmetric algorithm: " + algorithm);
}
}
public static KeyParameter MakeKey(SymmetricKeyAlgorithmTag algorithm, byte[] keyBytes)
{
string symmetricCipherName = GetSymmetricCipherName(algorithm);
return ParameterUtilities.CreateKeyParameter(symmetricCipherName, keyBytes);
}
public static KeyParameter MakeRandomKey(SymmetricKeyAlgorithmTag algorithm, SecureRandom random)
{
int keySize = GetKeySize(algorithm);
byte[] array = new byte[(keySize + 7) / 8];
random.NextBytes(array);
return MakeKey(algorithm, array);
}
internal static byte[] EncodePassPhrase(char[] passPhrase, bool utf8)
{
if (passPhrase != null)
{
if (!utf8)
{
return Strings.ToByteArray(passPhrase);
}
return Encoding.UTF8.GetBytes(passPhrase);
}
return null;
}
public static KeyParameter MakeKeyFromPassPhrase(SymmetricKeyAlgorithmTag algorithm, S2k s2k, char[] passPhrase)
{
return DoMakeKeyFromPassPhrase(algorithm, s2k, EncodePassPhrase(passPhrase, utf8: false), clearPassPhrase: true);
}
public static KeyParameter MakeKeyFromPassPhraseUtf8(SymmetricKeyAlgorithmTag algorithm, S2k s2k, char[] passPhrase)
{
return DoMakeKeyFromPassPhrase(algorithm, s2k, EncodePassPhrase(passPhrase, utf8: true), clearPassPhrase: true);
}
public static KeyParameter MakeKeyFromPassPhraseRaw(SymmetricKeyAlgorithmTag algorithm, S2k s2k, byte[] rawPassPhrase)
{
return DoMakeKeyFromPassPhrase(algorithm, s2k, rawPassPhrase, clearPassPhrase: false);
}
internal static KeyParameter DoMakeKeyFromPassPhrase(SymmetricKeyAlgorithmTag algorithm, S2k s2k, byte[] rawPassPhrase, bool clearPassPhrase)
{
int keySize = GetKeySize(algorithm);
byte[] array = new byte[(keySize + 7) / 8];
int num = 0;
int num2 = 0;
while (num < array.Length)
{
IDigest digest;
if (s2k != null)
{
string digestName = GetDigestName(s2k.HashAlgorithm);
try
{
digest = DigestUtilities.GetDigest(digestName);
}
catch (Exception exception)
{
throw new PgpException("can't find S2k digest", exception);
}
for (int i = 0; i != num2; i++)
{
digest.Update(0);
}
byte[] iV = s2k.GetIV();
switch (s2k.Type)
{
case 0:
digest.BlockUpdate(rawPassPhrase, 0, rawPassPhrase.Length);
break;
case 1:
digest.BlockUpdate(iV, 0, iV.Length);
digest.BlockUpdate(rawPassPhrase, 0, rawPassPhrase.Length);
break;
case 3:
{
long iterationCount = s2k.IterationCount;
digest.BlockUpdate(iV, 0, iV.Length);
digest.BlockUpdate(rawPassPhrase, 0, rawPassPhrase.Length);
iterationCount -= iV.Length + rawPassPhrase.Length;
while (iterationCount > 0)
{
if (iterationCount < iV.Length)
{
digest.BlockUpdate(iV, 0, (int)iterationCount);
break;
}
digest.BlockUpdate(iV, 0, iV.Length);
iterationCount -= iV.Length;
if (iterationCount < rawPassPhrase.Length)
{
digest.BlockUpdate(rawPassPhrase, 0, (int)iterationCount);
iterationCount = 0L;
}
else
{
digest.BlockUpdate(rawPassPhrase, 0, rawPassPhrase.Length);
iterationCount -= rawPassPhrase.Length;
}
}
break;
}
default:
throw new PgpException("unknown S2k type: " + s2k.Type);
}
}
else
{
try
{
digest = DigestUtilities.GetDigest("MD5");
for (int j = 0; j != num2; j++)
{
digest.Update(0);
}
digest.BlockUpdate(rawPassPhrase, 0, rawPassPhrase.Length);
}
catch (Exception exception2)
{
throw new PgpException("can't find MD5 digest", exception2);
}
}
byte[] array2 = DigestUtilities.DoFinal(digest);
if (array2.Length > array.Length - num)
{
Array.Copy(array2, 0, array, num, array.Length - num);
}
else
{
Array.Copy(array2, 0, array, num, array2.Length);
}
num += array2.Length;
num2++;
}
if (clearPassPhrase && rawPassPhrase != null)
{
Array.Clear(rawPassPhrase, 0, rawPassPhrase.Length);
}
return MakeKey(algorithm, array);
}
public static void WriteFileToLiteralData(Stream output, char fileType, FileInfo file)
{
PgpLiteralDataGenerator pgpLiteralDataGenerator = new PgpLiteralDataGenerator();
Stream pOut = pgpLiteralDataGenerator.Open(output, fileType, file.Name, file.Length, file.LastWriteTime);
PipeFileContents(file, pOut, 32768);
}
public static void WriteFileToLiteralData(Stream output, char fileType, FileInfo file, byte[] buffer)
{
PgpLiteralDataGenerator pgpLiteralDataGenerator = new PgpLiteralDataGenerator();
Stream pOut = pgpLiteralDataGenerator.Open(output, fileType, file.Name, file.LastWriteTime, buffer);
PipeFileContents(file, pOut, buffer.Length);
}
private static void PipeFileContents(FileInfo file, Stream pOut, int bufSize)
{
FileStream fileStream = file.OpenRead();
byte[] array = new byte[bufSize];
try
{
int count;
while ((count = fileStream.Read(array, 0, array.Length)) > 0)
{
pOut.Write(array, 0, count);
}
}
finally
{
Array.Clear(array, 0, array.Length);
Platform.Dispose(pOut);
Platform.Dispose(fileStream);
}
}
private static bool IsPossiblyBase64(int ch)
{
if ((ch < 65 || ch > 90) && (ch < 97 || ch > 122) && (ch < 48 || ch > 57) && ch != 43 && ch != 47 && ch != 13)
{
return ch == 10;
}
return true;
}
public static Stream GetDecoderStream(Stream inputStream)
{
if (!inputStream.CanSeek)
{
throw new ArgumentException("inputStream must be seek-able", "inputStream");
}
long position = inputStream.Position;
int num = inputStream.ReadByte();
if ((num & 0x80) != 0)
{
inputStream.Position = position;
return inputStream;
}
if (!IsPossiblyBase64(num))
{
inputStream.Position = position;
return new ArmoredInputStream(inputStream);
}
byte[] array = new byte[60];
int i = 1;
int num2 = 1;
array[0] = (byte)num;
for (; i != 60; i++)
{
if ((num = inputStream.ReadByte()) < 0)
{
break;
}
if (!IsPossiblyBase64(num))
{
inputStream.Position = position;
return new ArmoredInputStream(inputStream);
}
if (num != 10 && num != 13)
{
array[num2++] = (byte)num;
}
}
inputStream.Position = position;
if (i < 4)
{
return new ArmoredInputStream(inputStream);
}
byte[] array2 = new byte[8];
Array.Copy(array, 0, array2, 0, array2.Length);
try
{
byte[] array3 = Base64.Decode(array2);
bool hasHeaders = (array3[0] & 0x80) == 0;
return new ArmoredInputStream(inputStream, hasHeaders);
}
catch (IOException ex)
{
throw ex;
}
catch (Exception ex2)
{
throw new IOException(ex2.Message);
}
}
internal static IWrapper CreateWrapper(SymmetricKeyAlgorithmTag encAlgorithm)
{
switch (encAlgorithm)
{
case SymmetricKeyAlgorithmTag.Aes128:
case SymmetricKeyAlgorithmTag.Aes192:
case SymmetricKeyAlgorithmTag.Aes256:
return WrapperUtilities.GetWrapper("AESWRAP");
case SymmetricKeyAlgorithmTag.Camellia128:
case SymmetricKeyAlgorithmTag.Camellia192:
case SymmetricKeyAlgorithmTag.Camellia256:
return WrapperUtilities.GetWrapper("CAMELLIAWRAP");
default:
throw new PgpException("unknown wrap algorithm: " + encAlgorithm);
}
}
internal static byte[] GenerateIV(int length, SecureRandom random)
{
byte[] array = new byte[length];
random.NextBytes(array);
return array;
}
internal static S2k GenerateS2k(HashAlgorithmTag hashAlgorithm, int s2kCount, SecureRandom random)
{
byte[] iv = GenerateIV(8, random);
return new S2k(hashAlgorithm, iv, s2kCount);
}
}

View File

@@ -0,0 +1,163 @@
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities.Date;
namespace Org.BouncyCastle.Bcpg.OpenPgp;
public class PgpV3SignatureGenerator
{
private PublicKeyAlgorithmTag keyAlgorithm;
private HashAlgorithmTag hashAlgorithm;
private PgpPrivateKey privKey;
private ISigner sig;
private IDigest dig;
private int signatureType;
private byte lastb;
public PgpV3SignatureGenerator(PublicKeyAlgorithmTag keyAlgorithm, HashAlgorithmTag hashAlgorithm)
{
this.keyAlgorithm = keyAlgorithm;
this.hashAlgorithm = hashAlgorithm;
dig = DigestUtilities.GetDigest(PgpUtilities.GetDigestName(hashAlgorithm));
sig = SignerUtilities.GetSigner(PgpUtilities.GetSignatureName(keyAlgorithm, hashAlgorithm));
}
public void InitSign(int sigType, PgpPrivateKey key)
{
InitSign(sigType, key, null);
}
public void InitSign(int sigType, PgpPrivateKey key, SecureRandom random)
{
privKey = key;
signatureType = sigType;
try
{
ICipherParameters parameters = key.Key;
if (random != null)
{
parameters = new ParametersWithRandom(key.Key, random);
}
sig.Init(forSigning: true, parameters);
}
catch (InvalidKeyException exception)
{
throw new PgpException("invalid key.", exception);
}
dig.Reset();
lastb = 0;
}
public void Update(byte b)
{
if (signatureType == 1)
{
doCanonicalUpdateByte(b);
}
else
{
doUpdateByte(b);
}
}
private void doCanonicalUpdateByte(byte b)
{
switch (b)
{
case 13:
doUpdateCRLF();
break;
case 10:
if (lastb != 13)
{
doUpdateCRLF();
}
break;
default:
doUpdateByte(b);
break;
}
lastb = b;
}
private void doUpdateCRLF()
{
doUpdateByte(13);
doUpdateByte(10);
}
private void doUpdateByte(byte b)
{
sig.Update(b);
dig.Update(b);
}
public void Update(byte[] b)
{
if (signatureType == 1)
{
for (int i = 0; i != b.Length; i++)
{
doCanonicalUpdateByte(b[i]);
}
}
else
{
sig.BlockUpdate(b, 0, b.Length);
dig.BlockUpdate(b, 0, b.Length);
}
}
public void Update(byte[] b, int off, int len)
{
if (signatureType == 1)
{
int num = off + len;
for (int i = off; i != num; i++)
{
doCanonicalUpdateByte(b[i]);
}
}
else
{
sig.BlockUpdate(b, off, len);
dig.BlockUpdate(b, off, len);
}
}
public PgpOnePassSignature GenerateOnePassVersion(bool isNested)
{
return new PgpOnePassSignature(new OnePassSignaturePacket(signatureType, hashAlgorithm, keyAlgorithm, privKey.KeyId, isNested));
}
public PgpSignature Generate()
{
long num = DateTimeUtilities.CurrentUnixMs() / 1000;
byte[] array = new byte[5]
{
(byte)signatureType,
(byte)(num >> 24),
(byte)(num >> 16),
(byte)(num >> 8),
(byte)num
};
sig.BlockUpdate(array, 0, array.Length);
dig.BlockUpdate(array, 0, array.Length);
byte[] encoding = sig.GenerateSignature();
byte[] array2 = DigestUtilities.DoFinal(dig);
byte[] fingerprint = new byte[2]
{
array2[0],
array2[1]
};
MPInteger[] signature = ((keyAlgorithm == PublicKeyAlgorithmTag.RsaSign || keyAlgorithm == PublicKeyAlgorithmTag.RsaGeneral) ? PgpUtilities.RsaSigToMpi(encoding) : PgpUtilities.DsaSigToMpi(encoding));
return new PgpSignature(new SignaturePacket(3, signatureType, privKey.KeyId, keyAlgorithm, hashAlgorithm, num * 1000, fingerprint, signature));
}
}

View File

@@ -0,0 +1,93 @@
using System;
using System.IO;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.Nist;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Math.EC;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.Encoders;
namespace Org.BouncyCastle.Bcpg.OpenPgp;
public sealed class Rfc6637Utilities
{
private static readonly byte[] ANONYMOUS_SENDER = Hex.Decode("416E6F6E796D6F75732053656E64657220202020");
private Rfc6637Utilities()
{
}
public static string GetAgreementAlgorithm(PublicKeyPacket pubKeyData)
{
ECDHPublicBcpgKey eCDHPublicBcpgKey = (ECDHPublicBcpgKey)pubKeyData.Key;
return eCDHPublicBcpgKey.HashAlgorithm switch
{
HashAlgorithmTag.Sha256 => "ECCDHwithSHA256CKDF",
HashAlgorithmTag.Sha384 => "ECCDHwithSHA384CKDF",
HashAlgorithmTag.Sha512 => "ECCDHwithSHA512CKDF",
_ => throw new ArgumentException("Unknown hash algorithm specified: " + eCDHPublicBcpgKey.HashAlgorithm),
};
}
public static DerObjectIdentifier GetKeyEncryptionOID(SymmetricKeyAlgorithmTag algID)
{
return algID switch
{
SymmetricKeyAlgorithmTag.Aes128 => NistObjectIdentifiers.IdAes128Wrap,
SymmetricKeyAlgorithmTag.Aes192 => NistObjectIdentifiers.IdAes192Wrap,
SymmetricKeyAlgorithmTag.Aes256 => NistObjectIdentifiers.IdAes256Wrap,
_ => throw new PgpException("unknown symmetric algorithm ID: " + algID),
};
}
public static int GetKeyLength(SymmetricKeyAlgorithmTag algID)
{
return algID switch
{
SymmetricKeyAlgorithmTag.Aes128 => 16,
SymmetricKeyAlgorithmTag.Aes192 => 24,
SymmetricKeyAlgorithmTag.Aes256 => 32,
_ => throw new PgpException("unknown symmetric algorithm ID: " + algID),
};
}
public static byte[] CreateKey(PublicKeyPacket pubKeyData, ECPoint s)
{
byte[] parameters = CreateUserKeyingMaterial(pubKeyData);
ECDHPublicBcpgKey eCDHPublicBcpgKey = (ECDHPublicBcpgKey)pubKeyData.Key;
return Kdf(eCDHPublicBcpgKey.HashAlgorithm, s, GetKeyLength(eCDHPublicBcpgKey.SymmetricKeyAlgorithm), parameters);
}
public static byte[] CreateUserKeyingMaterial(PublicKeyPacket pubKeyData)
{
MemoryStream memoryStream = new MemoryStream();
ECDHPublicBcpgKey eCDHPublicBcpgKey = (ECDHPublicBcpgKey)pubKeyData.Key;
byte[] encoded = eCDHPublicBcpgKey.CurveOid.GetEncoded();
memoryStream.Write(encoded, 1, encoded.Length - 1);
memoryStream.WriteByte((byte)pubKeyData.Algorithm);
memoryStream.WriteByte(3);
memoryStream.WriteByte(1);
memoryStream.WriteByte((byte)eCDHPublicBcpgKey.HashAlgorithm);
memoryStream.WriteByte((byte)eCDHPublicBcpgKey.SymmetricKeyAlgorithm);
memoryStream.Write(ANONYMOUS_SENDER, 0, ANONYMOUS_SENDER.Length);
byte[] array = PgpPublicKey.CalculateFingerprint(pubKeyData);
memoryStream.Write(array, 0, array.Length);
return memoryStream.ToArray();
}
private static byte[] Kdf(HashAlgorithmTag digestAlg, ECPoint s, int keyLen, byte[] parameters)
{
byte[] encoded = s.XCoord.GetEncoded();
string digestName = PgpUtilities.GetDigestName(digestAlg);
IDigest digest = DigestUtilities.GetDigest(digestName);
digest.Update(0);
digest.Update(0);
digest.Update(0);
digest.Update(1);
digest.BlockUpdate(encoded, 0, encoded.Length);
digest.BlockUpdate(parameters, 0, parameters.Length);
byte[] data = DigestUtilities.DoFinal(digest);
return Arrays.CopyOfRange(data, 0, keyLen);
}
}

View File

@@ -0,0 +1,81 @@
using System.IO;
using Org.BouncyCastle.Utilities.IO;
namespace Org.BouncyCastle.Bcpg.OpenPgp;
public sealed class SXprUtilities
{
private class MyS2k : S2k
{
private readonly long mIterationCount64;
public override long IterationCount => mIterationCount64;
internal MyS2k(HashAlgorithmTag algorithm, byte[] iv, long iterationCount64)
: base(algorithm, iv, (int)iterationCount64)
{
mIterationCount64 = iterationCount64;
}
}
private SXprUtilities()
{
}
private static int ReadLength(Stream input, int ch)
{
int num = ch - 48;
while ((ch = input.ReadByte()) >= 0 && ch != 58)
{
num = num * 10 + ch - 48;
}
return num;
}
internal static string ReadString(Stream input, int ch)
{
int num = ReadLength(input, ch);
char[] array = new char[num];
for (int i = 0; i != array.Length; i++)
{
array[i] = (char)input.ReadByte();
}
return new string(array);
}
internal static byte[] ReadBytes(Stream input, int ch)
{
int num = ReadLength(input, ch);
byte[] array = new byte[num];
Streams.ReadFully(input, array);
return array;
}
internal static S2k ParseS2k(Stream input)
{
SkipOpenParenthesis(input);
ReadString(input, input.ReadByte());
byte[] iv = ReadBytes(input, input.ReadByte());
long iterationCount = long.Parse(ReadString(input, input.ReadByte()));
SkipCloseParenthesis(input);
return new MyS2k(HashAlgorithmTag.Sha1, iv, iterationCount);
}
internal static void SkipOpenParenthesis(Stream input)
{
int num = input.ReadByte();
if (num != 40)
{
throw new IOException("unknown character encountered");
}
}
internal static void SkipCloseParenthesis(Stream input)
{
int num = input.ReadByte();
if (num != 41)
{
throw new IOException("unknown character encountered");
}
}
}

View File

@@ -0,0 +1,20 @@
using System.IO;
using Org.BouncyCastle.Utilities.IO;
namespace Org.BouncyCastle.Bcpg.OpenPgp;
public class WrappedGeneratorStream : FilterStream
{
private readonly IStreamGenerator gen;
public WrappedGeneratorStream(IStreamGenerator gen, Stream str)
: base(str)
{
this.gen = gen;
}
public override void Close()
{
gen.Close();
}
}

View File

@@ -0,0 +1,21 @@
using System;
namespace Org.BouncyCastle.Bcpg;
public abstract class OutputStreamPacket
{
private readonly BcpgOutputStream bcpgOut;
internal OutputStreamPacket(BcpgOutputStream bcpgOut)
{
if (bcpgOut == null)
{
throw new ArgumentNullException("bcpgOut");
}
this.bcpgOut = bcpgOut;
}
public abstract BcpgOutputStream Open();
public abstract void Close();
}

View File

@@ -0,0 +1,5 @@
namespace Org.BouncyCastle.Bcpg;
public class Packet
{
}

View File

@@ -0,0 +1,27 @@
namespace Org.BouncyCastle.Bcpg;
public enum PacketTag
{
Reserved = 0,
PublicKeyEncryptedSession = 1,
Signature = 2,
SymmetricKeyEncryptedSessionKey = 3,
OnePassSignature = 4,
SecretKey = 5,
PublicKey = 6,
SecretSubkey = 7,
CompressedData = 8,
SymmetricKeyEncrypted = 9,
Marker = 10,
LiteralData = 11,
Trust = 12,
UserId = 13,
PublicSubkey = 14,
UserAttribute = 17,
SymmetricEncryptedIntegrityProtected = 18,
ModificationDetectionCode = 19,
Experimental1 = 60,
Experimental2 = 61,
Experimental3 = 62,
Experimental4 = 63
}

View File

@@ -0,0 +1,29 @@
using System;
namespace Org.BouncyCastle.Bcpg;
public enum PublicKeyAlgorithmTag
{
RsaGeneral = 1,
RsaEncrypt = 2,
RsaSign = 3,
ElGamalEncrypt = 16,
Dsa = 17,
[Obsolete("Use 'ECDH' instead")]
EC = 18,
ECDH = 18,
ECDsa = 19,
ElGamalGeneral = 20,
DiffieHellman = 21,
Experimental_1 = 100,
Experimental_2 = 101,
Experimental_3 = 102,
Experimental_4 = 103,
Experimental_5 = 104,
Experimental_6 = 105,
Experimental_7 = 106,
Experimental_8 = 107,
Experimental_9 = 108,
Experimental_10 = 109,
Experimental_11 = 110
}

View File

@@ -0,0 +1,92 @@
using System.IO;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.IO;
namespace Org.BouncyCastle.Bcpg;
public class PublicKeyEncSessionPacket : ContainedPacket
{
private int version;
private long keyId;
private PublicKeyAlgorithmTag algorithm;
private byte[][] data;
public int Version => version;
public long KeyId => keyId;
public PublicKeyAlgorithmTag Algorithm => algorithm;
internal PublicKeyEncSessionPacket(BcpgInputStream bcpgIn)
{
version = bcpgIn.ReadByte();
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();
algorithm = (PublicKeyAlgorithmTag)bcpgIn.ReadByte();
switch (algorithm)
{
case PublicKeyAlgorithmTag.RsaGeneral:
case PublicKeyAlgorithmTag.RsaEncrypt:
data = new byte[1][] { new MPInteger(bcpgIn).GetEncoded() };
break;
case PublicKeyAlgorithmTag.ElGamalEncrypt:
case PublicKeyAlgorithmTag.ElGamalGeneral:
{
MPInteger mPInteger = new MPInteger(bcpgIn);
MPInteger mPInteger2 = new MPInteger(bcpgIn);
data = new byte[2][]
{
mPInteger.GetEncoded(),
mPInteger2.GetEncoded()
};
break;
}
case PublicKeyAlgorithmTag.EC:
data = new byte[1][] { Streams.ReadAll(bcpgIn) };
break;
default:
throw new IOException("unknown PGP public key algorithm encountered");
}
}
public PublicKeyEncSessionPacket(long keyId, PublicKeyAlgorithmTag algorithm, byte[][] data)
{
version = 3;
this.keyId = keyId;
this.algorithm = algorithm;
this.data = new byte[data.Length][];
for (int i = 0; i < data.Length; i++)
{
this.data[i] = Arrays.Clone(data[i]);
}
}
public byte[][] GetEncSessionKey()
{
return data;
}
public override void Encode(BcpgOutputStream bcpgOut)
{
MemoryStream memoryStream = new MemoryStream();
BcpgOutputStream bcpgOutputStream = new BcpgOutputStream(memoryStream);
bcpgOutputStream.WriteByte((byte)version);
bcpgOutputStream.WriteLong(keyId);
bcpgOutputStream.WriteByte((byte)algorithm);
for (int i = 0; i < data.Length; i++)
{
bcpgOutputStream.Write(data[i]);
}
Platform.Dispose(bcpgOutputStream);
bcpgOut.WritePacket(PacketTag.PublicKeyEncryptedSession, memoryStream.ToArray(), oldFormat: true);
}
}

View File

@@ -0,0 +1,93 @@
using System;
using System.IO;
using Org.BouncyCastle.Utilities.Date;
namespace Org.BouncyCastle.Bcpg;
public class PublicKeyPacket : ContainedPacket
{
private int version;
private long time;
private int validDays;
private PublicKeyAlgorithmTag algorithm;
private IBcpgKey key;
public virtual int Version => version;
public virtual PublicKeyAlgorithmTag Algorithm => algorithm;
public virtual int ValidDays => validDays;
public virtual IBcpgKey Key => key;
internal PublicKeyPacket(BcpgInputStream bcpgIn)
{
version = bcpgIn.ReadByte();
time = (uint)((bcpgIn.ReadByte() << 24) | (bcpgIn.ReadByte() << 16) | (bcpgIn.ReadByte() << 8) | bcpgIn.ReadByte());
if (version <= 3)
{
validDays = (bcpgIn.ReadByte() << 8) | bcpgIn.ReadByte();
}
algorithm = (PublicKeyAlgorithmTag)bcpgIn.ReadByte();
switch (algorithm)
{
case PublicKeyAlgorithmTag.RsaGeneral:
case PublicKeyAlgorithmTag.RsaEncrypt:
case PublicKeyAlgorithmTag.RsaSign:
key = new RsaPublicBcpgKey(bcpgIn);
break;
case PublicKeyAlgorithmTag.Dsa:
key = new DsaPublicBcpgKey(bcpgIn);
break;
case PublicKeyAlgorithmTag.ElGamalEncrypt:
case PublicKeyAlgorithmTag.ElGamalGeneral:
key = new ElGamalPublicBcpgKey(bcpgIn);
break;
case PublicKeyAlgorithmTag.EC:
key = new ECDHPublicBcpgKey(bcpgIn);
break;
case PublicKeyAlgorithmTag.ECDsa:
key = new ECDsaPublicBcpgKey(bcpgIn);
break;
default:
throw new IOException("unknown PGP public key algorithm encountered");
}
}
public PublicKeyPacket(PublicKeyAlgorithmTag algorithm, DateTime time, IBcpgKey key)
{
version = 4;
this.time = DateTimeUtilities.DateTimeToUnixMs(time) / 1000;
this.algorithm = algorithm;
this.key = key;
}
public virtual DateTime GetTime()
{
return DateTimeUtilities.UnixMsToDateTime(time * 1000);
}
public virtual byte[] GetEncodedContents()
{
MemoryStream memoryStream = new MemoryStream();
BcpgOutputStream bcpgOutputStream = new BcpgOutputStream(memoryStream);
bcpgOutputStream.WriteByte((byte)version);
bcpgOutputStream.WriteInt((int)time);
if (version <= 3)
{
bcpgOutputStream.WriteShort((short)validDays);
}
bcpgOutputStream.WriteByte((byte)algorithm);
bcpgOutputStream.WriteObject((BcpgObject)key);
return memoryStream.ToArray();
}
public override void Encode(BcpgOutputStream bcpgOut)
{
bcpgOut.WritePacket(PacketTag.PublicKey, GetEncodedContents(), oldFormat: true);
}
}

View File

@@ -0,0 +1,21 @@
using System;
namespace Org.BouncyCastle.Bcpg;
public class PublicSubkeyPacket : PublicKeyPacket
{
internal PublicSubkeyPacket(BcpgInputStream bcpgIn)
: base(bcpgIn)
{
}
public PublicSubkeyPacket(PublicKeyAlgorithmTag algorithm, DateTime time, IBcpgKey key)
: base(algorithm, time, key)
{
}
public override void Encode(BcpgOutputStream bcpgOut)
{
bcpgOut.WritePacket(PacketTag.PublicSubkey, GetEncodedContents(), oldFormat: true);
}
}

View File

@@ -0,0 +1,37 @@
using System;
namespace Org.BouncyCastle.Bcpg;
public class RevocationKey : SignatureSubpacket
{
public virtual RevocationKeyTag SignatureClass => (RevocationKeyTag)GetData()[0];
public virtual PublicKeyAlgorithmTag Algorithm => (PublicKeyAlgorithmTag)GetData()[1];
public RevocationKey(bool isCritical, bool isLongLength, byte[] data)
: base(SignatureSubpacketTag.RevocationKey, isCritical, isLongLength, data)
{
}
public RevocationKey(bool isCritical, RevocationKeyTag signatureClass, PublicKeyAlgorithmTag keyAlgorithm, byte[] fingerprint)
: base(SignatureSubpacketTag.RevocationKey, isCritical, isLongLength: false, CreateData(signatureClass, keyAlgorithm, fingerprint))
{
}
private static byte[] CreateData(RevocationKeyTag signatureClass, PublicKeyAlgorithmTag keyAlgorithm, byte[] fingerprint)
{
byte[] array = new byte[2 + fingerprint.Length];
array[0] = (byte)signatureClass;
array[1] = (byte)keyAlgorithm;
Array.Copy(fingerprint, 0, array, 2, fingerprint.Length);
return array;
}
public virtual byte[] GetFingerprint()
{
byte[] array = GetData();
byte[] array2 = new byte[array.Length - 2];
Array.Copy(array, 2, array2, 0, array2.Length);
return array2;
}
}

View File

@@ -0,0 +1,7 @@
namespace Org.BouncyCastle.Bcpg;
public enum RevocationKeyTag : byte
{
ClassDefault = 128,
ClassSensitive = 64
}

View File

@@ -0,0 +1,43 @@
using System;
using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Bcpg;
public class RevocationReason : SignatureSubpacket
{
public RevocationReason(bool isCritical, bool isLongLength, byte[] data)
: base(SignatureSubpacketTag.RevocationReason, isCritical, isLongLength, data)
{
}
public RevocationReason(bool isCritical, RevocationReasonTag reason, string description)
: base(SignatureSubpacketTag.RevocationReason, isCritical, isLongLength: false, CreateData(reason, description))
{
}
private static byte[] CreateData(RevocationReasonTag reason, string description)
{
byte[] array = Strings.ToUtf8ByteArray(description);
byte[] array2 = new byte[1 + array.Length];
array2[0] = (byte)reason;
Array.Copy(array, 0, array2, 1, array.Length);
return array2;
}
public virtual RevocationReasonTag GetRevocationReason()
{
return (RevocationReasonTag)GetData()[0];
}
public virtual string GetRevocationDescription()
{
byte[] array = GetData();
if (array.Length == 1)
{
return string.Empty;
}
byte[] array2 = new byte[array.Length - 1];
Array.Copy(array, 1, array2, 0, array2.Length);
return Strings.FromUtf8ByteArray(array2);
}
}

View File

@@ -0,0 +1,10 @@
namespace Org.BouncyCastle.Bcpg;
public enum RevocationReasonTag : byte
{
NoReason = 0,
KeySuperseded = 1,
KeyCompromised = 2,
KeyRetired = 3,
UserNoLongerValid = 32
}

View File

@@ -0,0 +1,46 @@
using System;
using Org.BouncyCastle.Math;
namespace Org.BouncyCastle.Bcpg;
public class RsaPublicBcpgKey : BcpgObject, IBcpgKey
{
private readonly MPInteger n;
private readonly MPInteger e;
public BigInteger PublicExponent => e.Value;
public BigInteger Modulus => n.Value;
public string Format => "PGP";
public RsaPublicBcpgKey(BcpgInputStream bcpgIn)
{
n = new MPInteger(bcpgIn);
e = new MPInteger(bcpgIn);
}
public RsaPublicBcpgKey(BigInteger n, BigInteger e)
{
this.n = new MPInteger(n);
this.e = new MPInteger(e);
}
public override byte[] GetEncoded()
{
try
{
return base.GetEncoded();
}
catch (Exception)
{
return null;
}
}
public override void Encode(BcpgOutputStream bcpgOut)
{
bcpgOut.WriteObjects(n, e);
}
}

View File

@@ -0,0 +1,87 @@
using System;
using Org.BouncyCastle.Math;
namespace Org.BouncyCastle.Bcpg;
public class RsaSecretBcpgKey : BcpgObject, IBcpgKey
{
private readonly MPInteger d;
private readonly MPInteger p;
private readonly MPInteger q;
private readonly MPInteger u;
private readonly BigInteger expP;
private readonly BigInteger expQ;
private readonly BigInteger crt;
public BigInteger Modulus => p.Value.Multiply(q.Value);
public BigInteger PrivateExponent => d.Value;
public BigInteger PrimeP => p.Value;
public BigInteger PrimeQ => q.Value;
public BigInteger PrimeExponentP => expP;
public BigInteger PrimeExponentQ => expQ;
public BigInteger CrtCoefficient => crt;
public string Format => "PGP";
public RsaSecretBcpgKey(BcpgInputStream bcpgIn)
{
d = new MPInteger(bcpgIn);
p = new MPInteger(bcpgIn);
q = new MPInteger(bcpgIn);
u = new MPInteger(bcpgIn);
expP = d.Value.Remainder(p.Value.Subtract(BigInteger.One));
expQ = d.Value.Remainder(q.Value.Subtract(BigInteger.One));
crt = q.Value.ModInverse(p.Value);
}
public RsaSecretBcpgKey(BigInteger d, BigInteger p, BigInteger q)
{
int num = p.CompareTo(q);
if (num >= 0)
{
if (num == 0)
{
throw new ArgumentException("p and q cannot be equal");
}
BigInteger bigInteger = p;
p = q;
q = bigInteger;
}
this.d = new MPInteger(d);
this.p = new MPInteger(p);
this.q = new MPInteger(q);
u = new MPInteger(p.ModInverse(q));
expP = d.Remainder(p.Subtract(BigInteger.One));
expQ = d.Remainder(q.Subtract(BigInteger.One));
crt = q.ModInverse(p);
}
public override byte[] GetEncoded()
{
try
{
return base.GetEncoded();
}
catch (Exception)
{
return null;
}
}
public override void Encode(BcpgOutputStream bcpgOut)
{
bcpgOut.WriteObjects(d, p, q, u);
}
}

View File

@@ -0,0 +1,125 @@
using System;
using System.IO;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.IO;
namespace Org.BouncyCastle.Bcpg;
public class S2k : BcpgObject
{
private const int ExpBias = 6;
public const int Simple = 0;
public const int Salted = 1;
public const int SaltedAndIterated = 3;
public const int GnuDummyS2K = 101;
public const int GnuProtectionModeNoPrivateKey = 1;
public const int GnuProtectionModeDivertToCard = 2;
internal int type;
internal HashAlgorithmTag algorithm;
internal byte[] iv;
internal int itCount = -1;
internal int protectionMode = -1;
public virtual int Type => type;
public virtual HashAlgorithmTag HashAlgorithm => algorithm;
public virtual long IterationCount => 16 + (itCount & 0xF) << (itCount >> 4) + 6;
public virtual int ProtectionMode => protectionMode;
internal S2k(Stream inStr)
{
type = inStr.ReadByte();
algorithm = (HashAlgorithmTag)inStr.ReadByte();
if (type != 101)
{
if (type != 0)
{
iv = new byte[8];
if (Streams.ReadFully(inStr, iv, 0, iv.Length) < iv.Length)
{
throw new EndOfStreamException();
}
if (type == 3)
{
itCount = inStr.ReadByte();
}
}
}
else
{
inStr.ReadByte();
inStr.ReadByte();
inStr.ReadByte();
protectionMode = inStr.ReadByte();
}
}
public S2k(HashAlgorithmTag algorithm)
{
type = 0;
this.algorithm = algorithm;
}
public S2k(HashAlgorithmTag algorithm, byte[] iv)
{
type = 1;
this.algorithm = algorithm;
this.iv = iv;
}
public S2k(HashAlgorithmTag algorithm, byte[] iv, int itCount)
{
type = 3;
this.algorithm = algorithm;
this.iv = iv;
this.itCount = itCount;
}
public virtual byte[] GetIV()
{
return Arrays.Clone(iv);
}
[Obsolete("Use 'IterationCount' property instead")]
public long GetIterationCount()
{
return IterationCount;
}
public override void Encode(BcpgOutputStream bcpgOut)
{
bcpgOut.WriteByte((byte)type);
bcpgOut.WriteByte((byte)algorithm);
if (type != 101)
{
if (type != 0)
{
bcpgOut.Write(iv);
}
if (type == 3)
{
bcpgOut.WriteByte((byte)itCount);
}
}
else
{
bcpgOut.WriteByte(71);
bcpgOut.WriteByte(78);
bcpgOut.WriteByte(85);
bcpgOut.WriteByte((byte)protectionMode);
}
}
}

View File

@@ -0,0 +1,132 @@
using System.IO;
using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Bcpg;
public class SecretKeyPacket : ContainedPacket
{
public const int UsageNone = 0;
public const int UsageChecksum = 255;
public const int UsageSha1 = 254;
private PublicKeyPacket pubKeyPacket;
private readonly byte[] secKeyData;
private int s2kUsage;
private SymmetricKeyAlgorithmTag encAlgorithm;
private S2k s2k;
private byte[] iv;
public SymmetricKeyAlgorithmTag EncAlgorithm => encAlgorithm;
public int S2kUsage => s2kUsage;
public S2k S2k => s2k;
public PublicKeyPacket PublicKeyPacket => pubKeyPacket;
internal SecretKeyPacket(BcpgInputStream bcpgIn)
{
if (this is SecretSubkeyPacket)
{
pubKeyPacket = new PublicSubkeyPacket(bcpgIn);
}
else
{
pubKeyPacket = new PublicKeyPacket(bcpgIn);
}
s2kUsage = bcpgIn.ReadByte();
if (s2kUsage == 255 || s2kUsage == 254)
{
encAlgorithm = (SymmetricKeyAlgorithmTag)bcpgIn.ReadByte();
s2k = new S2k(bcpgIn);
}
else
{
encAlgorithm = (SymmetricKeyAlgorithmTag)s2kUsage;
}
if ((s2k == null || s2k.Type != 101 || s2k.ProtectionMode != 1) && s2kUsage != 0)
{
if (encAlgorithm < SymmetricKeyAlgorithmTag.Aes128)
{
iv = new byte[8];
}
else
{
iv = new byte[16];
}
bcpgIn.ReadFully(iv);
}
secKeyData = bcpgIn.ReadAll();
}
public SecretKeyPacket(PublicKeyPacket pubKeyPacket, SymmetricKeyAlgorithmTag encAlgorithm, S2k s2k, byte[] iv, byte[] secKeyData)
{
this.pubKeyPacket = pubKeyPacket;
this.encAlgorithm = encAlgorithm;
if (encAlgorithm != SymmetricKeyAlgorithmTag.Null)
{
s2kUsage = 255;
}
else
{
s2kUsage = 0;
}
this.s2k = s2k;
this.iv = Arrays.Clone(iv);
this.secKeyData = secKeyData;
}
public SecretKeyPacket(PublicKeyPacket pubKeyPacket, SymmetricKeyAlgorithmTag encAlgorithm, int s2kUsage, S2k s2k, byte[] iv, byte[] secKeyData)
{
this.pubKeyPacket = pubKeyPacket;
this.encAlgorithm = encAlgorithm;
this.s2kUsage = s2kUsage;
this.s2k = s2k;
this.iv = Arrays.Clone(iv);
this.secKeyData = secKeyData;
}
public byte[] GetIV()
{
return Arrays.Clone(iv);
}
public byte[] GetSecretKeyData()
{
return secKeyData;
}
public byte[] GetEncodedContents()
{
MemoryStream memoryStream = new MemoryStream();
BcpgOutputStream bcpgOutputStream = new BcpgOutputStream(memoryStream);
bcpgOutputStream.Write(pubKeyPacket.GetEncodedContents());
bcpgOutputStream.WriteByte((byte)s2kUsage);
if (s2kUsage == 255 || s2kUsage == 254)
{
bcpgOutputStream.WriteByte((byte)encAlgorithm);
bcpgOutputStream.WriteObject(s2k);
}
if (iv != null)
{
bcpgOutputStream.Write(iv);
}
if (secKeyData != null && secKeyData.Length > 0)
{
bcpgOutputStream.Write(secKeyData);
}
return memoryStream.ToArray();
}
public override void Encode(BcpgOutputStream bcpgOut)
{
bcpgOut.WritePacket(PacketTag.SecretKey, GetEncodedContents(), oldFormat: true);
}
}

View File

@@ -0,0 +1,24 @@
namespace Org.BouncyCastle.Bcpg;
public class SecretSubkeyPacket : SecretKeyPacket
{
internal SecretSubkeyPacket(BcpgInputStream bcpgIn)
: base(bcpgIn)
{
}
public SecretSubkeyPacket(PublicKeyPacket pubKeyPacket, SymmetricKeyAlgorithmTag encAlgorithm, S2k s2k, byte[] iv, byte[] secKeyData)
: base(pubKeyPacket, encAlgorithm, s2k, iv, secKeyData)
{
}
public SecretSubkeyPacket(PublicKeyPacket pubKeyPacket, SymmetricKeyAlgorithmTag encAlgorithm, int s2kUsage, S2k s2k, byte[] iv, byte[] secKeyData)
: base(pubKeyPacket, encAlgorithm, s2kUsage, s2k, iv, secKeyData)
{
}
public override void Encode(BcpgOutputStream bcpgOut)
{
bcpgOut.WritePacket(PacketTag.SecretSubkey, GetEncodedContents(), oldFormat: true);
}
}

View File

@@ -0,0 +1,9 @@
namespace Org.BouncyCastle.Bcpg.Sig;
public class EmbeddedSignature : SignatureSubpacket
{
public EmbeddedSignature(bool critical, bool isLongLength, byte[] data)
: base(SignatureSubpacketTag.EmbeddedSignature, critical, isLongLength, data)
{
}
}

View File

@@ -0,0 +1,30 @@
namespace Org.BouncyCastle.Bcpg.Sig;
public class Exportable : SignatureSubpacket
{
private static byte[] BooleanToByteArray(bool val)
{
byte[] array = new byte[1];
if (val)
{
array[0] = 1;
return array;
}
return array;
}
public Exportable(bool critical, bool isLongLength, byte[] data)
: base(SignatureSubpacketTag.Exportable, critical, isLongLength, data)
{
}
public Exportable(bool critical, bool isExportable)
: base(SignatureSubpacketTag.Exportable, critical, isLongLength: false, BooleanToByteArray(isExportable))
{
}
public bool IsExportable()
{
return data[0] != 0;
}
}

View File

@@ -0,0 +1,52 @@
using System;
using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Bcpg.Sig;
public class Features : SignatureSubpacket
{
public static readonly byte FEATURE_MODIFICATION_DETECTION = 1;
public bool SupportsModificationDetection => SupportsFeature(FEATURE_MODIFICATION_DETECTION);
private static byte[] FeatureToByteArray(byte feature)
{
return new byte[1] { feature };
}
public Features(bool critical, bool isLongLength, byte[] data)
: base(SignatureSubpacketTag.Features, critical, isLongLength, data)
{
}
public Features(bool critical, byte feature)
: base(SignatureSubpacketTag.Features, critical, isLongLength: false, FeatureToByteArray(feature))
{
}
public bool SupportsFeature(byte feature)
{
return Array.IndexOf((Array)data, (object?)feature) >= 0;
}
private void SetSupportsFeature(byte feature, bool support)
{
if (feature == 0)
{
throw new ArgumentException("cannot be 0", "feature");
}
int num = Array.IndexOf((Array)data, (object?)feature);
if (num >= 0 != support)
{
if (support)
{
data = Arrays.Append(data, feature);
return;
}
byte[] array = new byte[data.Length - 1];
Array.Copy(data, 0, array, 0, num);
Array.Copy(data, num + 1, array, num, array.Length - num);
data = array;
}
}
}

View File

@@ -0,0 +1,31 @@
namespace Org.BouncyCastle.Bcpg.Sig;
public class IssuerKeyId : SignatureSubpacket
{
public long KeyId => ((long)(data[0] & 0xFF) << 56) | ((long)(data[1] & 0xFF) << 48) | ((long)(data[2] & 0xFF) << 40) | ((long)(data[3] & 0xFF) << 32) | ((long)(data[4] & 0xFF) << 24) | ((long)(data[5] & 0xFF) << 16) | ((long)(data[6] & 0xFF) << 8) | (long)((ulong)data[7] & 0xFFuL);
protected static byte[] KeyIdToBytes(long keyId)
{
return new byte[8]
{
(byte)(keyId >> 56),
(byte)(keyId >> 48),
(byte)(keyId >> 40),
(byte)(keyId >> 32),
(byte)(keyId >> 24),
(byte)(keyId >> 16),
(byte)(keyId >> 8),
(byte)keyId
};
}
public IssuerKeyId(bool critical, bool isLongLength, byte[] data)
: base(SignatureSubpacketTag.IssuerKeyId, critical, isLongLength, data)
{
}
public IssuerKeyId(bool critical, long keyId)
: base(SignatureSubpacketTag.IssuerKeyId, critical, isLongLength: false, KeyIdToBytes(keyId))
{
}
}

View File

@@ -0,0 +1,27 @@
namespace Org.BouncyCastle.Bcpg.Sig;
public class KeyExpirationTime : SignatureSubpacket
{
public long Time => ((long)(data[0] & 0xFF) << 24) | ((long)(data[1] & 0xFF) << 16) | ((long)(data[2] & 0xFF) << 8) | (long)((ulong)data[3] & 0xFFuL);
protected static byte[] TimeToBytes(long t)
{
return new byte[4]
{
(byte)(t >> 24),
(byte)(t >> 16),
(byte)(t >> 8),
(byte)t
};
}
public KeyExpirationTime(bool critical, bool isLongLength, byte[] data)
: base(SignatureSubpacketTag.KeyExpireTime, critical, isLongLength, data)
{
}
public KeyExpirationTime(bool critical, long seconds)
: base(SignatureSubpacketTag.KeyExpireTime, critical, isLongLength: false, TimeToBytes(seconds))
{
}
}

View File

@@ -0,0 +1,60 @@
using System;
namespace Org.BouncyCastle.Bcpg.Sig;
public class KeyFlags : SignatureSubpacket
{
public const int CertifyOther = 1;
public const int SignData = 2;
public const int EncryptComms = 4;
public const int EncryptStorage = 8;
public const int Split = 16;
public const int Authentication = 32;
public const int Shared = 128;
public int Flags
{
get
{
int num = 0;
for (int i = 0; i != data.Length; i++)
{
num |= (data[i] & 0xFF) << i * 8;
}
return num;
}
}
private static byte[] IntToByteArray(int v)
{
byte[] array = new byte[4];
int num = 0;
for (int i = 0; i != 4; i++)
{
array[i] = (byte)(v >> i * 8);
if (array[i] != 0)
{
num = i;
}
}
byte[] array2 = new byte[num + 1];
Array.Copy(array, 0, array2, 0, array2.Length);
return array2;
}
public KeyFlags(bool critical, bool isLongLength, byte[] data)
: base(SignatureSubpacketTag.KeyFlags, critical, isLongLength, data)
{
}
public KeyFlags(bool critical, int flags)
: base(SignatureSubpacketTag.KeyFlags, critical, isLongLength: false, IntToByteArray(flags))
{
}
}

View File

@@ -0,0 +1,72 @@
using System;
using System.IO;
using System.Text;
namespace Org.BouncyCastle.Bcpg.Sig;
public class NotationData : SignatureSubpacket
{
public const int HeaderFlagLength = 4;
public const int HeaderNameLength = 2;
public const int HeaderValueLength = 2;
public bool IsHumanReadable => data[0] == 128;
public NotationData(bool critical, bool isLongLength, byte[] data)
: base(SignatureSubpacketTag.NotationData, critical, isLongLength, data)
{
}
public NotationData(bool critical, bool humanReadable, string notationName, string notationValue)
: base(SignatureSubpacketTag.NotationData, critical, isLongLength: false, CreateData(humanReadable, notationName, notationValue))
{
}
private static byte[] CreateData(bool humanReadable, string notationName, string notationValue)
{
MemoryStream memoryStream = new MemoryStream();
memoryStream.WriteByte((byte)(humanReadable ? 128 : 0));
memoryStream.WriteByte(0);
memoryStream.WriteByte(0);
memoryStream.WriteByte(0);
byte[] array = null;
byte[] bytes = Encoding.UTF8.GetBytes(notationName);
int num = System.Math.Min(bytes.Length, 255);
array = Encoding.UTF8.GetBytes(notationValue);
int num2 = System.Math.Min(array.Length, 255);
memoryStream.WriteByte((byte)(num >> 8));
memoryStream.WriteByte((byte)num);
memoryStream.WriteByte((byte)(num2 >> 8));
memoryStream.WriteByte((byte)num2);
memoryStream.Write(bytes, 0, num);
memoryStream.Write(array, 0, num2);
return memoryStream.ToArray();
}
public string GetNotationName()
{
int count = (data[4] << 8) + data[5];
int index = 8;
return Encoding.UTF8.GetString(data, index, count);
}
public string GetNotationValue()
{
int num = (data[4] << 8) + data[5];
int count = (data[6] << 8) + data[7];
int index = 8 + num;
return Encoding.UTF8.GetString(data, index, count);
}
public byte[] GetNotationValueBytes()
{
int num = (data[4] << 8) + data[5];
int num2 = (data[6] << 8) + data[7];
int sourceIndex = 8 + num;
byte[] array = new byte[num2];
Array.Copy(data, sourceIndex, array, 0, num2);
return array;
}
}

View File

@@ -0,0 +1,34 @@
namespace Org.BouncyCastle.Bcpg.Sig;
public class PreferredAlgorithms : SignatureSubpacket
{
private static byte[] IntToByteArray(int[] v)
{
byte[] array = new byte[v.Length];
for (int i = 0; i != v.Length; i++)
{
array[i] = (byte)v[i];
}
return array;
}
public PreferredAlgorithms(SignatureSubpacketTag type, bool critical, bool isLongLength, byte[] data)
: base(type, critical, isLongLength, data)
{
}
public PreferredAlgorithms(SignatureSubpacketTag type, bool critical, int[] preferences)
: base(type, critical, isLongLength: false, IntToByteArray(preferences))
{
}
public int[] GetPreferences()
{
int[] array = new int[data.Length];
for (int i = 0; i != array.Length; i++)
{
array[i] = data[i] & 0xFF;
}
return array;
}
}

View File

@@ -0,0 +1,30 @@
namespace Org.BouncyCastle.Bcpg.Sig;
public class PrimaryUserId : SignatureSubpacket
{
private static byte[] BooleanToByteArray(bool val)
{
byte[] array = new byte[1];
if (val)
{
array[0] = 1;
return array;
}
return array;
}
public PrimaryUserId(bool critical, bool isLongLength, byte[] data)
: base(SignatureSubpacketTag.PrimaryUserId, critical, isLongLength, data)
{
}
public PrimaryUserId(bool critical, bool isPrimaryUserId)
: base(SignatureSubpacketTag.PrimaryUserId, critical, isLongLength: false, BooleanToByteArray(isPrimaryUserId))
{
}
public bool IsPrimaryUserId()
{
return data[0] != 0;
}
}

View File

@@ -0,0 +1,30 @@
namespace Org.BouncyCastle.Bcpg.Sig;
public class Revocable : SignatureSubpacket
{
private static byte[] BooleanToByteArray(bool value)
{
byte[] array = new byte[1];
if (value)
{
array[0] = 1;
return array;
}
return array;
}
public Revocable(bool critical, bool isLongLength, byte[] data)
: base(SignatureSubpacketTag.Revocable, critical, isLongLength, data)
{
}
public Revocable(bool critical, bool isRevocable)
: base(SignatureSubpacketTag.Revocable, critical, isLongLength: false, BooleanToByteArray(isRevocable))
{
}
public bool IsRevocable()
{
return data[0] != 0;
}
}

View File

@@ -0,0 +1,35 @@
using System;
using Org.BouncyCastle.Utilities.Date;
namespace Org.BouncyCastle.Bcpg.Sig;
public class SignatureCreationTime : SignatureSubpacket
{
protected static byte[] TimeToBytes(DateTime time)
{
long num = DateTimeUtilities.DateTimeToUnixMs(time) / 1000;
return new byte[4]
{
(byte)(num >> 24),
(byte)(num >> 16),
(byte)(num >> 8),
(byte)num
};
}
public SignatureCreationTime(bool critical, bool isLongLength, byte[] data)
: base(SignatureSubpacketTag.CreationTime, critical, isLongLength, data)
{
}
public SignatureCreationTime(bool critical, DateTime date)
: base(SignatureSubpacketTag.CreationTime, critical, isLongLength: false, TimeToBytes(date))
{
}
public DateTime GetTime()
{
long num = (uint)((data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3]);
return DateTimeUtilities.UnixMsToDateTime(num * 1000);
}
}

View File

@@ -0,0 +1,27 @@
namespace Org.BouncyCastle.Bcpg.Sig;
public class SignatureExpirationTime : SignatureSubpacket
{
public long Time => ((long)(data[0] & 0xFF) << 24) | ((long)(data[1] & 0xFF) << 16) | ((long)(data[2] & 0xFF) << 8) | (long)((ulong)data[3] & 0xFFuL);
protected static byte[] TimeToBytes(long t)
{
return new byte[4]
{
(byte)(t >> 24),
(byte)(t >> 16),
(byte)(t >> 8),
(byte)t
};
}
public SignatureExpirationTime(bool critical, bool isLongLength, byte[] data)
: base(SignatureSubpacketTag.ExpireTime, critical, isLongLength, data)
{
}
public SignatureExpirationTime(bool critical, long seconds)
: base(SignatureSubpacketTag.ExpireTime, critical, isLongLength: false, TimeToBytes(seconds))
{
}
}

View File

@@ -0,0 +1,34 @@
namespace Org.BouncyCastle.Bcpg.Sig;
public class SignerUserId : SignatureSubpacket
{
private static byte[] UserIdToBytes(string id)
{
byte[] array = new byte[id.Length];
for (int i = 0; i != id.Length; i++)
{
array[i] = (byte)id[i];
}
return array;
}
public SignerUserId(bool critical, bool isLongLength, byte[] data)
: base(SignatureSubpacketTag.SignerUserId, critical, isLongLength, data)
{
}
public SignerUserId(bool critical, string userId)
: base(SignatureSubpacketTag.SignerUserId, critical, isLongLength: false, UserIdToBytes(userId))
{
}
public string GetId()
{
char[] array = new char[data.Length];
for (int i = 0; i != array.Length; i++)
{
array[i] = (char)(data[i] & 0xFF);
}
return new string(array);
}
}

View File

@@ -0,0 +1,27 @@
namespace Org.BouncyCastle.Bcpg.Sig;
public class TrustSignature : SignatureSubpacket
{
public int Depth => data[0] & 0xFF;
public int TrustAmount => data[1] & 0xFF;
private static byte[] IntToByteArray(int v1, int v2)
{
return new byte[2]
{
(byte)v1,
(byte)v2
};
}
public TrustSignature(bool critical, bool isLongLength, byte[] data)
: base(SignatureSubpacketTag.TrustSig, critical, isLongLength, data)
{
}
public TrustSignature(bool critical, int depth, int trustAmount)
: base(SignatureSubpacketTag.TrustSig, critical, isLongLength: false, IntToByteArray(depth, trustAmount))
{
}
}

Some files were not shown because too many files have changed in this diff Show More