Cifrado en Android equivalente a MCRYPT_RIJNDAEL_256 de php

Estoy usando el siguiente código php para el cifrado:


$enc_request = base64_encode( mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $this->_app_key, json_encode($request_params), MCRYPT_MODE_ECB) ); 

Ahora trato de encriptar el android y obtener las diferentes cadenas encriptadas. A continuación está el código de Android:


 public void enc(){ byte[] rawKey = getRawKey("my_key".getBytes()); SecretKeySpec skeySpec = new SecretKeySpec(rawKey, "AES"); Cipher cipher = Cipher.getInstance("AES"); cipher.init(Cipher.ENCRYPT_MODE, skeySpec); byte[] encrypted = cipher.doFinal("my_message".getBytes()); String result=Base64.encodeToString(encrypted, Base64.DEFAULT); } private static byte[] getRawKey(byte[] seed) throws Exception { KeyGenerator kgen = KeyGenerator.getInstance("AES"); SecureRandom sr = SecureRandom.getInstance("SHA1PRNG"); sr.setSeed(seed); kgen.init(256, sr); SecretKey skey = kgen.generateKey(); byte[] raw = skey.getEncoded(); return raw; } 

¿Podría alguien ayudarme, donde estoy equivocado? Y obtenga la misma cadena cifrada correcta en Android también.

mcrypt_encrypt() un método main en Java usando Bouncy Castle para mostrar el funcionamiento interno de mcrypt_encrypt() utilizado en la muestra de tu código.

Esto es principalmente para mostrar a otros desarrolladores que mcrypt_encrypt() PHP es un método muy peligroso de usar. No fallará mucho, pero eso es porque más bien continúa donde debería haberse detenido hace mucho tiempo. Por ejemplo, agrega o elimina valores de la clave. Emite una advertencia cuando lo hace, pero no se mostrará directamente en el código.

 public static void main(String[] args) throws DataLengthException, IllegalStateException, InvalidCipherTextException { // just some constants boolean ENCRYPT = true; boolean DECRYPT = false; // the key is either in binary in PHP or a string (dynamic isn't it?), lets assume ASCII byte[] givenKey = args[0].getBytes(Charset.forName("ASCII")); // determine the key size dynamically, somebody thought this was a good idea... // NOTE: PHP will emit a warning if the key size is larger, but will simply use the // largest key size otherwise final int keysize; if (givenKey.length <= 128 / Byte.SIZE) { keysize = 128; } else if (givenKey.length <= 192 / Byte.SIZE) { keysize = 192; } else { keysize = 256; } // create a 256 bit key by adding zero bytes to the decoded key byte[] keyData = new byte[keysize / Byte.SIZE]; System.arraycopy(givenKey, 0, keyData, 0, Math.min(givenKey.length, keyData.length)); KeyParameter key = new KeyParameter(keyData); // create a Rijndael cipher with 256 bit block size, this is not AES BlockCipher rijndael = new RijndaelEngine(256); // use a padding method that only works on data that cannot end with zero valued bytes ZeroBytePadding c = new ZeroBytePadding(); // use ECB mode encryption, which should never be used PaddedBufferedBlockCipher pbbc = new PaddedBufferedBlockCipher(rijndael, c); // initialize the cipher using the key (no need for an IV, this is ECB) pbbc.init(ENCRYPT, key); // create a plain text byte array byte[] plaintext = args[1].getBytes(Charset.forName("UTF8")); // create a buffer for the ciphertext byte[] ciphertext = new byte[pbbc.getOutputSize(plaintext.length)]; int offset = 0; offset += pbbc.processBytes(plaintext, 0, plaintext.length, ciphertext, offset); offset += pbbc.doFinal(ciphertext, offset); // show the ciphertext System.out.println(new String(Hex.encode(ciphertext), Charset.forName("ASCII"))); // reverse the encryption pbbc.init(DECRYPT, key); byte[] decrypted = new byte[pbbc.getOutputSize(ciphertext.length)]; offset = 0; offset += pbbc.processBytes(ciphertext, 0, ciphertext.length, decrypted, offset); offset += pbbc.doFinal(decrypted, offset); // this will probably print out correctly, but it isn't actually correct System.out.println(new String(decrypted, Charset.forName("UTF8"))); // check out the zero's at the end System.out.println(new String(Hex.encode(decrypted), Charset.forName("UTF8"))); // so lets make it a bit shorter... the PHP way // note that in PHP, the string may *not* contain a null terminator // add it yourself before printing the string System.out.println(new String(decrypted, Charset.forName("UTF8")).replaceAll("\\x00+$", "")); } 

Advertencia : el código anterior contiene ZeroBytePadding . Más tarde descubrí que hay una diferencia entre Bouncy Castle y PHP a este respecto: Bouncy Castle espera que siempre tengas que rellenar, mientras que PHP no lo hace. Así que Bouncy agrega 1..n bytes mientras que PHP agrega 0 ... (n-1) bytes, donde n es el tamaño del bloque (32 bytes para Rijndael-256/256). Por lo tanto, puede que tenga que hacer el relleno / deslocking usted mismo; ¡asegúrese de probar las cajas de borde!