将PHP Rijndael算法重写为Java(Android)
我需要用Java和php编码一个字符串,结果必须相同 给出了以下条件:将PHP Rijndael算法重写为Java(Android),java,php,android,aes,rijndael,Java,Php,Android,Aes,Rijndael,我需要用Java和php编码一个字符串,结果必须相同 给出了以下条件: 算法:RIJNDAEL-128 钥匙:5P443M2Q1R9A7F5R3ME1Z08642 模式:欧洲央行 初始化向量:不适用(因为我们使用ECB,IV被忽略) 要编码的字符串:201412181656005P443m2Q1R9A7f5r3e1z08642 PHP 输出:WD0FHYPLBGDPHchSQL7VVCIKWJWN5HVP0W9F4SGKWAWEDCSJVFKWTM5LHBCZJSRW 更新: 我将填充从NoPa
要编码的字符串:201412181656005P443m2Q1R9A7f5r3e1z08642
PHP
输出:WD0FHYPLBGDPHchSQL7VVCIKWJWN5HVP0W9F4SGKWAWEDCSJVFKWTM5LHBCZJSRW
更新:
我将填充从NoPadding
更改为PKCS5Padding
这是正确的吗?我不确定,因为如果你看PHP代码。没有指定任何填充(我自己基于语法的假设)
其他见解:
阅读有关填充(无填充)的内容。一定与问题有关。看起来您的PHP版本使用AES-128,根据定义,AES-128使用128位(16字节)密钥。但是,看起来您传入了一个25字节的键(
5P443m2Q1R9A7f5r3e1z08642
),我不确定发生这种情况时PHP会做什么
Java版本的getKeyBytes()方法只返回所提供密钥的前16个字节,因此它只使用该字节进行加密
尝试将PHP版本中的键截断为5P443m2Q1R9A7f5r
,您将得到相同的结果。除了可能不同的端部。在这一点上,问题将是填充。您可以在明文上应用pkcs5\u pad
PHP函数,使其与Java版本匹配
所有这些都说明,如果这只是为了学习,那也没关系。否则,为了实际使用,您必须修改。我更改了
byte[]keyBytes=new byte[16]
tobyte[]keyBytes=新字节[32]
在getKeyBytes
方法中,它工作得很好。当我尝试运行您的代码时,出现以下异常:javax.crypto.IllegalBlockSizeException:com.sun.crypto.provider.CipherCore.finalNoPadding(CipherCore.java:1016)上的输入长度不是16字节的倍数
AES/Rijndael平台之间的兼容性确实很难。注意块大小,您需要对其进行填充,并确保填充到最接近的整除值16。请注意,当AES iv大小为16字节时,您正在创建一个32字节的iv。最好不要使用mcrypt,它是弃用软件,多年来未更新,并且不支持标准PKCS#7(née PKCS#5)填充,只有非标准的空填充,甚至不能用于二进制数据。mcrypt在2003年就有很多杰出的作品。。取而代之的是考虑使用,它是维护和正确的。
<?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);
}
}