/// <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; }
/// <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); } }
private string signEnvelopeData(string msg) { Stream privateKeyStream = getPrivateKeyStream(_privateKey); MemoryStream result = new MemoryStream(); ArmoredOutputStream aOut = new ArmoredOutputStream(result); BcpgOutputStream bOut = null; char[] privateKeyPassword = _passPhrase.ToCharArray(); var utf8Encoding = new System.Text.UTF8Encoding(); try { PgpSecretKey sk = readSecretKey(privateKeyStream); PgpPrivateKey pk = sk.ExtractPrivateKey(privateKeyPassword); PgpSignatureGenerator sigGen = new PgpSignatureGenerator(sk.PublicKey.Algorithm,HashAlgorithmTag.Sha256); PgpSignatureSubpacketGenerator spGen = new PgpSignatureSubpacketGenerator(); var enumerator = sk.PublicKey.GetUserIds().GetEnumerator(); if(enumerator.MoveNext()) { spGen.SetSignerUserId(false, (string)enumerator.Current); sigGen.SetHashedSubpackets(spGen.Generate()); } aOut.BeginClearText(HashAlgorithmTag.Sha256); sigGen.InitSign(PgpSignature.CanonicalTextDocument, pk); byte[] msgBytes = utf8Encoding.GetBytes(msg); sigGen.Update(msgBytes, 0, msgBytes.Length); aOut.Write(msgBytes, 0, msgBytes.Length); bOut = new BcpgOutputStream(aOut); aOut.EndClearText(); sigGen.Generate().Encode(bOut); using (BinaryReader br = new BinaryReader(result)) { br.BaseStream.Position = 0; return utf8Encoding.GetString(br.ReadBytes((int)result.Length)); } } catch (Exception e) { Console.WriteLine("This happened: " + e.Message); throw new Exception("Signing Failed: " + e.Message); } finally { try { if (privateKeyStream != null) privateKeyStream.Close(); //if(bOut != null) //bOut.Close(); //aOut.Close(); result.Close(); } catch (IOException) {} } }
/// <summary> /// Add a signing subkey with specific hashed and unhashed packets associated with it and /// default certifications, including the primary-key binding signature. /// </summary> /// <param name="keyPair">Public/private key pair.</param> /// <param name="hashedPackets">Hashed packet values to be included in certification.</param> /// <param name="unhashedPackets">Unhashed packets values to be included in certification.</param> /// <param name="hashAlgorithm">The hash algorithm.</param> /// <param name="primaryKeyBindingHashAlgorithm">The primary-key binding hash algorithm.</param> /// <exception cref="Org.BouncyCastle.Bcpg.OpenPgp.PgpException">exception adding subkey: </exception> /// <exception cref="PgpException"></exception> public void AddSubKey( PgpKeyPair keyPair, PgpSignatureSubpacketVector hashedPackets, PgpSignatureSubpacketVector unhashedPackets, HashAlgorithmTag hashAlgorithm, HashAlgorithmTag primaryKeyBindingHashAlgorithm) { try { PgpSignatureGenerator sGen = new PgpSignatureGenerator(masterKey.PublicKey.Algorithm, hashAlgorithm); // // Generate the certification // sGen.InitSign(PgpSignature.SubkeyBinding, masterKey.PrivateKey); // add primary key binding sub packet PgpSignatureGenerator pGen = new PgpSignatureGenerator(keyPair.PublicKey.Algorithm, primaryKeyBindingHashAlgorithm); pGen.InitSign(PgpSignature.PrimaryKeyBinding, keyPair.PrivateKey); PgpSignatureSubpacketGenerator spGen = new PgpSignatureSubpacketGenerator(hashedPackets); spGen.SetEmbeddedSignature(false, pGen.GenerateCertification(masterKey.PublicKey, keyPair.PublicKey)); sGen.SetHashedSubpackets(spGen.Generate()); sGen.SetUnhashedSubpackets(unhashedPackets); IList subSigs = Platform.CreateArrayList(); subSigs.Add(sGen.GenerateCertification(masterKey.PublicKey, keyPair.PublicKey)); keys.Add(new PgpSecretKey(keyPair.PrivateKey, new PgpPublicKey(keyPair.PublicKey, null, subSigs), encAlgorithm, rawPassPhrase, false, useSha1, rand, false)); } catch (PgpException) { throw; } catch (Exception e) { throw new PgpException("exception adding subkey: ", e); } }
public static void SignFile(Stream input, Stream outputStream, Stream keyIn, char[] pass) { var secretKey = ReadSecretKey(keyIn); var privateKey = secretKey.ExtractPrivateKey(pass); var signatureGenerator = new PgpSignatureGenerator(secretKey.PublicKey.Algorithm, HashAlgorithmTag.Sha1); var subpacketGenerator = new PgpSignatureSubpacketGenerator(); signatureGenerator.InitSign(PgpSignature.CanonicalTextDocument, privateKey); foreach (string userId in secretKey.PublicKey.GetUserIds()) { var signatureSubpacketGenerator = new PgpSignatureSubpacketGenerator(); signatureSubpacketGenerator.SetSignerUserId(isCritical: false, userId: userId); signatureGenerator.SetHashedSubpackets(signatureSubpacketGenerator.Generate()); // Just the first one! break; } // Closing armouredOutputStream does not close the underlying stream var armouredOutputStream = new ArmoredOutputStream(outputStream); using (var bcpgOutputStream = new BcpgOutputStream(armouredOutputStream)) { armouredOutputStream.BeginClearText(HashAlgorithmTag.Sha1); int chr; while ((chr = input.ReadByte()) > 0) { signatureGenerator.Update((byte)chr); bcpgOutputStream.Write((byte)chr); } // For some reason we need to add a trailing newline bcpgOutputStream.Write((byte)'\n'); armouredOutputStream.EndClearText(); signatureGenerator.Generate().Encode(bcpgOutputStream); } }
//src: http://stackoverflow.com/questions/17953852/generating-pgp-key-ring-using-bouncy-castle-c-results-in-key-id-ffffffff public static PgpKeyRingGenerator generateKeyRingGenerator(String identity, String password) { KeyRingParams keyRingParams = new KeyRingParams(); keyRingParams.Password = password; keyRingParams.Identity = identity; keyRingParams.PrivateKeyEncryptionAlgorithm = SymmetricKeyAlgorithmTag.Aes128; keyRingParams.SymmetricAlgorithms = new SymmetricKeyAlgorithmTag[] { SymmetricKeyAlgorithmTag.Aes256/*, SymmetricKeyAlgorithmTag.Aes192, SymmetricKeyAlgorithmTag.Aes128*/ //TODO: delete ? }; keyRingParams.HashAlgorithms = new HashAlgorithmTag[] { HashAlgorithmTag.Sha256, //TODO: delete ? + check Parameters //HashAlgorithmTag.Sha1, //HashAlgorithmTag.Sha384, HashAlgorithmTag.Sha512, //HashAlgorithmTag.Sha224, }; IAsymmetricCipherKeyPairGenerator generator = GeneratorUtilities.GetKeyPairGenerator("RSA"); generator.Init(keyRingParams.RsaParams); /* Create the master (signing-only) key. */ PgpKeyPair masterKeyPair = new PgpKeyPair( PublicKeyAlgorithmTag.RsaSign, generator.GenerateKeyPair(), DateTime.UtcNow ); PgpSignatureSubpacketGenerator masterSubpckGen = new PgpSignatureSubpacketGenerator(); masterSubpckGen.SetKeyFlags(false, PgpKeyFlags.CanSign | PgpKeyFlags.CanCertify); //create var for preferred symmetric algorithms int [] iPreferedSymmetricAlgorithms = new int[keyRingParams.SymmetricAlgorithms.Length]; for (int i = 0; i < keyRingParams.SymmetricAlgorithms.Length; i++) { iPreferedSymmetricAlgorithms[i] = (int) keyRingParams.SymmetricAlgorithms[i]; } masterSubpckGen.SetPreferredSymmetricAlgorithms (false, iPreferedSymmetricAlgorithms); //create var for preferred hash algorithms int [] iPreferedHashAlgorithms = new int[keyRingParams.HashAlgorithms.Length]; for (int i = 0; i < keyRingParams.HashAlgorithms.Length; i++) { iPreferedHashAlgorithms[i] = (int) keyRingParams.HashAlgorithms[i]; } masterSubpckGen.SetPreferredHashAlgorithms (false, iPreferedHashAlgorithms); /* Create a signing and encryption key for daily use. */ PgpKeyPair encKeyPair = new PgpKeyPair( PublicKeyAlgorithmTag.RsaGeneral, generator.GenerateKeyPair(), DateTime.UtcNow); PgpSignatureSubpacketGenerator encSubpckGen = new PgpSignatureSubpacketGenerator(); encSubpckGen.SetKeyFlags(false, PgpKeyFlags.CanEncryptCommunications | PgpKeyFlags.CanEncryptStorage); masterSubpckGen.SetPreferredSymmetricAlgorithms(false, iPreferedSymmetricAlgorithms); masterSubpckGen.SetPreferredHashAlgorithms (false, iPreferedHashAlgorithms); /* Create the key ring. */ PgpKeyRingGenerator keyRingGen = new PgpKeyRingGenerator( PgpSignature.DefaultCertification, masterKeyPair, keyRingParams.Identity, keyRingParams.PrivateKeyEncryptionAlgorithm.Value, keyRingParams.GetPassword(), true, masterSubpckGen.Generate(), null, new SecureRandom()); /* Add encryption subkey. */ keyRingGen.AddSubKey(encKeyPair, encSubpckGen.Generate(), null); return keyRingGen; }
/// <summary> /// Build a PGP key pair /// </summary> /// <param name="bits">number of bits in key, e.g. 2048</param> /// <param name="identifier">key identifier, e.g. "Your Name <*****@*****.**>" </param> /// <param name="password">key password or null</param> /// <param name="privateKey">returned ascii private key</param> /// <param name="publicKey">returned ascii public key</param> public static void PGPGenerateKey(int bits, string identifier, string password, out string privateKey, out string publicKey) { // generate a new RSA keypair RsaKeyPairGenerator gen = new RsaKeyPairGenerator(); gen.Init(new RsaKeyGenerationParameters(BigInteger.ValueOf(0x101), new Org.BouncyCastle.Security.SecureRandom(), bits, 80)); AsymmetricCipherKeyPair pair = gen.GenerateKeyPair(); // create PGP subpacket PgpSignatureSubpacketGenerator hashedGen = new PgpSignatureSubpacketGenerator(); hashedGen.SetKeyFlags(true, PgpKeyFlags.CanCertify | PgpKeyFlags.CanSign | PgpKeyFlags.CanEncryptCommunications | PgpKeyFlags.CanEncryptStorage); hashedGen.SetPreferredCompressionAlgorithms(false, new int[] { (int)CompressionAlgorithmTag.Zip }); hashedGen.SetPreferredHashAlgorithms(false, new int[] { (int)HashAlgorithmTag.Sha1 }); hashedGen.SetPreferredSymmetricAlgorithms(false, new int[] { (int)SymmetricKeyAlgorithmTag.Cast5 }); PgpSignatureSubpacketVector sv = hashedGen.Generate(); PgpSignatureSubpacketGenerator unhashedGen = new PgpSignatureSubpacketGenerator(); // create the PGP key PgpSecretKey secretKey = new PgpSecretKey( PgpSignature.DefaultCertification, PublicKeyAlgorithmTag.RsaGeneral, pair.Public, pair.Private, DateTime.Now, identifier, SymmetricKeyAlgorithmTag.Cast5, (password != null ? password.ToCharArray() : null), hashedGen.Generate(), unhashedGen.Generate(), new Org.BouncyCastle.Security.SecureRandom()); // extract the keys using (MemoryStream ms = new MemoryStream()) { using (ArmoredOutputStream ars = new ArmoredOutputStream(ms)) { secretKey.Encode(ars); } privateKey = Encoding.ASCII.GetString(ms.ToArray()); } using (MemoryStream ms = new MemoryStream()) { using (ArmoredOutputStream ars = new ArmoredOutputStream(ms)) { secretKey.PublicKey.Encode(ars); } publicKey = Encoding.ASCII.GetString(ms.ToArray()); } }
/// <summary> /// Attempt to sign a PGP message using the specific private key. /// </summary> /// <param name="messageStream">Stream containing the message to sign.</param> /// <param name="signatureStream">Stream to write the signature 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="hashAlgorithmTag">The hash algorithm tag to use for signing.</param> /// <param name="armor">Whether to wrap the message with ASCII armor.</param> /// <returns>Whether the signature completed successfully.</returns> public static bool Sign(Stream messageStream, Stream signatureStream, PgpPublicKey senderPublicKey, PgpPrivateKey senderPrivateKey, HashAlgorithmTag hashAlgorithmTag = HashAlgorithmTag.Sha256, 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; } // Handle ASCII armor. if (armor) { using (ArmoredOutputStream armoredStream = new ArmoredOutputStream(signatureStream)) { armoredStream.BeginClearText(hashAlgorithmTag); // Process each character in the message. int messageChar; while ((messageChar = messageStream.ReadByte()) >= 0) { armoredStream.WriteByte((byte)messageChar); signatureGenerator.Update((byte)messageChar); } armoredStream.EndClearText(); using (BcpgOutputStream bcpgStream = new BcpgOutputStream(armoredStream)) { signatureGenerator.Generate().Encode(bcpgStream); } } } else { // Process each character in the message. int messageChar; while ((messageChar = messageStream.ReadByte()) >= 0) { signatureGenerator.Update((byte)messageChar); } signatureGenerator.Generate().Encode(signatureStream); } return true; }
/// <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 static void setSignatureSubpackets(PgpSecretKey pgpSec, PgpSignatureGenerator signatureGenerator) { IEnumerable it = pgpSec.PublicKey.GetUserIds(); var e = it.GetEnumerator(); if (e.MoveNext()) { PgpSignatureSubpacketGenerator spGen = new PgpSignatureSubpacketGenerator(); spGen.SetSignerUserId(false, (String)e.Current); signatureGenerator.SetHashedSubpackets(spGen.Generate()); } }
public static PgpKeyRingGenerator CreateKeyRingGenerator(string identity, string password) { var dateTimeNowUtc = DateTime.UtcNow; KeyRingParams keyRingParams = new KeyRingParams(); keyRingParams.Password = password; keyRingParams.Identity = identity; keyRingParams.PrivateKeyEncryptionAlgorithm = SymmetricKeyAlgorithmTag.Aes256; keyRingParams.SymmetricAlgorithms = new SymmetricKeyAlgorithmTag[] { SymmetricKeyAlgorithmTag.Aes256, SymmetricKeyAlgorithmTag.Aes192, SymmetricKeyAlgorithmTag.Aes128 }; keyRingParams.HashAlgorithms = new HashAlgorithmTag[] { HashAlgorithmTag.Sha256, HashAlgorithmTag.Sha1, HashAlgorithmTag.Sha384, HashAlgorithmTag.Sha512, HashAlgorithmTag.Sha224, }; IAsymmetricCipherKeyPairGenerator generator = GeneratorUtilities.GetKeyPairGenerator("RSA"); generator.Init(keyRingParams.RsaParams); /* Create the master (signing-only) key. */ PgpKeyPair masterKeyPair = new PgpKeyPair( PublicKeyAlgorithmTag.RsaSign, generator.GenerateKeyPair(), dateTimeNowUtc); Debug.WriteLine("Generated master key with ID " + masterKeyPair.KeyId.ToString("X")); PgpSignatureSubpacketGenerator masterSubpckGen = new PgpSignatureSubpacketGenerator(); var secondsUntilExpires = (long)(dateTimeNowUtc.AddDays(2) - dateTimeNowUtc).TotalSeconds; masterSubpckGen.SetKeyExpirationTime(false, secondsUntilExpires); masterSubpckGen.SetKeyFlags(false, PgpKeyFlags.CanSign | PgpKeyFlags.CanCertify | PgpKeyFlags.CanEncryptCommunications | PgpKeyFlags.CanEncryptStorage); masterSubpckGen.SetPreferredSymmetricAlgorithms(false, (from a in keyRingParams.SymmetricAlgorithms select (int)a).ToArray()); masterSubpckGen.SetPreferredHashAlgorithms(false, (from a in keyRingParams.HashAlgorithms select (int)a).ToArray()); /* Create a signing and encryption key for daily use. */ PgpKeyPair encKeyPair = new PgpKeyPair( PublicKeyAlgorithmTag.RsaGeneral, generator.GenerateKeyPair(), dateTimeNowUtc); Debug.WriteLine("Generated encryption key with ID " + encKeyPair.KeyId.ToString("X")); PgpSignatureSubpacketGenerator encSubpckGen = new PgpSignatureSubpacketGenerator(); encSubpckGen.SetKeyFlags(false, PgpKeyFlags.CanEncryptCommunications | PgpKeyFlags.CanEncryptStorage); encSubpckGen.SetKeyExpirationTime(false, secondsUntilExpires); masterSubpckGen.SetPreferredSymmetricAlgorithms(false, (from a in keyRingParams.SymmetricAlgorithms select (int)a).ToArray()); masterSubpckGen.SetPreferredHashAlgorithms(false, (from a in keyRingParams.HashAlgorithms select (int)a).ToArray()); /* Create the key ring. */ PgpKeyRingGenerator keyRingGen = new PgpKeyRingGenerator( PgpSignature.DefaultCertification, masterKeyPair, keyRingParams.Identity, keyRingParams.PrivateKeyEncryptionAlgorithm.Value, keyRingParams.GetPassword(), true, masterSubpckGen.Generate(), null, new SecureRandom()); /* Add encryption subkey. */ keyRingGen.AddSubKey(encKeyPair, encSubpckGen.Generate(), null); return keyRingGen; }
/// <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()); } }
/// <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 SignClear(string data, string key, Encoding encoding, 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 + "\"."); // Setup signature stuff // var signatureData = new PgpSignatureGenerator(senderKey.PublicKey.Algorithm, HashAlgorithmTag.Sha1); signatureData.InitSign(PgpSignature.CanonicalTextDocument, 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); armoredOut.BeginClearText(HashAlgorithmTag.Sha1); // Remove any extra trailing whitespace. // this should not include \r or \n. data = data.TrimEnd(null); using (var stringReader = new StringReader(data)) { do { var line = stringReader.ReadLine(); if (line == null) break; // Lines must have all white space removed line = line.TrimEnd(null); line = line.TrimEnd(new char[] {' ', '\t', '\r', '\n'}); line += "\r\n"; signatureData.Update(encoding.GetBytes(line)); armoredOut.Write(encoding.GetBytes(line)); } while (true); } // Write extra line before signature block. armoredOut.Write(encoding.GetBytes("\r\n")); armoredOut.EndClearText(); using (var outputStream = new BcpgOutputStream(armoredOut)) { signatureData.Generate().Encode(outputStream); } } return encoding.GetString(sout.ToArray()); } }
/// <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()); } }
/** * 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(); } }
private PgpSignatureGenerator InitSignatureGenerator(Stream compressedOut) { const bool IsCritical = false; const bool IsNested = false; PublicKeyAlgorithmTag tag = m_encryptionKeys.SecretKey.PublicKey.Algorithm; PgpSignatureGenerator pgpSignatureGenerator = new PgpSignatureGenerator(tag, HashAlgorithmTag.Sha1); pgpSignatureGenerator.InitSign(PgpSignature.BinaryDocument, m_encryptionKeys.PrivateKey); foreach (string userId in m_encryptionKeys.SecretKey.PublicKey.GetUserIds()) { PgpSignatureSubpacketGenerator subPacketGenerator = new PgpSignatureSubpacketGenerator(); subPacketGenerator.SetSignerUserId(IsCritical, userId); pgpSignatureGenerator.SetHashedSubpackets(subPacketGenerator.Generate()); // Just the first one! break; } pgpSignatureGenerator.GenerateOnePassVersion(IsNested).Encode(compressedOut); return pgpSignatureGenerator; }
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(); }
/* * create a clear text signed file. */ private static void SignFile( string fileName, Stream keyIn, Stream outputStream, char[] pass, string digestName) { HashAlgorithmTag digest; if (digestName.Equals("SHA256")) { digest = HashAlgorithmTag.Sha256; } else if (digestName.Equals("SHA384")) { digest = HashAlgorithmTag.Sha384; } else if (digestName.Equals("SHA512")) { digest = HashAlgorithmTag.Sha512; } else if (digestName.Equals("MD5")) { digest = HashAlgorithmTag.MD5; } else if (digestName.Equals("RIPEMD160")) { digest = HashAlgorithmTag.RipeMD160; } else { digest = HashAlgorithmTag.Sha1; } PgpSecretKey pgpSecKey = PgpExampleUtilities.ReadSecretKey(keyIn); PgpPrivateKey pgpPrivKey = pgpSecKey.ExtractPrivateKey(pass); PgpSignatureGenerator sGen = new PgpSignatureGenerator(pgpSecKey.PublicKey.Algorithm, digest); PgpSignatureSubpacketGenerator spGen = new PgpSignatureSubpacketGenerator(); sGen.InitSign(PgpSignature.CanonicalTextDocument, pgpPrivKey); IEnumerator enumerator = pgpSecKey.PublicKey.GetUserIds().GetEnumerator(); if (enumerator.MoveNext()) { spGen.SetSignerUserId(false, (string) enumerator.Current); sGen.SetHashedSubpackets(spGen.Generate()); } Stream fIn = File.OpenRead(fileName); ArmoredOutputStream aOut = new ArmoredOutputStream(outputStream); aOut.BeginClearText(digest); // // note the last \n/\r/\r\n in the file is ignored // MemoryStream lineOut = new MemoryStream(); int lookAhead = ReadInputLine(lineOut, fIn); ProcessLine(aOut, sGen, lineOut.ToArray()); if (lookAhead != -1) { do { lookAhead = ReadInputLine(lineOut, lookAhead, fIn); sGen.Update((byte) '\r'); sGen.Update((byte) '\n'); ProcessLine(aOut, sGen, lineOut.ToArray()); } while (lookAhead != -1); } fIn.Close(); aOut.EndClearText(); BcpgOutputStream bOut = new BcpgOutputStream(aOut); sGen.Generate().Encode(bOut); aOut.Close(); }
/// <summary> /// Sign data using key /// </summary> /// <param name="data">Data to sign</param> /// <param name="key">Email address of key</param> /// <param name="headers">Headers to add to signed message</param> /// <param name="wrapLines">Automatically wrap lines that are too long</param> /// <param name="encoding">s</param> /// <returns>Returns ascii armored signature</returns> public string SignClear(string data, string key, Encoding encoding, Dictionary<string, string> headers, bool wrapLines = true) { Context = new CryptoContext(Context); PgpSecretKey senderMasterKey; var senderKey = GetSecretKeyForSigning(key, out senderMasterKey); if (senderKey == null) throw new SecretKeyNotFoundException("Error, unable to locate signing key \"" + key + "\"."); // Setup signature stuff // var signatureData = new PgpSignatureGenerator(senderKey.PublicKey.Algorithm, GetHashAlgTagFromString(Context.Digest)); signatureData.InitSign(PgpSignature.CanonicalTextDocument, senderKey.ExtractPrivateKey(Context.PasswordCallback(senderMasterKey, senderKey))); foreach (string userId in senderKey.PublicKey.GetUserIds()) { var subPacketGenerator = new PgpSignatureSubpacketGenerator(); subPacketGenerator.SetSignerUserId(false, userId); signatureData.SetHashedSubpackets(subPacketGenerator.Generate()); // Just the first one! break; } // Split any long lines if we are asked to do so. var mailLines = data.Split('\n'); if (wrapLines && mailLines.Any(line => line.Length > 70)) { var lines = new List<string>(mailLines); for (var i = 0; i < lines.Count; i++) { var line = lines[i]; if (line.Length <= 70) continue; var newLine = line.Substring(70); line = line.Substring(0, 70); lines[i] = line; lines.Insert(i + 1, newLine); } var sb = new StringBuilder(data.Length + 20); foreach (var line in lines) sb.AppendLine(line.TrimEnd('\r', '\n')); data = sb.ToString(); } // Now lets do our signing stuff using (var sout = new MemoryStream()) { using (var armoredOut = new ArmoredOutputStream(sout)) { foreach (var header in headers) armoredOut.SetHeader(header.Key, header.Value); armoredOut.BeginClearText(GetHashAlgTagFromString(Context.Digest)); // Remove any extra trailing whitespace. // this should not include \r or \n. data = data.TrimEnd(null); using (var stringReader = new StringReader(data)) { do { var line = stringReader.ReadLine(); if (line == null) break; // Lines must have all white space removed line = line.TrimEnd(null); line = line.TrimEnd(' ', '\t', '\r', '\n'); line += "\r\n"; signatureData.Update(encoding.GetBytes(line)); armoredOut.Write(encoding.GetBytes(line)); } while (true); } // Write extra line before signature block. armoredOut.Write(encoding.GetBytes("\r\n")); armoredOut.EndClearText(); using (var outputStream = new BcpgOutputStream(armoredOut)) signatureData.Generate().Encode(outputStream); } return encoding.GetString(sout.ToArray()); } }