2011-08-08 180 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