.NET 8解密AES128GCM加密的PKCS7-envelopedData文件方案
AES-128-GCM加密的PKCS7-envelopedData文件解密解决方案分享
我有一个采用AES-128-GCM加密的PKCS7-envelopedData格式加密文件,耗时两天多排查解决,发现不少人遇到同类问题,特分享最终可行的解密步骤。
文件的OpenSSL解析信息如下:
contentType: pkcs7-envelopedData (1.2.840.113549.1.7.3) encryptedContentInfo: contentType: pkcs7 - data( 1.2.840.113549.1.7.1 ) contentEncryptionAlgorithm: algorithm: aes - 128 - gcm( 2.16.840.1.101.3.4.1.6 ) parameter: SEQUENCE: 0:d = 0 hl = 2 l = 17 cons: SEQUENCE 2:d = 1 hl = 2 l = 12 prim: OCTET STRING[ HEX DUMP ]:17B3CFB9CA81F40E16E2C253 16:d = 1 hl = 2 l = 1 prim: INTEGER: 10
尝试.NET 8自带API失败
在Windows 11环境下,首先尝试使用.NET 8内置的EnvelopedCms类解密,但失败:
byte[] encryptedData = File.ReadAllBytes(@"D:\EBT.enc"); X509Certificate2 certificate = new X509Certificate2(@"D:\EBT_ENCR.PFX", "Abc123"); X509Certificate2Collection coll = new X509Certificate2Collection(); coll.Add(certificate); EnvelopedCms cms = new EnvelopedCms(); System.Security.Cryptography.Pkcs.ContentInfo content = new System.Security.Cryptography.Pkcs.ContentInfo(encryptedData); cms.Decode(encryptedData); // 报错:The OID value is invalid. cms.Decode(content.Content);// 报错:The OID value is invalid. cms.Decrypt(coll);
失败原因:.NET 8原生不支持AES-128-GCM算法的PKCS7解密。
尝试Portable.BouncyCastle 1.9.0失败
改用Portable.BouncyCastle 1.9.0版本尝试解密,但遇到类型转换异常:
// Portable.BouncyCastle 1.9.0 MemoryStream ms = new MemoryStream(File.ReadAllBytes(@"D:\EBT_ENCR.PFX")); Org.BouncyCastle.Pkcs.Pkcs12Store st = new Org.BouncyCastle.Pkcs.Pkcs12Store(ms, "Abc123".ToCharArray()); AsymmetricKeyEntry k = null; foreach (Object a in st.Aliases) { if (st.IsKeyEntry((String)a)) { k = st.GetKey((String)a); } } CmsEnvelopedData ced = new CmsEnvelopedData(encryptedData); RecipientInformationStore rec = ced.GetRecipientInfos(); foreach (RecipientInformation r in rec.GetRecipients()) { String sn = r.RecipientID.SerialNumber.ToString(16).ToUpperInvariant(); if (sn == certificate.SerialNumber) { byte[] res = r.GetContent(k.Key); // 此处报错 File.WriteAllBytes(@"D:\EBT_res.zip", res); } }
报错信息:
// ParameterUtilities.cs, canonical = "AES128" ICipherParameters GetCipherParameters( ... int basicIVKeySize = FindBasicIVSize(canonical); if (basicIVKeySize != -1 || canonical == "RIJNDAEL" || canonical == "SKIPJACK" || canonical == "TWOFISH") { iv = ((Asn1OctetString) asn1Params).GetOctets(); // Unable to cast object of type 'Org.BouncyCastle.Asn1.DerSequence' to type 'Org.BouncyCastle.Asn1.Asn1OctetString'. } ...
使用BouncyCastle.Cryptography 2.3.0成功解密
升级到BouncyCastle.Cryptography.dll 2.3.0.53016版本,调整证书加载方式后成功解密:
错误的证书加载方式(失败)
最初尝试导出证书再加载,遇到私钥不可导出的异常:
Org.BouncyCastle.Pkcs.Pkcs12Store st = new Org.BouncyCastle.Pkcs.Pkcs12StoreBuilder().Build(); MemoryStream stream = new MemoryStream(certificate.Export(X509ContentType.Pfx, "Abc123")); // 报错:Key not valid for use in specified state // StorePal.Windows.Export.cs: // if (!Interop.Crypt32.PFXExportCertStore( _certStore, ref dataBlob, password, Interop.Crypt32.PFXExportFlags.EXPORT_PRIVATE_KEYS | Interop.Crypt32.PFXExportFlags.REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY )) // throw Marshal.GetHRForLastWin32Error().ToCryptographicException(); // 使用X509ContentType.Pkcs12也会报同样错误 st.Load(stream, "Abc123".ToCharArray());
尝试用证书原始数据加载,同样失败:
MemoryStream stream = new MemoryStream(certificate.RawData);
报错:illegal object in GetInstance: Org.BouncyCastle.Asn1.DLSequence,错误来自DerInteger.cs:
throw new ArgumentException("illegal object in GetInstance: " + Platform.GetTypeName(obj));
正确的证书加载方式(成功)
直接读取PFX文件的原始字节流加载,成功加载证书及私钥:
byte[] certificateRawData = File.ReadAllBytes(@"D:\EBT_ENCR.pfx"); MemoryStream stream = new MemoryStream(certificateRawData); Org.BouncyCastle.Pkcs.Pkcs12Store st = new Org.BouncyCastle.Pkcs.Pkcs12StoreBuilder().Build(); st.Load(stream, "Abc123".ToCharArray());
加载成功后,沿用Portable.BouncyCastle版本中的剩余解密代码即可完成解密。
内容的提问来源于stack exchange,提问作者Sleepy
相关产品推荐
相关产品推荐

