我有以下代码来提取私钥
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));
}
我想在
JceOpenSSLPKCS8DecryptorProviderBuilder
时从转换器获取公钥。有什么办法吗?谢谢,
最佳答案
最简单的方法(虽然对我来说感觉很丑陋)是将私钥“ back”转换为OpenSSL的“ legacy”形式之一,然后PEMParser
可以将其转换成两个半部的PEMKeyPair
,从中可以选择公众。否则,必须根据密钥算法(也称为类型)来定制方法,但是可以更高效,我更喜欢。这两个选项供您考虑:
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());
}