TLDR: ваш (первый) метод верен
Для фона фактическое поле extensions
в (тело = TBSCertificate
из) сертификата X.509 представляет / кодирует значение каждого расширения как OCTET STRING, «оборачивающая» кодировку DER действительного значения .
Но в Bouncy при вызове более старых перегрузок X509v3CertificateBuilder.addExtension
, третьим параметром которых является либо ASN1Encodable
(объект значения), либо byte[]
(его кодирование), вам не нужно выполнять OCTET STRING самостоятельно;ExtensionsGenerator
используемый внутри застройщика сделает это за вас.Фактически, создание DEROctetString
самостоятельно здесь фактически создает (сертификат, содержащий) расширение, значение которого «дважды обернуто» - СТРОКА ОКТЕТА, содержащая DER другой СТРОКИ ОКТЕТА, содержащая DER действительного значения, что неверно.
Тем не менее, последние версии (1.53 и выше) содержат другую перегрузку, которая вместо отдельного OID, логическое значение, принимает один объект org.bouncycastle.asn1.x509.Extension
, который содержит эти три - и создание этого объекта отличается: его конструкторы принимают либокодирование (и обертывание) или DEROctetString
объект, который вы создаете сами, и чьи конструкторы, в свою очередь, принимают либо кодировку, либо кодируемую.(На самом деле он объявлен как суперкласс ASN1OctetString
, но вы хотите использовать подкласс DER
, потому что тела сертификатов должны быть полностью DER.) Таким образом, (любое из) следующее также верно:
certbuilder.addExtension(new Extension(Extension.extendedKeyUsage, false, eku.getEncoded()))
certbuilder.addExtension(new Extension(Extension.extendedKeyUsage, false, new DEROctetString(eku)))
certbuilder.addExtension(new Extension(Extension.extendedKeyUsage, false, new DEROctetString(eku.getEncoded())))
Вы уверены, что это не один из последних двух, которые вы видели в другом месте?