我有一个公用/专用密钥对,必须将公用密钥放入证书中。
为了澄清:我需要转换公钥,因为EBICS Standard 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);
}
}