web-dev-qa-db-fra.com

Comment utiliser les clés générées par OpenSSL en Java?

J'ai ma paire de clés publiques et privées et mon certificat. Celles-ci ont été créées dans OpenSSL (pourquoi? Car on m'a demandé de le faire dans OpenSSL). Maintenant, je veux utiliser ces choses pour créer une application Java qui utilise des signatures numériques. Comment puis-je utiliser mes clés privées et publiques pour crypter/décrypter des informations (et utiliser le certificat pour voir si les données sont Quelles sont les classes de Java qui me permettent de le faire?

Mes clés sont en texte clair quelque chose comme ceci:

-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDDuyg3h0VbP9iZ6RCxSU6x4WX4
anAwedMVUTqF0WHlvHl1Kiqa6N6TiUk23uXAVUX8RwLFjXWHlG0xwW7mGByA2mX9
5oPQpQFu8C70aMuUotGv87iiLi0UKCZV+9wS9rMdg5LHu1mMPilwgOO6MlyTxKem
-----END PUBLIC KEY-----

MISE À JOUR

J'ai créé ce code mais je ne peux toujours pas utiliser la clé privée pour signer une chaîne.

public void encryptHash(String hashToEncrypt, String pathOfKey, String Algorithm) {
    FileInputStream fis = null;
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    int len;

        File f = new File(pathOfKey);

        fis = new FileInputStream(pathOfKey);
        len = 0;
        while((len = fis.read()) != -1){
            baos.write(len);
        }

        KeyFactory kf = KeyFactory.getInstance(Algorithm); //Algorithm = "RSA"
        KeySpec keySpec = new PKCS8EncodedKeySpec(baos.toByteArray());
        baos.close();
        PrivateKey privateKey = kf.generatePrivate(keySpec);  //Here's the exception thrown

        Signature rsaSigner = Signature.getInstance("SHA1withRSA");
        rsaSigner.initSign(privateKey);

        fis = new FileInputStream(hashToEncrypt);
        BufferedInputStream bis = new BufferedInputStream(fis);
        byte[] buffer = new byte[1024];
        len = 0;
        while((len = bis.read(buffer)) >= 0){
            try {
                rsaSigner.update(buffer, 0, len);
            } catch (SignatureException ex) {
                Logger.getLogger(DataEncryptor.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        bis.close();

        byte[] signature = rsaSigner.sign();

        System.out.println(new String(signature));
}

l'exception que je reçois est

dic 09, 2011 12:49:02 PM firmaelectronica.DataEncryptor encryptHash
Grave: null
Java.security.spec.InvalidKeySpecException: Java.security.InvalidKeyException: IOException : DER input, Integer tag error
    at Sun.security.rsa.RSAKeyFactory.engineGeneratePrivate(RSAKeyFactory.Java:217)
    at Java.security.KeyFactory.generatePrivate(KeyFactory.Java:372)
    at firmaelectronica.DataEncryptor.encryptHash(DataEncryptor.Java:40)
    at firmaelectronica.FirmaElectronica.main(FirmaElectronica.Java:39)
Caused by: Java.security.InvalidKeyException: IOException : DER input, Integer tag error
    at Sun.security.pkcs.PKCS8Key.decode(PKCS8Key.Java:361)
    at Sun.security.pkcs.PKCS8Key.decode(PKCS8Key.Java:367)
    at Sun.security.rsa.RSAPrivateCrtKeyImpl.<init>(RSAPrivateCrtKeyImpl.Java:91)
    at Sun.security.rsa.RSAPrivateCrtKeyImpl.newKey(RSAPrivateCrtKeyImpl.Java:75)
    at Sun.security.rsa.RSAKeyFactory.generatePrivate(RSAKeyFactory.Java:316)
    at Sun.security.rsa.RSAKeyFactory.engineGeneratePrivate(RSAKeyFactory.Java:213)
    ... 3 more
11
BRabbit27

Si vous avez une clé publique sous cette forme (et non dans un certificat), je vous recommande d'utiliser BouncyCastle 's PEMReader. Sa méthode readObject() peut lire beaucoup pour les formats: clés publiques, certificats, clés privées (même si vous devrez peut-être utiliser la méthode avec un mot de passe) ...

Si vous ne souhaitez pas utiliser BouncyCastle, vous pouvez lire les certificats à l'aide d'un CertificateFactory (voir exemples). Avec un certificat au format PEM dans un InputStream:

CertificateFactory cf = CertificateFactory.getInstance("X.509");
Certificate cert = cf.generateCertificate(inputStream);

Pour les clés privées, si votre clé privée est une structure PKCS # 8 au format DER, vous pouvez la lire directement en utilisant PKCS8EncodedKeySpec . Par exemple:

KeyFactory kf = KeyFactory.getInstance("RSA");
// Read privateKeyDerByteArray from DER file.
KeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyDerByteArray);
PrivateKey key = kf.generatePrivate(keySpec);

Vous pouvez convertir votre clé privée en PKCS # 8 à l'aide de openssl pkcs8 -topk8 (Rappelez-vous -outform DER, Vous pouvez également vérifier les suites de chiffrement car toutes ne sont pas prises en charge par les deux Java et OpenSSL).

  • Du point de vue de l'utilisation du magasin de clés:

Si vous ne voulez pas faire beaucoup de programmation pour gérer les clés, pour aller entre Java et OpenSSL, il est pratique d'utiliser le format PKCS # 12.

Si les clés et certificats que vous avez produits avec OpenSSL ne sont pas déjà dans un conteneur p12:

openssl pkcs12 -export -in cert.pem -inkey key.pem -out store.p12

En général, vous pouvez utiliser directement le, en utilisant le type de magasin de clés "PKCS12" De Java (au lieu de "JKS" par défaut).

Si nécessaire, vous pouvez convertir ce fichier de clés PKCS12 dans un autre format (par exemple JKS) en utilisant keytool (Java 6+):

keytool -importkeystore -srckeystore store.p12 -srcstoretype PKCS12 \
     -destkeystore store.jks -deststoretype JKS

(Essentiellement, l'opération opposée à celle décrite dans cette question .)

Quoi qu'il en soit, que ce soit en utilisant PEMReader ou en chargeant votre clé/certificat à partir d'un KeyStore, vous devriez pouvoir obtenir des instances de PrivateKey et Certificate (ou PublicKey directement).

Vous pouvez vérifier que la signature d'un Certificate a été effectuée à l'aide de la clé privée correspondant à une clé publique donnée à l'aide de sa méthode verify(PublicKey).

Avec eux, vous pouvez également utiliser API de signature numérique . C'est une API plus générale pour n'importe quelle signature de document, et je ne vérifierais pas nécessairement une signature de certificat avec elle (je préfère utiliser l'API du chemin de certification pour cela, car elle construira également la chaîne).

10
Bruno