AES на стороне Java – расшифровка на стороне PHP и выбор одного ключа

Я использую AES, и я хочу согласиться на ключ, который я могу использовать на стороне Java для шифрования строки, я жестко задаю один и тот же ключ на стороне php и расшифрую строку, если строки совпадают. Я аутентифицирован для входа внутрь.

Следующий мой код в Java:

public class AESencrp { private static final String ALGO = "AES"; private static final byte[] keyValue = new byte[] { 'T', 'h', 'e', 'B', 'e', 's', 't', 'S', 'e', 'c', 'r','e', 't', 'K', 'e', 'y' }; public static String encrypt(String Data) throws Exception { Key key = generateKey(); Cipher c = Cipher.getInstance(ALGO); c.init(Cipher.ENCRYPT_MODE, key); byte[] encVal = c.doFinal(Data.getBytes()); String encryptedValue = new BASE64Encoder().encode(encVal); return encryptedValue; } public static String decrypt(String encryptedData) throws Exception { Key key = generateKey(); Cipher c = Cipher.getInstance(ALGO); c.init(Cipher.DECRYPT_MODE, key); byte[] decordedValue = new BASE64Decoder().decodeBuffer(encryptedData); byte[] decValue = c.doFinal(decordedValue); String decryptedValue = new String(decValue); return decryptedValue; } private static Key generateKey() throws Exception { Key key = new SecretKeySpec(keyValue, ALGO); return key; } } 

Вот функция, которую я использую в PHP:

 function fnDecrypt() { // echo $_POST['key']; $sValue = $_POST['key']; $sSecretKey = "TheBestSecretKey"; return rtrim( mcrypt_decrypt( MCRYPT_RIJNDAEL_256, $sSecretKey, base64_decode($sValue), MCRYPT_MODE_CBC, mcrypt_create_iv( mcrypt_get_iv_size( MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC ), MCRYPT_RAND ) ), "\0" ); } 

Однако кажется, что я всегда получаю разный расшифрованный текст на стороне php, я чувствую, что проблема связана с ключом, а поскольку я жестко его кодирую, это поведение не должно возникать, никаких намеков?

Кажется, у вас есть несколько вещей, которые вы делаете неправильно, я перехожу к ним по порядку:

Всегда указывайте "Algorithm/Mode/Padding" при создании экземпляра Cipher в Java. В противном случае вы никогда не узнаете, какой режим и дополнение будут использоваться, что особенно проблематично, если вы хотите передавать зашифрованные данные между различными платформами и языками программирования, так как они, вероятно, будут иметь разные значения по умолчанию. (например, заполнение по умолчанию Java – это PKCS1Padding, где, как PHP mcrypt_decrypt() требуется ZeroBytePadding )
Поэтому инициализируйте ALGO с помощью:

 /* ZeroBytePadding should better not be used in practice */ private static final String ALGO = "AES/CBC/ZeroBytePadding"; 

Как уже упоминал Роланд Янсен , Java AES – это 128-битная версия. Поэтому используйте PHP:

 MCRYPT_RIJNDAEL_128 

В-третьих, вы должны всегда указывать разные случайные IV для каждого шифрования (не должны быть секретными). Затем вы должны использовать тот же IV для дешифрования. Таким образом, вам также придется генерировать IV в java, после чего вы переходите на PHP и используете для расшифровки там.

 byte[] iv = new byte[16]; // must be 16 bytes for AES-128 new SecureRandom().nextBytes(iv); // generate random bytes IvParameterSpec ivSpec = new IvParameterSpec(iv); /* create instance of Cipher and keys */ cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec); 

На данный момент вы также генерируете случайный IV в PHP, который, очевидно, не приведет к желаемому открытому тексту. Итак, сделайте следующее в php для дешифрования:

  $key = "{insert Java encryption key here}"; $iv; = "{insert Java encryption IV here}"; mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $ciphertext, MCRYPT_MODE_CBC, $iv); 

Если после этих исправлений он по-прежнему не работает, проблема, вероятно, в кодировании зашифрованного текста или ключа / IV-Strings. Попробуйте убедиться, что вы передаете точно такие же данные в PHP, которые вы получаете из cipher.doFinal в Java.

Надеюсь, я могу вам помочь.

Эта ссылка http://www.androidsnippets.com/encrypt-decrypt-between-android-and-php содержит руководство, которое поможет вам. Если вы хотите изменить SecretKey.