| Verschlüsselte Java Preferences |
|
|
|
| Sonntag, den 17. Juli 2011 um 09:47 Uhr |
|
Wer Passwörter oder sensitive Daten mit java.util.prefs.Preferences speichen will stösst schnell auf das Problem, das die Daten im Klartext (Unter Windows in der Registry, unter Linux / MacOs in versteckten Dateien im home Ordner) gespeichert werden. Die folgende Wrapper Klasse bietet eine komfortable und effiziente Möglichkeit die Werte in den Preferences zu verschlüsseln. Die Exceptions sollten natürlich anders gefangen werden. Als Base64 Encoder und Decoder empfielt sich der Einsatz einer OpenSource Implementation, wie z.B. der aus Apache Commons Codec, da die properitäre API von com.sun zum Beispiel nicht im OpenJDK enthalten ist. Crypted Java Preferences Class public class ConfigCrypted{
// Nur als Beispiel, der Key sollte anders gespeichert werden
private static final String skey = "[B@4b99f84b15462"; // 16 Chars
private static final String ivx = "1234567890123456"; // 16 Chars
// AES Als Algorithmus
private static final SecretKeySpec keySpec = new SecretKeySpec(skey.getBytes(), "AES");
private static final IvParameterSpec ivSpec = new IvParameterSpec(ivx.getBytes());
// javax.crypto.Cipher Instanz zum Entschlüsseln
private static Cipher cipher_enc = getCypher(keySpec, ivSpec, Cipher.ENCRYPT_MODE);
// javax.crypto.Cipher Instanz zum Verschlüsseln
private static Cipher cipher_dec = getCypher(keySpec, ivSpec, Cipher.DECRYPT_MODE);
// Die Preferenzen für die gewünschte Klasse
private static Preferences prefs = Preferences.userRoot().node(XYZ.class.getName());
// Erstellt eine neue Instanz des Cyphers
public static Cipher getCypher(SecretKeySpec keySpec,
IvParameterSpec ivSpec, int mode) {
Cipher cipher;
try {
// Neue Instanz von Cipher mit AES als Algorithmus
cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("invalid algorithm", e);
} catch (NoSuchPaddingException e) {
throw new RuntimeException("invalid padding", e);
}
try {
cipher.init(mode, keySpec, ivSpec);
} catch (InvalidKeyException e) {
throw new CryptographyException("invalid key", e);
} catch (InvalidAlgorithmParameterException e) {
throw new RuntimeException("invalid algorithm parameter.", e);
}
return cipher;
}
/**
* Verschlüsselt den Wert und speichert ihn dann
* @param name - Schlüssel in der Config
* @param value - Unverschlüsselter Wert der gespeichert werden soll
*/
public static void setCrypted(String name, String value) {
try {
byte[] stringBytes = value.getBytes("UTF8");
// Verschlüsselt den Klartext Wert
byte[] raw = cipher_enc.doFinal(stringBytes);
// Konvertiert das verschlüsselte ByteArray in das Base64 Format
// (einfachere Darstellung)
String base64 = Base64.encode(raw);
// Speichert den verschlüsselten String in den Preferences
prefs.put(name, base64);
// System.out.println("RAW: " + raw);
} catch (Exception ex) {
ex.printStackTrace();
}
}
/**
* Gibt den entschlüsselten Wert aus den Preferences zurück
* @param name - Schlüssel in der Config
* @return entschlüsselter Wert
*/
public static String getCrypted(String name) {
try {
// Hole den verschlüsselten Wert aus der Config
String encrypted = prefs.get(name, null);
if(encrypted == null)
return null; // Return wenn null
// Dekodiere den gespeicherten Wert aus dem Base64 Format
byte[] raw = Base64Encode.decode(encrypted);
// Entschlüssele den gespeicherten Format mit unserem Cipher
byte[] stringBytes = cipher_dec.doFinal(raw);
// Erstelle einen neuen String aus dem entschlüsselten Wert
String val = new String(stringBytes, "UTF8");
// System.out.println("Decrypted: " + val);
return val;
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
}
|





