【发布时间】:2018-09-22 19:11:28
【问题描述】:
简介
我正在将 Java 库转换为 .Net。
该库是多态假名解密的实现,将在荷兰用于解密欧洲 eIDAS 电子识别服务领域的“BSNk”。
我已经转换了大部分库,并与 Java 版本的作者一起验证了结果。 下一步是让 .Net 库真正可用于荷兰公司,而这正是我在过去 2 周中遇到的问题。
算法使用 PEM 文件中的椭圆曲线作为计算部分之一。但是客户端(库的用户)会以 p7 和 p8 文件的形式收到此文件,您可以将其转换/提取/解码(?)为 PEM 数据。
问题
如何从 te p7+p8 文件获取 C# 中的 PEM 字符串?
最好只使用 System.Security.Cryptography.Pkcs,但我目前在其他部分使用 BouncyCastle(因为 Java 版本使用了)。 未在下面列出,但我也尝试使用 SignedCms 和 EnvelopedCms 执行此操作,但除了(对我而言)无法理解的错误之外什么也没得到。我在密码学方面没有太多经验,但在过去的几周里学到了很多东西。
如果我理解正确,我会将其解释为 p7 文件是 PEM 消息的信封,并且使用 p8 文件中的私钥对信封进行签名/加密?
代码
public static string ConvertToPem(string p7File, string p8File)
{
var p7Data = File.ReadAllBytes(p7File);
var p8Data = File.ReadAllBytes(p8File);
// Java version gets the private key like this:
// KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(bytesArray));
var privateKey = PrivateKeyFactory.CreateKey(p8Data);
var parser = new CmsEnvelopedDataParser(p7Data);
var recipients = parser.GetRecipientInfos().GetRecipients().OfType<RecipientInformation>();
var recipientInformation = recipients.First();
//Java version gets the message like this:
//final byte[] message = keyInfo.getContent(new JceKeyTransEnvelopedRecipient(key).setProvider("BC"));
var keyInfo = (KeyTransRecipientInformation)recipientInformation;
var message = keyInfo.GetContent(privateKey);
return Encoding.ASCII.GetString(message);
}
2018 年 8 月 10 日更新 根据 Java 库作者的提示,我尝试跳过自动转换为 PEM 并仅使用 openssl 对其进行解密的问题。不幸的是,用于解密文件的 openssl 命令也失败了!无论是在 Windows 上还是在 Linux 上。奇怪的是,这是使用在 Java 库中使用时可以正常工作的相同文件完成的。 p8坏了吗?它是否仅在 Java JceKeyTransEnvelopedRecipient 中使用时才兼容???
openssl cms -decrypt -inform DER -in dv_keys_ID_D_oin.p7 -inkey privatep8.key -out id.pem
(我也尝试使用 PEM 代替 DER,但无济于事。文件位于 GitHub 存储库中)
2018 年 9 月 10 日更新 感谢 Carl 找出了看似损坏的 p8 文件的原因。我们必须先将二进制 DER p8 转换为 base64 编码的 PEM,而不是直接使用 openssl cms 对其进行解密。
openssl pkcs8 -inform der -outform pem -in private.p8 -out private-p8.pem -topk8 -nocrypt
我们也可以在 c# 中通过读取 p8 文件中的字节,将它们转换为 Base64 并在其周围添加 BEGIN/END PRIVATE KEY 页眉/页脚来做到这一点。
资源
您可以看到此代码在我的项目中作为单元测试被使用并失败。该项目还包括匹配的 p7、p8 和 PEM 文件进行测试。
Java 版本可以在这里找到:https://github.com/BramvanPelt/PPDecryption
我的工作版本可以在这里找到:https://github.com/MartijnKooij/PolymorphicPseudonymisation
【问题讨论】:
-
您应该可以使用 BouncyCastle 的
PemParser读取 p8 密钥文件 -
我正在寻找它的反面。我有 p7 数据和 p8 密钥,我需要从中创建一个 PEM。如果我没记错的话,PemParser 用于读取 PEM 数据。
-
根据文档,
PemParser:用于解析包含 X509 证书、PKCS8 编码密钥和 PKCS7 对象的 OpenSSL PEM 编码流的类。 -
PemParser 似乎已在 C# 中重命名为 PemReader。该评论确实在 PemReader 类之上,但它所能做的就是在 PEM 文件中读取......至少,这就是我能在其中找到的全部内容。还有一个 PEMWriter 但我找不到与 p7 和 p8 数据的关系...
-
你得到了这个糟糕的填充异常,对吧?会不会是 c# 实现包含错误?我正在考虑的一种策略是获取 Bouncy Castle c# 源代码及其单元测试,并使用与 pkcs#7 文件使用的加密算法相同的加密算法定义单元测试。其他策略是试用 Microsoft 库,但随后我们需要设置 x509 证书集合。 x509 证书是否可以从您拥有的资源中轻松制作?
标签: c# cryptography bouncycastle pem pkcs#7