Этот пост описывает, как использовать архитектуру криптографии Java (JCA), которая позволяет использовать криптографические сервисы в ваших приложениях.
Услуги криптографической архитектуры Java
JCA предоставляет ряд криптографических сервисов, таких как дайджесты сообщений и подписи .
Эти сервисы доступны через специальные API-интерфейсы, такие как MessageDigest
и Signature
.
Криптографические сервисы абстрагируют разные алгоритмы. Например, для дайджестов вы можете использовать MD5 или SHA1 . Вы указываете алгоритм в качестве параметра для метода getInstance()
криптографического класса обслуживания:
1
|
MessageDigest digest = MessageDigest.getInstance( "MD5" ); |
Вы найдете значение параметра для вашего алгоритма в документации имени стандартного алгоритма JCA.
Некоторые алгоритмы имеют параметры. Например, алгоритм для генерации пары секретный / открытый ключ будет принимать размер ключа в качестве параметра. Вы указываете параметр (ы), используя метод initialize()
:
1
2
|
KeyPairGenerator generator = KeyPairGenerator.getInstance( "DSA" ); generator.initialize( 1024 ); |
Если вы не initialize()
метод initialize()
, будет использовано какое-то значение по умолчанию, которое может быть, а может и не быть тем, что вы хотите.
К сожалению, API для инициализации не на 100% согласован между сервисами.
Например, класс Cipher
использует init()
с аргументом, указывающим шифрование или дешифрование, в то время как класс Signature
использует initSign()
для подписи и initVerify()
для проверки.
Поставщики архитектуры криптографии Java
JCA сохраняет ваш код независимым от реализации конкретного криптографического алгоритма через систему провайдера .
Поставщики ранжируются в соответствии с порядком предпочтений, который настраивается (см. Ниже). Наилучшее предпочтение — 1, следующее наилучшее — 2 и т. Д. Порядок предпочтений позволяет JCA выбрать наилучшего доступного поставщика, реализующего данный алгоритм.
В качестве альтернативы вы можете указать конкретного поставщика во втором аргументе getInstance()
:
1
|
Signature signature = Signature.getInstance( "SHA1withDSA" , "SUN" ); |
JRE поставляется с группой поставщиков из Oracle по умолчанию. Однако из-за исторических ограничений на экспорт это не самые безопасные реализации. Чтобы получить доступ к более совершенным алгоритмам и ключам большего размера, установите файлы политик неограниченной юрисдикции расширения криптографии Java .
Обновление : обратите внимание, что приведенное выше утверждение верно для Oracle JRE. OpenJDK не имеет такого же ограничения .
Сделайте ваше использование криптографии настраиваемым
Вы всегда должны убедиться, что криптографические сервисы, которые использует ваше приложение, являются настраиваемыми.
Если вы сделаете это, вы можете изменить криптографический алгоритм и / или реализацию без выпуска патча.
Это особенно ценно, когда становится доступной новая атака на (реализацию) алгоритма.
JCA упрощает настройку использования криптографии.
Метод getInstance()
принимает как имя алгоритма, так и имя поставщика, реализующего этот алгоритм. Вы должны прочитать оба и любые значения параметров алгоритма из какого-либо файла конфигурации.
Также убедитесь, что вы храните свой код СУХОЙ и создаете экземпляры криптографических сервисов в одном месте.
Убедитесь, что запрошенный алгоритм и / или поставщик действительно доступны.
Метод getInstance()
NoSuchAlgorithmException
когда данный алгоритм или поставщик недоступен, поэтому вы должны это отловить. Тогда самым безопасным вариантом является сбой, и кто-то должен убедиться, что система настроена правильно. Если вы продолжите, несмотря на ошибку конфигурации, вы можете получить систему, которая менее безопасна, чем требуется.
Обратите внимание, что Oracle рекомендует не указывать провайдера . Причины, которые они приводят, состоят в том, что не все поставщики могут быть доступны на всех платформах, и что указание поставщика может означать, что вы упускаете возможности оптимизации.
Вы должны сопоставить эти недостатки с риском быть уязвимым.
Развертывание конкретных поставщиков с известными характеристиками в вашем приложении может нейтрализовать недостатки, о которых упоминает Oracle.
Добавление поставщиков криптографических услуг
Система провайдеров является расширяемой, поэтому вы можете добавлять провайдеров.
Например, вы можете использовать Bouncy Castle с открытым исходным кодом или коммерческих поставщиков RSA BSAFE .
Чтобы добавить провайдера, вы должны убедиться, что его jar-файл доступен для приложения. Вы можете поместить это в classpath для этой цели.
Кроме того, вы можете сделать его установленным расширением , поместив его в каталог $JAVA_HOME/lib/ext
, где $JAVA_HOME
— это расположение вашего дистрибутива JDK / JRE.
Основное различие между этими двумя подходами состоит в том, что установленным расширениям по умолчанию предоставляются все разрешения , тогда как код на пути к классам — нет. Это важно, когда (часть) ваш код выполняется в песочнице .
Некоторые сервисы, такие как Cipher
, требуют подписи файла провайдера.
Следующим шагом является регистрация провайдера в системе провайдера JCA. Самый простой способ — использовать Security.addProvider()
:
1
|
Security.addProvider( new BouncyCastleProvider()); |
Вы также можете установить порядок предпочтений поставщика, используя метод Security.insertProviderAt()
:
1
|
Security.insertProviderAt ( new JsafeJCE(), 1 ); |
Недостатком этого подхода является то, что он связывает ваш код с провайдером, поскольку вы должны импортировать класс провайдера. Это не может быть важной проблемой в модульной системе, такой как OSGi .
Еще одна вещь, на которую стоит обратить внимание, это то, что для кода требуется, чтобы SecurityPermission
добавлял провайдера.
Поставщик также можно настроить как часть вашей среды с помощью статической регистрации, добавив запись в java.security
свойств java.security
(находится в $JAVA_HOME/jre/lib/security/java.security
):
1
2
|
security.provider. 1 =com.rsa.jsafe.provider.JsafeJCE security.provider. 2 =sun.security.provider.Sun |
Имена свойств в этом файле начинаются с security.provider.
и заканчивается предпочтением провайдера. Значение свойства — это полное имя класса, реализующего Provider
.
Реализация собственного провайдера криптографических услуг
Не делай этого . Вы ошибетесь и будете уязвимы для атак.
Использование провайдеров криптографических услуг
В документации для провайдера должно быть указано, какое имя провайдера следует использовать в качестве второго аргумента для getInstance()
. Например, Bouncy Castle использует BC
, а RSA BSAFE использует JsafeJCE
.
У большинства провайдеров есть собственные API, а также соответствующие API JCA. Не используйте пользовательские API, так как это сделает невозможным настройку используемых алгоритмов и поставщиков.
Не все алгоритмы и реализации созданы равными
Важно отметить, что разные алгоритмы и реализации имеют разные характеристики и могут сделать их более или менее подходящими для вашей ситуации.
Например, некоторые организации разрешают только те алгоритмы и реализации, которые сертифицированы FIPS 140-2 или включены в список криптографических алгоритмов NSA Suite B.
Всегда убедитесь, что вы понимаете криптографические потребности вашего клиента.
Использование JCA в среде OSGi
Метод getInstance()
является фабричным методом, который использует интерфейс поставщика услуг (SPI). Это проблематично в мире OSGi, поскольку OSGi нарушает допущение инфраструктуры SPI о наличии единого пути к классам.
Другая потенциальная проблема заключается в том, что JCA требует подписать несколько банок. Если эти jar-файлы не являются действительными OSGi-пакетами, вы не можете запустить их через bnd, чтобы сделать их так, поскольку это сделает подпись недействительной.
К счастью, вы можете убить обеих птиц одним камнем. Поместите jar-файл вашего провайдера в classpath вашей основной программы, то есть программы, которая запускает каркас OSGi.
Затем экспортируйте пакет поставщика из системного пакета OSGi, используя системное свойство org.osgi.framework.system.packages.extra
. Это заставит системный пакет экспортировать этот пакет.
Теперь вы можете просто использовать Import-Package
в пакете провайдера в ваших пакетах.
Существуют и другие варианты решения этих проблем, если вы не можете использовать вышеуказанное решение.
Ссылка: Использование криптографии в приложениях Java от нашего партнера по JCG Ремона Синнема в блоге по безопасной разработке программного обеспечения .