2009-09-08 14 views
10

Ich versuche, einige Inhalte mit einem privaten RSA-Schlüssel zu verschlüsseln.Verschlüsseln mit RSA privaten Schlüssel in Java

Ich verfolge dieses Beispiel: http://www.junkheap.net/content/public_key_encryption_java

aber Umwandlung es eher als öffentlich-private Schlüssel zu verwenden. Nach diesem Beispiel denke ich, was ich tun müssen, ist:

  • lesen in einem DER-Format privaten Schlüssel
  • Generieren eines PCKS8EncodedKeySpec
  • Anruf generatePrivate() von KeyFactory einen privaten Schlüssel-Objekt zu erhalten
  • verwenden Sie, dass private Schlüssel-Objekt mit dem Cipher Objekt der Verschlüsselungs

So zu tun, die Schritte:

der Schlüssel wurde fro erzeugt m openssl mit:

openssl genrsa -aes256 -out private.pem 2048

und wurde dann auf DER-Format konvertiert mit:

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

I erzeugen die PKCS8EncodedKeySpec mit:

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; 

Und dann den privaten Schlüssel erzeugen Objekt mit:

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; 

jedoch auf den Aufruf:

pk = kf.generatePrivate(privateKeySpec); 

ich:

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) 

Fragen:

  • Ist der allgemeine Ansatz richtig?
  • Ist die PCKS8EncodedKeySpec die richtige Keypec zu verwenden?
  • Haben Sie Gedanken über den ungültigen Schlüsselspezifikationsfehler?
+0

ich durch diese gingen und erzeugt sie mit Java: http://stackoverflow.com/questions/19640735/load-public-key-data-from -file – Hayro

Antwort

6

Zunächst einmal, ich bin verwirrt, warum Sie mit einem privaten Schlüssel zum Verschlüsseln ein Cipher verwenden mögen, anstatt mit einem Signature unterzeichnen. Ich bin nicht sicher, dass alle RSA Cipher Anbieter den richtigen Blocktyp für die Einrichtung verwenden, aber es ist einen Versuch wert.

Aber abgesehen davon, denke ich, dass Sie versuchen, einen nicht-Standard OpenSSL-Format-Schlüssel zu laden. Das Konvertieren in DER mit rsa ist im Wesentlichen nur eine Base-64-Decodierung; Die Struktur des Schlüssels ist nicht PKCS # 8.

Stattdessen nach genrsa, verwenden Sie den Befehl openssl pkcs8 den generierten Schlüssel unverschlüsselt PKCS # 8, DER-Format zu konvertieren:

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

Dies wird produzieren einen unverschlüsselten privaten Schlüssel, der mit einem PKCS8EncodedKeySpec geladen werden kann.

+0

Ehrlich gesagt, war mir Signature nicht bewusst. Um sicherzustellen, dass ich seine Verwendung verstehe, würde ich das Signaturobjekt initialisieren, Update mit den Bytes, die ich unterschreiben möchte, aufrufen und dann Zeichen aufrufen? Und dann kann ich die vom Zeichen zurückgegebenen Bytes als meine digitale Signatur speichern? – wadesworld

+0

Ja, das ist die richtige Verwendung. – erickson

+0

Hallo. Irgendjemand hat das Problem endlich gelöst? Ich habe einen privaten Schlüssel, den ich nicht in Java laden kann, um mit der Unterzeichnungsphase fortzufahren. Mein privater Schlüssel ist RSA, PKCS # 8 DER und es hat ein Passwort. Wie kann ich das in Java laden? Die Ausnahme in meinem Fall ist 'java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException: DER-Eingabe, Integer-Tag-Fehler' – BRabbit27

10

Sie können nicht mit dem privaten Schlüssel verschlüsseln. Wenn JCE dir das erlaubt, ist es nur Zufall.

Sie müssen Signatur verwenden. Hier sind die Code-Schnipsel zu tun,

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

's/public/private /' in Ihrer ersten Zeile. – caf

+0

Perfekt - vielen Dank! – wadesworld

4

Es ist kein Zufall, dass die Verschlüsselung mit privaten Schlüssel erlaubt ist. Wenn Sie eine Signatur in einzelne Hashing- und Verschlüsselungsfunktionen aufteilen möchten, ist das Verschlüsseln mit einem privaten Schlüssel unerlässlich. Lets sagen, ich habe ein Dokument, das ich signieren muss und mein Schlüssel befindet sich in einem Netzwerk HSM. Jetzt streame ich entweder das gesamte Dokument zum Signieren an das HSM oder ich kann einen lokalen Hash erstellen und ihn zur Verschlüsselung allein zum HSM streamen. Meine Wahl hängt davon ab, ob die lokale Hash-Berechnung mir eine bessere Leistung gibt, als eine viz-delegierte Hash-Berechnung mit Netzwerk-Latenz.

2

Diese Frage ist ziemlich alt, aber ich stolperte kürzlich über das Problem (ich implementiere die Anforderungen eines Protokolls, das Verschlüsselung mit privatem Schlüssel erfordert). Ich werde nur die Post von forum zitieren:

ich auf das gleiche Problem vor kurzem gestolpert, eingereicht PMR 22265,49R und IBM Support nach Rücksprache mit „Entwicklung“ (wer auch immer diejenigen sind) entschieden, dass private Schlüssel können nicht verwendet werden für die Verschlüsselung. Egal, wie sehr ich versuchte, mit ihnen zu argumentieren, dass private Schlüssel nicht für den Datenschutz verwendet werden sollten, was nur ein Zweck hinter der Verschlüsselung ist, und dass es völlig in Ordnung ist, private Schlüssel für die Verschlüsselung zu verwenden, um Nichtabstreitbarkeit zu erreichen, waren sie unerschütterlich in ihrem Glauben. Du musst Leute lieben, die darauf bestehen, dass 2x2 = 5.

So habe ich dieses Problem behoben: Im Wesentlichen habe ich ein öffentliches Schlüsselobjekt mit dem Kryptomaterial des privaten Schlüssels erstellt. Sie müssen das umgekehrte Verfahren ausführen, um ein privates Schlüsselobjekt mit dem Kryptomaterial des öffentlichen Schlüssels zu erstellen, um es mit dem öffentlichen Schlüssel zu entschlüsseln, wenn Sie die Ausnahme "Öffentlicher Schlüssel kann nicht entschlüsselt werden" vermeiden können.

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

Das ist sehr riskant, wenn Sie den Exponenten des privaten Schlüssels als den öffentlichen Exponenten behandeln und ihn verteilen, denn angesichts des privaten Schlüssels (den Sie den "öffentlichen Schlüssel" nennen) ist es einfach, den tatsächlichen öffentlichen Schlüssel abzuleiten (den Sie jetzt sind) Aufruf des "privaten Schlüssels"). Lassen Sie diesen "öffentlichen Schlüssel" nicht versehentlich in der Öffentlichkeit offen, sonst wird Ihr System kompromittiert. Es kann so einfach sein, zu raten, dass der Exponent des "privaten Schlüssels" 65537 ist. –

+0

Ich habe so lange gesucht. Ich bin so dankbar für diese Antwort. Der Name "privater und öffentlicher Schlüssel" ist in diesem Anwendungsfall völlig falsch, aber es gibt Situationen, in denen dies relevant ist. –

+0

@JimFlood Wenn ich richtig verstehe und meine Situation ähnlich ist, erstellt dmitry eine 'RSAPublicKeySpec', um die privaten Schlüsseldaten zu speichern. Offensichtlich wird er nicht den privaten Schlüssel verteilen, sondern nur den ursprünglichen öffentlichen Schlüssel, der nun dazu verwendet werden kann, zu beweisen (entschlüsseln), dass der private Schlüssel zur Verschlüsselung diente - d. H. Nichtabstreitbarkeit. – Guss

0

try this:

java.security.Security.addProvider(
        new org.bouncycastle.jce.provider.BouncyCastleProvider() 
      ); 
Verwandte Themen