2011-08-08 214 views
8

我見過很多帖子,其次是一些教程,但似乎沒有工作。有時候,他們引用了一些沒有找到的類。我可以指出一個地方,我可以得到一個簡單的教程,展示如何加密和解密文件。PgP加密和解密使用BouncyCastle c#

我對Pgp非常陌生,歡迎任何幫助。

回答

3

這個怎麼樣:

PartialInputStream during Bouncycastle PGP decryption

而且,拉鍊包含的例子在這裏:

http://www.bouncycastle.org/csharp/

希望這有助於。如果你仍然陷入困境,可以發佈一些關於編譯器抱怨什麼類的更多細節,社區將會看一看。

+0

嗨。我想我會寫一個完整的解決方案,並將我的代碼發佈到可能出現的錯誤。將檢查解密代碼。 – ritcoder

+3

在[link]找到了一個例子(http://blogs.microsoft.co.il/blogs/kim/archive/2009/01/23/pgp-zip-encrypted-files-with-c.aspx)。它既有加密也有解密。謝謝 – ritcoder

21

我知道這個問題已經過去幾年了,但它仍然是#1或#2在谷歌搜索相關的PGP解密使用Bouncy城​​堡。由於看起來很難找到一個完整,簡潔的例子,我想在這裏分享我的工作解決方案來解密PGP文件。這只是其源文件中包含的Bouncy Castle示例的修改版本。

using System; 
using System.IO; 
using Org.BouncyCastle.Bcpg.OpenPgp; 
using Org.BouncyCastle.Utilities.IO; 

namespace PGPDecrypt 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      DecryptFile(
       @"path_to_encrypted_file.pgp", 
       @"path_to_secret_key.asc", 
       "your_password_here".ToCharArray(), 
       "output.txt" 
      ); 
     } 

     private static void DecryptFile(
      string inputFileName, 
      string keyFileName, 
      char[] passwd, 
      string defaultFileName) 
     { 
      using (Stream input = File.OpenRead(inputFileName), 
        keyIn = File.OpenRead(keyFileName)) 
      { 
       DecryptFile(input, keyIn, passwd, defaultFileName); 
      } 
     } 

     private static void DecryptFile(
      Stream inputStream, 
      Stream keyIn, 
      char[] passwd, 
      string defaultFileName) 
     { 
      inputStream = PgpUtilities.GetDecoderStream(inputStream); 

      try 
      { 
       PgpObjectFactory pgpF = new PgpObjectFactory(inputStream); 
       PgpEncryptedDataList enc; 

       PgpObject o = pgpF.NextPgpObject(); 
       // 
       // the first object might be a PGP marker packet. 
       // 
       if (o is PgpEncryptedDataList) 
       { 
        enc = (PgpEncryptedDataList)o; 
       } 
       else 
       { 
        enc = (PgpEncryptedDataList)pgpF.NextPgpObject(); 
       } 

       // 
       // find the secret key 
       // 
       PgpPrivateKey sKey = null; 
       PgpPublicKeyEncryptedData pbe = null; 
       PgpSecretKeyRingBundle pgpSec = new PgpSecretKeyRingBundle(
        PgpUtilities.GetDecoderStream(keyIn)); 

       foreach (PgpPublicKeyEncryptedData pked in enc.GetEncryptedDataObjects()) 
       { 
        sKey = FindSecretKey(pgpSec, pked.KeyId, passwd); 

        if (sKey != null) 
        { 
         pbe = pked; 
         break; 
        } 
       } 

       if (sKey == null) 
       { 
        throw new ArgumentException("secret key for message not found."); 
       } 

       Stream clear = pbe.GetDataStream(sKey); 

       PgpObjectFactory plainFact = new PgpObjectFactory(clear); 

       PgpObject message = plainFact.NextPgpObject(); 

       if (message is PgpCompressedData) 
       { 
        PgpCompressedData cData = (PgpCompressedData)message; 
        PgpObjectFactory pgpFact = new PgpObjectFactory(cData.GetDataStream()); 

        message = pgpFact.NextPgpObject(); 
       } 

       if (message is PgpLiteralData) 
       { 
        PgpLiteralData ld = (PgpLiteralData)message; 

        string outFileName = ld.FileName; 
        if (outFileName.Length == 0) 
        { 
         outFileName = defaultFileName; 
        } 

        Stream fOut = File.Create(outFileName); 
        Stream unc = ld.GetInputStream(); 
        Streams.PipeAll(unc, fOut); 
        fOut.Close(); 
       } 
       else if (message is PgpOnePassSignatureList) 
       { 
        throw new PgpException("encrypted message contains a signed message - not literal data."); 
       } 
       else 
       { 
        throw new PgpException("message is not a simple encrypted file - type unknown."); 
       } 

       if (pbe.IsIntegrityProtected()) 
       { 
        if (!pbe.Verify()) 
        { 
         Console.Error.WriteLine("message failed integrity check"); 
        } 
        else 
        { 
         Console.Error.WriteLine("message integrity check passed"); 
        } 
       } 
       else 
       { 
        Console.Error.WriteLine("no message integrity check"); 
       } 
      } 
      catch (PgpException e) 
      { 
       Console.Error.WriteLine(e); 

       Exception underlyingException = e.InnerException; 
       if (underlyingException != null) 
       { 
        Console.Error.WriteLine(underlyingException.Message); 
        Console.Error.WriteLine(underlyingException.StackTrace); 
       } 
      } 
     } 

     private static PgpPrivateKey FindSecretKey(PgpSecretKeyRingBundle pgpSec, long keyID, char[] pass) 
     { 
      PgpSecretKey pgpSecKey = pgpSec.GetSecretKey(keyID); 

      if (pgpSecKey == null) 
      { 
       return null; 
      } 

      return pgpSecKey.ExtractPrivateKey(pass); 
     } 
    } 
} 
+1

不完全符合我的需求,但足夠接近我的需求。爲我節省了大量的工作。 Bouncy Castle仍然是我在.NET中爲PGP找到的最好的免費解決方案,它也擊敗了一些付費的解決方案。 – dave

+0

你知道如何解決「加密消息包含簽名消息 - 而不是文字數據。」錯誤? –

+0

@MokhAkh,如果你看看我的代碼,你會發現當消息是PgpOnePassSignatureList而不是預期的PgpLiteralData時會引發這個錯誤。我不知道你確切的情況,但我猜如果你開始搜索SO或谷歌PgpOnePassSignatureList,你會開始弄清楚。 – Dan