예제 #1
0
        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());
                    }
                }
        }
예제 #2
0
    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;
      }
    }