无法使用 MimeKit 解密 p7m

Posted

技术标签:

【中文标题】无法使用 MimeKit 解密 p7m【英文标题】:Unable to decrypt p7m using MimeKit 【发布时间】:2018-06-02 08:28:37 【问题描述】:

我从我的电子邮件信息中找到了我的smime.p7m,我将其作为流读取并尝试使用 MimeKit 对其进行解密,但使用 Operation is not valid due to the current state of the object. 失败

using (MemoryStream ms = new MemoryStream(data)) 
    CryptographyContext.Register(typeof(WindowsSecureMimeContext));
    ApplicationPkcs7Mime p7m = new ApplicationPkcs7Mime(SecureMimeType.EnvelopedData, ms);
    var ctx = new WindowsSecureMimeContext(StoreLocation.CurrentUser);
    p7m.Verify(ctx, out MimeEntity output);

遵循https://github.com/jstedfast/MimeKit 上的示例也无济于事。任何熟悉 MimeKit 的人都可以插话吗?

编辑:

解密p7m后,我应该使用MimeParser来解析内容吗?我从解密中得到以下信息:

Content-Type: application/x-pkcs7-mime; name=smime.p7m; smime-type=signed-data
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename=smime.p7m

MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEHAaCAJIAEWUNvbnRl
bnQtVHlwZTogdGV4dC9wbGFpbjsNCgljaGFyc2V0PSJ1cy1hc2NpaSINCkNvbnRlbnQtVHJhbnNm
ZXItRW5jb2Rpbmc6IDdiaXQNCg0KdGVzdA0KAAAAAAAAoIImTTCCBaIwggOKoAMCAQICBguC3JQz
...more...

但是当用MimeParser解析时,

System.FormatException: Failed to parse message headers.
   at MimeKit.MimeParser.ParseMessage(Byte* inbuf, CancellationToken cancellationToken)
   at MimeKit.MimeParser.ParseMessage(CancellationToken cancellationToken)

更新:

啊,原来如此,调用Decrypt 只会给我SignedData,然后我需要调用Verify 来提取原始数据......这有点误导,我认为Verify 会简单地验证它...这就是为什么我不费心打电话给它的原因,因为我真的不需要验证它...也许应该打电话给Decode?这就是我最初想要做的,((MimePart) signedData).Content.DecodeTo(...)

所以最后,我不得不做这样的事情来提取数据。

CryptographyContext.Register(typeof(WindowsSecureMimeContext));
ApplicationPkcs7Mime p7m = new ApplicationPkcs7Mime(SecureMimeType.EnvelopedData, ms);
var ctx = new WindowsSecureMimeContext(StoreLocation.CurrentUser);

if (p7m != null && p7m.SecureMimeType == SecureMimeType.EnvelopedData)

    // the top-level MIME part of the message is encrypted using S/MIME
    p7m = p7m.Decrypt() as ApplicationPkcs7Mime;



if (p7m != null && p7m.SecureMimeType == SecureMimeType.SignedData)

    p7m.Verify(out MimeEntity original);    // THE REAL DECRYPTED DATA
    using (MemoryStream dump = new MemoryStream())
    
        original.WriteTo(dump);
        decrypted = dump.GetBuffer();
    

【问题讨论】:

data 包含什么?我打赌这不是正确的内容。使用MimeMessage.Load()解析消息,然后找到ApplicationPkcs7MimeBodyPart进行验证。检查 MimeKit 的 github 存储库中的单元测试以查看示例。 data 是 p7m 附件,它首先被读取为字节,然后转换为 MemoryStream,以便将其转换为 ApplicationPkcs7Mime 【参考方案1】:

您收到 InvalidOperationException 是因为您在 EncryptedData 上调用 Verify()。

你需要调用 Decrypt()。

Verify() 用于 SignedData。

【讨论】:

谢谢你,你是对的,我尝试了各种不同的东西,最初没有代码CryptographyContext.Register。添加该行后,我没有回去尝试Decrypt它。 如果我将输出MimeEntity 替换为p7m 可以吗?意思是p7m = (ApplicationPkcs7Mime) p7m.Decrypt(ctx);。只是为了让我可以打电话给Verify 如果你知道解密后的内容是一个ApplicationPkcs7Mime对象,是的。 我应该使用MimeParser 来解析解密的内容吗?我收到了Failed to parse message headers. 查看更新的问题。 你做错了什么。请添加您的代码,以便我看到您在做什么。

以上是关于无法使用 MimeKit 解密 p7m的主要内容,如果未能解决你的问题,请参考以下文章

用于解密 SMIME.p7m 文件的 Javascript 库

如何使用公钥加密字符串并使用 MimeKit 使用私钥解密?

MIMEKIT Multipart Signed.Verify 如何禁用证书吊销列表检查?

MimeKit 附件正文编码问题

使用 OpenSSL 解码/提取 smime.p7m 文件内容(带有嵌入文件的电子邮件)?

使用密码加密/解密数据,而数据库管理员无法解密