Сертификаты X.509 могут включать поля использования ключа (KU) и поля расширенного использования ключа (EKU). Техническая заметка Oracle, описывающая, как создать подпись * RIA , создает сертификат без каких-либо флагов использования ключей, что прекрасно работает (если вы можете заставить доверенный ЦС подписать его)
Но все больше и больше CA выдает сертификаты с этими полями использования ключей. При наличии эти поля ограничивают использование сертификата. Плагин Java проверяет наличие этих полей в EndEntityChecker :
/**
* Check whether this certificate can be used for code signing.
* @throws CertificateException if not.
*/
private void checkCodeSigning(X509Certificate cert)
throws CertificateException {
Set<String> exts = getCriticalExtensions(cert);
if (checkKeyUsage(cert, KU_SIGNATURE) == false) {
throw new ValidatorException
("KeyUsage does not allow digital signatures",
ValidatorException.T_EE_EXTENSIONS, cert);
}
if (checkEKU(cert, exts, OID_EKU_CODE_SIGNING) == false) {
throw new ValidatorException
("Extended key usage does not permit use for code signing",
ValidatorException.T_EE_EXTENSIONS, cert);
}
if (!SimpleValidator.getNetscapeCertTypeBit(cert, NSCT_SSL_CLIENT)) {
throw new ValidatorException
("Netscape cert type does not permit use for SSL client",
ValidatorException.T_EE_EXTENSIONS, cert);
}
// do not check Netscape cert type for JCE code signing checks
// (some certs were issued with incorrect extensions)
if (variant.equals(Validator.VAR_JCE_SIGNING) == false) {
if (!SimpleValidator.getNetscapeCertTypeBit(cert, NSCT_CODE_SIGNING)) {
throw new ValidatorException
("Netscape cert type does not permit use for code signing",
ValidatorException.T_EE_EXTENSIONS, cert);
}
exts.remove(SimpleValidator.OID_NETSCAPE_CERT_TYPE);
}
// remove extensions we checked
exts.remove(SimpleValidator.OID_KEY_USAGE);
exts.remove(SimpleValidator.OID_EXTENDED_KEY_USAGE);
checkRemainingExtensions(exts);
}
Методы проверки выглядят следующим образом:
/**
* Utility method checking if the extended key usage extension in
* certificate cert allows use for expectedEKU.
*/
private boolean checkEKU(X509Certificate cert, Set<String> exts,
String expectedEKU) throws CertificateException {
List<String> eku = cert.getExtendedKeyUsage();
if (eku == null) {
return true;
}
return eku.contains(expectedEKU) || eku.contains(OID_EKU_ANY_USAGE);
}
Таким образом, если не указан KU или EKU, средство проверки KU или EKU с радостью возвращает значение true.
Но
- если указаны KU, цифровая подпись KU должна быть одной из них.
- если указаны какие-либо EKU, либо подпись кода EKU (идентифицированная oid 1.3.6.1.5.5.7.3.3), либо EKU любое использование (идентифицированная oid 2.5 .29.37.0) также должно быть указано.
Наконец, метод checkRemainingExtensions
проверяет оставшиеся критические EKU. Единственные другие важные EKU, которые могут присутствовать - это
- базовые ограничения (oid "2.5.29.19") и
- имя субъекта alt (oid 2.5.29.17)
Если он находит любой другой критический EKU, он возвращает false.