public string Decrypt(string passphrase, string encryptedText) { if (string.IsNullOrWhiteSpace(passphrase)) { throw new ArgumentNullException(); } using (var unencrypted = new MemoryStream()) using (var encrypted = new MemoryStream(Encoding.ASCII.GetBytes(encryptedText))) { _gpg.Passphrase = passphrase; _gpg.OutputType = OutputTypes.AsciiArmor; _gpg.Decrypt(encrypted, unencrypted); using (var reader = new StreamReader(unencrypted)) { unencrypted.Position = 0; return(reader.ReadToEnd()); } } }
internal void DecryptEmail(Outlook.MailItem mailItem) { string mail = mailItem.Body; Outlook.OlBodyFormat mailType = mailItem.BodyFormat; if (mailType != Outlook.OlBodyFormat.olFormatPlain) { MessageBox.Show( "OutlookGnuPG can only decrypt plain text mails.", "Invalid Mail Format", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } if (Regex.IsMatch(mailItem.Body, _pgpEncryptedHeader) == false) { MessageBox.Show( "OutlookGnuPG cannot help here.", "Mail is not encrypted", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); return; } // Still no gpg.exe path... Annoy the user once again, maybe he'll get it ;) if (string.IsNullOrEmpty(_settings.GnuPgPath)) Settings(); // Stubborn, give up if (string.IsNullOrEmpty(_settings.GnuPgPath)) { MessageBox.Show( "OutlookGnuPG can only decrypt when you provide a valid gpg.exe path. Please open Settings and configure it.", "Invalid GnuPG Executable", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } string passphrase = string.Empty; string privateKey = string.Empty; // Popup UI to select the passphrase and private key. Passphrase passphraseDialog = new Passphrase(_settings.DefaultKey, "Decrypt"); DialogResult passphraseResult = passphraseDialog.ShowDialog(); if (passphraseResult != DialogResult.OK) { // The user closed the passphrase dialog, prevent sending the mail return; } passphrase = passphraseDialog.EnteredPassphrase; privateKey = passphraseDialog.SelectedKey; passphraseDialog.Close(); if (string.IsNullOrEmpty(privateKey)) { MessageBox.Show( "OutlookGnuPG needs a private key for decrypting. No keys were detected.", "Invalid Private Key", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } // Decrypt without fd-status (might already blow up, early out) // Decrypt with fd-status and cut out the stdout of normal decrypt (prevents BAD/GOODMC messages in message confusing us) string stdOutResult = string.Empty; using (MemoryStream inputStream = new MemoryStream(mail.Length)) using (MemoryStream outputStream = new MemoryStream()) { using (StreamWriter writer = new StreamWriter(inputStream)) { writer.Write(mail); writer.Flush(); inputStream.Position = 0; try { _gnuPg.OutputStatus = false; _gnuPg.Passphrase = passphrase; _gnuPg.Decrypt(inputStream, outputStream, new MemoryStream()); } catch (Exception ex) { string error = ex.Message; // We deal with bad signature later if (!error.ToLowerInvariant().Contains("bad signature")) { MessageBox.Show( error, "GnuPG Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } } } using (StreamReader reader = new StreamReader(outputStream)) { outputStream.Position = 0; stdOutResult = reader.ReadToEnd(); } } string verifyResult = string.Empty; string errorResult = string.Empty; using (MemoryStream inputStream = new MemoryStream(mail.Length)) using (MemoryStream outputStream = new MemoryStream()) using (MemoryStream errorStream = new MemoryStream()) { using (StreamWriter writer = new StreamWriter(inputStream)) { writer.Write(mail); writer.Flush(); inputStream.Position = 0; try { _gnuPg.OutputStatus = true; _gnuPg.Passphrase = passphrase; _gnuPg.Decrypt(inputStream, outputStream, errorStream); } catch (Exception ex) { string error = ex.Message; // We deal with bad signature later if (!error.ToLowerInvariant().Contains("bad signature")) { MessageBox.Show( error, "GnuPG Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } } } using (StreamReader reader = new StreamReader(outputStream)) { outputStream.Position = 0; verifyResult = reader.ReadToEnd(); } using (StreamReader reader = new StreamReader(errorStream)) { errorStream.Position = 0; errorResult = reader.ReadToEnd(); } } verifyResult = verifyResult.Replace(stdOutResult, string.Empty); // Verify: status-fd // stdOut: the message // error: gpg error/status if (verifyResult.Contains("BADMDC")) { errorResult = RemoveInvalidAka(errorResult.Replace("gpg: ", string.Empty)); MessageBox.Show( errorResult, "Invalid Encryption", MessageBoxButtons.OK, MessageBoxIcon.Error); } else if (verifyResult.Contains("GOODMDC")) { // Decrypted OK, check for validsig if (verifyResult.Contains("BADSIG")) { errorResult = RemoveInvalidAka(errorResult.Replace("gpg: ", string.Empty)); MessageBox.Show( errorResult, "Invalid Signature", MessageBoxButtons.OK, MessageBoxIcon.Error); } else if (verifyResult.Contains("GOODSIG")) { errorResult = RemoveInvalidAka(errorResult.Replace("gpg: ", string.Empty)); MessageBox.Show( errorResult, "Valid Signature", MessageBoxButtons.OK, MessageBoxIcon.Information); // Valid signature! mailItem.Body = stdOutResult; } else { // No signature? mailItem.Body = stdOutResult; } } else { errorResult = RemoveInvalidAka(errorResult.Replace("gpg: ", string.Empty)); errorResult = errorResult.Replace("WARNING", Environment.NewLine + "WARNING"); DialogResult res = MessageBox.Show( errorResult + Environment.NewLine + "Decrypt mail anyway?", "Unknown Encryption", MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation); if (res == DialogResult.OK) mailItem.Body = stdOutResult; } }