Um Ihr Szenario zu testen, habe ich einen privaten RSA-Schlüssel mit openssl
.
openssl genrsa -out private.pem 1024
Dann habe ich diesen Schlüssel in das PKCS#8 DER-Format konvertiert.
openssl pkcs8 -topk8 -inform PEM -in private.pem -outform DER -out private.der -nocrypt
Das Handbuch der openssl
bezieht sich auf PKCS#8 und DER sowohl als Formate Das heißt, für mich geschieht Folgendes:
pkcs8
sagt openssl
dass ich mit privaten Schlüsseln im PKCS#8-Format arbeiten möchte.
-topk8
sagt ihm, dass der private Schlüssel, den ich mit -in
est no in PKCS#8 (andernfalls wird davon ausgegangen, dass sie es ist).
-inform
y -in
angeben, dass ich den (PEM) privaten Schlüssel in PKCS#8 konvertieren möchte (ohne -topk8
wird versucht, einen Schlüssel, der bereits im PKCS#8-Format vorliegt, in ein Standard Schlüsselformat).
-outform
y -out
sagt ihm, dass ich einen DER-formatierten Schlüssel als Ausgabe haben möchte.
-nocrypt
sagt ihm, dass ich den Schlüssel nicht verschlüsseln will.
Dann habe ich mit meinem RSA-Schlüssel (im Standardformat) ein Zertifikat erstellt.
openssl req -new -x509 -keyform PEM -key private.pem -outform DER -out public.der
Das Zertifikat enthält den öffentlichen Schlüssel, der meinem privaten Schlüssel entspricht.
Danach habe ich sowohl den privaten Schlüssel als auch das Zertifikat mit Base64 verschlüsselt.
base64 private.der > private.der.b64
base64 public.der > public.der.b64
Die folgenden Dateien wurden erstellt.
private.pem # standard
private.der # pkcs8/DER
private.der.b64
public.der # x509/DER
public.der.b64
public static void main(String[] args) throws IOException, GeneralSecurityException {
// get a handle on the base64 encoded key and certificate
File privateKeyFile = new File("private.der.b64");
File publicKeyFile = new File("public.der.b64");
// pull them into arrays
byte[] privateKeyBytes = toByteArray(privateKeyFile);
byte[] publicKeyBytes = toByteArray(publicKeyFile);
// decode them
privateKeyBytes = toDecodedBase64ByteArray(privateKeyBytes);
publicKeyBytes = toDecodedBase64ByteArray(publicKeyBytes);
// get the private key
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
KeySpec privateKeySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
PrivateKey privateKey = keyFactory.generatePrivate(privateKeySpec);
// get the public key
CertificateFactory certificateFactory = CertificateFactory.getInstance("X509");
Certificate certificate = certificateFactory.generateCertificate(new ByteArrayInputStream(publicKeyBytes));
PublicKey publicKey = certificate.getPublicKey();
}
private static byte[] toByteArray(File file) throws IOException {
// java 7's try-with-resources statement
try (FileInputStream in = new FileInputStream(file);
FileChannel channel = in.getChannel()) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
channel.transferTo(0, channel.size(), Channels.newChannel(out));
return out.toByteArray();
}
}
private static byte[] toDecodedBase64ByteArray(byte[] base64EncodedByteArray) {
return DatatypeConverter.parseBase64Binary(
new String(base64EncodedByteArray, Charset.forName("UTF-8")));
}
Das Hauptproblem war, dass man ein Zertifikat statt eines öffentlichen Schlüssels hatte. Das Zertifikat enthält den öffentlichen Schlüssel, aber es kann nicht mit X509EncodedKeySpec(...)
Deshalb ist die CertificateFactory
muss stattdessen verwendet werden.
(Nebenbei bemerkt aquí ist ein großartiger Artikel/Tutorial über openssl
und die Verwendung von Java-Kryptographie. Ich habe meine Informationen teilweise von dort).