Quando genero una coppia di chiavi RSA utilizzando l’API Java, la chiave pubblica è codificata nel formato X.509 e la chiave privata è codificata nel formato PKCS # 8. Sto cercando di codificare entrambi come PKCS # 1. È ansible? Ho passato una notevole quantità di tempo a consultare i documenti Java, ma non ho trovato una soluzione. Il risultato è lo stesso quando utilizzo i provider Java e Bouncy Castle.
Ecco uno snippet del codice:
KeyPairGenerator keygen = KeyPairGenerator.getInstance("RSA","BC"); keygen.initialize(1024); KeyPair pair = keygen.generateKeyPair(); PrivateKey priv = pair.getPrivate(); PublicKey pub = pair.getPublic(); byte[] privBytes = priv.getEncoded(); byte[] pubBytes = pub.getEncoded();
I due array di byte risultanti sono formattati come X.509 (pubblico) e PKCS # 8 (privato).
Qualsiasi aiuto sarebbe molto apprezzato. Ci sono dei post simili ma nessuno risponde alla mia domanda.
Grazie
Avrai bisogno di BouncyCastle:
import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1Primitive; import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; import org.bouncycastle.util.io.pem.PemObject; import org.bouncycastle.util.io.pem.PemWriter;
I frammenti di codice qui sotto sono stati controllati e trovati funzionanti con Bouncy Castle 1.52.
Convertire la chiave privata da PKCS8 a PKCS1:
PrivateKey priv = pair.getPrivate(); byte[] privBytes = priv.getEncoded(); PrivateKeyInfo pkInfo = PrivateKeyInfo.getInstance(privBytes); ASN1Encodable encodable = pkInfo.parsePrivateKey(); ASN1Primitive primitive = encodable.toASN1Primitive(); byte[] privateKeyPKCS1 = primitive.getEncoded();
Converti la chiave privata in PKCS1 in PEM:
PemObject pemObject = new PemObject("RSA PRIVATE KEY", privateKeyPKCS1); StringWriter stringWriter = new StringWriter(); PemWriter pemWriter = new PemWriter(stringWriter); pemWriter.writeObject(pemObject); pemWriter.close(); String pemString = stringWriter.toString();
Verifica con la riga di comando OpenSSL che il formato della chiave è come previsto:
openssl rsa -in rsa_private_key.pem -noout -text
Convertire la chiave pubblica da X.509 SubjectPublicKeyInfo a PKCS1:
PublicKey pub = pair.getPublic(); byte[] pubBytes = pub.getEncoded(); SubjectPublicKeyInfo spkInfo = SubjectPublicKeyInfo.getInstance(pubBytes); ASN1Primitive primitive = spkInfo.parsePublicKey(); byte[] publicKeyPKCS1 = primitive.getEncoded();
Converti la chiave pubblica in PKCS1 in PEM:
PemObject pemObject = new PemObject("RSA PUBLIC KEY", publicKeyPKCS1); StringWriter stringWriter = new StringWriter(); PemWriter pemWriter = new PemWriter(stringWriter); pemWriter.writeObject(pemObject); pemWriter.close(); String pemString = stringWriter.toString();
Verifica con la riga di comando OpenSSL che il formato della chiave è come previsto:
openssl rsa -in rsa_public_key.pem -RSAPublicKey_in -noout -text
Mille grazie agli autori dei seguenti post:
Questi post contenevano informazioni utili, anche se a volte obsolete (ad esempio per le versioni precedenti di BouncyCastle), che mi hanno aiutato a build questo post.
Da RFC5208 , il formato non crittografato PKCS # 8 è costituito da una struttura PrivateKeyInfo
:
PrivateKeyInfo :: = SEQUENCE { versione versione, privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, privateKey PrivateKey, attributes [0] IMPLICIT Attributes OPTIONAL}
dove privateKey
è:
“… una stringa di ottetto il cui contenuto è il valore della chiave privata.L’interpretazione dei contenuti è definita nella registrazione dell’algoritmo della chiave privata.Per una chiave privata RSA, ad esempio, i contenuti sono una codifica BER di un valore di tipo RSAPrivateKey. ”
Questa struttura RSAPrivateKey
è solo la codifica PKCS # 1 della chiave, che possiamo estrarre usando BouncyCastle:
// pkcs8Bytes contains PKCS#8 DER-encoded key as a byte[] PrivateKeyInfo pki = PrivateKeyInfo.getInstance(pkcs8Bytes); RSAPrivateKeyStructure pkcs1Key = RSAPrivateKeyStructure.getInstance( pki.getPrivateKey()); byte[] pkcs1Bytes = pkcs1Key.getEncoded(); // etc.
Ho scritto un programma C per convertire la chiave privata pkcs8 in pkcs1. Funziona!
/***************************************** convert pkcs8 private key file to pkcs1 2013-1-25 Larry Wu created ****************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include
Il framework BouncyCastle ha un encoder PKCS1 per risolvere questo problema: http://www.bouncycastle.org/docs/docs1.6/index.html
Stavo cercando di generare chiavi pubbliche RSA OpenSSL-friendly in formato DER usando la libreria BountyCastle J2ME su BlackBerry, il mio codice:
public void testMe() throws Exception { RSAKeyPairGenerator generator = new RSAKeyPairGenerator(); generator.init(new RSAKeyGenerationParameters(BigInteger.valueOf(0x10001), new SecureRandom(), 512, 80)); AsymmetricCipherKeyPair keyPair = generator.generateKeyPair(); RSAKeyParameters params = (RSAKeyParameters) keyPair.getPublic(); RSAPublicKeyStructure struct = new RSAPublicKeyStructure(params.getModulus(), params.getExponent()); SubjectPublicKeyInfo info = new SubjectPublicKeyInfo(new AlgorithmIdentifier("1.2.840.113549.1.1.1"), struct); byte[] bytes = info.getDEREncoded(); FileOutputStream out = new FileOutputStream("/tmp/test.der"); out.write(bytes); out.flush(); out.close(); }
La chiave era ancora errata:
$ openssl asn1parse -in test.der -inform DER -i 0:d=0 hl=2 l= 90 cons: SEQUENCE 2:d=1 hl=2 l= 11 cons: SEQUENCE 4:d=2 hl=2 l= 9 prim: OBJECT :rsaEncryption 15:d=1 hl=2 l= 75 prim: BIT STRING
Ho cambiato org.bouncycastle.asn1.x509.AlgorithmIdentifier
public AlgorithmIdentifier( String objectId) { this.objectId = new DERObjectIdentifier(objectId); // This line has been added this.parametersDefined = true; }
E ora hai una bella chiave:
$ openssl asn1parse -in test.der -inform DER -i 0:d=0 hl=2 l= 92 cons: SEQUENCE 2:d=1 hl=2 l= 13 cons: SEQUENCE 4:d=2 hl=2 l= 9 prim: OBJECT :rsaEncryption 15:d=2 hl=2 l= 0 prim: NULL 17:d=1 hl=2 l= 75 prim: BIT STRING
Quale può essere usato per crittografare:
$ echo "123" | openssl rsautl -pubin -inkey test.der -encrypt -keyform DER -out y $ wc -cy 64 y
So che questo è un vecchio post. ma ho trascorso due giorni per risolvere questo problema e finalmente trovare BouncyCastle può farlo
ASN1Encodable
http://www.bouncycastle.org/docs/docs1.5on/org/bouncycastle/asn1/ASN1Encodable.html