2017-10-19 6 views
2

I openssl verwenden öffentliche und private DSA Schlüssel zu generieren und die folgenden Befehle ausführen:Kann nicht DSA-Schlüssel erhalten lesen von .pem-Dateien

openssl dsaparam -out dsaparam.pem 1024 
openssl gendsa -out dsaprivkey.pem dsaparam.pem 
openssl req -new -x509 -key dsaprivkey.pem -out dsacert.pem 

Und verwenden Sie die folgenden zwei Methoden, um diese Tasten zu laden:

public static PrivateKey loadPrivateKey() throws Exception { 
    String privateKeyPEM = FileUtils.readFileToString(new File("/Keys/dsaprivkey.pem"), StandardCharsets.UTF_8); 

    // strip of header, footer, newlines, whitespaces 
    privateKeyPEM = privateKeyPEM 
      .replace("-----BEGIN DSA PRIVATE KEY-----", "") 
      .replace("-----END DSA PRIVATE KEY-----", "") 
      .replaceAll("\\s", ""); 

    // decode to get the binary DER representation 
    byte[] privateKeyDER = Base64.getDecoder().decode(privateKeyPEM); 

    KeyFactory keyFactory = KeyFactory.getInstance("DSA"); 
    PrivateKey privateKey = keyFactory.generatePrivate(new PKCS8EncodedKeySpec(privateKeyDER)); 
    return privateKey; 
} 

public static PublicKey loadPublicKey() throws Exception { 
    String publicKeyPEM = FileUtils.readFileToString(new File("/Keys/dsacert.pem"), StandardCharsets.UTF_8); 

    // strip of header, footer, newlines, whitespaces 
    publicKeyPEM = publicKeyPEM 
      .replace("-----BEGIN CERTIFICATE-----", "") 
      .replace("-----END CERTIFICATE-----", "") 
      .replaceAll("\\s", ""); 

    // decode to get the binary DER representation 
    byte[] publicKeyDER = Base64.getDecoder().decode(publicKeyPEM); 

    KeyFactory keyFactory = KeyFactory.getInstance("DSA"); 
    PublicKey publicKey = keyFactory.generatePublic(new X509EncodedKeySpec(publicKeyDER)); 
    return publicKey; 
} 

Allerdings kann ich weder öffentlichen noch privaten Schlüssel lesen.

Wenn ich versuche, den öffentlichen Schlüssel zu lesen, die ich erhalten:

java.security.spec.InvalidKeySpecException: Inappropriate key specification: IOException: ObjectIdentifier() -- data isn't an object ID (tag = -96) 

Und wenn ich versuche, privaten Schlüssel zu lesen, die ich erhalten:

Exception in thread "main" java.security.spec.InvalidKeySpecException: Inappropriate key specification: IOException : algid parse error, not a sequence 

Wenn jemand die gleiche Situation, konfrontiert werde ich schätze wirklich jede mögliche Hilfe in Bezug auf dieses Problem

+1

Sie sollten einen Ihrer öffentlichen oder privaten Schlüssel erfassen. Ich vermute, es ist der Unterschied zwischen einem "öffentlichen Schlüssel" und "Subject Public Key Info", wobei letztere den Algorithmus und OID hat. Siehe auch [So lesen Sie die .pem-Datei, um den privaten und den öffentlichen Schlüssel zu erhalten] (https://stackoverflow.com/q/11787571/608639), [Laden des öffentlichen RSA-Schlüssels aus der Datei] (https://stackoverflow.com/q/11410770/608639), [PublicKey aus PEM-Datei auf Android, Java] (https://StackOverflow.com/q/45464949/608639), usw. Tauschen Sie einfach RSA für DSA. – jww

Antwort

3

Sie erzeugen nicht privaten und öffentlichen Schlüssel, Sie erzeugen privaten Schlüssel und (X.509) Zertifikat. Ein Zertifikat enthält einen öffentlichen Schlüssel, aber ist nicht dasselbe wie ein öffentlicher Schlüssel.

Um ein X.509-Zertifikat in Java, verwendet CertificateFactory (in der Regel direkt aus einer Datei) (see javadoc online) nicht KeyFactory (auf eine schlüsselabhängigen *Spec Klasse) zu lesen. Im Gegensatz zu KeyFactory (s) kann CertificateFactory entweder PEM- oder DER-Eingang verarbeiten, so dass Sie die Strips BEGIN/END und de-base64 nicht selbst ausführen müssen (außer Sie möchten).

Für den privaten Schlüssel haben Sie ein Problem ähnlich, aber nicht das gleiche wie die eine jww kommentierte. Für eine öffentliche Schlüsseldatei (die Sie nicht haben) verwendet OpenSSL standardmäßig das Format SubjectPublicKeyInfo, das Java X509EncodedKeySpec aufruft und OpenSSL intern PUBKEY aufruft. Jedoch für eine private Schlüsseldatei OpenSSL verwendet beide seine eigenen "Legacy" -Formaten und das standardisierte PKCS8-Format, aber Java PKCS8EncodedKeySpec unterstützt nur die zweite, Ihre Befehle verwenden die erste, und die Konvertierung zwischen ihnen in Code ist nicht trivial. Sie haben drei oder vielleicht vier Möglichkeiten:

  • Verwendung OpenSSL PKCS8-unverschlüsselt zu konvertieren: openssl pkcs8 -topk8 -nocrypt -in dsaprivkey.pem -out dsaprivfixed.pem # or in 1.0.0 up openssl pkey -in dsaprivkey.pem -out dsaprivfixed.pem

    Jetzt können Sie lesen diese mit dem entsandten Code mit Ausnahme der Linien zu entfernen sind -----BEGIN PRIVATE KEY----- und -----END PRIVATE KEY-----ohneDSA. Als eine kleine Verbesserung, wenn Sie getMimeDecoder verwenden, müssen Sie das Leerzeichen nicht selbst entfernen.

  • erzeugen PKCS8 (unverschlüsselt) mit zu beginnen, in OpenSSL 1.0.0 up: # you can generate the key within req instead of separately: openssl dsaparam -out params size openssl req -new -newkey dsa:params -x509 -nodes -keyout private.pem \ -out cert.pem # -nodes really means "don't encrypt key" for hysterical raisins # or in config file set encrypt_rsa_key=no (yes even for other algos!) # or omit it and set encrypt_key=no (more sensible) # # or you can use (new) genpkey instead of (old) gendsa: openssl dsaparam -out params size openssl genpkey -paramfile params -out private.pem openssl req -new -x509 -key private.pem -out cert.pem

    Jetzt sind Sie in der gleichen Situation sind wie oben.

  • Verwenden Sie die PEM-Funktionalität in BouncyCastle, um das Legacy-Format zu lesen.
    Siehe Reading elliptic curve private key from file with BouncyCastle
    und How to Load RSA Private Key From File

  • das Vermächtnis-Format lesen (wie Sie jetzt tun) und die für sie PKCS8 ASN.1-Codierung wieder aufzubauen und dann KeyFactory auf dem PKCS8 verwenden. Das ist viel komplizierter und ich empfehle es nicht. Ich habe ein bearbeitetes Beispiel für RSA (das ist einfacher) irgendwo, aber ich habe Probleme, es zu finden; Wird später hinzugefügt, wenn möglich.

Verwandte Themen