java - 将 RSA 公钥转换为证书
问题描述
我有一个公钥/私钥对,必须将公钥放入证书中。
澄清一下:我需要转换公钥,因为 EBICS 标准 3.0 不再允许发送普通公钥进行初始化,而是请求证书。
这是我的方法:
private X509DataType getX509dataFromUserKey(String keyType) {
logger.entry();
logger.info("Keytype: "+keyType);
RSAPublicKey pubKey = null;
org.w3._2000._09.xmldsig_.X509DataType x509data = new X509DataType();
if (keyType.equals("Sig"))
pubKey=currentUserEBICSKeys.getEUKey().getPublic();
else if (keyType.equals("Auth"))
pubKey=currentUserEBICSKeys.getAuthKey().getPublic();
else if (keyType.equals("Enc"))
pubKey=currentUserEBICSKeys.getEncKey().getPublic();
else {
logger.error("invalid keyType: "+keyType);
throw new RuntimeException("invalid keyType: "+keyType);
}
logger.info("length: "+pubKey.getEncoded().length);
CertificateFactory cf;
try {
cf = CertificateFactory.getInstance("X509");
byte[] pubKeyAsBytes = pubKey.getEncoded();
Certificate aha = cf.generateCertificate(new ByteArrayInputStream(pubKeyAsBytes));
JAXBElement<Certificate> certAsJax = new JAXBElement<Certificate>(new QName("http://www.w3.org/2000/09/xmldsig#", "X509Certificate"), Certificate.class, aha);
x509data.getX509IssuerSerialOrX509SKIOrX509SubjectName().add(certAsJax);
} catch (CertificateException e) {
logger.error(keyType, e);
throw new RuntimeException("Error creating certificate");
}
logger.exit();
return x509data;
}
当我运行代码时,它会抛出一个
java.security.cert.CertificateException: Unable to initialize, java.io.IOException: Short read of DER length
at sun.security.x509.X509CertImpl.<init>(X509CertImpl.java:198)
at sun.security.provider.X509Factory.engineGenerateCertificate(X509Factory.java:102)
at java.security.cert.CertificateFactory.generateCertificate(CertificateFactory.java:339)
所以我错过了将公钥转换为DER格式并将其作为字节数组传递给certificateFactory的部分
对于那些对明确解决方案感兴趣的人,这是我解决问题的代码:
private X509DataType getX509dataFromUserKey(String keyType) {
logger.entry();
logger.debug("Keytype: "+keyType);
RSAKeyPair keyPair = null;
org.w3._2000._09.xmldsig_.X509DataType x509data = new X509DataType();
if (keyType.equals(EU_Version)) {
keyPair = currentUserEBICSKeys.getEUKey();
} else if (keyType.equals(AuthenticationVersion)) {
keyPair = currentUserEBICSKeys.getAuthKey();
} else if (keyType.equals(EncryptionVersion)) {
keyPair = currentUserEBICSKeys.getEncKey();
} else {
logger.error("invalid keyType: "+keyType);
throw new RuntimeException("invalid keyType: "+keyType);
}
try {
String dn = "C=DE,O=Organization,CN="+EBICS_UserID;
java.security.cert.X509Certificate cert=generate(dn , keyPair);
keyHashes.put(keyType, getThumbprint(cert));
byte[] certData = cert.getEncoded();
JAXBElement<byte[]> certAsJax =
new JAXBElement<byte[]>(new QName("http://www.w3.org/2000/09/xmldsig#", "X509Certificate"),
byte[].class, null, certData);
x509data.getX509IssuerSerialOrX509SKIOrX509SubjectName().add(certAsJax);
logger.debug("cert added. "+cert.getType());
} catch (Exception e) {
logger.error(keyType, e);
throw new RuntimeException("Error creating certificate");
}
logger.exit();
return x509data;
}
public java.security.cert.X509Certificate generate(String dn, RSAKeyPair keyPair) throws CertificateException {
int days = 731;
String algorithm = "SHA256withRSA";
try {
Security.addProvider(new BouncyCastleProvider());
AlgorithmIdentifier sigAlgId = new DefaultSignatureAlgorithmIdentifierFinder().find(algorithm);
AlgorithmIdentifier digAlgId = new DefaultDigestAlgorithmIdentifierFinder().find(sigAlgId);
AsymmetricKeyParameter privateKeyAsymKeyParam = PrivateKeyFactory.createKey(keyPair.getPrivate().getEncoded());
SubjectPublicKeyInfo subPubKeyInfo = SubjectPublicKeyInfo.getInstance(keyPair.getPublic().getEncoded());
ContentSigner sigGen = new BcRSAContentSignerBuilder(sigAlgId, digAlgId).build(privateKeyAsymKeyParam);
X500Name name = new X500Name(dn);
Date from = new Date();
Date to = new Date(from.getTime() + days * 86400000L);
BigInteger sn = new BigInteger(64, new SecureRandom());
X509v3CertificateBuilder v3CertGen = new X509v3CertificateBuilder(name, sn, from, to, name, subPubKeyInfo);
//if (subjectAltName != null)
// v3CertGen.addExtension(Extension.subjectAlternativeName, false, subjectAltName);
X509CertificateHolder certificateHolder = v3CertGen.build(sigGen);
java.security.cert.X509Certificate cert = new JcaX509CertificateConverter().setProvider("BC").getCertificate(certificateHolder);
return cert;
} catch (CertificateException ce) {
throw ce;
} catch (Exception e) {
throw new CertificateException(e);
}
}
解决方案
推荐阅读
- python - 无法通过 PyPI 中的 pip 安装最新版本的软件包
- javascript - 隐藏/显示具有相同类的所有 div ID 上的内容
- java - JRE 或 JDK 问题和 Eclipse 无法运行
- laravel - 在 laravel5.6 中将图片上传字段设为可选
- maven - Maven 不会在所有配置的存储库中查找依赖项
- java - 带有 Spring Security 过滤器链、重定向循环的 Wicket 授权
- xml - 将 innerxml 解组为字符串指针
- c++ - Cocos2d-x 着色器场景过渡效果在 iOS 上无法正常工作
- c# - 自定义 NavigationView 面板以包含图像 UWP
- bash - 如何迭代bash中的分隔值