解密 MIME 内容时出错 - 遇到 ASN1 错误标签值
Error decrypting mime content - ASN1 bad tag value met
我编写了一个函数来创建 mime 消息并使用用户 public 证书加密内容,该证书存储在证书存储中,而私钥存储在我的智能卡上。我的函数只是将 pkcs7mime 内容保存到一个文件中。
我有另一个测试功能,它只是读取文件并尝试解密内容。但是,当我尝试解密时,出现错误:遇到 ASN1 错误标记值。
我的加密函数代码:
private static void EncryptMime()
{
MimeMessage mm = new MimeMessage();
var ctx = new WindowsSecureMimeContext();
mm.From.Add(new MailboxAddress("Bob", "Bob@diamondsg.onmicrosoft.com"));
mm.To.Add(new MailboxAddress("Alice", "Alice@diamondsg.onmicrosoft.com"));
mm.Subject = "Smime Test";
mm.Body = new TextPart("plain")
{
Text = @"This is a test."
};
var signer = mm.From.Mailboxes.FirstOrDefault();
var recipients = mm.To.Mailboxes.AsEnumerable();
ApplicationPkcs7Mime p7m = ApplicationPkcs7Mime.SignAndEncrypt(ctx, signer, DigestAlgorithm.Sha1, recipients, mm.Body);
MemoryStream ms = new MemoryStream();
p7m.WriteTo(ms, true);
byte[] bytes = ms.GetBuffer();
File.WriteAllBytes("smime.p7m", bytes);
}
这是我的解密函数:
private static void DecryptMime()
{
CryptographyContext.Register(typeof(WindowsSecureMimeContext));
string messagetext = "";
// Read the p7m file
byte[] bytes =
File.ReadAllBytes("smime.p7m");
MemoryStream ms = new MemoryStream(bytes);
ApplicationPkcs7Mime p7m = new ApplicationPkcs7Mime(SecureMimeType.EnvelopedData, ms);
// WindowsSecureMimeContext ctx = new WindowsSecureMimeContext(StoreLocation.CurrentUser);
if (p7m != null && p7m.SecureMimeType == SecureMimeType.EnvelopedData)
{
Console.WriteLine("Decrypting message...");
try
{
p7m = p7m.Decrypt() as ApplicationPkcs7Mime;
}
catch (Exception ex)
{
Console.WriteLine("Error decrypting: " + ex.Message);
}
}
if (p7m != null && p7m.SecureMimeType == SecureMimeType.CompressedData)
{
Console.WriteLine("Decompressing message...");
p7m = p7m.Decompress() as ApplicationPkcs7Mime;
}
if (p7m != null && p7m.SecureMimeType == SecureMimeType.SignedData)
{
Console.WriteLine("Verifying message...");
p7m.Verify(out MimeEntity entity);
MimeMessage mm = new MimeMessage(entity);
messagetext = mm.GetTextBody(MimeKit.Text.TextFormat.Text);
Console.WriteLine("Decrypted Message: " + messagetext);
}
}
编辑:
我尝试使用以下代码隔离问题:
MemoryStream ms = new MemoryStream();
p7m.WriteTo(ms);
ApplicationPkcs7Mime new_p7m = new ApplicationPkcs7Mime(SecureMimeType.EnvelopedData, ms);
if (new_p7m != null && new_p7m.SecureMimeType == SecureMimeType.EnvelopedData)
{
Console.WriteLine("Decrypting message...");
try
{
new_p7m = new_p7m.Decrypt() as ApplicationPkcs7Mime;
}
catch (Exception ex)
{
Console.WriteLine("Error decrypting: " + ex.Message);
}
}
所以问题似乎早在 WriteTo() 函数就开始了...
更新 #2:
好的,所以我在 p7m 和 new_p7m 对象上都做了一个 toString 。显然,内容不一样...
p7m: Content-Type: application/pkcs7-mime; smime-type=enveloped-data;
name=smime.p7m
Content-Disposition: attachment; filename=smime.p7m
Content-Transfer-Encoding: base64
MIIOOwYJKoZIhvcNAQcDoIIOLDCCDigCAQIxggEwMIIBLAIBAoAU2NQqDvYHJuMeC27IpyiV
....
New p7m: Content-Type: application/pkcs7-mime; smime-type=enveloped-data;
name=smime.p7m
Content-Disposition: attachment; filename=smime.p7m
Content-Transfer-Encoding: base64
Q29udGVudC1UeXBlOiBhcHBsaWNhdGlvbi9wa2NzNy1taW1lOyBzbWltZS10eXBlPWVudmVs
....
对,不知怎么的实际内容在变...很奇怪...
我敢打赌,您将内容保存到磁盘的代码正在写入损坏的文件:
MemoryStream ms = new MemoryStream();
p7m.WriteTo(ms, true);
byte[] bytes = ms.GetBuffer();
File.WriteAllBytes("smime.p7m", bytes);
上面代码的问题是 GetBuffer()
returns 在大多数情况下比内存流实际使用的字节多。上面的逻辑也会将内容保存在 base64 中,这可能不是你想要的。以下代码片段将 base64 内容解码到 smime.p7m 文件中:
using (var stream = File.Create ("smime.p7m"))
p7m.Content.DecodeTo (stream);
然后,要重构 MIME 部分以进行解密,请执行以下操作:
var bytes = File.ReadAllBytes ("smime.p7m");
var ms = new MemoryStream (bytes);
var p7m = new ApplicationPkcs7Mime (SecureMimeType.EnvelopedData, ms);
您遇到的问题是内容之前是 base64 编码的,不应该是。
当然,除非真的需要只保存原始内容然后重新构造 application/pkcs7-mime 部分,否则为什么不像这样保存整个 MIME 部分呢?
using (var stream = File.Create ("smime.p7m"))
p7m.WriteTo (stream);
然后像这样重新加载它:
using (var stream = File.OpenRead ("smime.p7m"))
p7m = (ApplicationPkcs7Mime) MimeEntity.Load (stream);
这样就不用担心出错了。
我编写了一个函数来创建 mime 消息并使用用户 public 证书加密内容,该证书存储在证书存储中,而私钥存储在我的智能卡上。我的函数只是将 pkcs7mime 内容保存到一个文件中。 我有另一个测试功能,它只是读取文件并尝试解密内容。但是,当我尝试解密时,出现错误:遇到 ASN1 错误标记值。
我的加密函数代码:
private static void EncryptMime()
{
MimeMessage mm = new MimeMessage();
var ctx = new WindowsSecureMimeContext();
mm.From.Add(new MailboxAddress("Bob", "Bob@diamondsg.onmicrosoft.com"));
mm.To.Add(new MailboxAddress("Alice", "Alice@diamondsg.onmicrosoft.com"));
mm.Subject = "Smime Test";
mm.Body = new TextPart("plain")
{
Text = @"This is a test."
};
var signer = mm.From.Mailboxes.FirstOrDefault();
var recipients = mm.To.Mailboxes.AsEnumerable();
ApplicationPkcs7Mime p7m = ApplicationPkcs7Mime.SignAndEncrypt(ctx, signer, DigestAlgorithm.Sha1, recipients, mm.Body);
MemoryStream ms = new MemoryStream();
p7m.WriteTo(ms, true);
byte[] bytes = ms.GetBuffer();
File.WriteAllBytes("smime.p7m", bytes);
}
这是我的解密函数:
private static void DecryptMime()
{
CryptographyContext.Register(typeof(WindowsSecureMimeContext));
string messagetext = "";
// Read the p7m file
byte[] bytes =
File.ReadAllBytes("smime.p7m");
MemoryStream ms = new MemoryStream(bytes);
ApplicationPkcs7Mime p7m = new ApplicationPkcs7Mime(SecureMimeType.EnvelopedData, ms);
// WindowsSecureMimeContext ctx = new WindowsSecureMimeContext(StoreLocation.CurrentUser);
if (p7m != null && p7m.SecureMimeType == SecureMimeType.EnvelopedData)
{
Console.WriteLine("Decrypting message...");
try
{
p7m = p7m.Decrypt() as ApplicationPkcs7Mime;
}
catch (Exception ex)
{
Console.WriteLine("Error decrypting: " + ex.Message);
}
}
if (p7m != null && p7m.SecureMimeType == SecureMimeType.CompressedData)
{
Console.WriteLine("Decompressing message...");
p7m = p7m.Decompress() as ApplicationPkcs7Mime;
}
if (p7m != null && p7m.SecureMimeType == SecureMimeType.SignedData)
{
Console.WriteLine("Verifying message...");
p7m.Verify(out MimeEntity entity);
MimeMessage mm = new MimeMessage(entity);
messagetext = mm.GetTextBody(MimeKit.Text.TextFormat.Text);
Console.WriteLine("Decrypted Message: " + messagetext);
}
}
编辑: 我尝试使用以下代码隔离问题:
MemoryStream ms = new MemoryStream();
p7m.WriteTo(ms);
ApplicationPkcs7Mime new_p7m = new ApplicationPkcs7Mime(SecureMimeType.EnvelopedData, ms);
if (new_p7m != null && new_p7m.SecureMimeType == SecureMimeType.EnvelopedData)
{
Console.WriteLine("Decrypting message...");
try
{
new_p7m = new_p7m.Decrypt() as ApplicationPkcs7Mime;
}
catch (Exception ex)
{
Console.WriteLine("Error decrypting: " + ex.Message);
}
}
所以问题似乎早在 WriteTo() 函数就开始了...
更新 #2: 好的,所以我在 p7m 和 new_p7m 对象上都做了一个 toString 。显然,内容不一样...
p7m: Content-Type: application/pkcs7-mime; smime-type=enveloped-data;
name=smime.p7m
Content-Disposition: attachment; filename=smime.p7m
Content-Transfer-Encoding: base64
MIIOOwYJKoZIhvcNAQcDoIIOLDCCDigCAQIxggEwMIIBLAIBAoAU2NQqDvYHJuMeC27IpyiV
....
New p7m: Content-Type: application/pkcs7-mime; smime-type=enveloped-data;
name=smime.p7m
Content-Disposition: attachment; filename=smime.p7m
Content-Transfer-Encoding: base64
Q29udGVudC1UeXBlOiBhcHBsaWNhdGlvbi9wa2NzNy1taW1lOyBzbWltZS10eXBlPWVudmVs
....
对,不知怎么的实际内容在变...很奇怪...
我敢打赌,您将内容保存到磁盘的代码正在写入损坏的文件:
MemoryStream ms = new MemoryStream();
p7m.WriteTo(ms, true);
byte[] bytes = ms.GetBuffer();
File.WriteAllBytes("smime.p7m", bytes);
上面代码的问题是 GetBuffer()
returns 在大多数情况下比内存流实际使用的字节多。上面的逻辑也会将内容保存在 base64 中,这可能不是你想要的。以下代码片段将 base64 内容解码到 smime.p7m 文件中:
using (var stream = File.Create ("smime.p7m"))
p7m.Content.DecodeTo (stream);
然后,要重构 MIME 部分以进行解密,请执行以下操作:
var bytes = File.ReadAllBytes ("smime.p7m");
var ms = new MemoryStream (bytes);
var p7m = new ApplicationPkcs7Mime (SecureMimeType.EnvelopedData, ms);
您遇到的问题是内容之前是 base64 编码的,不应该是。
当然,除非真的需要只保存原始内容然后重新构造 application/pkcs7-mime 部分,否则为什么不像这样保存整个 MIME 部分呢?
using (var stream = File.Create ("smime.p7m"))
p7m.WriteTo (stream);
然后像这样重新加载它:
using (var stream = File.OpenRead ("smime.p7m"))
p7m = (ApplicationPkcs7Mime) MimeEntity.Load (stream);
这样就不用担心出错了。