barbitoff programmer`s blog

Здесь я публикую заметки из программерской жизни: грабли, на которые мне случилось наступить, проблемы, для которых было найдено элегантное (или не очень) решение, а также все, с чем мне пришлось столкнуться и чем хотелось бы поделиться =)
PS Если хотите меня поблагодарить - на странице есть 3 места, чтобы это сделать =)

вторник, 10 апреля 2012 г.

Java: Валидация цепочки сертификатов с использованием расширения CRL Distribution Point с возможностью кэширования CRL

Java PKI API, а точнее, его реализация под названием PKIX, не имеет функционала по работе с расширением CRL Distribution Point (далее - CRL DP). Возможность проверки сертификатов по CRL есть, включается она следующим кодом:
builderParams.setRevocationEnabled(true);
, где builderParams - объект параметров построителя цепочки сертификатов PKIXBuilderParameters. Однако CertPathBuilder (или CertPathValidator) извлекают при этом эти самые CRL не по URL`у, указанному в CRL DP сертификата, а из т.н. CertStore.
Работа с CRL DP осуществляется уже на уровне реализации PKIX. Например, для Sun-овской реализации использование CRL DP при получении CRL включается следующим образом:
System.setProperty("com.sun.security.enableCRLDP", "true");    
Для реализации IBM устанавливаемое свойство имеет другое имя. 
Не знаю как в реализации от IBM, но в таковой от Sun я не нашел возможности как-либо управлять кэшированием CRL. Без кэширования использование проверки цепочки сертификатов в высоконагруженном веб-приложении практически невозможно: каждый запрос к приложению приводит к запросу CRL с Distribution Point (а если в цепочке сертификатов между проверяемым сертификатом и доверенным несколько сертификатов - то к нескольким CRL), что крайне негативно сказывается на производительности. Более того, каждый раз загружать CRL попросту не нужно (уж по крайней мере по несколько раз в минуту - точно).
Для решения этой проблемы можно воспользоваться открытой библиотекой jTrust: http://code.google.com/p/jtrust/. У неё тоже есть несколько минусов: во-первых, она жестко завязана на криптопровайдер Bouncy Castle, что особенно неудобно, когда в приложении уже используется другой криптопровайдер. Во-вторых, спроектирована библиотека таким образом, что предполагается её использование в качестве полной замены стандартному Java PKI API, а не как дополнение к нему, поэтому просто взять оттуда функционал по кэшированию CRL не получится. К тому же, реализация кэширования в ней имхо не вполне адекватная: для хранения CRL в кэше в памяти используются SoftReference, что приводит к очистке кэша сборщиком мусора, что, как минимум, не является ожидаемым поведением для кэша. В дополнение к этому, время жизни кэша отсчитывается почему-то не от момента загрузки CRL, а от момента времени, указанного в thisUpdate в самом CRL. Да ещё и устанавливать время жизни кэша можно только в часах. 
Подумав надо всем этим, я написал свою реализацию кэширующего репозитория для jTrust, код чуть позже выложу на github. А интегрировал в свое приложение библиотеку jTrust я следующим образом: строится и валидируется цепочка сертификатов средствами PKIX, а, точнее, его sun`овской реализации (неявно, т.к. эта реализация, как я понял, используется томкатом). При этом флаг revocationEnabled установлен в false, чтобы выполнялись все проверки, за исключением CRL. После успешного построения и валидации цепочки она дополняется trusted-сертификатом в конце (т.к. PKIX формирует цепочку, завершающуюся сертификатом, выданным доверенным субъектом, а jTrust оперирует цепочками, оканчивающимися непосредственно сертификатом самого доверенного субъекта), и используется CrlTrustLinker для проверки валидности каждой связи в цепочке (а в качестве репозитория CRL этот линкер использует мою самописную имплементацию интерфейса CrlRepository).

1 комментарий:

  1. Опция для IBM:
    java -Dcom.ibm.security.enableCRLDP=true

    src: http://publib.boulder.ibm.com/infocenter/javasdk/v6r0/index.jsp?topic=%2Fcom.ibm.java.security.component.doc%2Fsecurity-component%2FcertpathDocs%2Fibmcertstore.html

    ОтветитьУдалить