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