Come utilizzare le chiavi generate da OpenSSL in Java?

11

Ho la mia coppia di chiavi pubbliche e private e il mio certificato. Quelli creati in OpenSSL (perché ?, perché mi è stato chiesto di farlo in OpenSSL).   Ora voglio usare queste cose per creare un'app Java che usi le firme digitali.   Come posso utilizzare le mie chiavi private e pubbliche per crittografare / decifrare informazioni (e utilizzare il certificato per vedere se i dati sono validi? Quali sono le classi in java che mi consentono di farlo?

Le mie chiavi sono in testo semplice qualcosa del genere:

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

Aggiorna

Ho creato questo codice ma non riesco ancora a utilizzare la chiave privata per firmare una stringa.

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'eccezione che sto ottenendo è

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
    
posta BRabbit27 09.12.2011 - 00:22
fonte

1 risposta

10

Se hai una chiave pubblica in questo modulo (e non all'interno di un certificato), ti consigliamo di utilizzare BouncyCastle % s% co_de . Il suo metodo PEMReader può leggere molto per i formati: chiavi pubbliche, certificati, chiavi private (anche se potrebbe essere necessario utilizzare il metodo con una password) ...

Se non si desidera utilizzare BouncyCastle, è possibile leggere i certificati utilizzando un CertificateFactory (vedi esempi). Con un certificato in formato PEM in un InputStream:

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

Per le chiavi private, se la tua chiave privata è una struttura PKCS # 8 in formato DER, puoi leggerla direttamente usando PKCS8EncodedKeySpec . Ad esempio:

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

Puoi convertire la tua chiave privata in PKCS # 8 usando readObject() (ricorda openssl pkcs8 -topk8 , potresti anche voler controllare le suite di crittografia in quanto non tutte potrebbero essere comunemente supportate sia da Java che da OpenSSL).

  • Dal punto di vista dell'uso del keystore:

Se non vuoi fare molta programmazione per la gestione dei tasti, per passare da Java a OpenSSL, è comodo usare il formato PKCS # 12.

Se le chiavi e i certificati che hai prodotto con OpenSSL non sono già in un contenitore p12:

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

In generale, puoi utilizzare direttamente il tipo di keystore " -outform DER " di Java (anziché " PKCS12 " per impostazione predefinita).

Se necessario, puoi convertire questo keystore PKCS12 in un altro formato (ad es. JKS) utilizzando JKS (Java 6 +):

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

(Essenzialmente, l'operazione opposta a quella descritta in questa domanda .)

In entrambi i casi, indipendentemente dall'uso di keytool o dal caricamento della chiave / certificato da un PEMReader , dovresti riuscire a ottenere istanze di KeyStore e PrivateKey (o Certificate direttamente).

Puoi verificare che la firma di PublicKey sia stata eseguita utilizzando la chiave privata corrispondente a una determinata chiave pubblica utilizzando il suo metodo Certificate .

Con loro, puoi anche utilizzare l'API firma digitale . Si tratta di un'API più generale per qualsiasi firma di documento e non dovrei necessariamente verificare una firma del certificato con esso (preferisco usare l'API del percorso di certificazione per questo, dato che creerà anche la catena).

    
risposta data 09.12.2011 - 00:41
fonte

Leggi altre domande sui tag