/// <summary> /// Attempt to decrypt a PGP protected message using the matching private key. /// </summary> /// <param name="decryptedMessage">If successful, the decrypted message.</param> /// <returns>Whether the decryption completed successfully.</returns> public bool PgpDecrypt(PgpPrivateKey recipientPrivateKey, out byte[] decryptedMessage) { string encryptedBody = ""; // Process each MIME part. if (MimeParts != null) { for (int i = 0; i < MimeParts.Count; i++) { MimePart mimePart = MimeParts[i]; // Check if the MIME part is encrypted or signed using PGP. if (mimePart.Body.StartsWith("-----BEGIN PGP MESSAGE-----")) { encryptedBody = Functions.ReturnBetween(mimePart.Body, "-----BEGIN PGP MESSAGE-----\r\n", "\r\n-----END PGP MESSAGE-----"); break; } } } else { if (Body.StartsWith("-----BEGIN PGP MESSAGE-----")) { encryptedBody = Functions.ReturnBetween(Body, "-----BEGIN PGP MESSAGE-----\r\n", "\r\n-----END PGP MESSAGE-----"); } } // Process an encrypted body if found. if (!string.IsNullOrEmpty(encryptedBody)) { // Ignore the PGP headers. int doubleLineBreak = encryptedBody.IndexOf("\r\n\r\n"); if (doubleLineBreak > -1) { encryptedBody = encryptedBody.Substring(doubleLineBreak + 4); } // Attempt to decrypt the message and set the body if successful. if (Pgp.Decrypt(Encoding.UTF8.GetBytes(encryptedBody), out decryptedMessage, recipientPrivateKey)) { // Ensure a valid encoding. if (BodyEncoding == null) { BodyEncoding = Encoding.UTF8; } // Convert the byte array back to a string. Body = BodyEncoding.GetString(decryptedMessage); // If the body was successfully decrypted, attempt to decrypt attachments. foreach (Attachment attachment in Attachments) { // Only process attachments with names ending in ".pgp". if (attachment.Name.ToLower().EndsWith(".pgp")) { if (Pgp.Decrypt(attachment.ContentStream, out decryptedMessage, recipientPrivateKey)) { attachment.ContentStream = new MemoryStream(decryptedMessage); attachment.Name = attachment.Name.Substring(0, attachment.Name.Length - 4); } } } return(true); } else { return(false); } } else { decryptedMessage = null; return(false); } }
/// <summary> /// Attempt to verify a PGP signed message using the matching public key. /// </summary> /// <param name="senderPublicKey">BouncyCastle public key to be used for verification.</param> /// <returns>Whether the message's signature is verified.</returns> public bool PgpVerifySignature(PgpPublicKey senderPublicKey) { string pgpSignedMessage = ""; string pgpSignature = ""; // Process each MIME part. if (MimeParts != null) { int pgpSignedMessageIndex = -1; int pgpSignatureIndex = -1; for (int i = 0; i < MimeParts.Count; i++) { MimePart mimePart = MimeParts[i]; // Check if the MIME part is encrypted or signed using PGP. if (mimePart.Body.StartsWith("-----BEGIN PGP SIGNED MESSAGE-----")) { pgpSignedMessageIndex = i; } else if (mimePart.Body.StartsWith("-----BEGIN PGP SIGNATURE-----")) { pgpSignatureIndex = i; } } // Verify PGP signatures. if (pgpSignedMessageIndex > -1 && pgpSignatureIndex > -1) { pgpSignedMessage = MimeParts[pgpSignedMessageIndex].Body; pgpSignature = MimeParts[pgpSignatureIndex].Body; } } // If the signature isn't embedded as its own MIME part, extract from the body. if (string.IsNullOrEmpty(pgpSignedMessage) && string.IsNullOrEmpty(pgpSignature)) { pgpSignedMessage = Functions.ReturnBetween(Body, "-----BEGIN PGP SIGNED MESSAGE-----\r\n", "\r\n-----BEGIN PGP SIGNATURE-----"); pgpSignature = Functions.ReturnBetween(Body, "-----BEGIN PGP SIGNATURE-----\r\n", "\r\n-----END PGP SIGNATURE-----"); } // If a signature is embedded, attempt to verify. if (!string.IsNullOrEmpty(pgpSignedMessage) && !string.IsNullOrEmpty(pgpSignature)) { // Skip over PGP headers. int doubleLineBreak = pgpSignedMessage.IndexOf("\r\n\r\n"); if (doubleLineBreak > -1) { pgpSignedMessage = pgpSignedMessage.Substring(doubleLineBreak + 4); } doubleLineBreak = pgpSignature.IndexOf("\r\n\r\n"); if (doubleLineBreak > -1) { pgpSignature = pgpSignature.Substring(doubleLineBreak + 4); } // Verify the message with its signature. if (!string.IsNullOrEmpty(pgpSignedMessage) && !string.IsNullOrEmpty(pgpSignature)) { bool pgpSignatureVerified = Pgp.VerifySignature(Encoding.UTF8.GetBytes(pgpSignedMessage), Encoding.UTF8.GetBytes(Functions.FromBase64(pgpSignature)), senderPublicKey); if (pgpSignatureVerified) { Body = pgpSignedMessage; } return(pgpSignatureVerified); } } return(false); }