Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/270.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用mimekit解密带有附件的电子邮件_C#_Email Attachments_Pkcs#7_Smime_Mimekit - Fatal编程技术网

C# 使用mimekit解密带有附件的电子邮件

C# 使用mimekit解密带有附件的电子邮件,c#,email-attachments,pkcs#7,smime,mimekit,C#,Email Attachments,Pkcs#7,Smime,Mimekit,我们有一个方案来解密带有附件的电子邮件。我们使用的是mimekit库。我们还使用mimekit进行电子邮件加密,它工作正常 在我们的例子中,加密的电子邮件只有一个附件,没有这样的电子邮件正文。有一个Azure逻辑应用程序,它从Oiifce365邮箱(使用内置连接器)获取加密电子邮件,然后将详细信息发送到运行解密逻辑的Azure函数应用程序。解密证书存储在Azure密钥库中 下面是我们尝试过的代码,它显示异常 无法将类型为“Org.BouncyCastle.Asn1.DerApplicationS

我们有一个方案来解密带有附件的电子邮件。我们使用的是
mimekit
库。我们还使用
mimekit
进行电子邮件加密,它工作正常

在我们的例子中,加密的电子邮件只有一个附件,没有这样的电子邮件正文。有一个Azure
逻辑应用程序
,它从Oiifce365邮箱(使用内置连接器)获取加密电子邮件,然后将详细信息发送到运行解密逻辑的
Azure函数应用程序
。解密证书存储在Azure密钥库中

下面是我们尝试过的代码,它显示异常

无法将类型为“Org.BouncyCastle.Asn1.DerApplicationSpecific”的对象强制转换为类型为“Org.BouncyCastle.Asn1.Asn1SequenceParser”

[FunctionName(“decryptsime”)]
公共静态异步任务解密([HttpTrigger(AuthorizationLevel.Function,“post”,Route=null)]HttpRequest请求,ILogger日志)
{
尝试
{
var temporarySecurityTimeContext=新的TemporarySecureMimeContext();
//获取解密证书pfx
var keyVaultClient=ServiceProvider.GetRequiredService();
var decryptionCertBundle=keyVaultClient.GetSecretAsync(“https://my-key-vault.vault.azure.net/secrets/Decryption-Certificate-Base64/d7a84b415a494c1ebaseae88cff50028三、结果;
var decryptionCertBytes=Convert.FromBase64String(decryptionCertBundle.Value);
log.LogInformation($“解密证书的解码长度:{decryptionCertBytes.length}”);
//获取解密证书密码
var decryptionCertPasswordBundle=keyVaultClient.GetSecretAsync(“https://my-key-vault.vault.azure.net/secrets/Decryption-Certificate-Pass/34judc9f575f467a96d9483dfc8kf467三、结果;
var decryptionCertPassword=decryptionCertPasswordBundle.Value;
使用var stream=newmemoryStream(decryptionCertBytes);
导入(流,解密证书密码);
log.LogInformation(“将解密证书作为MemoryStream导入”);
使用var encryptedContentStream=wait GetMailAttachmentStreamAsync(req.Body,log);
log.LogInformation(“加载pkcs7 mime实体”);
ApplicationPkcs7Mime encryptedContent=(ApplicationPkcs7Mime)Wait MimeEntity.LoadAsync(ParserOptions.Default,ContentType.Parse(ParserOptions.Default,“应用程序/pkcs7 mime;smime类型=封装数据;名称=smime.p7m”)、encryptedContentStream);
LogInformation(“解密pkcs7 mime实体”);
MimeEntity decryptedContent=encryptedContent.Decrypt();
返回新的OkObjectResult(“OK”);
}
捕获(例外情况除外)
{
LogError(例如,“未能解密请求正文中的安全mime部分”);
投掷;
}
}
私有静态异步任务GetMailAttachmentStreamAsync(流AttachmentObject流,ILogger日志)
{
var memoryStream=新的memoryStream();
等待attachmentObjectStream.CopyToAsync(memoryStream);
memoryStream.Seek(0,SeekOrigin.Begin);
log.LogInformation($“已处理附件流。{memoryStream.Length}字节”);
返回内存流;
}

证书正在成功加载。电子邮件流还显示一些数据。但是,在运行解密时,它也会显示错误。任何帮助都会很有帮助。

下面是您的代码和一些修复程序(即摆脱类似
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;
}
[FunctionName(“decryptsime”)]
公共静态异步任务解密([HttpTrigger(AuthorizationLevel.Function,“post”,Route=null)]HttpRequest请求,ILogger日志)
{
尝试
{
使用var temporarySecurityTimeContext=new TemporarySecureMimeContext();
//获取解密证书pfx
var keyVaultClient=ServiceProvider.GetRequiredService();
var decryptionCertBundle=等待keyVaultClient.GetSecretAsync(“https://my-key-vault.vault.azure.net/secrets/Decryption-Certificate-Base64/d7a84b415a494c1ebaseae88cff50028");
var decryptionCertBytes=Convert.FromBase64String(decryptionCertBundle.Value);
log.LogInformation($“解密证书的解码长度:{decryptionCertBytes.length}”);
//获取解密证书密码
var decryptionCertPasswordBundle=等待keyVaultClient.GetSecretAsync(“https://my-key-vault.vault.azure.net/secrets/Decryption-Certificate-Pass/34judc9f575f467a96d9483dfc8kf467");
var decryptionCertPassword=decryptionCertPasswordBundle.Value;
使用var stream=newmemoryStream(decryptionCertBytes);
导入(流,解密证书密码);
log.LogInformation(“将解密证书作为MemoryStream导入”);
使用var encryptedContentStream=wait GetMailAttachmentStreamAsync(req.Body,log);
log.LogInformation(“加载pkcs7 mime实体”);
//理想情况下,您不会使用接受
//伪造的ContentType参数。这是一个巨大的黑客攻击,*可能*是原因
//你的问题。换句话说,MimeKit正在尝试的内容
//解密的格式可能不正确。要确定,我需要
//知道HttpRequest头和正文是什么样子的。
//
//我可能会建议您发送此请求的代码
//修改为发送
//将application/pkcs7 mime部分改为HTTP请求主体,以便
[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;
}