Bouncy Castle PGP 解密问题

Posted

技术标签:

【中文标题】Bouncy Castle PGP 解密问题【英文标题】:Bouncy Castle PGP Decryption Issue 【发布时间】:2012-06-21 20:14:50 【问题描述】:

我有一个使用 Bouncy Castle 进行 PGP 解密的应用程序,它在过去 8 个月左右的时间里运行没有任何问题,而在过去的 2 天里突然出现了一个问题,GetDataStream 方法抛出了一个问题例外:

异常消息:“错误设置非对称密码”。

内部异常消息:“不是 RSA 密钥”。

private static PgpObjectFactory getClearDataStream(PgpPrivateKey privateKey, PgpPublicKeyEncryptedData publicKeyED)

    // Exception throws here.
    Stream clearStream = publicKeyED.GetDataStream(privateKey);

    PgpObjectFactory clearFactory = new PgpObjectFactory(clearStream);
    return clearFactory;

密钥没有过期,没有过期日期:

我没有对应用程序进行任何更改,我没有触摸按键,所以我不太明白为什么会突然出现问题。有任何想法吗?我还可以使用我在应用程序中加载的相同密钥使用 Kleopatra 手动解密文件。

更新 1 - 我下载了 OpenPGP Library for .NET 的免费试用版,它看起来也可以使用 BouncyCastle,而且我使用相同的密钥解密文件没有问题。出于某种原因,我使用 BouncyCastle 进行了几个月的解密实现由于某种我无法识别的原因而停止工作。

更新 2 - 我从上周提取了有效的文件,并且我还下载了 BouncyCastle 的源代码,以便我可以逐步调试以查看异常抛出的位置和工作文件和不工作文件之间的变量有何不同。在 PgpPublicKeyEncryptedData 类的 GetDataStream 方法开头抛出异常:

byte[] plain = fetchSymmetricKeyData(privKey);

当我进入此方法时,对于我可以毫无问题地解密的文件,我注意到 keyData.Algorithm 变量设置为“ElGamalEncrypt”,而对于异常抛出的文件,文件 keyData.Algortithm设置为“RsaGeneral”。为什么这些会有所不同?向我发送文件的公司是否更改了他们的加密方法? BouncyCastle 是否不正确支持这种加密方法?

private byte[] fetchSymmetricKeyData(PgpPrivateKey privKey)

    IBufferedCipher c1 = GetKeyCipher(keyData.Algorithm);

    try
    
        c1.Init(false, privKey.Key);
    
    catch (InvalidKeyException e)
    
        throw new PgpException("error setting asymmetric cipher", e);
    

另外,不确定这是否相关,我们密钥的证书类型是 DSA。

更新 3 - 给定当前密钥,我一直无法弄清楚如何解决该问题。我昨天生成了新密钥(DSA 类型),使用新密钥后问题已解决。

更新 4 - 这个问题刚刚再次出现,我上次更新时使用的新密钥。再一次,PgpPublicKeyEncryptedData 类中的 keyData.Algorithm 现在被“RsaGeneral”而不是“ElGamalEncrypt”看到。为什么算法属性会改变?加密文件的人是否改变了什么?

【问题讨论】:

持有 RSA 密钥的证书可能已过期?你能检查一下吗? 我之前检查过,刚刚添加了一个截图,我们的密钥没有到期日期。此外,我可以使用 Kleopatra 等实用程序使用相同的密钥手动解密文件。所以钥匙很好。 如果你已经解决了你的问题,你应该把解决方案放在答案中并接受它 我真的希望这可能是关于月球反弹的 API。 大多数时候,当您遇到偶尔发生的问题时,并不是加密/解密过程本身。它通常与不正确的输入/输出有关。在加密的情况下,最常见的问题是字节被视为字符并按原样传输。问题是并非所有字节都编码为字符,从而导致数据丢失。密码学的有趣之处在于结果应该看起来像随机字符,因此这类问题不时出现是很常见的。使用随机生成的大型数据集进行测试以避免此类问题。 【参考方案1】:

看起来另一方正在加密其他/不同的密钥。 可能您的密钥环也包含 RSA 密钥,但 BouncyCastle 仅使用第一个 (???)。 使用 gpg,您可以通过发出检查加密文件的内容 gpg --list-packets YourEncryptedFile.pgp

之后,对“好”文件和您的密钥环应用相同的命令,并将密钥标识符与哪个文件加密进行比较。 由于您使用的是 DSA 密钥,因此文件应加密为 ElGamal 子密钥。

【讨论】:

【参考方案2】:

这可能很重要(来源:http://www.opensourcejavaphp.net/csharp/itextsharp/PgpPublicKeyEncryptedData.cs.html):

它解释了您的 keyData.Algorithm 的价值不同,但我仍然不确定的原因。很可能是输入文件。它可能不同(客户端使用不同的密钥?)

private static IBufferedCipher GetKeyCipher(
            PublicKeyAlgorithmTag algorithm)
        
            try
            
                switch (algorithm)
                
                    case PublicKeyAlgorithmTag.RsaEncrypt:
                    case PublicKeyAlgorithmTag.RsaGeneral:
                        return CipherUtilities.GetCipher("RSA//PKCS1Padding");
                    case PublicKeyAlgorithmTag.ElGamalEncrypt:
                    case PublicKeyAlgorithmTag.ElGamalGeneral:
                        return CipherUtilities.GetCipher("ElGamal/ECB/PKCS1Padding");
                    default:
                        throw new PgpException("unknown asymmetric algorithm: " + algorithm);
                
            
            catch (PgpException e)
            
                throw e;
            
            catch (Exception e)
            
                throw new PgpException("Exception creating cipher", e);
            
        

【讨论】:

以上是关于Bouncy Castle PGP 解密问题的主要内容,如果未能解决你的问题,请参考以下文章

Bouncy Castle 从公钥加密会话数据包中提取 PGP 会话密钥

为 Bouncy Castle C# API 使用多个键

使用 RSA Bouncy Castle 加密/解密无法正常工作

在 C# 中使用 Bouncy Castle 加密/解密

如何使用Bouncy Castle Crypto API来加密和解密数据

如何使用Bouncy Castle解密AES / CCM加密密文?