example encrypt decryption decrypt cipher cbc java android encryption aes coldfusion-9

cipher - java aes 128 encryption decryption example



Java SimpleCrypto Class para cifrado/descifrado que produce diferentes resultados en Coldfusion 9 y Java(Android) (1)

Estoy tratando de usar la ampliamente utilizada clase SimpleCrypto java para encriptar una cadena en Java (Android) y descifrar la cadena en ColdFusion 9 (y viceversa). Importé exactamente la misma clase SimpleCrypto en ColdFusion y lo llamé así:

<cfset myKey = "apple"> <cfscript> sc = createObject("java", "SimpleCrypto").init(); encrypted = sc.encrypt(myKey, "john"); </cfscript> <cfdump var="#encrypted#">

Al encriptar la cadena "john" con una clave de "manzana", se genera esto en CF: 9E90A36325AE4F4F7352D6469A7068A2

Cuando uso la clase EXACT SAME en Android:

String key = "apple"; try { sEncrypted = SimpleCrypto.encrypt(key, "john"); Log.d(TAG, sEncrypted); } catch (Exception e) { e.printStackTrace(); }

Las salidas de registro: CBE2ADDBA9882F545DFEC1700E7CD518

Huelga decir que me estoy volviendo loco porque estos resultados son diferentes. ¿Alguien sabe por qué usar el mismo código exacto en ColdFusion y Java produciría resultados diferentes? Cualquier ayuda sería muy apreciada.

Aquí está el código fuente de SimpleCrypto.java:

import java.security.SecureRandom; import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; /** * Usage: * <pre> * String crypto = SimpleCrypto.encrypt(masterpassword, cleartext) * ... * String cleartext = SimpleCrypto.decrypt(masterpassword, crypto) * </pre> * @author ferenc.hechler */ public class SimpleCrypto { public static String encrypt(String seed, String cleartext) throws Exception { byte[] rawKey = getRawKey(seed.getBytes()); byte[] result = encrypt(rawKey, cleartext.getBytes()); return toHex(result); } public static String decrypt(String seed, String encrypted) throws Exception { byte[] rawKey = getRawKey(seed.getBytes()); byte[] enc = toByte(encrypted); byte[] result = decrypt(rawKey, enc); return new String(result); } private static byte[] getRawKey(byte[] seed) throws Exception { KeyGenerator kgen = KeyGenerator.getInstance("AES"); SecureRandom sr = SecureRandom.getInstance("SHA1PRNG"); sr.setSeed(seed); kgen.init(128, sr); // 192 and 256 bits may not be available SecretKey skey = kgen.generateKey(); byte[] raw = skey.getEncoded(); return raw; } private static byte[] encrypt(byte[] raw, byte[] clear) throws Exception { SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES"); Cipher cipher = Cipher.getInstance("AES"); cipher.init(Cipher.ENCRYPT_MODE, skeySpec); byte[] encrypted = cipher.doFinal(clear); return encrypted; } private static byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception { SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES"); Cipher cipher = Cipher.getInstance("AES"); cipher.init(Cipher.DECRYPT_MODE, skeySpec); byte[] decrypted = cipher.doFinal(encrypted); return decrypted; } public static String toHex(String txt) { return toHex(txt.getBytes()); } public static String fromHex(String hex) { return new String(toByte(hex)); } public static byte[] toByte(String hexString) { int len = hexString.length()/2; byte[] result = new byte[len]; for (int i = 0; i < len; i++) result[i] = Integer.valueOf(hexString.substring(2*i, 2*i+2), 16).byteValue(); return result; } public static String toHex(byte[] buf) { if (buf == null) return ""; StringBuffer result = new StringBuffer(2*buf.length); for (int i = 0; i < buf.length; i++) { appendHex(result, buf[i]); } return result.toString(); } private final static String HEX = "0123456789ABCDEF"; private static void appendHex(StringBuffer sb, byte b) { sb.append(HEX.charAt((b>>4)&0x0f)).append(HEX.charAt(b&0x0f)); } }


El método getRawKey() es defectuoso. Utiliza una instancia de SecureRandom lugar de una función de derivación de clave (KDF).

Dependiendo de la implementación, el método setSeed() agregará la semilla al estado actual o la usará como la única semilla . El proveedor de Oracle en Java SE 7 y anteriores lo usará como único servidor, otros proveedores como los basados ​​en OpenSSL en las últimas versiones de Android simplemente pueden agregar la semilla al estado.

Además, la implementación exacta de "SHA1PRNG" no ha sido bien definida. Entonces diferentes proveedores pueden usar implementaciones diferentes. Utilice instancias de SecureRandom para la generación de números aleatorios.

Si tiene una contraseña, use una función de derivación de clave basada en contraseña, como PBKDF2, para convertirla en una clave adecuada. Si tiene un secreto con suficiente entropía, podría intentar encontrar una implementación de una Función de derivación de clave basada en claves (KBKDF), por ejemplo, HKDF en Bouncy Castle.

Además de la derivación de la clave, también hay problemas de codificación / descodificación con ese código de muestra. No lo uses, es un terrible ejemplo.