首页 > 解决方案 > 将 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);
    }
}

标签: javacertificatersa

解决方案


推荐阅读