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,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();
}
}