2013-03-03 36 views
3

我想用BouncyCastle用OpenPGP加密字符串(不是文件)。我使用GPG4win(Kleopatra)生成公钥/私钥对进行测试。我的代码工作,并输出加密的文件,但我无法再用Kleopatra解密该文件。我收到一条消息:“无法确定这是OpenPGP还是S/MIME签名 - 可能它不是签名?”。无法解密用BouncyCastle C加密的OpenPGP数据#

这里是我用来加密文件的代码:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using System.IO; 
using Org.BouncyCastle; 
using Org.BouncyCastle.OpenSsl; 
using Org.BouncyCastle.Crypto; 
using Org.BouncyCastle.Crypto.Engines; 
using Org.BouncyCastle.Security; 
using Org.BouncyCastle.Bcpg; 
using Org.BouncyCastle.Bcpg.OpenPgp; 
namespace RXNet 
{ 
public static class Encrypter //Inspired by http://blogs.microsoft.co.il/blogs/kim/archive/2009/01/23/pgp-zip-encrypted-files-with-c.aspx 
{ 
    private const int BUFFER_SIZE = 1 << 16; 
    public static string EncryptPackAndBase64(string strdata, string keyString) 
    { 
     if (strdata.Length == 0) 
      throw new ArgumentException("A blank string was provided."); 
     //Extract the key from PGP format 
     PgpPublicKey enckey = readPublicKeyFromString(keyString); 


     Stream outputStream = new MemoryStream(); 
     MemoryStream dataStream = new MemoryStream(Encoding.Unicode.GetBytes(strdata)); 

     using (Stream encryptedOut = ChainEncryptedOut(outputStream, enckey)) 
     using (Stream compressedOut = ChainCompressedOut(encryptedOut)) 
     { 

      //PgpSignatureGenerator signatureGenerator = InitSignatureGenerator(compressedOut); 

      using (Stream literalOut = ChainLiteralOut(compressedOut, dataStream.Length)) 
      { 
       WriteOutput(literalOut, dataStream); 
      } 
      return System.Convert.ToBase64String(((MemoryStream)outputStream).ToArray()); 
     } 





    } 

    private static byte[] ReadFully(Stream input) 
    { 
     using (MemoryStream ms = new MemoryStream()) 
     { 
      input.CopyTo(ms); 
      return ms.ToArray(); 
     } 
    } 

    private static PgpPublicKey readPublicKeyFromString(string base64str) 
    { 
     byte[] key = System.Convert.FromBase64String(base64str); 
     using (Stream keyIn = new MemoryStream(key)) 
     using (Stream inputStream = PgpUtilities.GetDecoderStream(keyIn)) 
     { 

      PgpPublicKeyRingBundle publicKeyRingBundle = new PgpPublicKeyRingBundle(inputStream); 

      PgpPublicKey foundKey = getFirstPublicKey(publicKeyRingBundle); 

      if (foundKey != null) 
       return foundKey; 

     } 

     throw new ArgumentException("No encryption key found in public key ring."); 
    } 

    private static PgpPublicKey getFirstPublicKey(PgpPublicKeyRingBundle publicKeyRingBundle) 
    { 

     foreach (PgpPublicKeyRing kRing in publicKeyRingBundle.GetKeyRings()) 
     { 

      PgpPublicKey key = kRing.GetPublicKeys() 
       .Cast<PgpPublicKey>() 
       .Where(k => k.IsEncryptionKey) 
       .FirstOrDefault(); 

      if (key != null) 
       return key; 

     } 

     return null; 

    } 

    private static Stream ChainCompressedOut(Stream encryptedOut) 
    { 

     PgpCompressedDataGenerator compressedDataGenerator = 

      new PgpCompressedDataGenerator(CompressionAlgorithmTag.Zip); 

     return compressedDataGenerator.Open(encryptedOut); 

    } 

    private static Stream ChainEncryptedOut(Stream outputStream, PgpPublicKey key) 
    { 

     PgpEncryptedDataGenerator encryptedDataGenerator; 

     encryptedDataGenerator = 

      new PgpEncryptedDataGenerator(SymmetricKeyAlgorithmTag.Cast5, new SecureRandom()); 

     encryptedDataGenerator.AddMethod(key); 

     return encryptedDataGenerator.Open(outputStream, new byte[BUFFER_SIZE]); 

    } 

    private static Stream ChainLiteralOut(Stream compressedOut, long length) 
    { 

     PgpLiteralDataGenerator pgpLiteralDataGenerator = new PgpLiteralDataGenerator(); 

     return pgpLiteralDataGenerator.Open(compressedOut, PgpLiteralData.Binary, PgpLiteralData.Console, length, DateTime.Now); 

    } 

    private static void WriteOutput(Stream literalOut, Stream inputStream) 
    { 

     int length = 0; 

     byte[] buf = new byte[BUFFER_SIZE]; 

     while ((length = inputStream.Read(buf, 0, buf.Length)) > 0) 
     { 

      literalOut.Write(buf, 0, length); 

     } 


    } 
} 
} 

然后我把它叫做如下:

string encc = Encrypter.EncryptPackAndBase64("Test 123 123 123", @"mQENBFEznzsBCADIg9CTEJygWls+b+pGqFcD9rx8XjGfo9l513Av0GpDKuCEaP+Dq4A1wox3RcK/ 
GgPJFUR2uKOTjOR9DLOoUewOhbej4jD/k1I3Hy6uybICqy6Og2lnntErNT06qwRZZyTvgcWbIHzv 
W3+RxursLPD6fHC1pf2FuiMTqM0Q11Y3CRn7auLu4EXUjYzNCSYUZNcPpAlh+GOmIuILUsZDpgks 
qnEh3Bhzv+nhL8lgwUfmnGfUBjTTuVqqymoAIFZx1eJBBZiDdrMBX4uAxSjk6YI2fGcscvUOapyk 
52FG58q8mAlxX+Ys8F60mm2A3kcMerkJQl5rQ5GTPGarTJ+Xn2oLABEBAAG0Ik1hdHQgSmFkY3ph 
ayA8bWF0dEB3cGFuZGJhY29uLmNvbT6JATgEEwECACIFAlEznzsCGw8GCwkIBwMCBhUIAgkKCwQW 
AgMBAh4BAheAAAoJEMMjybDZ/OUoT6sH/iw46MEWsc1A8447OUQ/7dqZpBrVXQZUzMkf7V/v/9bP 
A0Zh5VTcvwRGBawOZGfML1uMGEuiVOS0y1zy7YAWNs4qUkmCIWg4CBwWRpGFu2aBMK70rsRRoNFO 
GHYVVFwB7cS5qFZ2JUzI+SJb6BszV35TEeL1U/vkANRq3WSgDMCaHtWQbefVZ/3d4RYvBKujrASX 
KoAcIMQAMRR9if994gxRSs9m3BbB8snNB8QT40cGG5HeOiaYBsxFV8leOpd34NzOfVr5KxeB/qm9 
BdU8HW76FD+XPMONCCwCxZSRljUxcGzMPKZPb0OKaRFRXHcqvkd4SCJ6n1OGOcbeLdaXqFw="); 
      FileStream st = new FileStream(@"D:\enc.bin", FileMode.Create, FileAccess.Write); 
      var b = Convert.FromBase64String(encc); 
      st.Write(b, 0, b.Length); 
      st.Close(); 

在充分的环境中,我会得到的钥匙为Base64字符串,所以我就是这样传递它的原因。我试图使用钥匙的装甲版本,但它不起作用;这是我手动Base64'd的二进制版本。

回答

2

在验证通过Bouncy Castle在Kleopatra中加密的文件时,我遇到了同样的错误。

对我而言,解决方法是用.gpg扩展名重命名加密文件。