【问题标题】:RIJNDAEL 256 CBC encryption with IV in javaRIJNDAEL 256 CBC 加密与 Java 中的 IV
【发布时间】:2018-01-08 13:46:29
【问题描述】:

我有一个执行 Rijndael 加密的 PHP 代码的参考。我想将其转换为 java 代码,我尝试了几个示例,但没有一个对我有用。 这里是php代码:

$initialisationVector = hash("sha256", utf8_encode($myiv), TRUE);
$key = hash("sha256", utf8_encode($mykey), TRUE);
$encryptedValue = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256,$encryptKey, utf8_encode($mydata), MCRYPT_MODE_CBC, $initialisationVector));

这是我抛出的 java 代码:密钥长度不是 128/160/192/224/256 位

public static String encrypt() throws Exception{
    String myiv = "somevalue";
    String mykey = "somevalue";
    String mydata = "somevalue";
    String new_text = "";

    RijndaelEngine rijndael = new RijndaelEngine(256);
    CBCBlockCipher cbc_rijndael = new CBCBlockCipher(rijndael);
    ZeroBytePadding c = new ZeroBytePadding();
    PaddedBufferedBlockCipher pbbc = new PaddedBufferedBlockCipher(cbc_rijndael, c);

    byte[] iv_byte = sha256(myiv);

    byte[] givenKey = sha256(mykey);

    CipherParameters keyWithIV = new ParametersWithIV(new KeyParameter(givenKey), iv_byte);

    pbbc.init(true, keyWithIV);
    byte[] plaintext = mydata.getBytes(Charset.forName("UTF-8"));
    byte[] ciphertext = new byte[pbbc.getOutputSize(plaintext.length)];
    int offset = 0;
    offset += pbbc.processBytes(plaintext, 0, plaintext.length, ciphertext, offset);
    offset += pbbc.doFinal(ciphertext, offset);
    new_text = new String(new Base64().encode(ciphertext), Charset.forName("UTF-8"));
    System.out.println(new_text);
    return new_text;
}

public static byte[] sha256(String input) throws NoSuchAlgorithmException {
    MessageDigest md = MessageDigest.getInstance("SHA-256");
    byte[] messageDigest = md.digest(input.getBytes(Charset.forName("UTF-8")));
    return messageDigest;
}

我不太擅长密码学。提前致谢!

【问题讨论】:

  • 你的java sha256方法很不对。它不应该返回一个十六进制字符串(这也是错误生成的),它应该返回 byte[]。 input.getBytes() 应该是 input.getBytes(Charset.forName("UTF-8"))
  • 你需要调试。这意味着检查发送到加密函数和从加密函数返回的值并验证它们。此外,问题还需要一个 minimal reproducible example 完整的测试值,并在适当的情况下以十六进制输出。
  • 更新了 sha256 函数,现在它抛出 Key length not 128/160/192/224/256 bits
  • sha256(appId) 提供了一个 256 位的密钥,使用它即可。不需要final int keysize = 256;byte[] keyData = new byte[keysize];System.arraycopy(givenKey, 0, keyData, 0, Math.min(givenKey.length, keyData.length));。
  • 貌似生成了加密,但是和PHP块生成的不匹配,Java代码生成的也比较长。

标签: java encryption bouncycastle rijndael


【解决方案1】:

错误信息很清楚:“初始化向量的长度必须与块大小相同”。您正在指定 256 位(32 字节)块大小,请验证 iv_byte 是否为 32 字节。

有几个问题:

  1. 对于 IV 从哈希中获取字节,将字节传递给加密函数,BigInteger 没有位置。

  2. sha256(appId) 提供了一个 256 位的密钥,使用它即可。

以下不需要,sha256的结果是256位:

final int keysize = 256;
byte[] keyData = new byte[keysize];
System.arraycopy(givenKey, 0, keyData, 0, Math.min(givenKey.length, keyData.length));
  1. sha256(appId) 提供了一个 256 位的密钥,使用即可。

以下是不需要的:

final int keysize = 256; 
byte[] keyData = new byte[keysize];
System.arraycopy(givenKey, 0, keyData, 0, Math.min(givenKey.length, keyData.length));
  1. mcrypt“MCRYPT_RIJNDAEL_256”指定了 256 位块大小,这意味着它不是 AES,“MCRYPT_RIJNDAEL_128”是应该使用的 AES。

  2. mcrypt 使用非标准空填充,需要适应。

  3. 使用 SHA-256 哈希不够安全,请使用密码派生函数,例如 PBKDF2。

【讨论】:

  • 我无法修改 PHP 功能,我需要做的就是将 PHP 块转换为等效的 Java 代码。
  • 好奇:你为什么选择 256 位的块大小?
  • 不确定,因为我还没有开发那部分。
  • 更新了 sha256 函数,现在它抛出“Key length not 128/160/192/224/256 bits”
  • 密钥长度必须是这些长度之一,我建议坚持使用 128 位或 256 位的 AES 密钥长度。再次强调,调试是一项重要的开发人员技能。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-28
  • 1970-01-01
  • 2014-10-14
  • 1970-01-01
  • 2012-05-06
相关资源
最近更新 更多