package kellinwood.security.zipsigner.optional; import kellinwood.logging.LoggerInterface; import kellinwood.logging.LoggerManager; import kellinwood.security.zipsigner.Base64; import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; import java.io.*; public class PasswordObfuscator { private static PasswordObfuscator instance = null; static final String x = "harold-and-maude"; LoggerInterface logger; SecretKeySpec skeySpec; private PasswordObfuscator() { logger = LoggerManager.getLogger( PasswordObfuscator.class.getName()); skeySpec = new SecretKeySpec(x.getBytes(), "AES"); } public static PasswordObfuscator getInstance() { if (instance == null) instance = new PasswordObfuscator(); return instance; } public String encodeKeystorePassword( String keystorePath, String password) { return encode( keystorePath, password); } public String encodeKeystorePassword( String keystorePath, char[] password) { return encode( keystorePath, password); } public String encodeAliasPassword( String keystorePath, String aliasName, String password) { return encode( keystorePath+aliasName, password); } public String encodeAliasPassword( String keystorePath, String aliasName, char[] password) { return encode( keystorePath+aliasName, password); } public char[] decodeKeystorePassword( String keystorePath, String password) { return decode(keystorePath,password); } public char[] decodeAliasPassword( String keystorePath, String aliasName, String password) { return decode(keystorePath+aliasName,password); } public String encode( String junk, String password) { if (password == null) return null; char[] c = password.toCharArray(); String result = encode( junk, c); flush(c); return result; } public String encode( String junk, char[] password) { if (password == null) return null; try { // Instantiate the cipher Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); cipher.init(Cipher.ENCRYPT_MODE, skeySpec); ByteArrayOutputStream baos = new ByteArrayOutputStream(); Writer w = new OutputStreamWriter(baos); w.write(junk); w.write(password); w.flush(); byte[] encoded = cipher.doFinal( baos.toByteArray()); return Base64.encode( encoded); } catch (Exception x) { logger.error("Failed to obfuscate password", x); } return null; } public char[] decode( String junk, String password) { if (password == null) return null; try { // Instantiate the cipher Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); SecretKeySpec skeySpec = new SecretKeySpec(x.getBytes(), "AES"); cipher.init(Cipher.DECRYPT_MODE, skeySpec); byte[] bytes = cipher.doFinal( Base64.decode(password.getBytes())); BufferedReader r = new BufferedReader( new InputStreamReader( new ByteArrayInputStream( bytes))); char[] cb = new char[128]; int length = 0; int numRead; while ((numRead = r.read(cb, length, 128-length)) != -1) { length += numRead; } if (length <= junk.length()) return null; char[] result = new char[ length - junk.length()]; int j = 0; for (int i = junk.length(); i < length; i++) { result[j] = cb[i]; j += 1; } flush(cb); return result; } catch (Exception x) { logger.error("Failed to decode password", x); } return null; } public static void flush( char[] charArray) { if (charArray == null) return; for (int i = 0; i < charArray.length; i++) { charArray[i] = '\0'; } } public static void flush( byte[] charArray) { if (charArray == null) return; for (int i = 0; i < charArray.length; i++) { charArray[i] = 0; } } }