Ich schreibe einen kleinen Code, der den öffentlichen und den privaten Schlüssel liest, die in der PEM-Datei gespeichert sind. Ich verwende die folgenden Befehle, um die Schlüssel zu generieren.
Unterer Befehl zum Generieren eines Schlüsselpaars.
$openssl genrsa -out mykey.pem 2048
Dieser Befehl zum Generieren des privaten Schlüssels
$openssl pkcs8 -topk8 -inform PEM -outform PEM -in mykey.pem \
-out private_key.pem -nocrypt
und dieser Befehl, um den öffentlichen Schlüssel zu erhalten.
$ openssl rsa -in mykey.pem -pubout -outform DER -out public_key.der
Ich habe zwei Methoden geschrieben, die den privaten Schlüssel bzw. den öffentlichen Schlüssel lesen.
public PrivateKey getPemPrivateKey(String filename, String algorithm) throws Exception {
File f = new File(filename);
FileInputStream fis = new FileInputStream(f);
DataInputStream dis = new DataInputStream(fis);
byte[] keyBytes = new byte[(int) f.length()];
dis.readFully(keyBytes);
dis.close();
String temp = new String(keyBytes);
String privKeyPEM = temp.replace("-----BEGIN PRIVATE KEY-----\n", "");
privKeyPEM = privKeyPEM.replace("-----END PRIVATE KEY-----", "");
//System.out.println("Private key\n"+privKeyPEM);
Base64 b64 = new Base64();
byte [] decoded = b64.decode(privKeyPEM);
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(decoded);
KeyFactory kf = KeyFactory.getInstance(algorithm);
return kf.generatePrivate(spec);
}
public PublicKey getPemPublicKey(String filename, String algorithm) throws Exception {
File f = new File(filename);
FileInputStream fis = new FileInputStream(f);
DataInputStream dis = new DataInputStream(fis);
byte[] keyBytes = new byte[(int) f.length()];
dis.readFully(keyBytes);
dis.close();
String temp = new String(keyBytes);
String publicKeyPEM = temp.replace("-----BEGIN PUBLIC KEY-----\n", "");
publicKeyPEM = publicKeyPEM.replace("-----END PUBLIC KEY-----", "");
Base64 b64 = new Base64();
byte [] decoded = b64.decode(publicKeyPEM);
X509EncodedKeySpec spec =
new X509EncodedKeySpec(decoded);
KeyFactory kf = KeyFactory.getInstance(algorithm);
return kf.generatePublic(spec);
}
Ich denke, das ist eine naive Art, es zu tun. Ich könnte es nicht besser über das Internet machen. Kann mir jemand vorschlagen, wie man den gleichen Code am besten schreibt, um die generischen Fälle zu behandeln? Ich möchte keine Bibliothek von Drittanbietern verwenden.
Ich habe sehr grundlegende Kenntnisse im Singen / Verschlüsseln und verwende kaum Java-Sicherheits-APIs. Wenn ich also irgendwo keinen Sinn mache, dann bitte darauf hinweisen.
openssl -nocrypt
Befehl verwenden zu müssen ? Kann dieser Teil auch in Java ausgeführt werden?Antworten:
Versuchen Sie diese Klasse.
package groovy; import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.security.GeneralSecurityException; import java.security.InvalidKeyException; import java.security.KeyFactory; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.Signature; import java.security.SignatureException; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import javax.crypto.Cipher; import org.apache.commons.codec.binary.Base64; public class RSA { private static String getKey(String filename) throws IOException { // Read key from file String strKeyPEM = ""; BufferedReader br = new BufferedReader(new FileReader(filename)); String line; while ((line = br.readLine()) != null) { strKeyPEM += line + "\n"; } br.close(); return strKeyPEM; } public static RSAPrivateKey getPrivateKey(String filename) throws IOException, GeneralSecurityException { String privateKeyPEM = getKey(filename); return getPrivateKeyFromString(privateKeyPEM); } public static RSAPrivateKey getPrivateKeyFromString(String key) throws IOException, GeneralSecurityException { String privateKeyPEM = key; privateKeyPEM = privateKeyPEM.replace("-----BEGIN PRIVATE KEY-----\n", ""); privateKeyPEM = privateKeyPEM.replace("-----END PRIVATE KEY-----", ""); byte[] encoded = Base64.decodeBase64(privateKeyPEM); KeyFactory kf = KeyFactory.getInstance("RSA"); PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encoded); RSAPrivateKey privKey = (RSAPrivateKey) kf.generatePrivate(keySpec); return privKey; } public static RSAPublicKey getPublicKey(String filename) throws IOException, GeneralSecurityException { String publicKeyPEM = getKey(filename); return getPublicKeyFromString(publicKeyPEM); } public static RSAPublicKey getPublicKeyFromString(String key) throws IOException, GeneralSecurityException { String publicKeyPEM = key; publicKeyPEM = publicKeyPEM.replace("-----BEGIN PUBLIC KEY-----\n", ""); publicKeyPEM = publicKeyPEM.replace("-----END PUBLIC KEY-----", ""); byte[] encoded = Base64.decodeBase64(publicKeyPEM); KeyFactory kf = KeyFactory.getInstance("RSA"); RSAPublicKey pubKey = (RSAPublicKey) kf.generatePublic(new X509EncodedKeySpec(encoded)); return pubKey; } public static String sign(PrivateKey privateKey, String message) throws NoSuchAlgorithmException, InvalidKeyException, SignatureException, UnsupportedEncodingException { Signature sign = Signature.getInstance("SHA1withRSA"); sign.initSign(privateKey); sign.update(message.getBytes("UTF-8")); return new String(Base64.encodeBase64(sign.sign()), "UTF-8"); } public static boolean verify(PublicKey publicKey, String message, String signature) throws SignatureException, NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeyException { Signature sign = Signature.getInstance("SHA1withRSA"); sign.initVerify(publicKey); sign.update(message.getBytes("UTF-8")); return sign.verify(Base64.decodeBase64(signature.getBytes("UTF-8"))); } public static String encrypt(String rawText, PublicKey publicKey) throws IOException, GeneralSecurityException { Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.ENCRYPT_MODE, publicKey); return Base64.encodeBase64String(cipher.doFinal(rawText.getBytes("UTF-8"))); } public static String decrypt(String cipherText, PrivateKey privateKey) throws IOException, GeneralSecurityException { Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.DECRYPT_MODE, privateKey); return new String(cipher.doFinal(Base64.decodeBase64(cipherText)), "UTF-8"); } } Required jar library "common-codec-1.6"
quelle
Only RSAPublicKeySpec and X509EncodedKeySpec supported for RSA public keys
. Umgeschaltet aufX509EncodedKeySpec
und dann bekommenjava.security.InvalidKeyException: IOException: DerInputStream.getLength(): lengthTag=111, too big.
. Dies ist mit einer PEM-Datei von AWS EC2RSAPublicKeySpec
da Ihr öffentlicher Schlüssel imPKCS#1
Format und nicht imPKCS#8
Format zu sein scheint . Im letzteren Fall müssen Sie verwendenX509EncodedKeySpec
(und nichtPKCS8EncodedKeySpec
wie in der Antwort derzeit angegeben). Sie können einen Blick auf den Header zwischen den beiden unterscheiden,BEGIN RSA PUBLIC KEY
gegenüberBEGIN PUBLIC KEY
.RSAPublicKeySpec
. So ist es wahrscheinlich einfacher, nur konvertieren vonPKCS#1
zuPKCS#8
mitopenssl
oder ähnlichen Programmen ...Java 9+:
private byte[] loadPEM(String resource) throws IOException { URL url = getClass().getResource(resource); InputStream in = url.openStream(); String pem = new String(in.readAllBytes(), StandardCharsets.ISO_8859_1); Pattern parse = Pattern.compile("(?m)(?s)^---*BEGIN.*---*$(.*)^---*END.*---*$.*"); String encoded = parse.matcher(pem).replaceFirst("$1"); return Base64.getMimeDecoder().decode(encoded); } @Test public void test() throws Exception { KeyFactory kf = KeyFactory.getInstance("RSA"); CertificateFactory cf = CertificateFactory.getInstance("X.509"); PrivateKey key = kf.generatePrivate(new PKCS8EncodedKeySpec(loadPEM("test.key"))); PublicKey pub = kf.generatePublic(new X509EncodedKeySpec(loadPEM("test.pub"))); Certificate crt = cf.generateCertificate(getClass().getResourceAsStream("test.crt")); }
Java 8:
Ersetzen Sie den
in.readAllBytes()
Anruf durch einen Aufruf an:byte[] readAllBytes(InputStream in) throws IOException { ByteArrayOutputStream baos= new ByteArrayOutputStream(); byte[] buf = new byte[1024]; for (int read=0; read != -1; read = in.read(buf)) { baos.write(buf, 0, read); } return baos.toByteArray(); }
Vielen Dank an Daniel für das Erkennen von API-Kompatibilitätsproblemen
quelle
.pem
Datei nicht manuell aus der Box lesen kann , oder wir müssen dies tun :) Vielen Dank für die LösungEine Möglichkeit ist die Verwendung von PEMParser von bouncycastle :
Hier ist ein Beispiel für die Verwendung des Parser-Testcodes :
package org.bouncycastle.openssl.test; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.Reader; import java.math.BigInteger; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.PrivateKey; import java.security.PublicKey; import java.security.SecureRandom; import java.security.Security; import java.security.Signature; import java.security.interfaces.DSAPrivateKey; import java.security.interfaces.RSAPrivateCrtKey; import java.security.interfaces.RSAPrivateKey; import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.cms.CMSObjectIdentifiers; import org.bouncycastle.asn1.cms.ContentInfo; import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; import org.bouncycastle.asn1.x9.ECNamedCurveTable; import org.bouncycastle.asn1.x9.X9ECParameters; import org.bouncycastle.cert.X509CertificateHolder; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.openssl.PEMDecryptorProvider; import org.bouncycastle.openssl.PEMEncryptedKeyPair; import org.bouncycastle.openssl.PEMKeyPair; import org.bouncycastle.openssl.PEMParser; import org.bouncycastle.openssl.PEMWriter; import org.bouncycastle.openssl.PasswordFinder; import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter; import org.bouncycastle.openssl.jcajce.JceOpenSSLPKCS8DecryptorProviderBuilder; import org.bouncycastle.openssl.jcajce.JcePEMDecryptorProviderBuilder; import org.bouncycastle.operator.InputDecryptorProvider; import org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo; import org.bouncycastle.util.test.SimpleTest; /** * basic class for reading test.pem - the password is "secret" */ public class ParserTest extends SimpleTest { private static class Password implements PasswordFinder { char[] password; Password( char[] word) { this.password = word; } public char[] getPassword() { return password; } } public String getName() { return "PEMParserTest"; } private PEMParser openPEMResource( String fileName) { InputStream res = this.getClass().getResourceAsStream(fileName); Reader fRd = new BufferedReader(new InputStreamReader(res)); return new PEMParser(fRd); } public void performTest() throws Exception { PEMParser pemRd = openPEMResource("test.pem"); Object o; PEMKeyPair pemPair; KeyPair pair; while ((o = pemRd.readObject()) != null) { if (o instanceof KeyPair) { //pair = (KeyPair)o; //System.out.println(pair.getPublic()); //System.out.println(pair.getPrivate()); } else { //System.out.println(o.toString()); } } // test bogus lines before begin are ignored. pemRd = openPEMResource("extratest.pem"); while ((o = pemRd.readObject()) != null) { if (!(o instanceof X509CertificateHolder)) { fail("wrong object found"); } } // // pkcs 7 data // pemRd = openPEMResource("pkcs7.pem"); ContentInfo d = (ContentInfo)pemRd.readObject(); if (!d.getContentType().equals(CMSObjectIdentifiers.envelopedData)) { fail("failed envelopedData check"); } // // ECKey // pemRd = openPEMResource("eckey.pem"); ASN1ObjectIdentifier ecOID = (ASN1ObjectIdentifier)pemRd.readObject(); X9ECParameters ecSpec = ECNamedCurveTable.getByOID(ecOID); if (ecSpec == null) { fail("ecSpec not found for named curve"); } pemPair = (PEMKeyPair)pemRd.readObject(); pair = new JcaPEMKeyConverter().setProvider("BC").getKeyPair(pemPair); Signature sgr = Signature.getInstance("ECDSA", "BC"); sgr.initSign(pair.getPrivate()); byte[] message = new byte[] { (byte)'a', (byte)'b', (byte)'c' }; sgr.update(message); byte[] sigBytes = sgr.sign(); sgr.initVerify(pair.getPublic()); sgr.update(message); if (!sgr.verify(sigBytes)) { fail("EC verification failed"); } if (!pair.getPublic().getAlgorithm().equals("ECDSA")) { fail("wrong algorithm name on public got: " + pair.getPublic().getAlgorithm()); } if (!pair.getPrivate().getAlgorithm().equals("ECDSA")) { fail("wrong algorithm name on private"); } // // ECKey -- explicit parameters // pemRd = openPEMResource("ecexpparam.pem"); ecSpec = (X9ECParameters)pemRd.readObject(); pemPair = (PEMKeyPair)pemRd.readObject(); pair = new JcaPEMKeyConverter().setProvider("BC").getKeyPair(pemPair); sgr = Signature.getInstance("ECDSA", "BC"); sgr.initSign(pair.getPrivate()); message = new byte[] { (byte)'a', (byte)'b', (byte)'c' }; sgr.update(message); sigBytes = sgr.sign(); sgr.initVerify(pair.getPublic()); sgr.update(message); if (!sgr.verify(sigBytes)) { fail("EC verification failed"); } if (!pair.getPublic().getAlgorithm().equals("ECDSA")) { fail("wrong algorithm name on public got: " + pair.getPublic().getAlgorithm()); } if (!pair.getPrivate().getAlgorithm().equals("ECDSA")) { fail("wrong algorithm name on private"); } // // writer/parser test // KeyPairGenerator kpGen = KeyPairGenerator.getInstance("RSA", "BC"); pair = kpGen.generateKeyPair(); keyPairTest("RSA", pair); kpGen = KeyPairGenerator.getInstance("DSA", "BC"); kpGen.initialize(512, new SecureRandom()); pair = kpGen.generateKeyPair(); keyPairTest("DSA", pair); // // PKCS7 // ByteArrayOutputStream bOut = new ByteArrayOutputStream(); PEMWriter pWrt = new PEMWriter(new OutputStreamWriter(bOut)); pWrt.writeObject(d); pWrt.close(); pemRd = new PEMParser(new InputStreamReader(new ByteArrayInputStream(bOut.toByteArray()))); d = (ContentInfo)pemRd.readObject(); if (!d.getContentType().equals(CMSObjectIdentifiers.envelopedData)) { fail("failed envelopedData recode check"); } // OpenSSL test cases (as embedded resources) doOpenSslDsaTest("unencrypted"); doOpenSslRsaTest("unencrypted"); doOpenSslTests("aes128"); doOpenSslTests("aes192"); doOpenSslTests("aes256"); doOpenSslTests("blowfish"); doOpenSslTests("des1"); doOpenSslTests("des2"); doOpenSslTests("des3"); doOpenSslTests("rc2_128"); doOpenSslDsaTest("rc2_40_cbc"); doOpenSslRsaTest("rc2_40_cbc"); doOpenSslDsaTest("rc2_64_cbc"); doOpenSslRsaTest("rc2_64_cbc"); doDudPasswordTest("7fd98", 0, "corrupted stream - out of bounds length found"); doDudPasswordTest("ef677", 1, "corrupted stream - out of bounds length found"); doDudPasswordTest("800ce", 2, "unknown tag 26 encountered"); doDudPasswordTest("b6cd8", 3, "DEF length 81 object truncated by 56"); doDudPasswordTest("28ce09", 4, "DEF length 110 object truncated by 28"); doDudPasswordTest("2ac3b9", 5, "DER length more than 4 bytes: 11"); doDudPasswordTest("2cba96", 6, "DEF length 100 object truncated by 35"); doDudPasswordTest("2e3354", 7, "DEF length 42 object truncated by 9"); doDudPasswordTest("2f4142", 8, "DER length more than 4 bytes: 14"); doDudPasswordTest("2fe9bb", 9, "DER length more than 4 bytes: 65"); doDudPasswordTest("3ee7a8", 10, "DER length more than 4 bytes: 57"); doDudPasswordTest("41af75", 11, "unknown tag 16 encountered"); doDudPasswordTest("1704a5", 12, "corrupted stream detected"); doDudPasswordTest("1c5822", 13, "unknown object in getInstance: org.bouncycastle.asn1.DERUTF8String"); doDudPasswordTest("5a3d16", 14, "corrupted stream detected"); doDudPasswordTest("8d0c97", 15, "corrupted stream detected"); doDudPasswordTest("bc0daf", 16, "corrupted stream detected"); doDudPasswordTest("aaf9c4d",17, "corrupted stream - out of bounds length found"); doNoPasswordTest(); // encrypted private key test InputDecryptorProvider pkcs8Prov = new JceOpenSSLPKCS8DecryptorProviderBuilder().build("password".toCharArray()); pemRd = openPEMResource("enckey.pem"); PKCS8EncryptedPrivateKeyInfo encPrivKeyInfo = (PKCS8EncryptedPrivateKeyInfo)pemRd.readObject(); JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC"); RSAPrivateCrtKey privKey = (RSAPrivateCrtKey)converter.getPrivateKey(encPrivKeyInfo.decryptPrivateKeyInfo(pkcs8Prov)); if (!privKey.getPublicExponent().equals(new BigInteger("10001", 16))) { fail("decryption of private key data check failed"); } // general PKCS8 test pemRd = openPEMResource("pkcs8test.pem"); Object privInfo; while ((privInfo = pemRd.readObject()) != null) { if (privInfo instanceof PrivateKeyInfo) { privKey = (RSAPrivateCrtKey)converter.getPrivateKey(PrivateKeyInfo.getInstance(privInfo)); } else { privKey = (RSAPrivateCrtKey)converter.getPrivateKey(((PKCS8EncryptedPrivateKeyInfo)privInfo).decryptPrivateKeyInfo(pkcs8Prov)); } if (!privKey.getPublicExponent().equals(new BigInteger("10001", 16))) { fail("decryption of private key data check failed"); } } } private void keyPairTest( String name, KeyPair pair) throws IOException { PEMParser pemRd; ByteArrayOutputStream bOut = new ByteArrayOutputStream(); PEMWriter pWrt = new PEMWriter(new OutputStreamWriter(bOut)); pWrt.writeObject(pair.getPublic()); pWrt.close(); pemRd = new PEMParser(new InputStreamReader(new ByteArrayInputStream(bOut.toByteArray()))); SubjectPublicKeyInfo pub = SubjectPublicKeyInfo.getInstance(pemRd.readObject()); JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC"); PublicKey k = converter.getPublicKey(pub); if (!k.equals(pair.getPublic())) { fail("Failed public key read: " + name); } bOut = new ByteArrayOutputStream(); pWrt = new PEMWriter(new OutputStreamWriter(bOut)); pWrt.writeObject(pair.getPrivate()); pWrt.close(); pemRd = new PEMParser(new InputStreamReader(new ByteArrayInputStream(bOut.toByteArray()))); KeyPair kPair = converter.getKeyPair((PEMKeyPair)pemRd.readObject()); if (!kPair.getPrivate().equals(pair.getPrivate())) { fail("Failed private key read: " + name); } if (!kPair.getPublic().equals(pair.getPublic())) { fail("Failed private key public read: " + name); } } private void doOpenSslTests( String baseName) throws IOException { doOpenSslDsaModesTest(baseName); doOpenSslRsaModesTest(baseName); } private void doOpenSslDsaModesTest( String baseName) throws IOException { doOpenSslDsaTest(baseName + "_cbc"); doOpenSslDsaTest(baseName + "_cfb"); doOpenSslDsaTest(baseName + "_ecb"); doOpenSslDsaTest(baseName + "_ofb"); } private void doOpenSslRsaModesTest( String baseName) throws IOException { doOpenSslRsaTest(baseName + "_cbc"); doOpenSslRsaTest(baseName + "_cfb"); doOpenSslRsaTest(baseName + "_ecb"); doOpenSslRsaTest(baseName + "_ofb"); } private void doOpenSslDsaTest( String name) throws IOException { String fileName = "dsa/openssl_dsa_" + name + ".pem"; doOpenSslTestFile(fileName, DSAPrivateKey.class); } private void doOpenSslRsaTest( String name) throws IOException { String fileName = "rsa/openssl_rsa_" + name + ".pem"; doOpenSslTestFile(fileName, RSAPrivateKey.class); } private void doOpenSslTestFile( String fileName, Class expectedPrivKeyClass) throws IOException { JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC"); PEMDecryptorProvider decProv = new JcePEMDecryptorProviderBuilder().setProvider("BC").build("changeit".toCharArray()); PEMParser pr = openPEMResource("data/" + fileName); Object o = pr.readObject(); if (o == null || !((o instanceof PEMKeyPair) || (o instanceof PEMEncryptedKeyPair))) { fail("Didn't find OpenSSL key"); } KeyPair kp = (o instanceof PEMEncryptedKeyPair) ? converter.getKeyPair(((PEMEncryptedKeyPair)o).decryptKeyPair(decProv)) : converter.getKeyPair((PEMKeyPair)o); PrivateKey privKey = kp.getPrivate(); if (!expectedPrivKeyClass.isInstance(privKey)) { fail("Returned key not of correct type"); } } private void doDudPasswordTest(String password, int index, String message) { // illegal state exception check - in this case the wrong password will // cause an underlying class cast exception. try { PEMDecryptorProvider decProv = new JcePEMDecryptorProviderBuilder().setProvider("BC").build(password.toCharArray()); PEMParser pemRd = openPEMResource("test.pem"); Object o; while ((o = pemRd.readObject()) != null) { if (o instanceof PEMEncryptedKeyPair) { ((PEMEncryptedKeyPair)o).decryptKeyPair(decProv); } } fail("issue not detected: " + index); } catch (IOException e) { if (e.getCause() != null && !e.getCause().getMessage().endsWith(message)) { fail("issue " + index + " exception thrown, but wrong message"); } else if (e.getCause() == null && !e.getMessage().equals(message)) { e.printStackTrace(); fail("issue " + index + " exception thrown, but wrong message"); } } } private void doNoPasswordTest() throws IOException { PEMDecryptorProvider decProv = new JcePEMDecryptorProviderBuilder().setProvider("BC").build("".toCharArray()); PEMParser pemRd = openPEMResource("smimenopw.pem"); Object o; PrivateKeyInfo key = null; while ((o = pemRd.readObject()) != null) { key = (PrivateKeyInfo)o; } if (key == null) { fail("private key not detected"); } } public static void main( String[] args) { Security.addProvider(new BouncyCastleProvider()); runTest(new ParserTest()); } }
quelle
Nun, mein Code ist wie dein, mit kleinen Unterschieden ...
public static X509Certificate loadPublicX509(String fileName) throws GeneralSecurityException { InputStream is = null; X509Certificate crt = null; try { is = fileName.getClass().getResourceAsStream("/" + fileName); CertificateFactory cf = CertificateFactory.getInstance("X.509"); crt = (X509Certificate)cf.generateCertificate(is); } finally { closeSilent(is); } return crt; } public static PrivateKey loadPrivateKey(String fileName) throws IOException, GeneralSecurityException { PrivateKey key = null; InputStream is = null; try { is = fileName.getClass().getResourceAsStream("/" + fileName); BufferedReader br = new BufferedReader(new InputStreamReader(is)); StringBuilder builder = new StringBuilder(); boolean inKey = false; for (String line = br.readLine(); line != null; line = br.readLine()) { if (!inKey) { if (line.startsWith("-----BEGIN ") && line.endsWith(" PRIVATE KEY-----")) { inKey = true; } continue; } else { if (line.startsWith("-----END ") && line.endsWith(" PRIVATE KEY-----")) { inKey = false; break; } builder.append(line); } } // byte[] encoded = DatatypeConverter.parseBase64Binary(builder.toString()); PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encoded); KeyFactory kf = KeyFactory.getInstance("RSA"); key = kf.generatePrivate(keySpec); } finally { closeSilent(is); } return key; } public static void closeSilent(final InputStream is) { if (is == null) return; try { is.close(); } catch (Exception ign) {} }
quelle
-----BEGIN RSA PRIVATE KEY-----
ist ein anderes Format, NICHT PKCS8, und der Versuch, es als PKCS8 zu lesen, funktioniert nicht. Auch ein Zertifikat ist etwas anderes als ein roher öffentlicher Schlüssel, daher funktioniert dies für die Daten in diesem Q überhaupt nicht.Ich denke, in Ihrer Definition des privaten Schlüssels sollten Sie Folgendes ersetzen:
X509EncodedKeySpec spec = new X509EncodedKeySpec(decoded);
mit:
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(decoded);
Schauen Sie Ihren
openssl
Befehl:Und die Java-Ausnahme:
quelle
Java libs macht es fast zu einem Einzeiler, das öffentliche Zertifikat zu lesen, wie es von openssl generiert wird:
val certificate: X509Certificate = ByteArrayInputStream( publicKeyCert.toByteArray(Charsets.US_ASCII)) .use { CertificateFactory.getInstance("X.509") .generateCertificate(it) as X509Certificate }
Aber zum Teufel war das Lesen des privaten Schlüssels problematisch:
RSAPrivateKey
.siehe dazu: Endlösung in Kotlin
quelle
Um den öffentlichen Schlüssel zu erhalten, können Sie einfach Folgendes tun:
public static PublicKey getPublicKeyFromCertFile(final String certfile){ return new X509CertImpl(new FileInputStream(new File(certfile))).getPublicKey();
Um den privaten Schlüssel zu erhalten, ist es schwieriger:
public static PrivateKey getPrivateKeyFromKeyFile(final String keyfile){ try { Process p; p = Runtime.getRuntime().exec("openssl pkcs8 -nocrypt -topk8 -inform PEM " + "-in " + keyfile + " -outform DER -out " + keyfile + ".der"); p.waitFor(); System.out.println("Command executed" + (p.exitValue() == 0 ? " successfully" : " with error" )); } catch ( IOException | InterruptedException e) { e.printStackTrace(); System.exit(1); } PrivateKey myPrivKey = null; try { byte[] keyArray = Files.readAllBytes(Paths.get(keyfile + ".der")); PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyArray); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); myPrivKey = keyFactory.generatePrivate(keySpec); } catch (IOException | NoSuchAlgorithmException | InvalidKeySpecException e){ e.printStackTrace(); System.exit(1); } return myPrivKey; }
quelle
Lesen Sie den öffentlichen Schlüssel von pem (PK oder Cert). Kommt auf Bouncycastle an.
private static PublicKey getPublicKeyFromPEM(Reader reader) throws IOException { PublicKey key; try (PEMParser pem = new PEMParser(reader)) { JcaPEMKeyConverter jcaPEMKeyConverter = new JcaPEMKeyConverter(); Object pemContent = pem.readObject(); if (pemContent instanceof PEMKeyPair) { PEMKeyPair pemKeyPair = (PEMKeyPair) pemContent; KeyPair keyPair = jcaPEMKeyConverter.getKeyPair(pemKeyPair); key = keyPair.getPublic(); } else if (pemContent instanceof SubjectPublicKeyInfo) { SubjectPublicKeyInfo keyInfo = (SubjectPublicKeyInfo) pemContent; key = jcaPEMKeyConverter.getPublicKey(keyInfo); } else if (pemContent instanceof X509CertificateHolder) { X509CertificateHolder cert = (X509CertificateHolder) pemContent; key = jcaPEMKeyConverter.getPublicKey(cert.getSubjectPublicKeyInfo()); } else { throw new IllegalArgumentException("Unsupported public key format '" + pemContent.getClass().getSimpleName() + '"'); } } return key; }
Lesen Sie den privaten Schlüssel von PEM:
private static PrivateKey getPrivateKeyFromPEM(Reader reader) throws IOException { PrivateKey key; try (PEMParser pem = new PEMParser(reader)) { JcaPEMKeyConverter jcaPEMKeyConverter = new JcaPEMKeyConverter(); Object pemContent = pem.readObject(); if (pemContent instanceof PEMKeyPair) { PEMKeyPair pemKeyPair = (PEMKeyPair) pemContent; KeyPair keyPair = jcaPEMKeyConverter.getKeyPair(pemKeyPair); key = keyPair.getPrivate(); } else if (pemContent instanceof PrivateKeyInfo) { PrivateKeyInfo privateKeyInfo = (PrivateKeyInfo) pemContent; key = jcaPEMKeyConverter.getPrivateKey(privateKeyInfo); } else { throw new IllegalArgumentException("Unsupported private key format '" + pemContent.getClass().getSimpleName() + '"'); } } return key; }
quelle
Java unterstützt die sofortige Verwendung von DER für öffentliche und private Schlüssel (dies entspricht im Wesentlichen PEM, wie das OP verlangt, außer dass PEM-Dateien Basis-64-Daten sowie Kopf- und Fußzeilen enthalten).
Sie können sich auf diesen Code (Modulo-Ausnahmebehandlung) ohne externe Bibliothek verlassen, wenn Sie Java 8+ verwenden (dies setzt voraus, dass Ihre Schlüsseldateien im Klassenpfad verfügbar sind):
class Signer { private KeyFactory keyFactory; public Signer() { this.keyFactory = KeyFactory.getInstance("RSA"); } public PublicKey getPublicKey() { byte[] publicKey = readFileAsBytes("public-key.der"); X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey); return keyFactory.generatePublic(keySpec); } public PrivateKey getPrivateKey() { byte[] privateKey = readFileAsBytes("private-key.der"); PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKey); return keyFactory.generatePrivate(keySpec); } private URI readFileAsBytes(String name) { URI fileUri = getClass().getClassLoader().getResource(name).toURI(); return Files.readAllBytes(Paths.get(fileUri)); } }
Für den Datensatz können Sie einen PEM-Schlüssel mit dem folgenden Befehl in einen DER-Schlüssel konvertieren:
$ openssl pkcs8 -topk8 -inform PEM -outform DER -in private-key.pem -out private-key.der -nocrypt
Und erhalten Sie den öffentlichen Schlüssel in DER mit:
$ openssl rsa -in private-key.pem -pubout -outform DER -out public-key.der
quelle
Wenn eine PEM nur einen privaten RSA-Schlüssel ohne Verschlüsselung enthält, muss es sich um eine ASN.1-Sequenzstruktur mit 9 Zahlen handeln, um einen CRT-Schlüssel ( Chinese Remainder Theorem ) zu präsentieren:
Wir können Folgendes implementieren
RSAPrivateCrtKey
:class RSAPrivateCrtKeyImpl implements RSAPrivateCrtKey { private static final long serialVersionUID = 1L; BigInteger n, e, d, p, q, dp, dq, qinv; @Override public BigInteger getModulus() { return n; } @Override public BigInteger getPublicExponent() { return e; } @Override public BigInteger getPrivateExponent() { return d; } @Override public BigInteger getPrimeP() { return p; } @Override public BigInteger getPrimeQ() { return q; } @Override public BigInteger getPrimeExponentP() { return dp; } @Override public BigInteger getPrimeExponentQ() { return dq; } @Override public BigInteger getCrtCoefficient() { return qinv; } @Override public String getAlgorithm() { return "RSA"; } @Override public String getFormat() { throw new UnsupportedOperationException(); } @Override public byte[] getEncoded() { throw new UnsupportedOperationException(); } }
Lesen Sie dann den privaten Schlüssel aus einer PEM-Datei:
import sun.security.util.DerInputStream; import sun.security.util.DerValue; static RSAPrivateCrtKey getRSAPrivateKey(String keyFile) { RSAPrivateCrtKeyImpl prvKey = new RSAPrivateCrtKeyImpl(); try (BufferedReader in = new BufferedReader(new FileReader(keyFile))) { StringBuilder sb = new StringBuilder(); String line; while ((line = in.readLine()) != null) { // skip "-----BEGIN/END RSA PRIVATE KEY-----" if (!line.startsWith("--") || !line.endsWith("--")) { sb.append(line); } } DerInputStream der = new DerValue(Base64. getDecoder().decode(sb.toString())).getData(); der.getBigInteger(); // 0 prvKey.n = der.getBigInteger(); prvKey.e = der.getBigInteger(); // 65537 prvKey.d = der.getBigInteger(); prvKey.p = der.getBigInteger(); prvKey.q = der.getBigInteger(); prvKey.dp = der.getBigInteger(); prvKey.dq = der.getBigInteger(); prvKey.qinv = der.getBigInteger(); } catch (IllegalArgumentException | IOException e) { logger.warn(keyFile + ": " + e.getMessage()); return null; } }
quelle