Gestern Vormittag hat Bastian, ein AxxG Blog Leser, einen sehr interessanten Kommentar unter meinen Beitrag „Java: Verschlüsselung mit Beispiel (Quickstart)“ hinterlassen. Darin fragt er, wie man einen Schlüssel einer AES- oder RSA-Verschlüsselung sichern bzw. für andere Systeme verwenden kann.
Da die Antwort sehr umfangreich wurde, habe ich mich kurzerhand dazu entschlossen einen Beitrag, zu diesem Thema, zu verfassen.
Als erstes ist es wichtig seinen genertierten oder erstellten Key zu speichern.
// Datei File datei = new File("AES.key"); // zufaelligen Key erzeugen KeyGenerator keygen = KeyGenerator.getInstance("AES"); keygen.init(128); Key key = keygen.generateKey(); // Key in die Datei schreiben byte[] bytes = key.getEncoded(); FileOutputStream keyfos = new FileOutputStream(datei); keyfos.write(bytes); keyfos.close();
Etwas komplizierter geht es bei RSA:
// Datei File dir = new File("keys"); // Verzeichnis anlegen dir.mkdirs(); // zufaelligen Key erzeugen KeyPairGenerator keygen = KeyPairGenerator.getInstance("RSA"); keygen.initialize(1024); KeyPair keyPair = keygen.genKeyPair(); // schluessel lesen PrivateKey privateKey = keyPair.getPrivate(); PublicKey publicKey = keyPair.getPublic(); // Public Key sichern X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(publicKey.getEncoded()); FileOutputStream fos = new FileOutputStream(dir.getAbsoluteFile() + "/public.key"); fos.write(x509EncodedKeySpec.getEncoded()); fos.close(); // Private Key sichern PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(privateKey.getEncoded()); fos = new FileOutputStream(dir.getAbsoluteFile() + "/private.key"); fos.write(pkcs8EncodedKeySpec.getEncoded()); fos.close();
Wechsel
// Datei File datei = new File("AES.key"); // Key lesen FileInputStream fis = new FileInputStream(datei); byte[] encodedKey = new byte[(int) datei.length()]; fis.read(encodedKey); fis.close(); // generiere Key SecretKey key = new SecretKeySpec(encodedKey, "AES");
//+++++++++++++++++++++++++++++++++ // Private key //+++++++++++++++++++++++++++++++++ // Datei File dateiPriK = new File("keys/private.key"); // Private Key lesen FileInputStream fis = new FileInputStream(dateiPriK); byte[] encodedPrivateKey = new byte[(int) dateiPriK.length()]; fis.read(encodedPrivateKey); fis.close(); // generiere Key KeyFactory keyFactory = KeyFactory.getInstance("RSA"); PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(encodedPrivateKey); PrivateKey privateKey = keyFactory.generatePrivate(privateKeySpec); //+++++++++++++++++++++++++++++++++ // Public key //+++++++++++++++++++++++++++++++++ // Datei File dateiPubK = new File("keys/public.key"); // Public key lesen fis = new FileInputStream(dateiPubK); byte[] encodedPublicKey = new byte[(int) dateiPubK.length()]; fis.read(encodedPublicKey); fis.close(); // generiere Key keyFactory = KeyFactory.getInstance("RSA"); X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(encodedPublicKey); PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);
Wie du sehen kannst, gibt es verschiedene Arten Keys in einer Datei zu speichern. Noch mal zusammengefasst:
Mit der Datei(der Key) und dem Wissen, welche Kodierung verwendet wurde, kann man die Verschlüsselung auf anderen Systemen oder in einer anderen Programmiersprache einsetzen. Oftmals bieten die Programmiersprachen schon Klassen zum einlesen des Keys an. Andere wiederum verlangen das Konvertieren des Key’s in ein anderes Format. Wie zum Beispiel PHP:
function pkcs8_to_pem($der) { static $BEGIN_MARKER = "-----BEGIN PRIVATE KEY-----"; static $END_MARKER = "-----END PRIVATE KEY-----"; $value = base64_encode($der); $pem = $BEGIN_MARKER . "\n"; $pem .= chunk_split($value, 64, "\n"); $pem .= $END_MARKER . "\n"; return $pem;
function x509_to_pem($der) { static $BEGIN_MARKER = "-----BEGIN PUBLIC KEY-----"; static $END_MARKER = "-----END PUBLIC KEY-----"; $value = base64_encode($der); $pem = $BEGIN_MARKER . "\n"; $pem .= chunk_split($value, 64, "\n"); $pem .= $END_MARKER . "\n"; return $pem;
Diese brauch den Key als PEM BASE64 verschlüsselt. Andere Programmiersprachen brauchen ggf. andere Formate, je nach Anwendungsfall.
Ich hoffe, dass ich damit deine Frage beantworten konnte:-)
Copyright © 2013 AxxG – Alexander Gräsel
Hallo,
wie sieht das eigentlich aus, wenn ich auf dem Smartphone soeine Verschlüsselung einsetzen will. Wie sicher ist es, wenn ich die Dateien mit den Schlüsseln auf dem Smartphone liegen habe?
Wenn jemand diese Schlüssel-Daten klaut, kann er damit Nachrichten von mir entschlüsseln? Wenn ja, gibt es eine Möglichkeit, sich davor zu schützen?
Ansonsten vielen Dank für diese Tolle Einführung!
Hallo du,
auf jedem Endgerät hast du das Problem, was du da beschrieben hast. Aber wie immer gilt auch hier die 80-20-Regel. D.h. wenn du den Schlüssel nicht auf der SD-Karte ablegst, sondern in einer anwendungsspezifischen Datenbank als String speicherst und das Feld zusätzlich per IMEI symmetrisch verschlüsselt, hältst du ca. 80 % der Bösewichte auf.
Die restlichen 20% wird schwierig….
Hört sich für mich nicht viel sicherer an den Schlüssel mit der IMEI zu verschlüsseln. Meiner Meinung wäre ein zusätzliches Kennwort das der Benutzer eingeben kann eine Sicherheitserweiterung. Das Kennwort würde dazu dienen die Datenbank zu symetrisch entschlüsseln/verschlüsselen.
Hey.. ich stehe vor dem Problem, dass es quasi von mir verlangt wird, den public key als String weiterzureichen.. Also frage ich mich, als Java-Anfänger, wie ich das bewerkstelligen könnte ^^ ich bin mal gespannt, ob ich noch eine Antwort bekomme 😛
oh… Nachtrag: Ich habe gelesen, Keys seien nicht in Strings umzuwandeln? Leider kann ich mit einem byte[] array in dieser Fragestellung nichts anfangen D:
Warum solltest du keine Antwort bekommen?! 😀
Such mal nach Base64 🙂
Viele Grüße
Alexander
Vielen Dank!!!!!