gpt4 book ai didi

java - 使用 Java 的 RIJNDAEL 加密

转载 作者:塔克拉玛干 更新时间:2023-11-03 06:03:34 24 4
gpt4 key购买 nike

我需要在 Java 和 php 中对明文进行编码,结果必须相同。

给出以下条件:

  1. 算法:RIJNDAEL-128
  2. key :1234567890123456
  3. 模式:循环流化
  4. 初始化 vector :1234567890123456

以下代码有效并满足第一个和第二个要求,但它使用 ECB 作为模式,因此不使用初始化 vector :

PHP:

 <?php  
$cipher = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_ECB, '');
$cleartext = 'abcdefghijklmnop';
$key128 = '1234567890123456';
$iv = '1234567890123456';

if (mcrypt_generic_init($cipher, $key128, $iv) != -1) //Parameter iv will be ignored in ECB mode
{
$cipherText = mcrypt_generic($cipher,$cleartext );
mcrypt_generic_deinit($cipher);
printf(bin2hex($cipherText));
}
?>

输出为:fcad715bd73b5cb0488f840f3bad7889

Java:

public class AES {

public static void main(String[] args) throws Exception {
String cleartext = "abcdefghijklmnop";
String key = "1234567890123456";
SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted = cipher.doFinal(cleartext.getBytes());
System.out.println(asHex(encrypted));
}

public static String asHex(byte buf[]) {
StringBuffer strbuf = new StringBuffer(buf.length * 2);
int i;
for (i = 0; i < buf.length; i++) {
if (((int) buf[i] & 0xff) < 0x10)
strbuf.append("0");
strbuf.append(Long.toString((int) buf[i] & 0xff, 16));
}
return strbuf.toString();
}

}

输出为(与PHP版本相同):fcad715bd73b5cb0488f840f3bad7889

现在为了满足要求 3 和 4,我在我的 PHP 版本中将模式更改为 MCRYPT_MODE_CFB,这样代码如下所示:

 <?php  
$cipher = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CFB, '');
$cleartext = 'abcdefghijklmnop';
$key128 = '1234567890123456';
$iv = '1234567890123456';


if (mcrypt_generic_init($cipher, $key128, $iv) != -1) //Parameter iv will be ignored in ECB mode
{
$cipherText = mcrypt_generic($cipher,$cleartext );
mcrypt_generic_deinit($cipher);
printf(bin2hex($cipherText));
}
?>

这导致以下输出:14a53328feee801b3ee67b2fd627fea0

在 JAVA 版本中,我也调整了模式并将 iv 添加到我的 Cipher 对象的 init 函数中。

public class AES {

public static void main(String[] args) throws Exception {
String cleartext = "abcdefghijklmnop";
String key = "1234567890123456";
SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES/CFB/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, new IvParameterSpec("1234567890123456".getBytes()));
byte[] encrypted = cipher.doFinal(cleartext.getBytes());
System.out.println(asHex(encrypted));
}

public static String asHex(byte buf[]) {
StringBuffer strbuf = new StringBuffer(buf.length * 2);
int i;
for (i = 0; i < buf.length; i++) {
if (((int) buf[i] & 0xff) < 0x10)
strbuf.append("0");
strbuf.append(Long.toString((int) buf[i] & 0xff, 16));
}
return strbuf.toString();
}

}

但这里输出的是 141eae68b93af782b284879a55b36f70,这与 PHP 版本不同。

有人知道 JAVA 和 PHP 版本之间的区别吗?

最佳答案

它没有很好地记录,但是 PHP 的 MCRYPT_RIJNDAEL_128MCRYPT_MODE_CFB 产生的结果与 Java 的 AES/CFB8/NoPadding 一致。

所以 PHP 中的这一行:

$encrypted = base64_encode( mcrypt_encrypt( MCRYPT_RIJNDAEL_128, $key, $cleartext, MCRYPT_MODE_CFB, $iv ) );

在 Java 中匹配这个 block :

SecretKeySpec   key = new SecretKeySpec(KEY.getBytes(), "AES");
IvParameterSpec iv = new IvParameterSpec(IV.getBytes());

Cipher cipher = Cipher.getInstance("AES/CFB8/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, key, iv);

byte[] output = cipher.doFinal(cleartext.getBytes());

String signature = Base64.encode(output);

关于java - 使用 Java 的 RIJNDAEL 加密,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10136585/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com