首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何解密PKCS7消息

如何解密PKCS7消息
EN

Stack Overflow用户
提问于 2021-07-23 16:22:22
回答 1查看 3.7K关注 0票数 0

我无法在C#中解密一些XML文件。

我对密码学知之甚少,但据我所知,我有一个密码保护证书,包含一个私钥和一个公钥。

通过将密码应用于证书,我将获得解密所接收文件所需的私钥。

我想解密的消息驻留在PKCS7 (CMS?)格式化文件。我想我需要解析这些文件,解密它们,然后不签字。

我不知道该怎么做。我已经尝试了我发现的工具,这是显而易见的候选人,以帮助我完成这项任务,但我无法使它工作。

在这一点上,我真的想知道,有什么是我不理解的吗?还是我用错了工具来做这份工作?

下面是我在一堆代码中的一些尝试:

代码语言:javascript
复制
public string DecryptFailingExample()
{
    var content = File.ReadAllBytes("encryptedFileWithDataThatIWant.xml.enc");
    var cert = new X509Certificate2("certificateFile.pfx", "PasswordForFile");

    //This code didn't work. rsa.Decrypt would throw: "The length of the data to decrypt is not valid for the size of this key."
    //using RSA rsa = cert.GetRSAPrivateKey();
    //var decryptedBytes = rsa.Decrypt(content, RSAEncryptionPadding.OaepSHA1); //I tried all possible paddings - Nothing worked


    //So I tried this instead:
    SignedCms signedCms = new SignedCms();
    signedCms.Decode(content); //Crash: ASN1 corrupted data; The provided data is tagged with 'Universal' class value '13', but it should have been 'Universal' class value '16'.
    var ecms = new EnvelopedCms();
    
    //If I try to skip SignedCms and pass "content" directly to EnvelopedCms, I will get: "ASN1 bad tag value met."
    ecms.Decode(signedCms.ContentInfo.Content); //Crash: 
    ecms.Decrypt(new X509Certificate2Collection(cert));
}

这就是我想解密的消息:

--开始PKCS7 7

MIAGCSqGSIb3DQEHA6BAMIACAQAxggGEMIIBgAIBADBoMFExCzAJBgNVBAYTAkRF MSQwIgYDVQQKExtFdXJvcGVhbiBFbmVyZ3kgRXhjaGFuZ2UgQUcxHDAaBgNVB4MT

3nPyd3c9iGyKhWdQPPr/SRWB/l9bCjkla81MgTcj1rRGQyPJXpkyxpc9U4YYZnxt eHkcJMVWDw9ErThok8nh/7bkE4KbWBaLZAac+9occ4deDrlu0wAAAAAAAAAAAAA=

-结束PKCS7 7

编辑:这里是另一个不起作用的最小示例。

代码语言:javascript
复制
//Step 1: Load PKCS7 message from disk
var content = File.ReadAllBytes("encryptedFileWithDataThatIWant.xml.enc");

//Step 2: Load .pfx certificate from disk 
var cert = new X509Certificate2("certificateFile.pfx", "Password");

//Step 3: Create instance of EnvelopedCms
var ecms = new EnvelopedCms();

//Step 4: Add certificate for decoding
ecms.Certificates.Add(cert);

//Step 5: Decode the PKCS7 message
ecms.Decode(content); //Internal.Cryptography.CryptoThrowHelper.WindowsCryptographicException: 'ASN1 bad tag value met.'

除了.PFX文件之外,我还拥有一个带有私有证书的PEM文件。看起来是这样的:

-开始RSA私钥

Proc类型: 4,加密DEK-Info: AES-256-CBC,915538553FEFBA6A98930E4BFFDA1E68

Pk0FHxXNHukA62FSmuzzE+gqHgeauZr6z+lqTcbf55cakrQzHQOQUnR0w5kCFPPg

L7U2cWJpbNsRNmBcTyH1WWJ4hYoCqdl9G6Zey4y/EQbZl1DKXtmIiLZSneF0VU9u

-最终RSA私钥

我试过像这样导入密钥,但这似乎行不通:

代码语言:javascript
复制
var pem = File.ReadAllBytes("pemFile.pem");
var pemChars = Encoding.UTF8.GetString(pem);
var rsa = RSA.Create();
rsa.ImportFromEncryptedPem(pemChars, "Password"); //System.ArgumentException: 'No supported key formats were found. Check that the input represents the contents of a PEM-encoded key file, not the path to such a file. (Parameter 'input')'
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-07-26 09:16:48

明白了!

感谢@MaartenBodewes让我走上正轨。我想解码的文件不是二进制文件,而是文本文件。将文件读取为文本,然后转换为二进制文件,就足以使其工作。

工作代码看起来大致是这样的,并且可以根据我的具体情况进一步简化。实际上,它将处理PKCS7和CMS标记+二进制和文本文件。

代码语言:javascript
复制
public string Decrypt()
{
    var ecms = Read("encryptedFileWithDataThatIWant.xml.enc");
    var cert = new X509Certificate2("certificateFile.pfx", "Password");
    ecms.Decrypt(new X509Certificate2Collection{cert});
    return Encoding.UTF8.GetString(ecms.ContentInfo.Content);
}

private static EnvelopedCms Read(string fileName)
{
    //Try read as binary
    var maybeFirstException = TryRead(File.ReadAllBytes(fileName), out var ecms);
    if (maybeFirstException is null)
    {
        return ecms;
    }

    //Otherwise read as text, convert to binary and try again
    var text = File
        .ReadAllText(fileName)
        .Replace("-----BEGIN PKCS7-----", string.Empty)
        .Replace("-----BEGIN CMS-----", string.Empty)
        .Replace("-----END PKCS7-----", string.Empty)
        .Replace("-----END CMS-----", string.Empty);

    
    var binary = Convert.FromBase64String(text);
        
    var maybeSecondException = TryRead(binary, out ecms);
    if (maybeSecondException is null)
    {
        return ecms;
    }

    throw new AggregateException("Tried to decode file as both binary and text, but both attempts failed", new List<Exception>
    {
        maybeFirstException,
        maybeSecondException
    });
}

private static Exception TryRead(byte[] bytes, out EnvelopedCms ecms)
{
    ecms = new EnvelopedCms();
    try
    {
        ecms.Decode(bytes);
        return null;
    }
    catch (CryptographicException e)
    {
        return e;
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68502279

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档