Этот пост описывает, как использовать архитектуру криптографии Java (JCA), которая позволяет использовать криптографические сервисы в ваших приложениях.
Услуги криптографической архитектуры Java

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

Чтобы добавить провайдера, вы должны убедиться, что его 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.JsafeJCEsecurity.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 Ремона Синнема в блоге по безопасной разработке программного обеспечения .
