.NET Core 2.1-3.0 的加密中断性变更

此页上记录了以下重大更改:

破坏性变更 已引入的版本
Linux 上不再支持 BEGIN TRUSTED CERTIFICATE 语法 3.0
EnvelopedCms 默认为 AES-256 加密 3.0
RSAOpenSsl 密钥生成的最小大小已增加 3.0
.NET Core 3.0 更喜欢 OpenSSL 1.1.x 到 OpenSSL 1.0.x 3.0
CryptoStream.Dispose 仅在执行写入操作时才转换最终块 3.0
已考虑 SignedCms.ComputeSignature 的布尔参数 2.1

.NET Core 3.0

Linux 上的根证书不再支持“BEGIN TRUSTED CERTIFICATE”语法

Linux 和其他类似 Unix 的系统(但不能是 macOS)上的根证书可以采用两种形式显示:标准 BEGIN CERTIFICATE PEM 标头和特定于 OpenSSL 的 BEGIN TRUSTED CERTIFICATE PEM 标头。 后一种语法允许进行额外的配置,从而导致 .NET Core 的 System.Security.Cryptography.X509Certificates.X509Chain 类出现兼容性问题。 BEGIN TRUSTED CERTIFICATE 从 .NET Core 3.0 开始的链引擎不再加载根证书内容。

更改描述

以前,语法BEGIN CERTIFICATEBEGIN TRUSTED CERTIFICATE用于填充根信任列表。 如果使用了BEGIN TRUSTED CERTIFICATE语法,并且文件中指定了其他选项,那么X509Chain可能会报告明确禁止链信任(X509ChainStatusFlags.ExplicitDistrust)。 不过,如果在以前加载的文件中,也使用 BEGIN CERTIFICATE 语法指定了证书,则允许链信任。

从 .NET Core 3.0 开始, BEGIN TRUSTED CERTIFICATE 不再读取内容。 如果未通过标准 BEGIN CERTIFICATE 语法指定证书,则 X509Chain 报告根不受信任(X509ChainStatusFlags.UntrustedRoot)。

已引入的版本

3.0

大多数应用程序不受此更改的影响,但由于权限问题而看不到这两个根证书源的应用程序在升级后可能会遇到意外 UntrustedRoot 错误。

许多 Linux 发行版将根证书写入两个位置:一个目录中每个文件包含一个证书,以及将多个证书串联到一个文件中。 在某些发行版中,一个文件对应一个证书的目录使用BEGIN TRUSTED CERTIFICATE语法,而文件合并使用标准BEGIN CERTIFICATE语法。 确保将任何自定义根证书以BEGIN CERTIFICATE的格式添加到至少一个位置,并确保应用程序能够读取这两个位置。

典型目录为 /etc/ssl/certs/ ,典型的串联文件为 /etc/ssl/cert.pem。 使用命令 openssl version -d 确定特定于平台的根,这可能与 /etc/ssl/不同。 例如,在 Ubuntu 18.04 上,目录为 /usr/lib/ssl/certs/ ,文件为 /usr/lib/ssl/cert.pem。 但是,/usr/lib/ssl/certs/ 是指向 /etc/ssl/certs/ 的符号链接,而 /usr/lib/ssl/cert.pem 不存在。

$ openssl version -d
OPENSSLDIR: "/usr/lib/ssl"
$ ls -al /usr/lib/ssl
total 12
drwxr-xr-x  3 root root 4096 Dec 12 17:10 .
drwxr-xr-x 73 root root 4096 Feb 20 15:18 ..
lrwxrwxrwx  1 root root   14 Mar 27  2018 certs -> /etc/ssl/certs
drwxr-xr-x  2 root root 4096 Dec 12 17:10 misc
lrwxrwxrwx  1 root root   20 Nov 12 16:58 openssl.cnf -> /etc/ssl/openssl.cnf
lrwxrwxrwx  1 root root   16 Mar 27  2018 private -> /etc/ssl/private

类别

密码学

受影响的 API


EnvelopedCms 默认为 AES-256 加密

使用 EnvelopedCms 的默认对称加密算法已从 TripleDES 更改为 AES-256。

更改描述

在以前的版本中,当使用EnvelopedCms加密数据而不通过构造函数重载指定对称加密算法时,数据将使用 TripleDES/3DES/3DEA/DES3-EDE 算法进行加密。

从 .NET Core 3.0(通过 System.Security.Cryptography.Pkcs NuGet 包的版本 4.6.0 开始),默认算法已更改为 AES-256,实现算法现代化,并提高默认选项的安全性。 如果消息收件人证书具有(非 EC)Diffie-Hellman 公钥,则由于底层平台的限制,加密操作可能会失败并显示 CryptographicException

在以下示例代码中,如果在 .NET Core 2.2 或更早版本上运行,则使用 TripleDES 加密数据。 如果在 .NET Core 3.0 或更高版本上运行,则使用 AES-256 对其进行加密。

EnvelopedCms cms = new EnvelopedCms(content);
cms.Encrypt(recipient);
return cms.Encode();

已引入的版本

3.0

如果受到更改的负面影响,可以通过显式指定包含类型EnvelopedCms参数的构造函数中的AlgorithmIdentifier加密算法标识符来还原 TripleDES 加密,例如:

Oid tripleDesOid = new Oid("1.2.840.113549.3.7", null);
AlgorithmIdentifier tripleDesIdentifier = new AlgorithmIdentifier(tripleDesOid);
EnvelopedCms cms = new EnvelopedCms(content, tripleDesIdentifier);

cms.Encrypt(recipient);
return cms.Encode();

类别

密码学

受影响的 API


RSAOpenSsl 密钥生成的最小大小已增加

在 Linux 上生成新 RSA 密钥的最小大小已从 384 位增加到 512 位。

更改描述

从 .NET Core 3.0 开始,Linux 上LegalKeySizesRSA.CreateRSAOpenSsl的 RSA 实例中RSACryptoServiceProvider属性报告的最小法定密钥大小已从 384 增加到 512。

因此,在 .NET Core 2.2 和更早版本中,像 RSA.Create(384) 这样的方法调用能够成功。 在 .NET Core 3.0 及更高版本中,方法调用 RSA.Create(384) 会引发一个异常,指示大小太小。

之所以进行此更改是因为在 Linux 上执行加密作的 OpenSSL 在版本 1.0.2 和 1.1.0 之间提高了其最小值。 .NET Core 3.0 更喜欢 OpenSSL 1.1.x 到 1.0.x,并且提出了最低报告版本以反映这一新的更高依赖项限制。

已引入的版本

3.0

如果调用任何受影响的 API,请确保任何生成的密钥的大小不小于提供程序的最小值。

注释

384 位 RSA 已被视为不安全(与 512 位 RSA 一样)。 新式建议(如 NIST 特殊出版物 800-57 第 1 版 4)建议 2048 位作为新生成的密钥的最低大小。

类别

密码学

受影响的 API


.NET Core 3.0 更偏好 OpenSSL 1.1.x 而不是 OpenSSL 1.0.x

适用于 Linux 的 .NET Core 可跨多个 Linux 分发版工作,可同时支持 OpenSSL 1.0.x 和 OpenSSL 1.1.x。 .NET Core 2.1 和 .NET Core 2.2 先查找 1.0.x,然后回退到 1.1.x;.NET Core 3.0 首先查找 1.1.x。 此更改是为了添加对新加密标准的支持。

此更改可能会影响库或应用程序,这些库或应用程序与 .NET Core 中的 OpenSSL 特定互操作类型进行平台互操作。

更改描述

在 .NET Core 2.2 及更早版本中,运行时更喜欢加载 OpenSSL 1.0.x 而不是 1.1.x。 这意味着,与 OpenSSL 互操作的 IntPtrSafeHandle 类型倾向于与 libcrypto.so.1.0.0 / libcrypto.so.1.0 / libcrypto.so.10 一起使用。

从 .NET Core 3.0 开始,运行时优先加载 OpenSSL 1.1.x 而不是 OpenSSL 1.0.x,因此 IntPtrSafeHandle 类型用于与 OpenSSL 互操作时优先使用 libcrypto.so.1.1 / libcrypto.so.11 / libcrypto.so.1.1.0 / libcrypto.so.1.1.1。 因此,从 .NET Core 2.1 或 .NET Core 2.2 升级时,与 OpenSSL 直接互操作的库和应用程序的指针可能与 .NET Core 公开的值不兼容。

已引入的版本

3.0

进行直接操作的库和应用程序需要谨慎,以确保它们使用与 .NET Core 运行时相同的 OpenSSL 版本。

所有使用 .NET Core 加密类型中的 IntPtrSafeHandle 值并直接与 OpenSSL 交互的库或应用程序,都应将它们使用的库版本与新 SafeEvpPKeyHandle.OpenSslVersion 属性进行比较,以确保指针兼容。

类别

密码学

受影响的 API


CryptoStream.Dispose 仅在写入时转换最终块

用于完成 CryptoStream.Dispose 操作的 CryptoStream 方法不再尝试在读取时转换最终块。

更改描述

在以前的 .NET 版本中,如果用户在CryptoStream模式下使用Read执行了不完整的读取,方法Dispose可能会引发异常(例如,AES 算法使用填充时)。 引发异常的原因是尝试转换最终块,但数据不完整。

在 .NET Core 3.0 及更高版本中, Dispose 在读取时不再尝试转换最终块,这允许不完整的读取。

更改原因

此更改使得在网络操作被取消时,可以从加密流中进行不完整的读取,而无需捕获异常。

已引入的版本

3.0

大多数应用不应受到此更改的影响。

如果应用程序之前在读取不完整时捕获了异常,则可以删除该 catch 块。 如果应用在哈希方案中使用了最终块的转换,则可能需要确保在释放所有流之前先对其进行读取。

类别

密码学

受影响的 API


.NET Core 2.1

在 SignedCms.ComputeSignature 中,布尔参数得到遵守

在 .NET Core 中,silent 方法的布尔SignedCms.ComputeSignature(CmsSigner, Boolean)参数会被遵循。 如果此参数设置为 true,则不会显示 PIN 提示。

更改描述

在 .NET Framework 中,silent 方法的 SignedCms.ComputeSignature(CmsSigner, Boolean) 参数会被忽略,如果提供程序需要,仍然会始终显示 PIN 提示。 在 .NET Core 中, silent 将遵循该参数,如果设置为 true该参数,则永远不会显示 PIN 提示,即使提供程序需要该提示。

在 2.1 版的 .NET Core 中引入了对 CMS/PKCS #7 消息的支持。

已引入的版本

2.1

若要确保出现 PIN 提示(如果需要),桌面应用程序应调用 SignedCms.ComputeSignature(CmsSigner, Boolean) 布尔参数并将其设置为 false。 无论在 .NET Framework 中是否禁用无提示上下文,生成的行为都与 .NET Framework 上的行为相同。

类别

密码学

受影响的 API