解密 EnvelopedCms 不会双重展开
在 macOS 和 Linux 上的 .NET Core 2.0 中,EnvelopedCms 实现错误地将内容包装在额外的 ASN.1 OCTET STRING 值中。 为了在处理因此错误而创建的内容时保持兼容性,EnvelopedCms 类仍会查看解密内容,并尝试删除额外数据。 EnvelopedCms 在 Windows 上使用外部私钥时删除了额外数据,在所有其他操作系统上进行解密时也删除了这些数据。
遗憾的是,这种机会主义的兼容性代码无法区分错误创建的文档和正确创建但具有相同数据形状的文档。
旧行为
以前,如果解密的内容以字节值 0x04
开头,并且是一个合法编码的 ASN.1 BER 长度值(该值小于或等于内容中剩余的字节数),则 envelopedCms.ContentInfo.Content
属性中提供的数据在被视为 ASN.1 OCTET STRING 时只会收到与该值的内容八进制部分关联的数据。
例如,如果最初解密的内容是字节系列 { 0x04, 0x03, 0x01, 0x02, 0x03 }
或 { 0x04, 0x03, 0x01, 0x02, 0x03, [continued content] }
,则 envelopedCms.ContentInfo.Content
的值为字节序列 { 0x01, 0x02, 0x03 }
。
会完全报告不以 0x04
开头或以 0x04
开头但未遵循可接受编码长度值的值。
对于 EnvelopedCms.Decrypt 的某些重载,此行为仅在非 Windows 操作系统上发生。 有关详细信息,请参阅受影响的 API。
新行为
EnvelopedCms 类不再尝试解决上一个问题,并且始终忠实地报告解密内容。
如果要处理由 macOS 或 Linux 上 EnvelopedCms 类的 .NET Core 2.0 版本创建的文档,你将在内容开头看到额外的数据。
引入的版本
.NET 7
中断性变更的类型
此项更改可能会影响二进制兼容性。
更改原因
兼容性代码无法区分错误创建的文档和正在合法传输数据的文档(类似于 BER 编码的 ASN.1 OCTET STRING)。
由于 BER 编码的性质,受到此兼容性代码负面影响的调用方无法轻易恢复丢失的数据。
建议的操作
读取使用适用于 macOS 或 Linux 的 .NET Core 2.0 上的 EnvelopedCms 创建的文档的调用方可以添加代码来删除额外的数据。 若要将其删除,请使用 System.Formats.Asn1 NuGet 包中的 AsnDecoder 类,该包已是 EnvelopedCms 类的依赖项。
envelopedCms.Decrypt(...);
byte[] content = envelopedCms.ContentInfo.Content;
if (envelopedCms.ContentInfo.Oid.Value == "1.2.840.113549.1.7.1")
{
if (content?.Length > 0 && content[0] == 0x04)
{
try
{
content = AsnDecoder.ReadOctetString(content, AsnEncodingRules.BER, out _);
}
catch (AsnContentException)
{
}
}
}
受影响的 API
- System.Security.Cryptography.Pkcs.EnvelopedCms.Decrypt(RecipientInfo, AsymmetricAlgorithm)
- System.Security.Cryptography.Pkcs.EnvelopedCms.Decrypt(RecipientInfo, X509Certificate2Collection)(仅限非 Windows)
- System.Security.Cryptography.Pkcs.EnvelopedCms.Decrypt(RecipientInfo)(仅限非 Windows)
- System.Security.Cryptography.Pkcs.EnvelopedCms.Decrypt(X509Certificate2Collection)(仅限非 Windows)