/// <summary> /// Attempt to encrypt a message using PGP with the specified public key(s). /// </summary> /// <param name="messageStream">Stream containing the message to encrypt.</param> /// <param name="encryptedMessageStream">Stream to write the encrypted message into.</param> /// <param name="fileName">File name of for the message.</param> /// <param name="recipientPublicKeys">Collection of BouncyCastle public keys to be used for encryption.</param> /// <param name="symmetricKeyAlgorithmTag">The symmetric key algorithm tag to use for encryption.</param> /// <param name="armor">Whether to wrap the message with ASCII armor.</param> /// <returns>Whether the encryption completed successfully.</returns> public static bool Encrypt(Stream messageStream, Stream encryptedMessageStream, string fileName, IEnumerable<PgpPublicKey> recipientPublicKeys, SymmetricKeyAlgorithmTag symmetricKeyAlgorithmTag = SymmetricKeyAlgorithmTag.TripleDes, bool armor = true) { // Allow any of the corresponding keys to be used for decryption. PgpEncryptedDataGenerator encryptedDataGenerator = new PgpEncryptedDataGenerator(symmetricKeyAlgorithmTag, true, new SecureRandom()); foreach (PgpPublicKey publicKey in recipientPublicKeys) { encryptedDataGenerator.AddMethod(publicKey); } // Handle optional ASCII armor. if (armor) { using (Stream armoredStream = new ArmoredOutputStream(encryptedMessageStream)) { using (Stream encryptedStream = encryptedDataGenerator.Open(armoredStream, new byte[Constants.LARGEBUFFERSIZE])) { PgpCompressedDataGenerator compressedDataGenerator = new PgpCompressedDataGenerator(CompressionAlgorithmTag.Uncompressed); using (Stream compressedStream = compressedDataGenerator.Open(encryptedStream)) { PgpLiteralDataGenerator literalDataGenerator = new PgpLiteralDataGenerator(); using (Stream literalDataStream = literalDataGenerator.Open(encryptedStream, PgpLiteralData.Binary, fileName, DateTime.Now, new byte[Constants.LARGEBUFFERSIZE])) { messageStream.Seek(0, SeekOrigin.Begin); messageStream.CopyTo(literalDataStream); } } } } } else { using (Stream encryptedStream = encryptedDataGenerator.Open(encryptedMessageStream, new byte[Constants.LARGEBUFFERSIZE])) { PgpCompressedDataGenerator compressedDataGenerator = new PgpCompressedDataGenerator(CompressionAlgorithmTag.Uncompressed); using (Stream compressedStream = compressedDataGenerator.Open(encryptedStream)) { PgpLiteralDataGenerator literalDataGenerator = new PgpLiteralDataGenerator(); using (Stream literalDataStream = literalDataGenerator.Open(encryptedStream, PgpLiteralData.Binary, fileName, DateTime.Now, new byte[Constants.LARGEBUFFERSIZE])) { messageStream.Seek(0, SeekOrigin.Begin); messageStream.CopyTo(literalDataStream); } } } } return true; }
/// <summary> /// Attempt to encrypt a message using PGP with the specified public key(s). /// </summary> /// <param name="messageStream">Stream containing the message to encrypt.</param> /// <param name="fileName">File name of for the message.</param> /// <param name="signedAndEncryptedMessageStream">Stream to write the encrypted message into.</param> /// <param name="senderPublicKey">The BouncyCastle public key associated with the signature.</param> /// <param name="senderPrivateKey">The BouncyCastle private key to be used for signing.</param> /// <param name="recipientPublicKeys">Collection of BouncyCastle public keys to be used for encryption.</param> /// <param name="hashAlgorithmTag">The hash algorithm tag to use for signing.</param> /// <param name="symmetricKeyAlgorithmTag">The symmetric key algorithm tag to use for encryption.</param> /// <param name="armor">Whether to wrap the message with ASCII armor.</param> /// <returns>Whether the encryption completed successfully.</returns> public static bool SignAndEncrypt(Stream messageStream, string fileName, Stream signedAndEncryptedMessageStream, PgpPublicKey senderPublicKey, PgpPrivateKey senderPrivateKey, IEnumerable<PgpPublicKey> recipientPublicKeys, HashAlgorithmTag hashAlgorithmTag = HashAlgorithmTag.Sha256, SymmetricKeyAlgorithmTag symmetricKeyAlgorithmTag = SymmetricKeyAlgorithmTag.TripleDes, bool armor = true) { // Create a signature generator. PgpSignatureGenerator signatureGenerator = new PgpSignatureGenerator(senderPublicKey.Algorithm, hashAlgorithmTag); signatureGenerator.InitSign(PgpSignature.BinaryDocument, senderPrivateKey); // Add the public key user ID. foreach (string userId in senderPublicKey.GetUserIds()) { PgpSignatureSubpacketGenerator signatureSubGenerator = new PgpSignatureSubpacketGenerator(); signatureSubGenerator.SetSignerUserId(false, userId); signatureGenerator.SetHashedSubpackets(signatureSubGenerator.Generate()); break; } // Allow any of the corresponding keys to be used for decryption. PgpEncryptedDataGenerator encryptedDataGenerator = new PgpEncryptedDataGenerator(SymmetricKeyAlgorithmTag.TripleDes, true, new SecureRandom()); foreach (PgpPublicKey publicKey in recipientPublicKeys) { encryptedDataGenerator.AddMethod(publicKey); } // Handle optional ASCII armor. if (armor) { using (Stream armoredStream = new ArmoredOutputStream(signedAndEncryptedMessageStream)) { using (Stream encryptedStream = encryptedDataGenerator.Open(armoredStream, new byte[Constants.LARGEBUFFERSIZE])) { PgpCompressedDataGenerator compressedDataGenerator = new PgpCompressedDataGenerator(CompressionAlgorithmTag.Uncompressed); using (Stream compressedStream = compressedDataGenerator.Open(encryptedStream)) { signatureGenerator.GenerateOnePassVersion(false).Encode(compressedStream); PgpLiteralDataGenerator literalDataGenerator = new PgpLiteralDataGenerator(); using (Stream literalStream = literalDataGenerator.Open(compressedStream, PgpLiteralData.Binary, fileName, DateTime.Now, new byte[Constants.LARGEBUFFERSIZE])) { // Process each character in the message. int messageChar; while ((messageChar = messageStream.ReadByte()) >= 0) { literalStream.WriteByte((byte)messageChar); signatureGenerator.Update((byte)messageChar); } } signatureGenerator.Generate().Encode(compressedStream); } } } } else { using (Stream encryptedStream = encryptedDataGenerator.Open(signedAndEncryptedMessageStream, new byte[Constants.LARGEBUFFERSIZE])) { PgpCompressedDataGenerator compressedDataGenerator = new PgpCompressedDataGenerator(CompressionAlgorithmTag.Uncompressed); using (Stream compressedStream = compressedDataGenerator.Open(encryptedStream)) { signatureGenerator.GenerateOnePassVersion(false).Encode(compressedStream); PgpLiteralDataGenerator literalDataGenerator = new PgpLiteralDataGenerator(); using (Stream literalStream = literalDataGenerator.Open(compressedStream, PgpLiteralData.Binary, fileName, DateTime.Now, new byte[Constants.LARGEBUFFERSIZE])) { // Process each character in the message. int messageChar; while ((messageChar = messageStream.ReadByte()) >= 0) { literalStream.WriteByte((byte)messageChar); signatureGenerator.Update((byte)messageChar); } } signatureGenerator.Generate().Encode(compressedStream); } } } return true; }
/** * Encrypts given {@code message}. Output is written ot the {@code encryptedMessage} output stream. * Message is encrypted usign symmetric algorithm, default is {@link SymmetricKeyAlgorithmTags#TRIPLE_DES}. * * @param encryptedMessage * @param message * @param armor if output should be armored (BASE64 encoding of binary data) * @throws java.io.IOException * @throws java.security.NoSuchProviderException * @throws PgpException */ public void encryptMessage(Stream encryptedMessage, string message, bool armor) { PgpCompressedDataGenerator compressedDataGenerator = new PgpCompressedDataGenerator(CompressionAlgorithmTag.Zip); PgpLiteralDataGenerator literalDataGenerator = new PgpLiteralDataGenerator(); // we want to generate compressed data MemoryStream byteOut = new MemoryStream(); writeClearDataToByteOut(compressedDataGenerator, literalDataGenerator, Encoding.ASCII.GetBytes(message), byteOut); compressedDataGenerator.Close(); MemoryStream encryptedOut = new MemoryStream(); Stream outStream = encryptedOut; if (armor) { // output will be BASE64 encoded outStream = new ArmoredOutputStream(outStream); } Stream encryptedDataOut = null; try { byte[] bytes = byteOut.ToArray(); encryptedDataOut = createEncryptedDataGenerator().Open(outStream, bytes.Length); encryptedDataOut.Write(bytes, 0, bytes.Length); // obtain the actual bytes from the compressed stream } finally { if (encryptedDataOut != null) { encryptedDataOut.Close(); } outStream.Close(); } var encData = encryptedOut.ToArray(); encryptedMessage.Write(encData, 0, encData.Length); }
/// <summary> /// 加密并签名 /// 使用接受方的公钥进行加密 /// 使用发送方的私钥进行签名 /// 先压缩,再加密,再签名 /// </summary> /// <param name="kp"></param> /// <param name="cfg"></param> /// <param name="inputFile"></param> /// <param name="outputStream">普通的stream,或者Org.BouncyCastle.Bcpg.ArmoredOutputStream(如果使用加密文件使用ASCII)</param> public static void EncryptAndSign(System.IO.FileInfo inputFile, System.IO.Stream outputStream, GpgKeyPair kp, GpgEncryptSignCfg cfg) { var sr = new Org.BouncyCastle.Security.SecureRandom(); var pgpEncryptedDataGenerator = new Org.BouncyCastle.Bcpg.OpenPgp.PgpEncryptedDataGenerator(cfg.SymmetricKeyAlgorithmTag, cfg.IntegrityProtected, sr); pgpEncryptedDataGenerator.AddMethod(kp.PublickKey); var pgpCompressedDataGenerator = new Org.BouncyCastle.Bcpg.OpenPgp.PgpCompressedDataGenerator(cfg.CompressionAlgorithmTag); var pgpLiteralDataGenerator = new Org.BouncyCastle.Bcpg.OpenPgp.PgpLiteralDataGenerator(); using (var fs = inputFile.OpenRead()) using (var outputStreamEncrypted = pgpEncryptedDataGenerator.Open(outputStream, new byte[cfg.BufferSize])) using (var outputStreamEncryptedCompressed = pgpCompressedDataGenerator.Open(outputStreamEncrypted)) using (var outputStreamEncryptedCompressedLiteral = pgpLiteralDataGenerator.Open(outputStreamEncryptedCompressed, Org.BouncyCastle.Bcpg.OpenPgp.PgpLiteralData.Binary, inputFile.Name, inputFile.Length, inputFile.LastWriteTime)) { var pgpSignatureGenerator = new Org.BouncyCastle.Bcpg.OpenPgp.PgpSignatureGenerator(kp.PrivateKeySecreted.PublicKey.Algorithm, Org.BouncyCastle.Bcpg.HashAlgorithmTag.Sha256); pgpSignatureGenerator.InitSign(Org.BouncyCastle.Bcpg.OpenPgp.PgpSignature.BinaryDocument, kp.PrivateKey); var userId = kp.PrivateKeySecreted.PublicKey.GetUserIds().Cast <string>().First(); var pgpSignatureSubpacketGenerator = new Org.BouncyCastle.Bcpg.OpenPgp.PgpSignatureSubpacketGenerator(); pgpSignatureSubpacketGenerator.SetSignerUserId(cfg.IsCritical, userId); pgpSignatureGenerator.SetHashedSubpackets(pgpSignatureSubpacketGenerator.Generate()); pgpSignatureGenerator.GenerateOnePassVersion(cfg.IsNested).Encode(outputStreamEncryptedCompressedLiteral); int dataLenght = 0; var buffer = new byte[cfg.BufferSize]; while ((dataLenght = fs.Read(buffer, 0, buffer.Length)) > 0) { outputStreamEncryptedCompressedLiteral.Write(buffer, 0, dataLenght); pgpSignatureGenerator.Update(buffer, 0, dataLenght); } pgpSignatureGenerator.Generate().Encode(outputStreamEncryptedCompressedLiteral); } }
public static Stream PgpEncrypt(this Stream toEncrypt, PgpPublicKey encryptionKey, bool armor = true, bool verify = false) { var outStream = new MemoryStream(); var encryptor = new PgpEncryptedDataGenerator(SymmetricKeyAlgorithmTag.Cast5, verify, new SecureRandom()); var literalizer = new PgpLiteralDataGenerator(); var compressor = new PgpCompressedDataGenerator(CompressionAlgorithmTag.Zip); encryptor.AddMethod(encryptionKey); //it would be nice if these streams were read/write, and supported seeking. Since they are not, //we need to shunt the data to a read/write stream so that we can control the flow of data as we go. using (var stream = new MemoryStream()) // this is the read/write stream using (var armoredStream = armor ? new ArmoredOutputStream(stream) : stream as Stream) using (var compressedStream = compressor.Open(armoredStream)) { //data is encrypted first, then compressed, but because of the one-way nature of these streams, //other "interim" streams are required. The raw data is encapsulated in a "Literal" PGP object. var rawData = toEncrypt.ReadFully(); var buffer = new byte[1024]; using (var literalOut = new MemoryStream()) using (var literalStream = literalizer.Open(literalOut, PgpLiteralData.Binary, "STREAM", DateTime.UtcNow, buffer)) { literalStream.Write(rawData, 0, rawData.Length); literalStream.Close(); var literalData = literalOut.ReadFully(); //The literal data object is then encrypted, which flows into the compressing stream and //(optionally) into the ASCII armoring stream. using (var encryptedStream = encryptor.Open(compressedStream, literalData.Length)) { encryptedStream.Write(literalData, 0, literalData.Length); encryptedStream.Close(); compressedStream.Close(); armoredStream.Close(); //the stream processes are now complete, and our read/write stream is now populated with //encrypted data. Convert the stream to a byte array and write to the out stream. stream.Position = 0; var data = stream.ReadFully(); outStream.Write(data, 0, data.Length); } } } outStream.Position = 0; return outStream; }
private const int BufferSize = 0x10000; // should always be power of 2 #region Encrypt /// <summary> /// Encrypts the file. /// </summary> /// <param name="inputFile">The input file.</param> /// <param name="outputFile">The output file.</param> /// <param name="publicKeyFile">The public key file.</param> /// <param name="armor">if set to <c>true</c> [armor].</param> /// <param name="withIntegrityCheck">if set to <c>true</c> [with integrity check].</param> public static void EncryptFile(string inputFile, string outputFile, string publicKeyFile, bool armor, bool withIntegrityCheck) { try { using (Stream publicKeyStream = File.OpenRead(publicKeyFile)) { PgpPublicKey encKey = ReadPublicKey(publicKeyStream); using (MemoryStream bOut = new MemoryStream()) { PgpCompressedDataGenerator comData = new PgpCompressedDataGenerator(CompressionAlgorithmTag.Zip); PgpUtilities.WriteFileToLiteralData(comData.Open(bOut), PgpLiteralData.Binary, new FileInfo(inputFile)); comData.Close(); PgpEncryptedDataGenerator cPk = new PgpEncryptedDataGenerator(SymmetricKeyAlgorithmTag.Cast5, withIntegrityCheck, new SecureRandom()); cPk.AddMethod(encKey); byte[] bytes = bOut.ToArray(); using (Stream outputStream = File.Create(outputFile)) { if (armor) { using (ArmoredOutputStream armoredStream = new ArmoredOutputStream(outputStream)) { using (Stream cOut = cPk.Open(armoredStream, bytes.Length)) { cOut.Write(bytes, 0, bytes.Length); } } } else { using (Stream cOut = cPk.Open(outputStream, bytes.Length)) { cOut.Write(bytes, 0, bytes.Length); } } } } } } catch (PgpException e) { throw e; } }
private static void EncryptFile(Stream outputStream, string fileName, PgpPublicKey encKey, bool armor, bool withIntegrityCheck) { if (armor) outputStream = new ArmoredOutputStream(outputStream); try { MemoryStream bOut = new MemoryStream(); PgpCompressedDataGenerator comData = new PgpCompressedDataGenerator( CompressionAlgorithmTag.Zip); PgpUtilities.WriteFileToLiteralData( comData.Open(bOut), PgpLiteralData.Binary, new FileInfo(fileName)); comData.Close(); PgpEncryptedDataGenerator cPk = new PgpEncryptedDataGenerator( SymmetricKeyAlgorithmTag.Cast5, withIntegrityCheck, new SecureRandom()); cPk.AddMethod(encKey); byte[] bytes = bOut.ToArray(); Stream cOut = cPk.Open(outputStream, bytes.Length); cOut.Write(bytes, 0, bytes.Length); cOut.Close(); if (armor) outputStream.Close(); } catch (PgpException e) { Console.Error.WriteLine(e); Exception underlyingException = e.InnerException; if (underlyingException != null) { Console.Error.WriteLine(underlyingException.Message); Console.Error.WriteLine(underlyingException.StackTrace); } } }
/// <summary> /// 加密文件 /// 使用接收方的公钥加密文件 /// 先压缩,再加密, /// </summary> /// <param name="inputFile"></param> /// <param name="outputStream">普通的stream,或者Org.BouncyCastle.Bcpg.ArmoredOutputStream(如果使用加密文件使用ASCII)</param> /// <param name="pubKey"></param> /// <param name="cfg"></param> public static void Encrypt(System.IO.FileInfo inputFile, System.IO.Stream outputStream, System.IO.Stream publickKeyStream, GpgEncryptSignCfg cfg) { var sr = new Org.BouncyCastle.Security.SecureRandom(); var pgpEncryptedDataGenerator = new Org.BouncyCastle.Bcpg.OpenPgp.PgpEncryptedDataGenerator(cfg.SymmetricKeyAlgorithmTag, cfg.IntegrityProtected, sr); var pubKey = GpgKeyPair.ReadPublicKey(publickKeyStream); pgpEncryptedDataGenerator.AddMethod(pubKey); var pgpCompressedDataGenerator = new Org.BouncyCastle.Bcpg.OpenPgp.PgpCompressedDataGenerator(cfg.CompressionAlgorithmTag); var pgpLiteralDataGenerator = new Org.BouncyCastle.Bcpg.OpenPgp.PgpLiteralDataGenerator(); using (var fs = inputFile.OpenRead()) using (var outputStreamEncrypted = pgpEncryptedDataGenerator.Open(outputStream, new byte[cfg.BufferSize])) using (var outputStreamEncryptedCompressed = pgpCompressedDataGenerator.Open(outputStreamEncrypted)) using (var outputStreamEncryptedCompressedLiteral = pgpLiteralDataGenerator.Open(outputStreamEncryptedCompressed, Org.BouncyCastle.Bcpg.OpenPgp.PgpLiteralData.Binary, inputFile.Name, inputFile.Length, inputFile.LastWriteTime)) { int dataLenght = 0; var buffer = new byte[cfg.BufferSize]; while ((dataLenght = fs.Read(buffer, 0, buffer.Length)) > 0) { outputStreamEncryptedCompressedLiteral.Write(buffer, 0, dataLenght); } } }
/// <summary> /// Encrypt string using a PGP public key /// </summary> /// <param name="plain">plain text to encrypt</param> /// <param name="armoredPublicKey">public key in ASCII "-----BEGIN PGP PUBLIC KEY BLOCK----- .. -----END PGP PUBLIC KEY BLOCK-----" format</param> /// <returns>PGP message string</returns> public static string PGPEncrypt(string plain, string armoredPublicKey) { // encode data byte[] data = Encoding.UTF8.GetBytes(plain); // create the WinAuth public key PgpPublicKey publicKey = null; using (MemoryStream ms = new MemoryStream(Encoding.ASCII.GetBytes(armoredPublicKey))) { using (Stream dis = PgpUtilities.GetDecoderStream(ms)) { PgpPublicKeyRingBundle bundle = new PgpPublicKeyRingBundle(dis); foreach (PgpPublicKeyRing keyring in bundle.GetKeyRings()) { foreach (PgpPublicKey key in keyring.GetPublicKeys()) { if (key.IsEncryptionKey == true && key.IsRevoked() == false) { publicKey = key; break; } } } } } // encrypt the data using PGP using (MemoryStream encryptedStream = new MemoryStream()) { using (ArmoredOutputStream armored = new ArmoredOutputStream(encryptedStream)) { PgpEncryptedDataGenerator pedg = new PgpEncryptedDataGenerator(Org.BouncyCastle.Bcpg.SymmetricKeyAlgorithmTag.Cast5, true, new Org.BouncyCastle.Security.SecureRandom()); pedg.AddMethod(publicKey); using (Stream pedgStream = pedg.Open(armored, new byte[4096])) { PgpCompressedDataGenerator pcdg = new PgpCompressedDataGenerator(Org.BouncyCastle.Bcpg.CompressionAlgorithmTag.Zip); using (Stream pcdgStream = pcdg.Open(pedgStream)) { PgpLiteralDataGenerator pldg = new PgpLiteralDataGenerator(); using (Stream encrypter = pldg.Open(pcdgStream, PgpLiteralData.Binary, "", (long)data.Length, DateTime.Now)) { encrypter.Write(data, 0, data.Length); } } } } return Encoding.ASCII.GetString(encryptedStream.ToArray()); } }
/// <summary> /// Encrypt data to a set of recipients /// </summary> /// <param name="data">Data to encrypt</param> /// <param name="recipients">List of email addresses</param> /// <param name="recipients">Headers to add to ascii armor</param> /// <returns>Returns ascii armored encrypted data</returns> public string Encrypt(byte[] data, IList<string> recipients, Dictionary<string, string> headers) { Context = new CryptoContext(Context); var compressedData = new PgpCompressedDataGenerator(CompressionAlgorithmTag.Zip); var literalData = new PgpLiteralDataGenerator(); var cryptData = new PgpEncryptedDataGenerator(SymmetricKeyAlgorithmTag.Cast5, true, new SecureRandom()); foreach (var recipient in recipients) { var recipientKey = GetPublicKeyForEncryption(recipient); if (recipientKey == null) throw new PublicKeyNotFoundException("Error, unable to find recipient key \"" + recipient + "\"."); cryptData.AddMethod(recipientKey); } using (var sout = new MemoryStream()) { using (var armoredOut = new ArmoredOutputStream(sout)) { foreach(var header in headers) armoredOut.SetHeader(header.Key, header.Value); using (var clearOut = new MemoryStream()) { using (var compressedOut = compressedData.Open(clearOut)) using (var literalOut = literalData.Open( compressedOut, PgpLiteralData.Binary, "email", data.Length, DateTime.UtcNow)) { literalOut.Write(data, 0, data.Length); } var clearData = clearOut.ToArray(); using (var encryptOut = cryptData.Open(armoredOut, clearData.Length)) { encryptOut.Write(clearData, 0, clearData.Length); } } } return ASCIIEncoding.ASCII.GetString(sout.ToArray()); } }
/** * Generates an encapsulated signed file. */ public void signMessage(Stream unsignedContent, Stream signedContent, bool armor) { if (armor) { // output will be BASE64 encoded signedContent = new ArmoredOutputStream(signedContent); } PgpCompressedDataGenerator compressedDataGenerator = new PgpCompressedDataGenerator(CompressionAlgorithmTag.ZLib); PgpLiteralDataGenerator literalDataGenerator = new PgpLiteralDataGenerator(); try { BcpgOutputStream bcpgSignedContentOut = new BcpgOutputStream(compressedDataGenerator.Open(signedContent)); PgpPrivateKey pgpPrivateKey = secretKeyForSigning.ExtractPrivateKey(secretKeyPassword); PgpSignatureGenerator signatureGenerator = createSignatureGenerator(pgpPrivateKey); signatureGenerator.GenerateOnePassVersion(false).Encode(bcpgSignedContentOut); Stream literalDataOut = literalDataGenerator.Open(bcpgSignedContentOut, PgpLiteralData.Binary, "_CONSOLE", unsignedContent.Length, DateTime.Now); updateSignatureGeneratorWithInputBytes(unsignedContent, signatureGenerator, literalDataOut); signatureGenerator.Generate().Encode(bcpgSignedContentOut); } finally { literalDataGenerator.Close(); compressedDataGenerator.Close(); signedContent.Close(); } }
/// <summary> /// Cryptographically signs the content. /// </summary> /// <remarks> /// Cryptographically signs the content using the specified signer and digest algorithm. /// </remarks> /// <returns>A new <see cref="MimeKit.MimePart"/> instance /// containing the detached signature data.</returns> /// <param name="signer">The signer.</param> /// <param name="digestAlgo">The digest algorithm to use for signing.</param> /// <param name="content">The content.</param> /// <exception cref="System.ArgumentNullException"> /// <para><paramref name="signer"/> is <c>null</c>.</para> /// <para>-or-</para> /// <para><paramref name="content"/> is <c>null</c>.</para> /// </exception> /// <exception cref="System.ArgumentException"> /// <paramref name="signer"/> cannot be used for signing. /// </exception> /// <exception cref="System.ArgumentOutOfRangeException"> /// The <paramref name="digestAlgo"/> was out of range. /// </exception> /// <exception cref="System.NotSupportedException"> /// The <paramref name="digestAlgo"/> is not supported. /// </exception> /// <exception cref="System.OperationCanceledException"> /// The user chose to cancel the password prompt. /// </exception> /// <exception cref="System.UnauthorizedAccessException"> /// 3 bad attempts were made to unlock the secret key. /// </exception> public ApplicationPgpSignature Sign (PgpSecretKey signer, DigestAlgorithm digestAlgo, Stream content) { if (signer == null) throw new ArgumentNullException ("signer"); if (!signer.IsSigningKey) throw new ArgumentException ("The specified secret key cannot be used for signing.", "signer"); if (content == null) throw new ArgumentNullException ("content"); var hashAlgorithm = GetHashAlgorithm (digestAlgo); var memory = new MemoryBlockStream (); using (var armored = new ArmoredOutputStream (memory)) { var compresser = new PgpCompressedDataGenerator (CompressionAlgorithmTag.ZLib); using (var compressed = compresser.Open (armored)) { var signatureGenerator = new PgpSignatureGenerator (signer.PublicKey.Algorithm, hashAlgorithm); var buf = new byte[4096]; int nread; signatureGenerator.InitSign (PgpSignature.CanonicalTextDocument, GetPrivateKey (signer)); while ((nread = content.Read (buf, 0, buf.Length)) > 0) signatureGenerator.Update (buf, 0, nread); var signature = signatureGenerator.Generate (); signature.Encode (compressed); compressed.Flush (); } armored.Flush (); } memory.Position = 0; return new ApplicationPgpSignature (memory); }
static Stream Compress (Stream content) { var compresser = new PgpCompressedDataGenerator (CompressionAlgorithmTag.ZLib); var memory = new MemoryBlockStream (); using (var compressed = compresser.Open (memory)) { var literalGenerator = new PgpLiteralDataGenerator (); using (var literal = literalGenerator.Open (compressed, 't', "mime.txt", content.Length, DateTime.Now)) { content.CopyTo (literal, 4096); literal.Flush (); } compressed.Flush (); } memory.Position = 0; return memory; }
/// <summary> /// Cryptographically signs and encrypts the specified content for the specified recipients. /// </summary> /// <remarks> /// Cryptographically signs and encrypts the specified content for the specified recipients. /// </remarks> /// <returns>A new <see cref="MimeKit.MimePart"/> instance /// containing the encrypted data.</returns> /// <param name="signer">The signer.</param> /// <param name="digestAlgo">The digest algorithm to use for signing.</param> /// <param name="cipherAlgo">The encryption algorithm.</param> /// <param name="recipients">The recipients.</param> /// <param name="content">The content.</param> /// <exception cref="System.ArgumentNullException"> /// <para><paramref name="signer"/> is <c>null</c>.</para> /// <para>-or-</para> /// <para><paramref name="recipients"/> is <c>null</c>.</para> /// <para>-or-</para> /// <para><paramref name="content"/> is <c>null</c>.</para> /// </exception> /// <exception cref="System.ArgumentException"> /// <para><paramref name="signer"/> cannot be used for signing.</para> /// <para>-or-</para> /// <para>One or more of the recipient keys cannot be used for encrypting.</para> /// <para>-or-</para> /// <para>No recipients were specified.</para> /// </exception> /// <exception cref="System.NotSupportedException"> /// The specified encryption algorithm is not supported. /// </exception> /// <exception cref="System.OperationCanceledException"> /// The user chose to cancel the password prompt. /// </exception> /// <exception cref="System.UnauthorizedAccessException"> /// 3 bad attempts were made to unlock the secret key. /// </exception> public MimePart SignAndEncrypt (PgpSecretKey signer, DigestAlgorithm digestAlgo, EncryptionAlgorithm cipherAlgo, IEnumerable<PgpPublicKey> recipients, Stream content) { // TODO: document the exceptions that can be thrown by BouncyCastle if (signer == null) throw new ArgumentNullException ("signer"); if (!signer.IsSigningKey) throw new ArgumentException ("The specified secret key cannot be used for signing.", "signer"); if (recipients == null) throw new ArgumentNullException ("recipients"); if (content == null) throw new ArgumentNullException ("content"); var encrypter = new PgpEncryptedDataGenerator (GetSymmetricKeyAlgorithm (cipherAlgo), true); var hashAlgorithm = GetHashAlgorithm (digestAlgo); int count = 0; foreach (var recipient in recipients) { if (!recipient.IsEncryptionKey) throw new ArgumentException ("One or more of the recipient keys cannot be used for encrypting.", "recipients"); encrypter.AddMethod (recipient); count++; } if (count == 0) throw new ArgumentException ("No recipients specified.", "recipients"); var compresser = new PgpCompressedDataGenerator (CompressionAlgorithmTag.ZLib); using (var compressed = new MemoryBlockStream ()) { using (var signed = compresser.Open (compressed)) { var signatureGenerator = new PgpSignatureGenerator (signer.PublicKey.Algorithm, hashAlgorithm); signatureGenerator.InitSign (PgpSignature.CanonicalTextDocument, GetPrivateKey (signer)); var subpacket = new PgpSignatureSubpacketGenerator (); foreach (string userId in signer.PublicKey.GetUserIds ()) { subpacket.SetSignerUserId (false, userId); break; } signatureGenerator.SetHashedSubpackets (subpacket.Generate ()); var onepass = signatureGenerator.GenerateOnePassVersion (false); onepass.Encode (signed); var literalGenerator = new PgpLiteralDataGenerator (); using (var literal = literalGenerator.Open (signed, 't', "mime.txt", content.Length, DateTime.Now)) { var buf = new byte[4096]; int nread; while ((nread = content.Read (buf, 0, buf.Length)) > 0) { signatureGenerator.Update (buf, 0, nread); literal.Write (buf, 0, nread); } literal.Flush (); } var signature = signatureGenerator.Generate (); signature.Encode (signed); signed.Flush (); } compressed.Position = 0; var memory = new MemoryBlockStream (); using (var armored = new ArmoredOutputStream (memory)) { using (var encrypted = encrypter.Open (armored, compressed.Length)) { compressed.CopyTo (encrypted, 4096); encrypted.Flush (); } armored.Flush (); } memory.Position = 0; return new MimePart ("application", "octet-stream") { ContentDisposition = new ContentDisposition ("attachment"), ContentObject = new ContentObject (memory) }; } }
private void writeClearDataToByteOut(PgpCompressedDataGenerator compressedDataGenerator, PgpLiteralDataGenerator literalDataGenerator, byte[] clearData, Stream byteOut) { try { Stream pOut = literalDataGenerator.Open(compressedDataGenerator.Open(byteOut), // the compressed output stream PgpLiteralData.Binary, PgpLiteralData.Text.ToString(), // "filename" to store clearData.Length, // length of clear data DateTime.Now // current time ); pOut.Write(clearData, 0, clearData.Length); } finally { literalDataGenerator.Close(); } }
private static Stream ChainCompressedOut(Stream encryptedOut) { PgpCompressedDataGenerator compressedDataGenerator = new PgpCompressedDataGenerator(CompressionAlgorithmTag.Zip); return compressedDataGenerator.Open(encryptedOut); }
/// <summary> /// Sign data using key /// </summary> /// <param name="data">Data to sign</param> /// <param name="key">Email address of key</param> /// <returns>Returns ascii armored signature</returns> public string Sign(byte[] data, string key, Dictionary<string, string> headers) { Context = new CryptoContext(Context); var senderKey = GetSecretKeyForSigning(key); if (senderKey == null) throw new SecretKeyNotFoundException("Error, unable to locate signing key \"" + key + "\"."); var compressedData = new PgpCompressedDataGenerator(CompressionAlgorithmTag.Zip); var literalData = new PgpLiteralDataGenerator(); // Setup signature stuff // var tag = senderKey.PublicKey.Algorithm; var signatureData = new PgpSignatureGenerator(tag, HashAlgorithmTag.Sha256); signatureData.InitSign(PgpSignature.BinaryDocument, senderKey.ExtractPrivateKey(Context.Password)); foreach (string userId in senderKey.PublicKey.GetUserIds()) { var subPacketGenerator = new PgpSignatureSubpacketGenerator(); subPacketGenerator.SetSignerUserId(false, userId); signatureData.SetHashedSubpackets(subPacketGenerator.Generate()); // Just the first one! break; } // // using (var sout = new MemoryStream()) { using (var armoredOut = new ArmoredOutputStream(sout)) { foreach (var header in headers) armoredOut.SetHeader(header.Key, header.Value); using (var compressedOut = compressedData.Open(armoredOut)) using (var outputStream = new BcpgOutputStream(compressedOut)) { signatureData.GenerateOnePassVersion(false).Encode(outputStream); using (var literalOut = literalData.Open(outputStream, 'b', "", data.Length, DateTime.Now)) { literalOut.Write(data, 0, data.Length); signatureData.Update(data); } signatureData.Generate().Encode(outputStream); } } return ASCIIEncoding.ASCII.GetString(sout.ToArray()); } }
/// <summary> /// Signs then encrypts data using key and list of recipients. /// </summary> /// <param name="data">Data to encrypt</param> /// <param name="key">Signing key</param> /// <param name="recipients">List of keys to encrypt to</param> /// <returns>Returns ascii armored signed/encrypted data</returns> protected string SignAndEncrypt(byte[] data, string key, IList<string> recipients, Dictionary<string, string> headers, bool isBinary) { Context = new CryptoContext(Context); var senderKey = GetSecretKeyForEncryption(key); if (senderKey == null) throw new SecretKeyNotFoundException("Error, Unable to locate sender encryption key \"" + key + "\"."); var senderSignKey = GetSecretKeyForSigning(key); if (senderSignKey == null) throw new SecretKeyNotFoundException("Error, Unable to locate sender signing key \"" + key + "\"."); var compressedData = new PgpCompressedDataGenerator(CompressionAlgorithmTag.ZLib); var literalData = new PgpLiteralDataGenerator(); var cryptData = new PgpEncryptedDataGenerator(SymmetricKeyAlgorithmTag.Cast5, true, new SecureRandom()); foreach (var recipient in recipients) { var recipientKey = GetPublicKeyForEncryption(recipient); if (recipientKey == null) throw new PublicKeyNotFoundException("Error, unable to find recipient key \"" + recipient + "\"."); cryptData.AddMethod(recipientKey); } // Setup signature stuff // var signatureData = new PgpSignatureGenerator( senderSignKey.PublicKey.Algorithm, HashAlgorithmTag.Sha256); signatureData.InitSign( isBinary ? PgpSignature.BinaryDocument : PgpSignature.CanonicalTextDocument, senderSignKey.ExtractPrivateKey(Context.Password)); foreach (string userId in senderKey.PublicKey.GetUserIds()) { var subPacketGenerator = new PgpSignatureSubpacketGenerator(); subPacketGenerator.SetSignerUserId(false, userId); signatureData.SetHashedSubpackets(subPacketGenerator.Generate()); // Just the first one! break; } // // using (var sout = new MemoryStream()) { using (var armoredOut = new ArmoredOutputStream(sout)) { foreach (var header in headers) armoredOut.SetHeader(header.Key, header.Value); using (var clearOut = new MemoryStream()) { using (var compressedOut = compressedData.Open(clearOut)) { signatureData.GenerateOnePassVersion(false).Encode(compressedOut); using (var literalOut = literalData.Open( compressedOut, isBinary ? PgpLiteralData.Binary : PgpLiteralData.Text, "", data.Length, DateTime.UtcNow)) { literalOut.Write(data, 0, data.Length); signatureData.Update(data, 0, data.Length); } signatureData.Generate().Encode(compressedOut); } var clearData = clearOut.ToArray(); using (var encryptOut = cryptData.Open(armoredOut, clearData.Length)) { encryptOut.Write(clearData, 0, clearData.Length); } } } return ASCIIEncoding.ASCII.GetString(sout.ToArray()); } }
/** * Generate an encapsulated signed file. * * @param fileName * @param keyIn * @param outputStream * @param pass * @param armor */ private static void SignFile( string fileName, Stream keyIn, Stream outputStream, char[] pass, bool armor, bool compress) { if (armor) { outputStream = new ArmoredOutputStream(outputStream); } PgpSecretKey pgpSec = PgpExampleUtilities.ReadSecretKey(keyIn); PgpPrivateKey pgpPrivKey = pgpSec.ExtractPrivateKey(pass); PgpSignatureGenerator sGen = new PgpSignatureGenerator(pgpSec.PublicKey.Algorithm, HashAlgorithmTag.Sha1); sGen.InitSign(PgpSignature.BinaryDocument, pgpPrivKey); foreach (string userId in pgpSec.PublicKey.GetUserIds()) { PgpSignatureSubpacketGenerator spGen = new PgpSignatureSubpacketGenerator(); spGen.SetSignerUserId(false, userId); sGen.SetHashedSubpackets(spGen.Generate()); // Just the first one! break; } Stream cOut = outputStream; PgpCompressedDataGenerator cGen = null; if (compress) { cGen = new PgpCompressedDataGenerator(CompressionAlgorithmTag.ZLib); cOut = cGen.Open(cOut); } BcpgOutputStream bOut = new BcpgOutputStream(cOut); sGen.GenerateOnePassVersion(false).Encode(bOut); FileInfo file = new FileInfo(fileName); PgpLiteralDataGenerator lGen = new PgpLiteralDataGenerator(); Stream lOut = lGen.Open(bOut, PgpLiteralData.Binary, file); FileStream fIn = file.OpenRead(); int ch = 0; while ((ch = fIn.ReadByte()) >= 0) { lOut.WriteByte((byte) ch); sGen.Update((byte)ch); } fIn.Close(); lGen.Close(); sGen.Generate().Encode(bOut); if (cGen != null) { cGen.Close(); } if (armor) { outputStream.Close(); } }
public static void SignAndEncryptFile(string actualFileName, string embeddedFileName, Stream privateKeyStream, string passPhrase, Stream publicKeyStream, bool armor, bool withIntegrityCheck, Stream outputStream) { const int BUFFER_SIZE = 1 << 16; // should always be power of 2 if (armor) outputStream = new ArmoredOutputStream(outputStream); PgpPublicKey pubKey = ReadPublicKey(publicKeyStream); // Init encrypted data generator PgpEncryptedDataGenerator encryptedDataGenerator = new PgpEncryptedDataGenerator(SymmetricKeyAlgorithmTag.Cast5, withIntegrityCheck, new SecureRandom()); encryptedDataGenerator.AddMethod(pubKey); Stream encryptedOut = encryptedDataGenerator.Open(outputStream, new byte[BUFFER_SIZE]); // Init compression PgpCompressedDataGenerator compressedDataGenerator = new PgpCompressedDataGenerator(CompressionAlgorithmTag.Zip); Stream compressedOut = compressedDataGenerator.Open(encryptedOut); // Init signature PgpSecretKeyRingBundle pgpSecBundle = new PgpSecretKeyRingBundle(PgpUtilities.GetDecoderStream(privateKeyStream)); var pgpSecKey = ReadSecretKey(pgpSecBundle); if (pgpSecKey == null) throw new ArgumentException(pubKey.KeyId.ToString("X") + " could not be found in specified key ring bundle.", "keyId"); PgpPrivateKey pgpPrivKey = pgpSecKey.ExtractPrivateKey(passPhrase.ToCharArray()); PgpSignatureGenerator signatureGenerator = new PgpSignatureGenerator(pgpSecKey.PublicKey.Algorithm, HashAlgorithmTag.Sha1); signatureGenerator.InitSign(PgpSignature.BinaryDocument, pgpPrivKey); var userIds = pgpSecKey.PublicKey.GetUserIds(); string userId = null; foreach (string value in userIds) { // Just the first one! userId = value; break; } if (string.IsNullOrEmpty(userId)) { throw new ArgumentException(string.Format("Can't find userId in signing key. KeyId '{0}'.", pubKey.KeyId.ToString("X"))); } PgpSignatureSubpacketGenerator spGen = new PgpSignatureSubpacketGenerator(); spGen.SetSignerUserId(false, userId); signatureGenerator.SetHashedSubpackets(spGen.Generate()); signatureGenerator.GenerateOnePassVersion(false).Encode(compressedOut); // Create the Literal Data generator output stream PgpLiteralDataGenerator literalDataGenerator = new PgpLiteralDataGenerator(); // NOTE: Commented this out because it uses FileInfo to get stats on files and won't work properly FileInfo embeddedFile = new FileInfo(embeddedFileName); FileInfo actualFile = new FileInfo(actualFileName); if (!actualFile.Exists) { throw new FileNotFoundException(actualFile.FullName); } // TODO: Use lastwritetime from source file Stream literalOut = literalDataGenerator.Open(compressedOut, PgpLiteralData.Binary, embeddedFile.Name, actualFile.LastWriteTime, new byte[BUFFER_SIZE]); // Open the input file FileStream inputStream = actualFile.OpenRead(); byte[] buf = new byte[BUFFER_SIZE]; int len; while ((len = inputStream.Read(buf, 0, buf.Length)) > 0) { literalOut.Write(buf, 0, len); signatureGenerator.Update(buf, 0, len); } literalOut.Close(); literalDataGenerator.Close(); signatureGenerator.Generate().Encode(compressedOut); compressedOut.Close(); compressedDataGenerator.Close(); encryptedOut.Close(); encryptedDataGenerator.Close(); inputStream.Close(); if (armor) outputStream.Close(); }
//public static string GetPrivateKeyXml(string inputData) //{ // Stream inputStream = StreamHelper.GetStream(inputData); // PgpObjectFactory pgpFactory = new PgpObjectFactory(PgpUtilities.GetDecoderStream(inputStream)); // PgpObject pgp = null; // if (pgpFactory != null) // { // pgp = pgpFactory.NextPgpObject(); // } // PgpEncryptedDataList encryptedData = null; // if (pgp is PgpEncryptedDataList) // { // encryptedData = (PgpEncryptedDataList)pgp; // } // else // { // encryptedData = (PgpEncryptedDataList)pgpFactory.NextPgpObject(); // } // Stream privateKeyStream = File.OpenRead(PrivateKeyOnlyPath); // // find secret key // PgpSecretKeyRingBundle pgpKeyRing = new PgpSecretKeyRingBundle(PgpUtilities.GetDecoderStream(privateKeyStream)); // PgpPrivateKey privateKey = null; // foreach (PgpPublicKeyEncryptedData pked in encryptedData.GetEncryptedDataObjects()) // { // privateKey = FindSecretKey(pgpKeyRing, pked.KeyId, Password.ToCharArray()); // if (privateKey != null) // { // //pubKeyData = pked; // break; // } // } // // get xml: // RsaPrivateCrtKeyParameters rpckp = ((RsaPrivateCrtKeyParameters)privateKey.Key); // RSAParameters dotNetParams = DotNetUtilities.ToRSAParameters(rpckp); // RSA rsa = RSA.Create(); // rsa.ImportParameters(dotNetParams); // string xmlPrivate = rsa.ToXmlString(true); // return xmlPrivate; //} #endregion #region helpers /// <summary> /// /// </summary> /// <param name="clearData"></param> /// <param name="fileName">File name reference for compression to include (not fully qualified).</param> /// <param name="algorithm"></param> /// <returns></returns> private static byte[] Compress(byte[] clearData, string fileName, CompressionAlgorithmTag algorithm) { MemoryStream bOut = new MemoryStream(); PgpCompressedDataGenerator comData = new PgpCompressedDataGenerator(algorithm); Stream cos = comData.Open(bOut); // open it with the final destination PgpLiteralDataGenerator lData = new PgpLiteralDataGenerator(); // we want to Generate compressed data. This might be a user option later, // in which case we would pass in bOut. Stream pOut = lData.Open( cos, // the compressed output stream PgpLiteralData.Binary, fileName, // "filename" to store clearData.Length, // length of clear data DateTime.UtcNow // current time ); pOut.Write(clearData, 0, clearData.Length); pOut.Close(); comData.Close(); return bOut.ToArray(); }
//public static void EncryptPgpFile(string inputFile, string outputFile) //{ // // use armor: yes, use integrity check? yes? // EncryptPgpFile(inputFile, outputFile, PublicKeyPath, true, true); //} public static void EncryptPgpFile(string inputFile, string outputFile, string publicKeyFile, bool armor, bool withIntegrityCheck) { using (Stream publicKeyStream = File.OpenRead(publicKeyFile)) { PgpPublicKey pubKey = ReadPublicKey(publicKeyStream); using (MemoryStream outputBytes = new MemoryStream()) { PgpCompressedDataGenerator dataCompressor = new PgpCompressedDataGenerator(CompressionAlgorithmTag.Zip); PgpUtilities.WriteFileToLiteralData(dataCompressor.Open(outputBytes), PgpLiteralData.Binary, new FileInfo(inputFile)); dataCompressor.Close(); PgpEncryptedDataGenerator dataGenerator = new PgpEncryptedDataGenerator(SymmetricKeyAlgorithmTag.Cast5, withIntegrityCheck, new SecureRandom()); dataGenerator.AddMethod(pubKey); byte[] dataBytes = outputBytes.ToArray(); using (Stream outputStream = File.Create(outputFile)) { if (armor) { using (ArmoredOutputStream armoredStream = new ArmoredOutputStream(outputStream)) { IoHelper.WriteStream(dataGenerator.Open(armoredStream, dataBytes.Length), ref dataBytes); } } else { IoHelper.WriteStream(dataGenerator.Open(outputStream, dataBytes.Length), ref dataBytes); } } } } }