Мне нужно закодировать строку в Java и php, где результат должен быть таким же.
Приводятся следующие условия:
String to encode: 201412181656005P443m2Q1R9A7f5r3e1z08642
<?php class Cipher { private $securekey, $iv; function __construct($textkey) { $this->securekey = $textkey; $this->iv = mcrypt_create_iv(32); } function encryptR($input) { $enc = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $this->securekey, $input, MCRYPT_MODE_ECB, $this->iv); return base64_encode($enc); } function decryptR($input) { return trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $this->securekey, base64_decode($input), MCRYPT_MODE_ECB, $this->iv)); } } $raw_text = '201412181656005P443m2Q1R9A7f5r3e1z08642'; $secretKey = '5P443m2Q1R9A7f5r3e1z08642'; $cipher = new Cipher($secretKey); $encrypted = $cipher->encryptR($raw_text); ?>
encrypted = encrypt("201412181656005P443m2Q1R9A7f5r3e1z08642","5P443m2Q1R9A7f5r3e1z08642"); public class Crypt { private final String characterEncoding = "UTF-8"; private final String cipherTransformation = "AES/ECB/PKCS5Padding"; private final String aesEncryptionAlgorithm = "AES"; public byte[] decrypt(byte[] cipherText, byte[] key) throws Exception { Cipher cipher = Cipher.getInstance(cipherTransformation); SecretKeySpec secretKeySpecy = new SecretKeySpec(key, aesEncryptionAlgorithm); cipher.init(Cipher.DECRYPT_MODE, secretKeySpecy); cipherText = cipher.doFinal(cipherText); return cipherText; } public byte[] encrypt(byte[] plainText, byte[] key) throws Exception { Cipher cipher = Cipher.getInstance(cipherTransformation); SecretKeySpec secretKeySpec = new SecretKeySpec(key, aesEncryptionAlgorithm); cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec); plainText = cipher.doFinal(plainText); return plainText; } private byte[] getKeyBytes(String key) throws UnsupportedEncodingException{ byte[] keyBytes= new byte[16]; byte[] parameterKeyBytes= key.getBytes(characterEncoding); System.arraycopy(parameterKeyBytes, 0, keyBytes, 0, Math.min(parameterKeyBytes.length, keyBytes.length)); return keyBytes; } @SuppressLint("NewApi") public String encrypt(String plainText, String key) throws Exception { byte[] plainTextbytes = plainText.getBytes(characterEncoding); byte[] keyBytes = getKeyBytes(key); // Log.i("iv", ""+keyBytesIV); return Base64.encodeToString(encrypt(plainTextbytes,keyBytes), Base64.DEFAULT); } @SuppressLint("NewApi") public String decrypt(String encryptedText, String key) throws Exception { byte[] cipheredBytes = Base64.decode(encryptedText, Base64.DEFAULT); byte[] keyBytes = getKeyBytes(key); return new String(decrypt(cipheredBytes, keyBytes), characterEncoding); } }
Я изменил отступы от NoPadding
до PKCS5Padding
Это верно? Я не уверен, потому что если вы посмотрите на PHP-код. Не было задано никакого дополнения (мое собственное предположение, основанное на синтаксисе).
Информация о Mcrypt
Прочтите этот документ относительно заполнения (No Padding). Должно быть, это связано с проблемой.
Похоже, ваша версия PHP использует AES-128, которая по определению использует 128-битные (16-байтные) ключи. Однако похоже, что вы передали 25-байтовый ключ ( 5P443m2Q1R9A7f5r3e1z08642
), который я не уверен, что делает PHP, когда это происходит.
Метод getKeyBytes () вашей Java-версии возвращает только первые 16 байтов поставляемого ключа, поэтому он шифрует только это.
Попробуйте обрезать ключ в вашей версии PHP до 5P443m2Q1R9A7f5r
и вы получите тот же результат. За исключением конечной части, которая может быть другой. В этот момент проблема тогда будет дополнением. Вы можете применить PHP-функцию pkcs5_pad
в своем открытом тексте, чтобы она соответствовала вашей версии Java.
Все, что сказал, если это было только для учебных целей, все в порядке. В противном случае для фактического использования важно, чтобы вы не использовали режим шифрования ECB .
Я изменил byte[] keyBytes= new byte[16];
to byte[] keyBytes= new byte[32];
в методе getKeyBytes
он работал нормально.