2009-09-08 32 views
10

Sto tentando di crittografare del contenuto con una chiave privata RSA.Crittografia con chiave privata RSA in Java

Sto seguendo questo esempio: http://www.junkheap.net/content/public_key_encryption_java

ma la conversione in modo da utilizzare le chiavi private piuttosto che pubbliche. Seguendo questo esempio, penso che quello che ho bisogno di fare è:

  • leggere in un DER-formato di chiave privata
  • Generare un PCKS8EncodedKeySpec
  • chiamata generatePrivate() da KeyFactory per ottenere un oggetto chiave privata
  • utilizzare l'oggetto chiave privata con l'oggetto Cipher per fare la crittografia

Quindi, i passi:

la chiave è stato generato fro m OpenSSL con:

openssl genrsa -aes256 -out private.pem 2048

e poi è stato convertito in formato DER con:

openssl rsa -in private.pem -outform DER -out private.der

ho generare il PKCS8EncodedKeySpec con:

byte[] encodedKey = new byte[(int)inputKeyFile.length()]; 

try { 
    new FileInputStream(inputKeyFile).read(encodedKey); 
} catch (FileNotFoundException e) { 
    // TODO Auto-generated catch block 
    e.printStackTrace(); 
} catch (IOException e) { 
    // TODO Auto-generated catch block 
    e.printStackTrace(); 
} 

PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(encodedKey); 
return privateKeySpec; 

e quindi generare la chiave privata oggetto con:

PrivateKey pk = null; 

try { 
    KeyFactory kf = KeyFactory.getInstance(RSA_METHOD); 
    pk = kf.generatePrivate(privateKeySpec); 
} catch (NoSuchAlgorithmException e) { 
    // TODO Auto-generated catch block 
    e.printStackTrace(); 
} catch (InvalidKeySpecException e) { 
    // TODO Auto-generated catch block 
    e.printStackTrace(); 
} 
return pk; 

Tuttavia, la chiamata a:

pk = kf.generatePrivate(privateKeySpec); 

ottengo:

java.security.spec.InvalidKeySpecException: Unknown key spec. 
at com.sun.net.ssl.internal.ssl.JS_KeyFactory.engineGeneratePrivate(DashoA12275) 
at com.sun.net.ssl.internal.ssl.JSA_RSAKeyFactory.engineGeneratePrivate(DashoA12275) 
at java.security.KeyFactory.generatePrivate(KeyFactory.java:237) 

Domande:

  • è l'approccio generale giusto?
  • PCKS8EncodedKeySpec è il keyspec corretto da utilizzare?
  • Qualche idea sull'errore della chiave non valida?
+0

ho passato questo e li ha generati con Java: http://stackoverflow.com/questions/19640735/load-public-key-data-from -file – Hayro

risposta

6

Prima di tutto, io sono confuso perché si prevede di utilizzare un Cipher per cifrare con una chiave privata, piuttosto che la firma con un Signature. Non sono sicuro che tutti i provider RSA Cipher utilizzeranno il tipo di blocco corretto per l'installazione, ma vale la pena provare.

Tuttavia, a parte questo, penso che si stia tentando di caricare una chiave di formato OpenSSL non standard. La conversione in DER con rsa è essenzialmente solo una decodifica in base 64; la struttura della chiave non è PKCS # 8.

Invece, dopo genrsa, utilizzare il comando openssl pkcs8 per convertire la chiave generata per non crittografata PKCS # 8, formato DER:

openssl pkcs8 -topk8 -nocrypt -in private.pem -outform der -out private.der 

Questo produrrà una chiave privata in chiaro che può essere caricato con un PKCS8EncodedKeySpec.

+0

Onestamente, non ero a conoscenza di Signature. Per essere sicuro di averne compreso l'utilizzo, vorrei inizializzare l'oggetto firma, chiamare l'aggiornamento con i byte che voglio firmare e quindi chiamare il segno? E poi posso memorizzare i byte restituiti dal segno come firma digitale? – wadesworld

+0

Sì, questo è l'uso corretto. – erickson

+0

Ciao. Qualcuno alla fine ha risolto il problema? Ho una privateKey che non posso caricare in java per continuare con la fase di firma. La mia privateKey è RSA, PKCS # 8 DER e ha una password. Come posso caricarlo in java? L'eccezione nel mio caso è 'java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException: input DER, errore tag intero' – BRabbit27

10

Non è possibile crittografare con chiave privata. Se JCE ti permette di farlo, è solo per caso.

È necessario utilizzare la firma. Ecco lo snippet di codice per farlo,

signer = Signature.getInstance("SHA1withRSA"); 
signer.initSign(privateKey); // PKCS#8 is preferred 
signer.update(dataToSign); 
byte[] signature = signer.sign(); 
+1

's/public/private /' nella prima riga. – caf

+0

Perfetto - grazie mille! – wadesworld

4

Non è un caso che sia consentita la crittografia con chiave privata. Se si desidera interrompere una firma in singoli hashing e crittografia, la crittografia con chiave privata è essenziale. Diciamo che ho un documento che ho bisogno di firmare e la mia chiave risiede su una rete HSM. Ora o eseguo il flusso dell'intero documento sull'HSM per firmare o posso creare un hash locale e trasmetterlo all'HSM per la sola crittografia. La mia scelta dipenderà dal fatto che il calcolo dell'hash locale mi dà prestazioni migliori, vale a dire un calcolo hash delegato con latenza di rete.

2

Questa domanda è piuttosto vecchia, ma recentemente mi sono imbattuto nel problema (sto implementando i requisiti di alcuni protocolli che richiedono la crittografia con la chiave privata). Mi limito a citare il post dal forum:

Recentemente ho inciampato sulla stessa questione, presentato PMR 22265,49R, e supporto IBM dopo aver consultato "sviluppo" (chiunque questi sono) ha stabilito che le chiavi private non possono essere utilizzati per la crittografia. Non importa quanto ho provato a discutere con loro che le chiavi private non dovrebbero essere utilizzate per la protezione dei dati, che è solo uno degli scopi della crittografia, e che è perfettamente corretto usare le chiavi private per la crittografia per ottenere il non ripudio, erano irremovibili nella loro fede. Devi amare le persone, che insistono sul fatto che 2x2 = 5.

Ecco come ho lavorato a questo problema: Essenzialmente, ho creato un oggetto chiave pubblica con il materiale crittografico della chiave privata. Sarà necessario eseguire l'inverso, creare un oggetto chiave privata con il materiale crittografico della chiave pubblica, per decrittografarlo con una chiave pubblica se si desidera evitare l'eccezione "Chiave pubblica non può essere utilizzata per decodificare".

RSAPrivateCrtKey privateKey = (RSAPrivateCrtKey) ks.getKey(keyAlias, ksPassword.trim().toCharArray()); 
RSAPublicKeySpec spec = new RSAPublicKeySpec(
    privateKey.getModulus(), 
    privateKey.getPrivateExponent() 
); 
Key fakePublicKey = KeyFactory.getInstance("RSA").generatePublic(spec); 
encryptCipher.init(Cipher.ENCRYPT_MODE, fakePublicKey); 
+1

Questo è molto rischioso se si considera l'esponente della chiave privata come esponente pubblico e lo si distribuisce, perché data la chiave privata (che si chiama la "chiave pubblica") è facile ricavare la chiave pubblica effettiva (che ora si è chiamando la "chiave privata"). Non lasciare accidentalmente quella "chiave pubblica" in pubblico, altrimenti il ​​tuo sistema sarà compromesso. Potrebbe essere semplice come supporre che l'esponente della "chiave privata" sia 65537. –

+0

La stavo cercando così a lungo. Sono così grato per questa risposta. Il nome "chiave privata e pubblica" è totalmente sbagliato in questo caso d'uso, ma ci sono situazioni in cui ciò è rilevante. –

+0

@JimFlood Se ho capito bene e la mia situazione è simile, dmitry ha creato un 'RSAPublicKeySpec' per conservare i dati della chiave privata. Ovviamente non distribuirà la chiave privata, ma solo la chiave pubblica originale che può ora essere utilizzata per dimostrare (decrittografare) che la chiave privata era per la crittografia, ovvero il non ripudio. – Guss

0

provare questo:

java.security.Security.addProvider(
        new org.bouncycastle.jce.provider.BouncyCastleProvider() 
      ); 
Problemi correlati