Поделиться через


Изменения, нарушающие криптографию для .NET Core 2.1-3.0

На этой странице описаны следующие критические изменения:

Изменение, нарушающее совместимость Представленная версия
Синтаксис BEGIN TRUSTED CERTIFICATE больше не поддерживается в Linux 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

Синтаксис "BEGIN TRUSTED CERTIFICATE" больше не поддерживается для корневых сертификатов в Linux

Корневые сертификаты в Linux и других Unix-подобных системах (но не macOS) можно представить в двух формах: стандартный заголовок PEM BEGIN CERTIFICATE и относящийся к OpenSSL заголовок PEM BEGIN TRUSTED CERTIFICATE. Последний синтаксис допускает дополнительную конфигурацию, которая вызвала проблемы совместимости с классом System.Security.Cryptography.X509Certificates.X509Chain .NET Core. Содержимое корневого сертификата BEGIN TRUSTED CERTIFICATE больше не загружается подсистемой цепочек, начиная с .NET Core 3.0.

Описание изменения

Ранее синтаксисы BEGIN CERTIFICATE и BEGIN 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 (через версию 4.6.0 пакета NuGet System.Security.Cryptography.Pkcs) алгоритм по умолчанию изменён на AES-256 для модернизации алгоритмов и повышения безопасности стандартных параметров. Если в сертификате получателя сообщения используется открытый ключ Диффи-Хеллмана (не EC) операция шифрования может завершиться ошибкой 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

Если изменение отрицательно повлияет на работу, можете восстановить шифрование TripleDES, явно указав идентификатор алгоритма шифрования в конструкторе EnvelopedCms, который содержит параметр типа AlgorithmIdentifier, например:

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

Минимальный размер создаваемых ключей RSA в Linux увеличен с 384 до 512 бит.

Описание изменения

Начиная с версии .NET Core 3.0, минимальный допустимый размер ключа, сообщаемый свойством LegalKeySizes для экземпляров RSA из RSA.Create, RSAOpenSsl и RSACryptoServiceProvider в Linux, увеличился с 384 до 512.

В результате в .NET Core 2.2 и более ранних версий вызов такого метода, как RSA.Create(384), выполняется успешно. В .NET Core 3.0 и более поздних версий при вызове метода RSA.Create(384) создается исключение, указывающее на то, что размер слишком мал.

Изменение было внесено, поскольку OpenSSL, который выполняет криптографические операции в Linux, поднял минимальную поддерживаемую версию с 1.0.2 до 1.1.0. В .NET Core 3.0 предпочтительно использовать OpenSSL версии 1.1.x, нежели 1.0.x, и минимально поддерживаемая версия была повышена, чтобы отразить эту новую более высокую зависимость.

Представленная версия

3.0

Если вы вызываете любой затронутый API-интерфейс, убедитесь, что размер созданных ключей не меньше минимального значения, установленного поставщиком.

Замечание

Стандарт 384-битового шифрования RSA уже считается небезопасным (как и стандарт 512-битового шифрования). В современных документах, таких как NIST Special Publication 800-57 Part 1 Revision 4 (Специальная публикация NIST 800-57, часть 1, редакция 4), рекомендуется создавать ключи с минимальным размером 2048 бит.

Категория

Криптография

Затронутые API


Для .NET Core 3.0 более предпочтительным является использование OpenSSL 1.1.x вместо OpenSSL 1.0.x

.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. Это изменение было внесено, чтобы реализовать поддержку новых криптографических стандартов.

Это изменение может повлиять на библиотеки или приложения, которые отвечают за взаимодействие между платформой и типами взаимодействия на основе OpenSSL в .NET Core.

Описание изменения

В .NET Core 2.2 и предыдущих версиях для среды выполнения предпочтительной является загрузка OpenSSL 1.0.x вместо 1.1.x. Это означает, что типы IntPtr и SafeHandle для взаимодействия с OpenSSL используются с libcrypto.so.1.0.0, libcrypto.so.1.0 или libcrypto.so.10 согласно предпочтениям.

Начиная с .NET Core 3.0, для среды выполнения предпочтительной является загрузка OpenSSL 1.1.x вместо OpenSSL 1.0.x, поэтому типы IntPtr и SafeHandle для взаимодействия с OpenSSL используются с libcrypto.so.1.1, libcrypto.so.11, libcrypto.so.1.1.0 или libcrypto.so.1.1.1 согласно предпочтениям. В результате библиотеки и приложения, которые напрямую взаимодействуют с OpenSSL, могут иметь несовместимые указатели со значениями, предоставляемыми .NET Core, при обновлении с .NET Core 2.1 или .NET Core 2.2.

Представленная версия

3.0

Библиотеки и приложения, которые выполняют прямые операции с OpenSSL, должны использовать ту же версию OpenSSL, которую использует среда выполнения .NET Core.

Все библиотеки или приложения, использующие значения IntPtr или SafeHandle криптографических типов .NET Core непосредственно с 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значение .

Описание изменения

В .NET Framework параметр silent метода SignedCms.ComputeSignature(CmsSigner, Boolean) игнорируется, а окно ввода PIN-кода всегда запрашивается, если это требует поставщик. В .NET Core параметр silent соблюдается, и если задано значение true, запрос PIN-кода никогда не отображается, даже если он требуется поставщиком.

Поддержка сообщений CMS/PKCS #7 была введена в .NET Core в версии 2.1.

Представленная версия

2.1

Чтобы запрос ПИН-кода появлялся при необходимости, настольные приложения должны вызывать SignedCms.ComputeSignature(CmsSigner, Boolean) и устанавливать логический параметр false. Результирующее поведение совпадает с поведением в .NET Framework независимо от того, отключен ли там тихий контекст.

Категория

Криптография

Затронутые API