使用 mimekit 解密带附件的电子邮件
Decrypt Email with Attachments using mimekit
我们有一个方案可以解密带有附件的电子邮件。我们正在使用 mimekit
库。我们还使用 mimekit
进行电子邮件加密,它工作正常。
在我们的例子中,加密的电子邮件只有一个附件,没有这样的电子邮件正文。 Azure Logic App
从 Oiifce365 邮箱(使用内置连接器)获取加密电子邮件,然后将详细信息发送到运行解密逻辑的 Azure Function App
。解密证书存放在Azure Key Vault
.
下面是我们试过的代码,它显示异常说
Unable to cast object of type 'Org.BouncyCastle.Asn1.DerApplicationSpecific' to type 'Org.BouncyCastle.Asn1.Asn1SequenceParser'.
[FunctionName("DecryptSMIME")]
public static async Task<IActionResult> Decrypt([HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req, ILogger log)
{
try
{
var temporarySecurityMimeContext = new TemporarySecureMimeContext();
// get decryption Cert pfx
var keyVaultClient = ServiceProvider.GetRequiredService<IKeyVaultClient>();
var decryptionCertBundle = keyVaultClient.GetSecretAsync("https://my-key-vault.vault.azure.net/secrets/Decryption-Certificate-Base64/d7a84b415a494c1ebaseae88cff50028").Result;
var decryptionCertBytes = Convert.FromBase64String(decryptionCertBundle.Value);
log.LogInformation($"Decoded length of decryption certificate: '{decryptionCertBytes.Length}'");
// get decryption Cert password
var decryptionCertPasswordBundle = keyVaultClient.GetSecretAsync("https://my-key-vault.vault.azure.net/secrets/Decryption-Certificate-Pass/34judc9f575f467a96d9483dfc8kf467").Result;
var decryptionCertPassword = decryptionCertPasswordBundle.Value;
using var stream = new MemoryStream(decryptionCertBytes);
temporarySecurityMimeContext.Import(stream, decryptionCertPassword);
log.LogInformation("Imported The Decryption certificate as MemoryStream");
using var encryptedContentStream = await GetMailAttachmentStreamAsync(req.Body, log) ;
log.LogInformation("Loading pkcs7-mime entity.");
ApplicationPkcs7Mime encryptedContent = (ApplicationPkcs7Mime)await MimeEntity.LoadAsync(ParserOptions.Default, ContentType.Parse(ParserOptions.Default, "application/pkcs7-mime; smime-type=enveloped-data; name=smime.p7m"), encryptedContentStream);
log.LogInformation("Decrypting pkcs7-mime entity.");
MimeEntity decryptedContent = encryptedContent.Decrypt();
return new OkObjectResult("OK");
}
catch (Exception ex)
{
log.LogError(ex, "Failed to decrypt the secure mime part in the request body.");
throw;
}
}
private static async Task<MemoryStream> GetMailAttachmentStreamAsync(Stream attachmentObjectStream, ILogger log)
{
var memoryStream = new MemoryStream();
await attachmentObjectStream.CopyToAsync(memoryStream);
memoryStream.Seek(0, SeekOrigin.Begin);
log.LogInformation($"Attachment Stream Processed. {memoryStream.Length} Bytes");
return memoryStream;
}
证书加载成功。电子邮件流也显示一些数据。但是运行解密时,总是报错。任何帮助都会有所帮助。
下面是您的代码并进行了一些修复(即删除像 MethodAsync(...).Result
这样的错误做法的代码)。
我还冒昧地添加了一条大评论,要求提供更多信息。
[FunctionName("DecryptSMIME")]
public static async Task<IActionResult> Decrypt([HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req, ILogger log)
{
try
{
using var temporarySecurityMimeContext = new TemporarySecureMimeContext();
// get decryption Cert pfx
var keyVaultClient = ServiceProvider.GetRequiredService<IKeyVaultClient>();
var decryptionCertBundle = await keyVaultClient.GetSecretAsync("https://my-key-vault.vault.azure.net/secrets/Decryption-Certificate-Base64/d7a84b415a494c1ebaseae88cff50028");
var decryptionCertBytes = Convert.FromBase64String(decryptionCertBundle.Value);
log.LogInformation($"Decoded length of decryption certificate: '{decryptionCertBytes.Length}'");
// get decryption Cert password
var decryptionCertPasswordBundle = await keyVaultClient.GetSecretAsync("https://my-key-vault.vault.azure.net/secrets/Decryption-Certificate-Pass/34judc9f575f467a96d9483dfc8kf467");
var decryptionCertPassword = decryptionCertPasswordBundle.Value;
using var stream = new MemoryStream(decryptionCertBytes);
temporarySecurityMimeContext.Import(stream, decryptionCertPassword);
log.LogInformation("Imported The Decryption certificate as MemoryStream");
using var encryptedContentStream = await GetMailAttachmentStreamAsync(req.Body, log) ;
log.LogInformation("Loading pkcs7-mime entity.");
// Ideally, you would not use the MimeEntity.LoadAsync() method that takes a
// forged ContentType parameter. This is a huge hack and *may* be the cause
// of your problem. In other words, the content that MimeKit is trying to
// decrypt may be in the wrong format. To know for certain, I would need to
// know what the HttpRequest headers and Body look like.
//
// I would probably recommend that your code that sends this request be
// modified to send the entire raw MIME (i.e. including headers) of the
// application/pkcs7-mime part as the HTTP request body instead so that you
// would not need to forge the Content-Type header.
ApplicationPkcs7Mime encryptedContent = (ApplicationPkcs7Mime)await MimeEntity.LoadAsync(ParserOptions.Default, ContentType.Parse(ParserOptions.Default, "application/pkcs7-mime; smime-type=enveloped-data; name=smime.p7m"), encryptedContentStream);
log.LogInformation("Decrypting pkcs7-mime entity.");
MimeEntity decryptedContent = encryptedContent.Decrypt();
return new OkObjectResult("OK");
}
catch (Exception ex)
{
log.LogError(ex, "Failed to decrypt the secure mime part in the request body.");
throw;
}
}
private static async Task<MemoryStream> GetMailAttachmentStreamAsync(Stream attachmentObjectStream, ILogger log)
{
var memoryStream = new MemoryStream();
await attachmentObjectStream.CopyToAsync(memoryStream);
memoryStream.Seek(0, SeekOrigin.Begin);
log.LogInformation($"Attachment Stream Processed. {memoryStream.Length} Bytes");
return memoryStream;
}
我们有一个方案可以解密带有附件的电子邮件。我们正在使用 mimekit
库。我们还使用 mimekit
进行电子邮件加密,它工作正常。
在我们的例子中,加密的电子邮件只有一个附件,没有这样的电子邮件正文。 Azure Logic App
从 Oiifce365 邮箱(使用内置连接器)获取加密电子邮件,然后将详细信息发送到运行解密逻辑的 Azure Function App
。解密证书存放在Azure Key Vault
.
下面是我们试过的代码,它显示异常说
Unable to cast object of type 'Org.BouncyCastle.Asn1.DerApplicationSpecific' to type 'Org.BouncyCastle.Asn1.Asn1SequenceParser'.
[FunctionName("DecryptSMIME")]
public static async Task<IActionResult> Decrypt([HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req, ILogger log)
{
try
{
var temporarySecurityMimeContext = new TemporarySecureMimeContext();
// get decryption Cert pfx
var keyVaultClient = ServiceProvider.GetRequiredService<IKeyVaultClient>();
var decryptionCertBundle = keyVaultClient.GetSecretAsync("https://my-key-vault.vault.azure.net/secrets/Decryption-Certificate-Base64/d7a84b415a494c1ebaseae88cff50028").Result;
var decryptionCertBytes = Convert.FromBase64String(decryptionCertBundle.Value);
log.LogInformation($"Decoded length of decryption certificate: '{decryptionCertBytes.Length}'");
// get decryption Cert password
var decryptionCertPasswordBundle = keyVaultClient.GetSecretAsync("https://my-key-vault.vault.azure.net/secrets/Decryption-Certificate-Pass/34judc9f575f467a96d9483dfc8kf467").Result;
var decryptionCertPassword = decryptionCertPasswordBundle.Value;
using var stream = new MemoryStream(decryptionCertBytes);
temporarySecurityMimeContext.Import(stream, decryptionCertPassword);
log.LogInformation("Imported The Decryption certificate as MemoryStream");
using var encryptedContentStream = await GetMailAttachmentStreamAsync(req.Body, log) ;
log.LogInformation("Loading pkcs7-mime entity.");
ApplicationPkcs7Mime encryptedContent = (ApplicationPkcs7Mime)await MimeEntity.LoadAsync(ParserOptions.Default, ContentType.Parse(ParserOptions.Default, "application/pkcs7-mime; smime-type=enveloped-data; name=smime.p7m"), encryptedContentStream);
log.LogInformation("Decrypting pkcs7-mime entity.");
MimeEntity decryptedContent = encryptedContent.Decrypt();
return new OkObjectResult("OK");
}
catch (Exception ex)
{
log.LogError(ex, "Failed to decrypt the secure mime part in the request body.");
throw;
}
}
private static async Task<MemoryStream> GetMailAttachmentStreamAsync(Stream attachmentObjectStream, ILogger log)
{
var memoryStream = new MemoryStream();
await attachmentObjectStream.CopyToAsync(memoryStream);
memoryStream.Seek(0, SeekOrigin.Begin);
log.LogInformation($"Attachment Stream Processed. {memoryStream.Length} Bytes");
return memoryStream;
}
证书加载成功。电子邮件流也显示一些数据。但是运行解密时,总是报错。任何帮助都会有所帮助。
下面是您的代码并进行了一些修复(即删除像 MethodAsync(...).Result
这样的错误做法的代码)。
我还冒昧地添加了一条大评论,要求提供更多信息。
[FunctionName("DecryptSMIME")]
public static async Task<IActionResult> Decrypt([HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req, ILogger log)
{
try
{
using var temporarySecurityMimeContext = new TemporarySecureMimeContext();
// get decryption Cert pfx
var keyVaultClient = ServiceProvider.GetRequiredService<IKeyVaultClient>();
var decryptionCertBundle = await keyVaultClient.GetSecretAsync("https://my-key-vault.vault.azure.net/secrets/Decryption-Certificate-Base64/d7a84b415a494c1ebaseae88cff50028");
var decryptionCertBytes = Convert.FromBase64String(decryptionCertBundle.Value);
log.LogInformation($"Decoded length of decryption certificate: '{decryptionCertBytes.Length}'");
// get decryption Cert password
var decryptionCertPasswordBundle = await keyVaultClient.GetSecretAsync("https://my-key-vault.vault.azure.net/secrets/Decryption-Certificate-Pass/34judc9f575f467a96d9483dfc8kf467");
var decryptionCertPassword = decryptionCertPasswordBundle.Value;
using var stream = new MemoryStream(decryptionCertBytes);
temporarySecurityMimeContext.Import(stream, decryptionCertPassword);
log.LogInformation("Imported The Decryption certificate as MemoryStream");
using var encryptedContentStream = await GetMailAttachmentStreamAsync(req.Body, log) ;
log.LogInformation("Loading pkcs7-mime entity.");
// Ideally, you would not use the MimeEntity.LoadAsync() method that takes a
// forged ContentType parameter. This is a huge hack and *may* be the cause
// of your problem. In other words, the content that MimeKit is trying to
// decrypt may be in the wrong format. To know for certain, I would need to
// know what the HttpRequest headers and Body look like.
//
// I would probably recommend that your code that sends this request be
// modified to send the entire raw MIME (i.e. including headers) of the
// application/pkcs7-mime part as the HTTP request body instead so that you
// would not need to forge the Content-Type header.
ApplicationPkcs7Mime encryptedContent = (ApplicationPkcs7Mime)await MimeEntity.LoadAsync(ParserOptions.Default, ContentType.Parse(ParserOptions.Default, "application/pkcs7-mime; smime-type=enveloped-data; name=smime.p7m"), encryptedContentStream);
log.LogInformation("Decrypting pkcs7-mime entity.");
MimeEntity decryptedContent = encryptedContent.Decrypt();
return new OkObjectResult("OK");
}
catch (Exception ex)
{
log.LogError(ex, "Failed to decrypt the secure mime part in the request body.");
throw;
}
}
private static async Task<MemoryStream> GetMailAttachmentStreamAsync(Stream attachmentObjectStream, ILogger log)
{
var memoryStream = new MemoryStream();
await attachmentObjectStream.CopyToAsync(memoryStream);
memoryStream.Seek(0, SeekOrigin.Begin);
log.LogInformation($"Attachment Stream Processed. {memoryStream.Length} Bytes");
return memoryStream;
}