/// <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 + "\"."); PgpSecretKey senderMasterSignkey; var senderSignKey = GetSecretKeyForSigning(key, out senderMasterSignkey); 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(GetSymAlgTagFromString(Context.Cipher), 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, GetHashAlgTagFromString(Context.Digest)); signatureData.InitSign( isBinary ? PgpSignature.BinaryDocument : PgpSignature.CanonicalTextDocument, senderSignKey.ExtractPrivateKey(Context.PasswordCallback(senderMasterSignkey, senderSignKey))); 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 Sign(byte[] data, string key, Dictionary<string, string> headers) { logger.Trace("Sign({0}, {1})", data.Length, key); 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 + "\"."); var compressedData = new PgpCompressedDataGenerator(CompressionAlgorithmTag.Zip); var literalData = new PgpLiteralDataGenerator(); // Setup signature stuff // var tag = senderKey.PublicKey.Algorithm; var signatureData = new PgpSignatureGenerator(tag, GetHashAlgTagFromString(Context.Digest)); signatureData.InitSign(PgpSignature.BinaryDocument, 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; } // // 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> /// 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()); } }
/// <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); 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; } // // 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(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()); } }