有弹性的城堡-如何从JceOpenSSLPKCS8DecryptorProviderBuilder获取公钥信息 [英] Bouncy Castle - how to get Public Key Info from JceOpenSSLPKCS8DecryptorProviderBuilder

查看:111
本文介绍了有弹性的城堡-如何从JceOpenSSLPKCS8DecryptorProviderBuilder获取公钥信息的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下代码来提取私钥

I have the following code to extract Private Key

    PEMParser parser = new PEMParser(new InputStreamReader(new ByteArrayInputStream(decoded)));
    Object object = parser.readObject();
    PEMDecryptorProvider provider = new JcePEMDecryptorProviderBuilder()
            .build(props.getProperty(KeytoolFlags.KEYPASS.name()).toCharArray());

    JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider(BouncyCastleProvider.PROVIDER_NAME);
    if (object instanceof PEMEncryptedKeyPair) {
        KeyPair pair = converter.getKeyPair(((PEMEncryptedKeyPair) object).decryptKeyPair(provider));
        return loadPublic ? pair.getPublic() : pair.getPrivate();
    } else if (object instanceof PEMKeyPair) {
        return loadPublic ? converter.getPublicKey(((PEMKeyPair) (object)).getPublicKeyInfo())
                : converter.getPrivateKey(((PEMKeyPair) (object)).getPrivateKeyInfo());
    } else {
        InputDecryptorProvider p2 = new JceOpenSSLPKCS8DecryptorProviderBuilder()
                .setProvider(BouncyCastleProvider.PROVIDER_NAME)
                .build(props.getProperty(KeytoolFlags.KEYPASS.name()).toCharArray());
        return converter.getPrivateKey(((PKCS8EncryptedPrivateKeyInfo) object).decryptPrivateKeyInfo(p2));
    }

我想在<$ c $时从转换器获取公钥c> JceOpenSSLPKCS8DecryptorProviderBuilder 。

谢谢

推荐答案

最简单的方法尽管对我来说很丑陋,但它是将私钥 back转换为OpenSSL的旧版格式之一,然后 PEMParser 可以将其转换为 PEMKeyPair 两半,可以从中选择公众。否则,该方法必须根据密钥算法(也称为类型)进行定制,但是可以更高效,我更喜欢。以下是供您考虑的两个选项:

The simplest way, although it feels rather ugly to me, is to convert the private key 'back' to one of OpenSSL's 'legacy' forms, which PEMParser is then able to turn into a PEMKeyPair with both halves, from which the public can be selected. Otherwise, the method must be tailored depending on the key algorithm aka type, but can be more efficient which I like better. Here are both options for your consideration:

public static void SO57043669PKCS8_Public_BC (String[] args) throws Exception {
    Object p8e = new PEMParser (new FileReader (args[0])).readObject();
    // for PKCS8-encrypted result is org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo 
    PrivateKeyInfo p8i = ((PKCS8EncryptedPrivateKeyInfo)p8e).decryptPrivateKeyInfo(
            new JceOpenSSLPKCS8DecryptorProviderBuilder().build(args[1].toCharArray()) );
    // or get org.bouncycastle.asn1.pkcs.PrivateKeyInfo directly from PEMParser for PKCS8-clear
    PublicKey pub = null;
    if( args.length>=3 ){ // the simple way:
        PrivateKey prv = new JcaPEMKeyConverter().getPrivateKey(p8i);
        PemObject old = new JcaMiscPEMGenerator (prv,null).generate();
        StringWriter w1 = new StringWriter(); 
        PemWriter w2 = new PemWriter(w1);
        w2.writeObject(old); w2.close();
        Object pair = new PEMParser(new StringReader(w1.toString())).readObject();
        pub = new JcaPEMKeyConverter().getKeyPair((PEMKeyPair)pair).getPublic();
    }else{
        ASN1ObjectIdentifier id = p8i.getPrivateKeyAlgorithm().getAlgorithm();
        PKCS8EncodedKeySpec p8s = new PKCS8EncodedKeySpec (p8i.getEncoded());
        if( id.equals(PKCSObjectIdentifiers.rsaEncryption) ){
            // the standard PKCS1 private key format for RSA redundantly includes e
            KeyFactory rfact = KeyFactory.getInstance("RSA");
            RSAPrivateCrtKey rprv = (RSAPrivateCrtKey) rfact.generatePrivate(p8s);
            // or JcaPEMKeyConverter.getPrivateKey does the same thing
            pub = /*(RSAPublicKey)*/ rfact.generatePublic(
                    new RSAPublicKeySpec (rprv.getModulus(), rprv.getPublicExponent()));
        }else if( id.equals(X9ObjectIdentifiers.id_dsa) ){
            // the apparently ad-hoc format OpenSSL uses for DSA does not include y but it can be computed
            KeyFactory dfact = KeyFactory.getInstance("DSA");
            DSAPrivateKey dprv = (DSAPrivateKey) dfact.generatePrivate(p8s);
            // or JcaPEMKeyConverter.getPrivateKey does the same thing
            BigInteger p = dprv.getParams().getP(), q = dprv.getParams().getQ(), g = dprv.getParams().getG();
            pub = /*(DSAPublicKey)*/ dfact.generatePublic (
                    new DSAPublicKeySpec(g.modPow(dprv.getX(),p), p, q, g) );
            // warning: naive computation probably vulnerable to sidechannel attack if any  
        }else if( id.equals(X9ObjectIdentifiers.id_ecPublicKey) ){
            // the SECG SEC1 format for EC private key _in PKCS8 by OpenSSL_ 
            // includes []] BITSTR(Q) (but not [0] params which is already in the PKCS8 algid)
            org.bouncycastle.asn1.sec.ECPrivateKey eprv = org.bouncycastle.asn1.sec.ECPrivateKey.getInstance(p8i.parsePrivateKey());
            byte[] eenc = new SubjectPublicKeyInfo (p8i.getPrivateKeyAlgorithm(), eprv.getPublicKey().getOctets()).getEncoded(); 
            KeyFactory efact = KeyFactory.getInstance("EC");
            pub = /*(ECPublicKey)*/ KeyFactory.getInstance("EC").generatePublic(new X509EncodedKeySpec(eenc));
            //}else if maybe others ...
        }else throw new Exception ("unknown private key OID " + id);
    }
    System.out.println (pub.getAlgorithm() + " " + pub.getClass().getName());
}

这篇关于有弹性的城堡-如何从JceOpenSSLPKCS8DecryptorProviderBuilder获取公钥信息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆