Mimekit - 解密图 api mime 消息时遇到 ASN1 错误标记值

Mimekit - ASN1 bad tag value met when decrypting graph api mime message

我正在使用 mimekit 加密和解密 mime 消息并通过 Graph 发送它们 API,加密似乎工作正常但消息的接收者无法通过它的 Outlook 客户端解密消息.在其他加密邮件中,收件人生成的他可以在其 Outlook 客户端中看到挂锁,然后安装证书,然后解密邮件,但是当我通过 Graph API 发送邮件时,挂锁不存在。

此外,当我尝试获取已加密发送的相同消息然后解密时,出现以下错误:

asn1 bad tag value met   at Internal.Cryptography.Pal.Windows.DecryptorPalWindows.Decode(ReadOnlySpan`1 encodedMessage, Int32& version, ContentInfo& contentInfo, AlgorithmIdentifier& contentEncryptionAlgorithm, X509Certificate2Collection& originatorCerts, CryptographicAttributeObjectCollection& unprotectedAttributes)
   at Internal.Cryptography.Pal.Windows.PkcsPalWindows.Decode(ReadOnlySpan`1 encodedMessage, Int32& version, ContentInfo& contentInfo, AlgorithmIdentifier& contentEncryptionAlgorithm, X509Certificate2Collection& originatorCerts, CryptographicAttributeObjectCollection& unprotectedAttributes)
   at System.Security.Cryptography.Pkcs.EnvelopedCms.Decode(ReadOnlySpan`1 encodedMessage)
   at System.Security.Cryptography.Pkcs.EnvelopedCms.Decode(Byte[] encodedMessage)
   at MimeKit.Cryptography.WindowsSecureMimeContext.<DecryptAsync>d__45.MoveNext()
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
   at MimeKit.Cryptography.ApplicationPkcs7Mime.<DecryptAsync>d__11.MoveNext()
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at PasarelaLibrary.Bases.GraphService.BaseGraphPasarela.<Decrypt>d__12.MoveNext() in C:\Dev\Euroval\PasarelaAceuro\PasarelaLibrary\Bases\GraphService\BaseGraphPasarela.cs:line 321
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at PasarelaLibrary.Bases.GraphService.BaseGraphPasarela.<DownloadGraph>d__8.MoveNext() in C:\Dev\Euroval\PasarelaAceuro\PasarelaLibrary\Bases\GraphService\BaseGraphPasarela.cs:line 178

这是我正在使用的代码:

ClientSecretCredential clientSecretCredential = new ClientSecretCredential(
    _settings.GraphApiSettings.TenantId,
    _settings.GraphApiSettings.ClientId, 
    _settings.GraphApiSettings.ClientSecret, 
    options);
GraphServiceClient graphClient = new GraphServiceClient(clientSecretCredential, new string[] { _settings.GraphApiSettings.Scope });
var message = await graphClient.GetMessage(_settings.GraphApiSettings.UserId, fileId);
var encryptedContent = (ApplicationPkcs7Mime)await MimeEntity.LoadAsync(ParserOptions.Default, 
    ContentType.Parse(ParserOptions.Default, "application/pkcs7-mime; smime-type=enveloped-data; name=smime.p7m"), message);
var decriptedMessage = await Decrypt(encryptedContent);


public async Task<MimeEntity> Decrypt(ApplicationPkcs7Mime encryptedContent)
{
    var context = new WindowsSecureMimeContext(StoreLocation.CurrentUser);
    context.Import(StoreName.CertificateAuthority, _settings.GraphApiSettings.Certificate);
    return await encryptedContent.DecryptAsync(context);
}

public static async Task<Stream> GetMessage(this GraphServiceClient graphServiceClient, string userId, string messageId)
{
    var request = graphServiceClient.Users[userId].Messages[messageId].Request().GetHttpRequestMessage();

    request.RequestUri = new Uri(request.RequestUri.OriginalString + "/$value");
    var response = await graphServiceClient.HttpProvider.SendAsync(request);
    response.EnsureSuccessStatusCode();
    var content = await response.Content.ReadAsStreamAsync();
    content.Position = 0;
    return content;
}

如果您需要我提供更多信息来检查此错误,请告诉我。提前致谢!

试试这个:

ClientSecretCredential clientSecretCredential = new ClientSecretCredential(
    _settings.GraphApiSettings.TenantId,
    _settings.GraphApiSettings.ClientId, 
    _settings.GraphApiSettings.ClientSecret, 
    options);
GraphServiceClient graphClient = new GraphServiceClient(clientSecretCredential, new string[] { _settings.GraphApiSettings.Scope });
var messageStream = await graphClient.GetMessage(_settings.GraphApiSettings.UserId, fileId);
var message = await MimeMessage.LoadAsync(messageStream);
var encryptedContent = (ApplicationPkcs7Mime) message.Body;
var decriptedMessage = await Decrypt(encryptedContent);


public async Task<MimeEntity> Decrypt(ApplicationPkcs7Mime encryptedContent)
{
    var context = new WindowsSecureMimeContext(StoreLocation.CurrentUser);
    context.Import(StoreName.CertificateAuthority, _settings.GraphApiSettings.Certificate);
    return await encryptedContent.DecryptAsync(context);
}

public static async Task<Stream> GetMessage(this GraphServiceClient graphServiceClient, string userId, string messageId)
{
    var request = graphServiceClient.Users[userId].Messages[messageId].Request().GetHttpRequestMessage();

    request.RequestUri = new Uri(request.RequestUri.OriginalString + "/$value");
    var response = await graphServiceClient.HttpProvider.SendAsync(request);
    response.EnsureSuccessStatusCode();
    var content = await response.Content.ReadAsStreamAsync();
    content.Position = 0;
    return content;
}

如果 GetMessage() 返回的流包含完整的 MIME 消息,则不要使用为解析 HTTP multipart/form-data 响应而设计的 MimeEntity.LoadAsync() 方法。

MimeEntity.LoadAsync() API 采用 ContentType 参数的原因是 Content-Type header 是 HTTP 的 Content-Type header,因此 response.Content 将不包含 MIME headers.

但在你的情况下,HTTP 响应将有 2 组 header。 HTTP 响应 headers 和 MIME headers(它们都将包含在 response.Content 中)。