Я хочу создать SignerInfoGenerator (пакет org.bouncycastle.cms) с использованием постквантовых сертификатов / алгоритмов.
У меня есть работающий код для RSA, но я не могу заставить его работать, например, с XMSSMT. Программа генерирует исключение java.lang.NullPointerException (полный пример см. Ниже).
Я проверил исходный код Bouncy Castle и обнаружил проблему в строке 64 SignerInfoGenerator.java.
this.digester = digesterProvider.get(digAlgFinder.find(signer.getAlgorithmIdentifier()));
digAlgFinder.find (...) не может использовать AlgorithmIdentifier pqc-алгоритма.
(пожалуйста, поправьте меня, если я ошибаюсь)
Здесь пример выполнения (для RSA) / не работает (для XMSSMT):
public static void main(String[] args) throws OperatorCreationException, CertificateException, IOException,
NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException {
// RSA
//String algorithmName = "RSA";
//String signatureAlgorithmName = "SHA256withRSA";
//String provider = "BC";
// XMSSMT
String algorithmName = "XMSSMT";
String signatureAlgorithmName = "SHA256withXMSSMT";
String provider = "BCPQC";
// code used by both RSA and XMSSMT
if (Security.getProvider("BC") == null) {
Security.addProvider(new BouncyCastleProvider());
}
if (Security.getProvider("BCPQC") == null) {
Security.addProvider(new BouncyCastlePQCProvider());
}
KeyPair keyPair = createKeyPair(algorithmName);
PrivateKey privateKey = (PrivateKey) keyPair.getPrivate();
X509Certificate cert = createCertificate(keyPair, signatureAlgorithmName); // OperatorCreationException,
// CertificateException, IOException
JcaContentSignerBuilder contentSignerBuilder = new JcaContentSignerBuilder(signatureAlgorithmName);
contentSignerBuilder.setProvider(provider);
ContentSigner contentSigner = contentSignerBuilder.build(privateKey); // OperatorCreationException
JcaDigestCalculatorProviderBuilder calculatorProviderBuilder = new JcaDigestCalculatorProviderBuilder();
calculatorProviderBuilder.setProvider(provider);
DigestCalculatorProvider digestCalculatorProvider = calculatorProviderBuilder.build(); // OperatorCreationException
JcaSignerInfoGeneratorBuilder builder = new JcaSignerInfoGeneratorBuilder(digestCalculatorProvider);
SignerInfoGenerator signerInfoGenerator = builder.build(contentSigner, cert); // CertificateEncodingException |
// OperatorCreationException
}
Последняя строка не работает с XMSSMT и приводит к
Exception in thread "main" java.lang.NullPointerException
at org.bouncycastle.jcajce.util.MessageDigestUtils.getDigestName(MessageDigestUtils.java:59)
at org.bouncycastle.operator.jcajce.OperatorHelper.createDigest(OperatorHelper.java:344)
at org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder$1.get(JcaDigestCalculatorProviderBuilder.java:51)
at org.bouncycastle.cms.SignerInfoGenerator.<init>(SignerInfoGenerator.java:82)
at org.bouncycastle.cms.SignerInfoGenerator.<init>(SignerInfoGenerator.java:48)
at org.bouncycastle.cms.SignerInfoGeneratorBuilder.createGenerator(SignerInfoGeneratorBuilder.java:138)
at org.bouncycastle.cms.SignerInfoGeneratorBuilder.build(SignerInfoGeneratorBuilder.java:96)
at org.bouncycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder.build(JcaSignerInfoGeneratorBuilder.java:72)
at org.bouncycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder.build(JcaSignerInfoGeneratorBuilder.java:84)
at xx.Test.main(Test.java:81)
Добавление этих двух кодов дает вам работающий пример, но они не важны:
public static KeyPair createKeyPair(String algorithmName)
throws NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException {
String provider;
if (algorithmName == "XMSSMT") {
if (Security.getProvider("BCPQC") == null) {
Security.addProvider(new BouncyCastlePQCProvider());
}
provider = "BCPQC";
} else {
if (Security.getProvider("BC") == null) {
Security.addProvider(new BouncyCastleProvider());
}
provider = "BC";
}
KeyPairGenerator keygen = KeyPairGenerator.getInstance(algorithmName, provider); // NoSuchAlgorithmException |
// NoSuchProviderException
if (algorithmName == "XMSSMT") {
XMSSMTParameterSpec bcSpec = new XMSSMTParameterSpec(10, 5, XMSSMTParameterSpec.SHA256);
keygen.initialize(bcSpec, new SecureRandom()); // InvalidAlgorithmParameterException
} else if (algorithmName == "RSA") {
keygen.initialize(1028, new SecureRandom());
}
return keygen.generateKeyPair();
}
(в основном из Самоподписанный сертификат X509 с Bouncy Castle на Java )
public static X509Certificate createCertificate(KeyPair keypair, String signatureAlgorithmName)
throws IOException, OperatorCreationException, CertificateException {
SecureRandom random = new SecureRandom();
X500Name subject = new X500NameBuilder(BCStyle.INSTANCE).addRDN(BCStyle.CN, "xxx.com").build();
byte[] id = new byte[20];
random.nextBytes(id);
BigInteger serial = new BigInteger(160, random);
X509v3CertificateBuilder certificate = new JcaX509v3CertificateBuilder(subject, serial,
Date.from(LocalDate.of(2000, 1, 1).atStartOfDay(ZoneOffset.UTC).toInstant()),
Date.from(LocalDate.of(2035, 1, 1).atStartOfDay(ZoneOffset.UTC).toInstant()), subject,
keypair.getPublic());
certificate.addExtension(Extension.subjectKeyIdentifier, false, id);
certificate.addExtension(Extension.authorityKeyIdentifier, false, id);
BasicConstraints constraints = new BasicConstraints(true);
certificate.addExtension(Extension.basicConstraints, true, constraints.getEncoded());
KeyUsage usage = new KeyUsage(KeyUsage.keyCertSign | KeyUsage.digitalSignature);
certificate.addExtension(Extension.keyUsage, false, usage.getEncoded());
ExtendedKeyUsage usageEx = new ExtendedKeyUsage(
new KeyPurposeId[] { KeyPurposeId.id_kp_serverAuth, KeyPurposeId.id_kp_clientAuth });
certificate.addExtension(Extension.extendedKeyUsage, false, usageEx.getEncoded());
ContentSigner signer = new JcaContentSignerBuilder(signatureAlgorithmName).build(keypair.getPrivate());
X509CertificateHolder holder = certificate.build(signer);
JcaX509CertificateConverter converter = new JcaX509CertificateConverter();
converter.setProvider(new BouncyCastleProvider());
return converter.getCertificate(holder);
}
Как мне создать SignerInfoGenerator с помощью pqc-алгоритмов?
Спасибо за помощь: -)