/// <summary>Create a key pair from a PgpPrivateKey and a PgpPublicKey.</summary> /// <param name="pub">The public key.</param> /// <param name="priv">The private key.</param> public PgpKeyPair( PgpPublicKey pub, PgpPrivateKey priv) { this.pub = pub; this.priv = priv; }
/// <summary> /// Return the algorithm code for the symmetric algorithm used to encrypt the data. /// </summary> public SymmetricKeyAlgorithmTag GetSymmetricAlgorithm( PgpPrivateKey privKey) { byte[] plain = fetchSymmetricKeyData(privKey); return((SymmetricKeyAlgorithmTag)plain[0]); }
/// <summary>Initialise the generator for signing.</summary> public void InitSign( int sigType, PgpPrivateKey key, SecureRandom random) { this.privKey = key; this.signatureType = sigType; try { ICipherParameters cp = key.Key; if (random != null) { cp = new ParametersWithRandom(key.Key, random); } sig.Init(true, cp); } catch (InvalidKeyException e) { throw new PgpException("invalid key.", e); } dig.Reset(); lastb = 0; }
public PgpKeyPair( PublicKeyAlgorithmTag algorithm, AsymmetricKeyParameter pubKey, AsymmetricKeyParameter privKey, DateTime time) { this.pub = new PgpPublicKey(algorithm, pubKey, time); this.priv = new PgpPrivateKey(privKey, pub.KeyId); }
internal PgpSecretKey( PgpPrivateKey privKey, PgpPublicKey pubKey, SymmetricKeyAlgorithmTag encAlgorithm, char[] passPhrase, bool useSha1, SecureRandom rand) : this(privKey, pubKey, encAlgorithm, passPhrase, useSha1, rand, false) { }
/// <summary> /// Public and secret key provider. /// </summary> /// <param name="publicKey">The public key data.</param> /// <param name="secretKey">The secret key data.</param> /// <param name="keyID">The unique key id of the public secret key pair.</param> /// <param name="password">The password used to protect the secret key.</param> /// <returns>The RSA cryto service provider.</returns> public RSACryptoServiceProvider PublicKeySecretKey(System.IO.Stream publicKey, System.IO.Stream secretKey, long keyID, string password = null) { // Read the public key data. Key.Bcpg.OpenPgp.PgpPublicKey pgpPublicKey = ReadPublicKey(publicKey); // Find the secret key Key.Bcpg.OpenPgp.PgpPrivateKey privateKey = null; Key.Bcpg.OpenPgp.PgpSecretKeyRingBundle secretKeyRingBundle = new Key.Bcpg.OpenPgp.PgpSecretKeyRingBundle(Key.Bcpg.OpenPgp.PgpUtilities.GetDecoderStream(secretKey)); // Find the private key (secret key). privateKey = FindSecretKey(secretKeyRingBundle, keyID, password.ToArray()); // Assign the rsa parameters. RSAParameters rsaPrivateParam = new RSAParameters(); Key.Crypto.Parameters.RsaKeyParameters rsaPrivatePublic = (Key.Crypto.Parameters.RsaKeyParameters)pgpPublicKey.GetKey(); Key.Crypto.Parameters.RsaPrivateCrtKeyParameters rsaCrtPrivateParam = (Key.Crypto.Parameters.RsaPrivateCrtKeyParameters)privateKey.Key; // Assign the rsa parameters. rsaPrivateParam.D = rsaCrtPrivateParam.Exponent.ToByteArrayUnsigned(); rsaPrivateParam.DP = rsaCrtPrivateParam.DP.ToByteArrayUnsigned(); rsaPrivateParam.DQ = rsaCrtPrivateParam.DQ.ToByteArrayUnsigned(); rsaPrivateParam.InverseQ = rsaCrtPrivateParam.QInv.ToByteArrayUnsigned(); rsaPrivateParam.P = rsaCrtPrivateParam.P.ToByteArrayUnsigned(); rsaPrivateParam.Q = rsaCrtPrivateParam.Q.ToByteArrayUnsigned(); rsaPrivateParam.Modulus = rsaPrivatePublic.Modulus.ToByteArrayUnsigned(); rsaPrivateParam.Exponent = rsaPrivatePublic.Exponent.ToByteArrayUnsigned(); // Create the encyption provider. RSACryptoServiceProvider rsaEncryptProvider = new RSACryptoServiceProvider(); rsaEncryptProvider.ImportParameters(rsaPrivateParam); // Return the rsa provider. return(rsaEncryptProvider); }
/// <summary> /// Decrypt the stream. /// </summary> /// <param name="decrypted">The stream containing the decrypted data.</param> /// <param name="input">The data to decrypt.</param> /// <param name="secretKey">The secret key used for decryption.</param> /// <param name="password">The password used to protect the secret key.</param> /// <returns>Returns null if no integrity packet exists; false if message failed integrity check; true if message integrity check passed.</returns> public bool?Decrypt(System.IO.Stream decrypted, System.IO.Stream input, System.IO.Stream secretKey, string password) { // Get decorder stream. input = Key.Bcpg.OpenPgp.PgpUtilities.GetDecoderStream(input); System.IO.Stream clear = null; System.IO.Stream unc = null; try { // Load the encrypted input stream. Key.Bcpg.OpenPgp.PgpEncryptedDataList encryptedDataList = null; Key.Bcpg.OpenPgp.PgpObjectFactory objectFactory = new Key.Bcpg.OpenPgp.PgpObjectFactory(input); Key.Bcpg.OpenPgp.PgpObject o = objectFactory.NextPgpObject(); // The first object might be a PGP marker packet. if (o is Key.Bcpg.OpenPgp.PgpEncryptedDataList) { // Get the data list. encryptedDataList = (Key.Bcpg.OpenPgp.PgpEncryptedDataList)o; } else { // Get the next object. encryptedDataList = (Key.Bcpg.OpenPgp.PgpEncryptedDataList)objectFactory.NextPgpObject(); } // Find the secret key Key.Bcpg.OpenPgp.PgpPrivateKey privateKey = null; Key.Bcpg.OpenPgp.PgpPublicKeyEncryptedData publicKeyEncryptedData = null; Key.Bcpg.OpenPgp.PgpSecretKeyRingBundle secretKeyRingBundle = new Key.Bcpg.OpenPgp.PgpSecretKeyRingBundle(Key.Bcpg.OpenPgp.PgpUtilities.GetDecoderStream(secretKey)); // For each object find the secret key. foreach (Key.Bcpg.OpenPgp.PgpPublicKeyEncryptedData pked in encryptedDataList.GetEncryptedDataObjects()) { // Find the private key (secret key). privateKey = FindSecretKey(secretKeyRingBundle, pked.KeyId, password.ToArray()); // If the private key exists. if (privateKey != null) { // This is the private key. publicKeyEncryptedData = pked; break; } } // If a private key was not found. if (privateKey == null) { throw new ArgumentException("secret key for message not found."); } // Get the data stream. clear = publicKeyEncryptedData.GetDataStream(privateKey); // Get the key message. Key.Bcpg.OpenPgp.PgpObjectFactory plainFact = new Key.Bcpg.OpenPgp.PgpObjectFactory(clear); Key.Bcpg.OpenPgp.PgpObject message = plainFact.NextPgpObject(); // If message is compressed. if (message is Key.Bcpg.OpenPgp.PgpCompressedData) { // Decompress the message. Key.Bcpg.OpenPgp.PgpCompressedData cData = (Key.Bcpg.OpenPgp.PgpCompressedData)message; Key.Bcpg.OpenPgp.PgpObjectFactory pgpFact = new Key.Bcpg.OpenPgp.PgpObjectFactory(cData.GetDataStream()); message = pgpFact.NextPgpObject(); } // If the message is literal data. if (message is Key.Bcpg.OpenPgp.PgpLiteralData) { Key.Bcpg.OpenPgp.PgpLiteralData ld = (Key.Bcpg.OpenPgp.PgpLiteralData)message; // Get the file name of the embedded encrypted file. string outFileName = ld.FileName; // Write the ecrypted data file to the decrypted stream. unc = ld.GetInputStream(); Key.Utilities.IO.Streams.PipeAll(unc, decrypted); } else if (message is Key.Bcpg.OpenPgp.PgpOnePassSignatureList) { throw new Exception("encrypted message contains a signed message - not literal data."); } else { throw new Exception("message is not a simple encrypted file - type unknown."); } // If the ecrypted file contains an integrity packet associated with it. if (publicKeyEncryptedData.IsIntegrityProtected()) { // If it has been verified. if (!publicKeyEncryptedData.Verify()) { // Message failed integrity check. return(false); } else { // Message integrity check passed. return(true); } } // No integrity packet exists. return(null); } catch (Exception) { throw; } finally { if (clear != null) { clear.Close(); } if (unc != null) { unc.Close(); } } }
/// <summary> /// Computes the hash value of the specified input stream using the specified /// hash algorithm, and signs the resulting hash value. /// </summary> /// <param name="inputStream">The input data for which to compute the hash.</param> /// <param name="rsaProvider">The RSA crypto service provider.</param> /// <param name="keyID">The unique key id of the public secret key pair.</param> /// <param name="hashAlgorithm">The hash algorithm to use to create the hash value.</param> /// <returns>The signature for the specified data.</returns> public byte[] SignData(Stream inputStream, RSACryptoServiceProvider rsaProvider, long keyID, Nequeo.Cryptography.HashcodeType hashAlgorithm = HashcodeType.SHA512) { MemoryStream output = null; Key.Bcpg.BcpgOutputStream pgpOutput = null; try { int ch; output = new MemoryStream(); // Export the signer private key parameters. RSAParameters rsaPrivateKeySignerParam = rsaProvider.ExportParameters(true); Key.Crypto.Parameters.RsaPrivateCrtKeyParameters rsaPrivateKeySigner = new Key.Crypto.Parameters.RsaPrivateCrtKeyParameters( new Key.Math.BigInteger(1, rsaPrivateKeySignerParam.Modulus), new Key.Math.BigInteger(1, rsaPrivateKeySignerParam.Exponent), new Key.Math.BigInteger(1, rsaPrivateKeySignerParam.D), new Key.Math.BigInteger(1, rsaPrivateKeySignerParam.P), new Key.Math.BigInteger(1, rsaPrivateKeySignerParam.Q), new Key.Math.BigInteger(1, rsaPrivateKeySignerParam.DP), new Key.Math.BigInteger(1, rsaPrivateKeySignerParam.DQ), new Key.Math.BigInteger(1, rsaPrivateKeySignerParam.InverseQ) ); // Get the private key. Key.Bcpg.OpenPgp.PgpPrivateKey privateKey = new Key.Bcpg.OpenPgp.PgpPrivateKey(rsaPrivateKeySigner, keyID); // Create a signature generator. Key.Bcpg.OpenPgp.PgpSignatureGenerator signatureGenerator = new Key.Bcpg.OpenPgp.PgpSignatureGenerator(Key.Bcpg.PublicKeyAlgorithmTag.RsaGeneral, GetHashAlgorithm(hashAlgorithm)); signatureGenerator.InitSign(Key.Bcpg.OpenPgp.PgpSignature.BinaryDocument, privateKey); // Create the output stream. pgpOutput = new Key.Bcpg.BcpgOutputStream(output); // Read the input stream. while ((ch = inputStream.ReadByte()) >= 0) { // Update the generator. signatureGenerator.Update((byte)ch); } // Write the hash to the output stream. Key.Bcpg.OpenPgp.PgpSignature signature = signatureGenerator.Generate(); signature.Encode(pgpOutput); // Return the signed value. return(output.ToArray()); } catch (Exception) { throw; } finally { if (output != null) { output.Close(); } if (pgpOutput != null) { pgpOutput.Close(); } } }
internal PgpSecretKey( PgpPrivateKey privKey, PgpPublicKey pubKey, SymmetricKeyAlgorithmTag encAlgorithm, char[] passPhrase, bool useSha1, SecureRandom rand, bool isMasterKey) { BcpgObject secKey; this.pub = pubKey; switch (pubKey.Algorithm) { case PublicKeyAlgorithmTag.RsaEncrypt: case PublicKeyAlgorithmTag.RsaSign: case PublicKeyAlgorithmTag.RsaGeneral: RsaPrivateCrtKeyParameters rsK = (RsaPrivateCrtKeyParameters)privKey.Key; secKey = new RsaSecretBcpgKey(rsK.Exponent, rsK.P, rsK.Q); break; case PublicKeyAlgorithmTag.Dsa: DsaPrivateKeyParameters dsK = (DsaPrivateKeyParameters)privKey.Key; secKey = new DsaSecretBcpgKey(dsK.X); break; case PublicKeyAlgorithmTag.ElGamalEncrypt: case PublicKeyAlgorithmTag.ElGamalGeneral: ElGamalPrivateKeyParameters esK = (ElGamalPrivateKeyParameters)privKey.Key; secKey = new ElGamalSecretBcpgKey(esK.X); break; default: throw new PgpException("unknown key class"); } try { MemoryStream bOut = new MemoryStream(); BcpgOutputStream pOut = new BcpgOutputStream(bOut); pOut.WriteObject(secKey); byte[] keyData = bOut.ToArray(); byte[] checksumBytes = Checksum(useSha1, keyData, keyData.Length); pOut.Write(checksumBytes); byte[] bOutData = bOut.ToArray(); if (encAlgorithm == SymmetricKeyAlgorithmTag.Null) { if (isMasterKey) { this.secret = new SecretKeyPacket(pub.publicPk, encAlgorithm, null, null, bOutData); } else { this.secret = new SecretSubkeyPacket(pub.publicPk, encAlgorithm, null, null, bOutData); } } else { S2k s2k; byte[] iv; byte[] encData = EncryptKeyData(bOutData, encAlgorithm, passPhrase, rand, out s2k, out iv); int s2kUsage = useSha1 ? SecretKeyPacket.UsageSha1 : SecretKeyPacket.UsageChecksum; if (isMasterKey) { this.secret = new SecretKeyPacket(pub.publicPk, encAlgorithm, s2kUsage, s2k, iv, encData); } else { this.secret = new SecretSubkeyPacket(pub.publicPk, encAlgorithm, s2kUsage, s2k, iv, encData); } } } catch (PgpException e) { throw e; } catch (Exception e) { throw new PgpException("Exception encrypting key", e); } }
/// <summary>Return the decrypted data stream for the packet.</summary> public Stream GetDataStream( PgpPrivateKey privKey) { byte[] plain = fetchSymmetricKeyData(privKey); IBufferedCipher c2; string cipherName = PgpUtilities.GetSymmetricCipherName((SymmetricKeyAlgorithmTag)plain[0]); string cName = cipherName; try { if (encData is SymmetricEncIntegrityPacket) { cName += "/CFB/NoPadding"; } else { cName += "/OpenPGPCFB/NoPadding"; } c2 = CipherUtilities.GetCipher(cName); } catch (PgpException e) { throw e; } catch (Exception e) { throw new PgpException("exception creating cipher", e); } if (c2 == null) { return(encData.GetInputStream()); } try { KeyParameter key = ParameterUtilities.CreateKeyParameter( cipherName, plain, 1, plain.Length - 3); byte[] iv = new byte[c2.GetBlockSize()]; c2.Init(false, new ParametersWithIV(key, iv)); encStream = BcpgInputStream.Wrap(new CipherStream(encData.GetInputStream(), c2, 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, iv, 0, iv.Length) < iv.Length) { throw new EndOfStreamException("unexpected end of stream."); } int v1 = encStream.ReadByte(); int v2 = encStream.ReadByte(); if (v1 < 0 || v2 < 0) { throw new EndOfStreamException("unexpected end of stream."); } // Note: the oracle attack on the "quick check" bytes is deemed // a security risk for typical public key encryption usages, // therefore we do not perform the check. // bool repeatCheckPassed = // iv[iv.Length - 2] == (byte)v1 // && iv[iv.Length - 1] == (byte)v2; // // // Note: some versions of PGP appear to produce 0 for the extra // // bytes rather than repeating the two previous bytes // bool zeroesCheckPassed = // v1 == 0 // && v2 == 0; // // if (!repeatCheckPassed && !zeroesCheckPassed) // { // throw new PgpDataValidationException("quick check failed."); // } return(encStream); } catch (PgpException e) { throw e; } catch (Exception e) { throw new PgpException("Exception starting decryption", e); } }
private byte[] fetchSymmetricKeyData( PgpPrivateKey privKey) { IBufferedCipher c1 = GetKeyCipher(keyData.Algorithm); try { c1.Init(false, privKey.Key); } catch (InvalidKeyException e) { throw new PgpException("error setting asymmetric cipher", e); } BigInteger[] keyD = keyData.GetEncSessionKey(); if (keyData.Algorithm == PublicKeyAlgorithmTag.RsaEncrypt || keyData.Algorithm == PublicKeyAlgorithmTag.RsaGeneral) { c1.ProcessBytes(keyD[0].ToByteArrayUnsigned()); } else { ElGamalPrivateKeyParameters k = (ElGamalPrivateKeyParameters)privKey.Key; int size = (k.Parameters.P.BitLength + 7) / 8; byte[] bi = keyD[0].ToByteArray(); int diff = bi.Length - size; if (diff >= 0) { c1.ProcessBytes(bi, diff, size); } else { byte[] zeros = new byte[-diff]; c1.ProcessBytes(zeros); c1.ProcessBytes(bi); } bi = keyD[1].ToByteArray(); diff = bi.Length - size; if (diff >= 0) { c1.ProcessBytes(bi, diff, size); } else { byte[] zeros = new byte[-diff]; c1.ProcessBytes(zeros); c1.ProcessBytes(bi); } } byte[] plain; try { plain = c1.DoFinal(); } catch (Exception e) { throw new PgpException("exception decrypting secret key", e); } if (!ConfirmCheckSum(plain)) { throw new PgpKeyValidationException("key checksum failed"); } return(plain); }
/// <summary>Initialise the generator for signing.</summary> public void InitSign( int sigType, PgpPrivateKey key) { InitSign(sigType, key, null); }