AES Encryption Android <-> iOS diferentes resultados en la longitud del post> 15 bytes

Tengo un problema real en la comprensión de la cifra / crypter en ambos dispositivos.

1. Si ciframos un post en iOS y en Android usando Cipher AES y la longitud de cadena de la cadena no es mayor que 16 (por ejemplo, "abcdefghijklmno") obtuvimos el mismo resultado después de encriptarlo con la misma key / contraseña.

2. Pero si tomamos un post más largo obtenemos resultados diferentes en iOS y Android (por ejemplo, "abcdefghijklmnop")

Hice bastante investigación sobre cómo get los mismos parameters para ambos dispositivos y al principio pensé que era seguro.

Aquí está mi código de encryption para encriptar:

public String encode(Context context, String password, String text) throws NoPassGivenException, NoTextGivenException { if (password.length() == 0 || password == null) { throw new NoPassGivenException("Please give Password"); } if (text.length() == 0 || text == null) { throw new NoTextGivenException("Please give text"); } try { SecretKeySpec skeySpec = getKey(password); byte[] clearText = text.getBytes("UTF8"); //IMPORTANT TO GET SAME RESULTS ON iOS and ANDROID final byte[] iv = new byte[16]; Arrays.fill(iv, (byte) 0x00); IvParameterSpec ivParameterSpec = new IvParameterSpec(iv); // Cipher is not thread safe //EDITED AFTER RIGHT ANSWER FROM //*** Cipher cipher = Cipher.getInstance("AES"); ***// // TO Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding"); cipher.init(Cipher.ENCRYPT_MODE, skeySpec, ivParameterSpec); String encrypedValue = Base64.encodeToString( cipher.doFinal(clearText), Base64.DEFAULT); Log.d(TAG, "Encrypted: " + text + " -> " + encrypedValue); return encrypedValue; } catch (InvalidKeyException e) { e.printStackTrace(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (BadPaddingException e) { e.printStackTrace(); } catch (NoSuchPaddingException e) { e.printStackTrace(); } catch (IllegalBlockSizeException e) { e.printStackTrace(); } catch (InvalidAlgorithmParameterException e) { e.printStackTrace(); } return ""; } public SecretKeySpec getKey(String password) throws UnsupportedEncodingException { int keyLength = 128; byte[] keyBytes = new byte[keyLength / 8]; // explicitly fill with zeros Arrays.fill(keyBytes, (byte) 0x0); // if password is shorter then key length, it will be zero-padded // to key length byte[] passwordBytes = password.getBytes("UTF-8"); int length = passwordBytes.length < keyBytes.length ? passwordBytes.length : keyBytes.length; System.arraycopy(passwordBytes, 0, keyBytes, 0, length); SecretKeySpec key = new SecretKeySpec(keyBytes, "AES"); return key; } 

Y aquí está el colgante iOS de mi colega:

 - (NSData *)AES128EncryptWithKey:(NSString *)key { // 'key' should be 32 bytes for AES256, // 16 bytes for AES256, will be null-padded otherwise char keyPtr[kCCKeySizeAES128 + 1]; // room for terminator (unused) bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding) // insert key in char array [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding]; NSUInteger dataLength = [self length]; size_t bufferSize = dataLength + kCCBlockSizeAES128; void *buffer = malloc(bufferSize); size_t numBytesEncrypted = 0; // the encryption method, use always same attributes in android and iPhone (fe PKCS7Padding) CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding, keyPtr, kCCKeySizeAES128, NULL /* initialization vector (optional) */, [self bytes], dataLength, /* input */ buffer, bufferSize, /* output */ &numBytesEncrypted); if (cryptStatus == kCCSuccess) { return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted]; } free(buffer); return nil; } 

Realmente me gusta entender cuál podría ser la diferencia y cómo evitarlo. La testing que exacto con cadenas más grandes que 15 caracteres me dio una pista, pero no sé por qué 🙂

Gracias de antemano chicos!

Compruebe qué relleno se está utilizando en ambos sistemas. El relleno diferente dará como resultado una salida diferente. No confíe en los valores pnetworkingeterminados, pero establezca explícitamente el relleno en ambos lados. Su segundo fragment de código establece explícitamente el relleno de PKCS7. Utiliza eso en ambos extremos.

Como regla general, no confíe en los valores pnetworkingeterminados entre diferentes sistemas. Configure explícitamente la IV, el modo, relleno, nonce o cualquier otra cosa que se necesite. Crypto está diseñado para fallar gravemente si incluso el más mínimo detalle no coincide.