2017-10-19 7 views
2

J'utilise OpenSSL pour générer DSA publiques et privées clés et exécuter les commandes suivantes:Impossible d'obtenir lire les clés DSA à partir de fichiers .pem

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

Et utiliser les deux méthodes suivantes pour charger ces clés:

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; 
} 

Cependant, je ne peux pas lire ni publique ni clé privée.

Lorsque je tente de lire la clé publique, je reçois:

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

Et quand je tente de lire la clé privée, je reçois:

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

Si quelqu'un fait face à la même situation, je vais vraiment apprécier toute aide en ce qui concerne ce problème

+1

Vous devriez ajouter une de vos clés publiques ou privées. Je soupçonne que c'est la différence entre une "clé publique" et une "information de clé publique soumise", où cette dernière a l'algorithme et l'OID. Voir aussi [Comment lire le fichier .pem pour obtenir la clé publique et privée] (https://stackoverflow.com/q/11787571/608639), [Charger la clé publique RSA du fichier] (https://stackoverflow.com/q/11410770/608639), [PublicKey du fichier PEM sur android, java] (https://stackoverflow.com/q/45464949/608639), etc. Il suffit d'échanger RSA pour DSA. – jww

Répondre

3

Vous ne générez pas de clé privée et publique, vous générez une clé privée et (X.509) certificat . Un certificat contient une clé publique mais n'est pas la même que une clé publique.

Pour lire un certificat X.509 en Java, utilisez CertificateFactory (généralement directement à partir d'un fichier) (see javadoc online) pas KeyFactory (sur une classe dépendante clé *Spec). Contrairement à KeyFactory (s), CertificateFactory peut gérer soit l'entrée PEM ou DER, de sorte que vous n'avez pas besoin de faire le strip-BEGIN/END et de-base64 vous-même (sauf si vous le souhaitez).

Pour la clé privée, vous avez un problème similaire mais pas le même que celui signalé par jww. Pour un fichier de clé publique (que vous n'avez pas) OpenSSL utilise par défaut le format SubjectPublicKeyInfo que Java appelle X509EncodedKeySpec et OpenSSL appelle en interne PUBKEY. OpenSSL utilise à la fois ses propres formats 'legacy' et le format PKCS8 standard, mais PKCS8EncodedKeySpec de Java ne supporte que le second, vos commandes utilisent le premier, et la conversion entre eux dans le code n'est pas banal. Vous avez trois ou peut-être quatre choix:

  • utiliser OpenSSL pour convertir à PKCS8-non crypté: openssl pkcs8 -topk8 -nocrypt -in dsaprivkey.pem -out dsaprivfixed.pem # or in 1.0.0 up openssl pkey -in dsaprivkey.pem -out dsaprivfixed.pem

    Maintenant, vous pouvez lire ceci avec le code affiché à l'exception des lignes à supprimer sont -----BEGIN PRIVATE KEY----- et -----END PRIVATE KEY-----sansDSA. Comme une petite amélioration, si vous utilisez getMimeDecoder vous n'avez pas besoin de supprimer les espaces vous-même.

  • PKCS8 générer (non crypté) pour commencer, dans OpenSSL 1.0.0 jusqu'à: # 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

    Maintenant, vous êtes dans la même situation que ci-dessus.

  • Utilisez la fonctionnalité PEM dans BouncyCastle pour lire le format hérité.
    Voir Reading elliptic curve private key from file with BouncyCastle
    et How to Load RSA Private Key From File

  • lire le format hérité (comme vous faites maintenant) et recompiler le codage ASN.1 PKCS8 pour elle et ensuite utiliser KeyFactory sur le PKCS8. C'est beaucoup plus compliqué et je ne le recommande pas. J'ai un exemple travaillé pour RSA (qui est plus simple) quelque part mais j'ai du mal à le trouver; ajoutera plus tard si possible.