跳至主要內容
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?

4563博客

全新的繁體中文 WordPress 網站
  • 首頁
  • PHP 的 AES 加密问题
未分類
5 5 月 2020

PHP 的 AES 加密问题

PHP 的 AES 加密问题

資深大佬 : youngs 15

为什么 PHP AES 解密 CBC 模式 iv 可以为空呢? 用 Java 去解密没有 iv 根本解密不出来啊,有什么办法解决?

大佬有話說 (19)

  • 主 資深大佬 : youngs

    同样的 js 的 CryptoJs 的 iv 也可以为空

  • 資深大佬 : GTim

    那是因为人家 PHP 底层调用的是 `openssl` 家的函数,`openssl` 家的函数的默认值就是 16 个 0

  • 主 資深大佬 : youngs

    @GTim 可是给 iv 赋 16 个 0,解密出来的不是原来的明文

  • 資深大佬 : binkcn

    @GTim

    似乎不是的,参见: https://blog.lancitou.net/how-to-generate-key-and-iv-in-openssl-aes/

    OPENSSL AES 算法中的 IV 是这样来的:

    “`
    hash1_128 = MD5(Passphrase + Salt)
    hash2_128 = MD5(hash1_128 + Passphrase + Salt)
    hash3_128 = MD5(hash2_128 + Passphrase + Salt)
    Key = hash1_128 + hash2_128
    IV = hash3_128
    “`

    另外,@youngs 不知道你用的是 PHP 什么版本,用的哪个函数在解 AES,最好有代码或者伪代码……

  • 主 資深大佬 : youngs

    @binkcn
    代码已经加上了

  • 資深大佬 : GTim

    @GTim CBC 模式是不需要 IV 的,你把你的 Java 代码也贴出来一下

  • 資深大佬 : jim9606

    CBC 、CFB 、OFB 等流密码模式都是需要 IV 的,不提供的就看默认值是啥了,反正必须要有。

    也就 ECB 不需要 IV (千万别用)

  • 資深大佬 : rekulas

    之前写过 c 版的 aes 虽然加了 iv 但是我不想记录这个 于是每次都是随机 iv 加密 空 iv 解密 解密后抛弃第一个块(因为第一个块无法解密) 后面的就是原始数据

    感觉你这问题和这有些关系 你可以使用相同的 iv(例如全 0 值) 打印解密后的原始数据看看一不一样

  • 資深大佬 : xLuoBo

    千万不要用 php 的 192 256 aes, key 和 iv 处理位数都和通用库不一样;
    他是一只特立独行的猪, 自己加的密只能自己解; 让别人懵逼去吧

  • 資深大佬 : james122333

    https://www.php.net/manual/en/function.mcrypt-module-open.php
    https://www.php.net/manual/en/function.mcrypt-generic-init.php

  • 主 資深大佬 : youngs

    @rekulas
    如果是全 0 的话和 Java 解密结果一致,但是都不是正确的解密结果。php 在 iv 为”的情况应该是有默认值,但是不知道这个默认值是啥

  • 主 資深大佬 : youngs

    @rekulas 解密出的结果是 SVRQVSSUS***********************91856 确实第一个块解不出来,但是解密出来的密文相比较原来的密文也是查着第一个块的结果,第一个块解密出来是大写字母。。。

  • 資深大佬 : binkcn

    @youngs

    有个关键问题是:你的密文是用 PHP 加密的吗?

    我刚才测试了 PHP 下加密的时候 iv 参数不能为空,即 mcrypt_generic_init() 函数第 3 个参数不能为空,一定要设置的,而根据官网文档的说法是建议设置为全 0 值(长度根据 mcrypt_enc_get_iv_size 来设置)。

    所以现在问题的关键是你的密文是怎么加密的,openssl ?还是其他语言?

  • 主 資深大佬 : youngs

    @binkcn 前端用 CryptoJS 加密的

    function Encrypt_aes2(word, privateKey) {
    var data = word;
    var key = CryptoJS.enc.Utf8.parse(‘1111111111111111’);
    var iv = CryptoJS.enc.Utf8.parse(”);
    //加密
    var encrypted = CryptoJS.AES.encrypt(data, key, { iv: iv, mode: CryptoJS.mode.CBC });
    console.log(‘encrypted.toString()’, encrypted.toString())
    // 这里是解密
    console.log(‘解密’ ,CryptoJS.AES.decrypt(encrypted.toString(), key, { iv: iv, mode: CryptoJS.mode.CBC }).toString(CryptoJS.enc.Utf8))
    return encrypted.toString();
    }

  • 資深大佬 : binkcn

    @youngs

    好了,话题终结了。

    看了下 CryptoJs 源码,和我在本帖 4 回复的猜想一样,如果你的 key 是个字符串,那么 CryptoJs 底层会用和 Openssl 兼容的函数来生成 iv:根据你的 key 和一个随机的 salt 经过若干次 md5 后生成的,每次 encrypt 的 iv 都不一样,具体方式见我 4 的伪代码。

    那么,怎么取到 CryptoJS 每次调用 AES.encrypt 时的 iv 呢?很简单……

    // Encrypt
    var ct = CryptoJS.AES.encrypt(‘my message’, ‘secret key 123’);

    var saltHex = ct.salt.toString(); // random salt
    var ctHex = ct.ciphertext.toString(); // actual ciphertext
    var ivHex = ct.iv.toString(); // generated IV

    console.log(saltHex);
    console.log(ctHex);
    console.log(ivHex);

    你可以试试用打印出来的 iv 到 PHP 或者 Java 里面去解解看。

  • 資深大佬 : binkcn

    完整的加密、解密,以及显示本次加密的 iv,在我这里测试是通过的。祝你好运:)

    // Encrypt
    var ct = CryptoJS.AES.encrypt(‘my message’, ‘secret key 123’);

    var saltHex = ct.salt.toString(); // random salt
    var ctHex = ct.ciphertext.toString(); // actual ciphertext
    var ivHex = ct.iv.toString(); // generated IV

    console.log(saltHex);
    console.log(ctHex);
    console.log(ivHex);

    // Decrypt
    var bytes = CryptoJS.AES.decrypt(ct.toString(), ‘secret key 123’, { iv: ct.iv, mode: CryptoJS.mode.CBC });
    var originalText = bytes.toString(CryptoJS.enc.Utf8);

    console.log(originalText);

  • 主 資深大佬 : youngs

    @binkcn 大佬,用 JAVA 怎么取到这个 IV 呢。。。。

  • 資深大佬 : binkcn

    @youngs 你前端用 CryptoJS 加密的时候,自己额外存一下本次加密时产生的 iv,回头用 java 解密的时候传进去就行了,这样最简单。

    如果,你现在想解密之前已经加密出来的密文,那么就稍微麻烦一些:

    首先,加密出来的密文是 base64 的,你 base64_decode 之后会发现开头是 “Salted__”这样的,然后紧跟着的 8 个字节就是 salt 了,然后根据我 4 的伪代码,Passphrase (即 key ) 和 Salt 你都有了,可以自己算出 iv 。

    这个部分你自己实现即可,18 点过了,我下班回家了…… 2333

  • 主 資深大佬 : youngs

    @binkcn 大佬!我解出来了。。。详细结果 append 到主题上,感谢~

文章導覽

上一篇文章
下一篇文章

AD

其他操作

  • 登入
  • 訂閱網站內容的資訊提供
  • 訂閱留言的資訊提供
  • WordPress.org 台灣繁體中文

51la

4563博客

全新的繁體中文 WordPress 網站
返回頂端
本站採用 WordPress 建置 | 佈景主題採用 GretaThemes 所設計的 Memory
4563博客
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?
在這裡新增小工具