Cryptography breaking changes

Important

This article is under construction. This is not a complete list of .NET Core breaking changes. For more information on .NET Core breaking changes, you can examine individual breaking changes issues in the dotnet/docs repository on GitHub.

The following is a list of cryptography-related breaking changes by .NET Core version.

.NET Core 3.0 Preview 9

Better argument validation in the Pkcs8PrivateKeyInfo constructor

Starting with .NET Core 3.0 Preview 9, the Pkcs8PrivateKeyInfo constructor validates the algorithmParameters parameter as a single BER-encoded value.

Change description

Before .NET Core 3.0 Preview 9, the Pkcs8PrivateKeyInfo constructor did not validate the algorithmParameters argument. When this argument represented an invalid value, the constructor would succeed, but a call to any of the Encode(), TryEncode, Encrypt, or TryEncrypt methods would throw either an ArgumentException for an argument they did not accept (preEncodedValue) or a CryptographicException.

If run with .NET Core 3.0 before Preview 9, the following code throws an exception only when the Encode() method is called:

byte[] algorithmParameters = { 0x05, 0x00, 0x05, 0x00 };

var info = new Pkcs8PrivateKeyInfo(algorithmId, algorithmParameters, privateKey);
// This line throws an ArgumentException for `preEncodedValue`:
byte[] encoded = info.Encode();

Starting with .NET Core 3.0 Preview 9, the argument is validated in the constructor, and an invalid value results in the method throwing a CryptographicException. This change moves the exception closer to the source of the data error. For example:

byte[] algorithmParameters = { 0x05, 0x00, 0x05, 0x00 };

// This line throws a CryptographicException
var info = new Pkcs8PrivateKeyInfo(algorithmId, algorithmParameters, privateKey);

Version introduced

3.0 Preview 9

Ensure that only valid algorithmParameters values are provided, or that calls to the Pkcs8PrivateKeyInfo constructor test for both ArgumentException and CryptographicException if exception handling is desired.

Category

Cryptography

Affected APIs

.NET Core 3.0

EnvelopedCms defaults to AES-256 encryption

The default symmetric encryption algorithm used by EnvelopedCms has changed from TripleDES to AES-256.

Change description

In .NET Core Preview 7 and earlier versions, when EnvelopedCms is used to encrypt data without specifying a symmetric encryption algorithm via a constructor overload, the data was encrypted with the TripleDES/3DES/3DEA/DES3-EDE algorithm.

Starting with .NET Core 3.0 Preview 8 (via version 4.6.0 of the System.Security.Cryptography.Pkcs NuGet package), the default algorithm has been changed to AES-256 for algorithm modernization and to improve the security of default options. If a message recipient certificate has a (non-EC) Diffie-Hellman public key, the encryption operation may fail with a CryptographicException due to limitations in the underlying platform.

In the following sample code, the data is encrypted with TripleDES if running on .NET Core 3.0 Preview 7 or earlier. If running on .NET Core 3.0 Preview 8 or later, it is encrypted with AES-256.

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

Version introduced

3.0 Preview 8

If you are negatively impacted by the change, you can restore TripleDES encryption by explicitly specifying the encryption algorithm identifier in an EnvelopedCms constructor that includes a parameter of type AlgorithmIdentifier, such as:

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()l

Category

Cryptography

Affected APIs


Minimum size for RSAOpenSsl key generation has increased

The minimum size for generating new RSA keys on Linux has increased from 384-bit to 512-bit.

Change description

Starting with .NET Core 3.0, the minimum legal key size reported by the LegalKeySizes property on RSA instances from RSA.Create, RSAOpenSsl.RSAOpenSsl, and RSACryptoServiceProvider.RSACryptoServiceProvider on Linux has increased from 384 to 512.

As a result, in .NET Core 2.2 and earlier versions, a method call such as RSA.Create(384) succeeds. In .NET Core 3.0 and later versions, the method call RSA.Create(384) throws an exception indicating the size is too small.

This change was made because OpenSSL, which performs the cryptographic operations on Linux, raised its minimum between versions 1.0.2 and 1.1.0. .NET Core 3.0 prefers OpenSSL 1.1.x to 1.0.x, and the minimum reported version was raised to reflect this new higher dependency limitation.

Version introduced

3.0

If you call any of the affected APIs, ensure that the size of any generated keys is not less than the provider minimum.

Note

384-bit RSA is already considered insecure (as is 512-bit RSA). Modern recommendations, such as NIST Special Publication 800-57 Part 1 Revision 4, suggest 2048-bit as the minimum size for newly generated keys.

Category

Cryptography

Affected APIs


.NET Core 3.0 prefers OpenSSL 1.1.x to OpenSSL 1.0.x

.NET Core for Linux, which works across multiple Linux distributions, can support both OpenSSL 1.0.x and OpenSSL 1.1.x. .NET Core 2.1 and .NET Core 2.2 look for 1.0.x first, then fall back to 1.1.x; .NET Core 3.0 looks for 1.1.x first. This change was made to add support for new cryptographic standards.

This change may impact libraries or applications that do platform interop with the OpenSSL-specific interop types in .NET Core.

Change description

In .NET Core 2.2 and earlier versions, the runtime prefers loading OpenSSL 1.0.x over 1.1.x. This means that the IntPtr and SafeHandle types for interop with OpenSSL are used with libcrypto.so.1.0.0 / libcrypto.so.1.0 / libcrypto.so.10 by preference.

Starting with .NET Core 3.0, the runtime prefers loading OpenSSL 1.1.x over OpenSSL 1.0.x, so the IntPtr and SafeHandle types for interop with OpenSSL are used with libcrypto.so.1.1 / libcrypto.so.11 / libcrypto.so.1.1.0 / libcrypto.so.1.1.1 by preference. As a result, libraries and applications that interoperate with OpenSSL directly may have incompatible pointers with the .NET Core-exposed values when upgrading from .NET Core 2.1 or .NET Core 2.2.

Version introduced

3.0

Libraries and applications that do direct operations with OpenSSL need to be careful to ensure they are using the same version of OpenSSL as the .NET Core runtime.

All libraries or applications that use IntPtr or SafeHandle values from the .NET Core cryptographic types directly with OpenSSL should compare the version of the library they use with the new SafeEvpPKeyHandle.OpenSslVersion property to ensure the pointers are compatible.

Category

Cryptography

Affected APIs