【发布时间】:2015-03-11 08:19:42
【问题描述】:
我需要在Java和php中编码一个字符串,结果必须相同。
给出以下条件:
- 算法:RIJNDAEL-128
- 密钥:5P443m2Q1R9A7f5r3e1z08642
- 模式:欧洲央行
- 初始化向量:N/A(因为我们使用 ECB,IV 被忽略)
String to encode: 201412181656005P443m2Q1R9A7f5r3e1z08642
PHP
<?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);
?>
输出: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, 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);
}
}
输出:wd0FHYpLbgdpHhcSql7VVCiKWJWN5hvP0W9F4sgKWAWeDcSjvfKWTM5LHBCZJSRw
更新:
我将填充从 NoPadding 更改为 PKCS5Padding
这是正确的吗?我不确定,因为如果您查看 PHP 代码。没有指定任何填充(我自己基于语法的假设)。
其他见解:
阅读此document 关于填充(无填充)。一定与问题有关。
【问题讨论】:
-
当我尝试运行您的代码时,出现以下异常:
javax.crypto.IllegalBlockSizeException: Input length not multiple of 16 bytes at com.sun.crypto.provider.CipherCore.finalNoPadding(CipherCore.java:1016) -
平台之间的 AES/Rijndael 兼容性确实很困难。注意块的大小,你需要填充它并确保它被填充到最接近的可整除值 16。
-
请注意,当 AES iv 大小为 16 字节时,您正在创建一个 32 字节的 iv。
标签: java php android aes rijndael