Daten zwischen PHP und JAVA mit RSA verschlüsselt auszutauschen gestaltet sich doch etwas schwieriger als anfangs gedacht. Nach etwas längerer Suche nach der Lösung habe ich mich entschlossen meinen Lösungsansatz hier zu veröffentlichen:
- Zuerst benötigen wir für den Server (PHP) und für den Client (JAVA) jeweils einen privaten und einen öffentlichen Schlüssel, diese erzeugen wir mit dem Kommandozeilentool openssl:
12openssl genrsa -out serverPrivateKey.pem 2048openssl rsa -in serverPrivateKey.pem -pubout -outform DER -out serverPublicKey.der
Mit dem ersten Befehl wird der private Schlüssel für den Server erzeugt und im openssl Standardformat PEM abgespeichert. Der zweite Befehl speichert dann den dazugehörigen öffentlichen Schlüssel im DER Format ab. (Das DER Format ist das Standardformat für JAVA’s RSA.) Umgekehrt benötigen wir dann noch noch den privatenSchlüssel des JAVA Client (im DER Format) sowie den öffentlichen Schlüssel des Clients im PEM Format:
123openssl genrsa -out clientPrivateKey.pem 2048openssl pkcs8 -topk8 -nocrypt -in clientPrivateKey.pem -outform der -out clientPrivateKey.deropenssl rsa -in clientPrivateKey.pem -pubout -outform PEM -out clientPublicKey.pemDie Zahl 2048 gibt die Größe des Schlüssels in Bit an. Weniger als 2048 sollte man heutzutage nicht verwenden. Wer auf Nummer sicher gehen will nimmt hier 4096.
- Im nächsten Schritt importieren wir den öffentlichen Schlüssel des Servers in unserem JAVA Client:
123456789File pubKeyFile = new File("keys/serverPublicKey.der");byte[] buffer = new byte[(int) pubKeyFile.length()];DataInputStream in = new DataInputStream(new FileInputStream(pubKeyFile));in.readFully(buffer);in.close();KeyFactory keyFactory = KeyFactory.getInstance("RSA");RSAPublicKey publicKey = (RSAPublicKey) keyFactory.generatePublic(new X509EncodedKeySpec(buffer));
- Nach dem importieren des publicKey können wir nun Daten verschlüsseln:
12345String text = "Geheimer Text!";Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1PADDING");cipher.init(Cipher.ENCRYPT_MODE, publicKey);byte[] encrypted = cipher.doFinal(text.getBytes());
Um mit den verschlüsselten Daten weiter arbeiten zu können, speichern wir diese ab:
1234FileOutputStream fos = new FileOutputStream("/tmp/encrypted");fos.write(encrypted);fos.flush();fos.close(); - Verschlüsselte Daten mit PHP entschlüsseln.
12345678<?php$encryptedData = file_get_contents('/tmp/encrypted');$privKeyFile = file_get_contents('keys/serverPrivateKey.pem');$privKey = openssl_get_privatekey($privKeyFile);openssl_private_decrypt($encryptedData, $decrypted, $privKey, OPENSSL_PKCS1_PADDING);print "$decrypted\n";Und als Ausgabe erhalten wir (wie erwartet):
Geheimer Text!
So das wars mit dem ersten Teil, der zweite Teil, mit der Verschlüsselung in der anderen Richtung folgt hoffentlich bald.
UPDATE:
2. Teil veröffentlich: RSA mit JAVA und PHP – Teil 2 (PHP -> JAVA)