我需要在
Java和PHP中编码一个字符串,其结果必须相同.
给出以下条件:
>算法:RIJNDAEL-128
>键:5P443m2Q1R9A7f5r3e1z08642
>模式:ECB
>初始化向量:N / A(因为我们使用的是ECB,所以忽略了IV)
要编码的字符串: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,base64_decode($input),$this->iv)); } } $raw_text = '201412181656005P443m2Q1R9A7f5r3e1z08642'; $secretKey = '5P443m2Q1R9A7f5r3e1z08642'; $cipher = new Cipher($secretKey); $encrypted = $cipher->encryptR($raw_text); ?>
输出:MbDHhIanWgySlMTOX ItgVKudVLXbtj7ig2GMQacVM9JhyAPvVQxLJnHpEj / vhqW
JAVA
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,keyBytes,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,characterEncoding); } }
输出:wd0FHYpLbgdpHhcsql7VVCiKWJWN5hvP0W9F4sgKWAWeDcSjvfKWTM5LHBCZJSRw
更新:
我将填充从NoPadding更改为PKCS5Padding
它是否正确?我不确定,因为你看看PHP代码.没有指定任何填充(我自己基于语法的假设).
额外洞察力:
阅读此document关于填充(无填充).一定是和这个问题有关.
看起来您的PHP版本使用AES-128,根据定义,它使用128位(16字节)密钥.然而,看起来你传入了一个25字节的密钥(5P443m2Q1R9A7f5r3e1z08642),我不确定当发生这种情况时PHP会做什么.
您的Java版本的getKeyBytes()方法仅返回提供的密钥的前16个字节,因此仅使用它加密.
尝试将PHP版本中的密钥截断为5P443m2Q1R9A7f5r,您将得到相同的结果.除了可能不同的末端部分.那时,问题就是填充.您可以在明文上应用pkcs5_pad PHP函数,使其与您的Java版本匹配.
所有这一切,如果这只是为了学习目的,那没关系.否则,对于实际使用,重要的是你do not use ECB cipher mode.