Método de encriptación para iPhone y Android

He intentado generar un text encryption usando el algorithm AES en ambas plataforms (Android e IPhone) pero el problema es que incluso usamos la misma biblioteca de desencryption de encryption (AES-128) y con las mismas variables fijas (key, IV, modo), pero Obtengo dos resultados diferentes para ellos.

Aprecio cualquier ayuda. Significado de la palabra

El siguiente código presenta los methods de encryption y desencryption utilizados,

Versión de código para Android:

  • Clave = "123456789abcdefg";
    • IV = "1111111111111111";
    • Texto sin formatting = "HelloThere";
    • Modo = "AES / CBC / NoPadding";

Código:

public class Crypto { 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(“CBC”); 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)); } 

}

Versión de código para iPhone:

 - (NSData *) transform:(CCOperation) encryptOrDecrypt data:(NSData *) inputData { NSData* secretKey = [Cipher md5:cipherKey]; CCCryptorRef cryptor = NULL; CCCryptorStatus status = kCCSuccess; uint8_t iv[kCCBlockSizeAES128]; memset((void *) iv, 0x0, (size_t) sizeof(iv)); status = CCCryptorCreate(encryptOrDecrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding, [secretKey bytes], kCCKeySizeAES128, iv, &cryptor); if (status != kCCSuccess) { return nil; } size_t bufsize = CCCryptorGetOutputLength(cryptor, (size_t)[inputData length], true); void * buf = malloc(bufsize * sizeof(uint8_t)); memset(buf, 0x0, bufsize); size_t bufused = 0; size_t bytesTotal = 0; status = CCCryptorUpdate(cryptor, [inputData bytes], (size_t)[inputData length], buf, bufsize, &bufused); if (status != kCCSuccess) { free(buf); CCCryptorRelease(cryptor); return nil; } bytesTotal += bufused; status = CCCryptorFinal(cryptor, buf + bufused, bufsize - bufused, &bufused); if (status != kCCSuccess) { free(buf); CCCryptorRelease(cryptor); return nil; } bytesTotal += bufused; CCCryptorRelease(cryptor); return [NSData dataWithBytesNoCopy:buf length:bytesTotal]; 

}

  + (NSData *) md5:(NSString *) stringToHash { const char *src = [stringToHash UTF8String]; unsigned char result[CC_MD5_DIGEST_LENGTH]; CC_MD5(src, strlen(src), result); return [NSData dataWithBytes:result length:CC_MD5_DIGEST_LENGTH]; 

}

Algunas de mis references:

  • http://automagical.rationalmind.net/2009/02/12/aes-interoperability-between-net-and-iphone/

  • http://code.google.com/p/aes-encryption-samples/wiki/HowToEncryptWithJava

Lo primero que debe comprobar son los bytes que está utilizando. Enumera su IV, key y text sin formatting como caracteres. Esos caracteres se convertirán en bytes utilizando algún tipo de encoding. Compruebe qué aspecto tienen los bytes , no los caracteres. Debe enumerar todo, byte por byte, en ambas máquinas y comparar. Alternativamente, especifique exactamente qué conversión va a usar en cada máquina. Los valores pnetworkingeterminados de la máquina podrían ser diferentes.

Una vez que sepa que los bytes de input son los mismos, entonces podemos search otros problemas.

Como punto secundario, generalmente es mejor usar relleno, como PKCS # 7; de esa manera no tiene que ajustar sus posts al tamaño del bloque de encryption.

oh hombre, olvidaste usar .getBytes ("UTF-8"); …

extremadamente importante.

EDITAR:

Sé que debería mejorar la calidad de esta respuesta, pero lo que dije aquí + lo que rossum dijo a continuación es el truco para corregir esto.

Es solo sobre el cumplimiento de encryption / desencryption: cuando trabajas en todas las plataforms, también tienes que tener el cumplimiento binary.

así que descarga los datos sin procesar e inspecciona si hay discrepancias hasta que tus ojos se desangren y encuentres y arregles con éxito esa pequeña peculiaridad que marca esa diferencia.

para empezar, .getBytes ("UTF-8") le proporcionará cadenas coherentes en entornos Java / Android (porque getBytes () no funciona de la forma en que esperaría que funcione a less que lea los documentos)

El código tiene varios problemas, pero la causa de que obtenga un text encryption diferente en cada encriptación en Android es que no está especificando una IV y se está generando una aleatoria. También dices 'sin relleno', pero el código de iOS está haciendo padding, y lo más probable es que Android también esté de forma pnetworkingeterminada, ya que no lo estás especificando explícitamente. Finalmente, necesita rellenar si está cifrando algo que no sea un múltiplo del tamaño del bloque (como muestra el text sin formatting). getBytes() pnetworkingeterminado para UTF-8 en Android, por lo que es el menor de sus problemas, pero explícalo.