import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.Map.Entry;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
//Eine Art Batch-File, nur zum Zweck alle Codebeispiele abzuspielen
public class GenEncryptedProperties {
public static void main(String[] args) throws NoSuchAlgorithmException, KeyStoreException, CertificateException, IOException, InvalidKeyException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException {
// Den geheimem Schlüssel einmalig erzeugen. Für Extraktion aus
// einem existierenden Keystore zur Wiederverwendung siehe
// DataConnectionApp.
final KeyGenerator keyGen = KeyGenerator.getInstance("Blowfish");
final Key highlySecretMasterKey = keyGen.generateKey();
// Dieses Passwort lassen wir geheim.
final String nonSecretKeyStorePassword = "keypass123";
// KeyStore erzeugen: Typ JCEKS ist notwendig, um Keys zu speichern,
// die kein PrivateKey sind.
final KeyStore keyStore = KeyStore.getInstance("JCEKS");
keyStore.load(null, nonSecretKeyStorePassword.toCharArray());
// Geheimes Passwort nur für authorisierte Nutzer,
final String userSecretKeyPassword="confidential!";
// Schlüssel und (-name) speichern
final String wellKnownMasterKeyAlias="masterkey";
keyStore.setKeyEntry(wellKnownMasterKeyAlias, highlySecretMasterKey, userSecretKeyPassword.toCharArray(), null);
// KeyStore auf Platte speichern.
final FileOutputStream fos = new FileOutputStream("keystore.bin");
keyStore.store(fos, nonSecretKeyStorePassword.toCharArray());
fos.close();
// Ein paar Properties veschlüsseln.
final Map<String, String> plainTextProperties = new HashMap<String, String>();
plainTextProperties.put("db.url", "oracle.company.com");
plainTextProperties.put("db.sid", "XE");
plainTextProperties.put("db.role", "SYSDBA");
plainTextProperties.put("db.username", "scott");
plainTextProperties.put("db.password", "tiger");
final Properties encryptedProperties = new Properties();
for(final Entry<String, String> entry : plainTextProperties.entrySet()) {
encryptedProperties.setProperty(entry.getKey(), encryptBlowfishBase64(entry.getValue(), highlySecretMasterKey));
}
// Properties speichern.
final FileOutputStream fos2 = new FileOutputStream("connection.properties");
encryptedProperties.store(fos2, "Secure database connection properties\nCrack me if you can! :-");
fos2.close();
}
public static final String encryptBlowfishBase64(final String content, final Key key) throws NoSuchAlgorithmException, IOException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
final ByteArrayOutputStream bos = new ByteArrayOutputStream(512);
// Den MD5 (16 byte) vor den zu verschlüsselnden Inhalt hängen.
// So kann man sicher prüfen, ob korrekt entschlüsslet wurde.
final MessageDigest md5 = MessageDigest.getInstance("MD5");
bos.write(md5.digest(content.getBytes()));
bos.write(content.getBytes());
//Blowfish Instanz erzeugen
final Cipher blowfish = Cipher.getInstance("Blowfish");
blowfish.init(Cipher.ENCRYPT_MODE, key);
// Verschlüsseln und Ergebnis BASE64 kodieren
return new String(Base64Coder.encode(blowfish.doFinal(bos.toByteArray())));
}
}