openresty 的 aes 算法, Java 实现对不上 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
dunhanson

openresty 的 aes 算法, Java 实现对不上

  •  
  •   dunhanson Jul 28, 2024 2308 views
    This topic created in 643 days ago, the information mentioned may be changed or developed.

    为啥对不上?好奇怪

    1 、openresty github 官方示例

    https://github.com/openresty/lua-resty-string

    local aes = require "resty.aes" local str = require "resty.string" local aes_128_cbc_md5 = aes:new("AKeyForAES") -- the default cipher is AES 128 CBC with 1 round of MD5 -- for the key and a nil salt local encrypted = aes_128_cbc_md5:encrypt("Secret message!") ngx.say("AES 128 CBC (MD5) Encrypted HEX: ", str.to_hex(encrypted)) ngx.say("AES 128 CBC (MD5) Decrypted: ", aes_128_cbc_md5:decrypt(encrypted)) 

    2 、自己编写 lua 测试

    local aes = require "resty.aes" local str = require "resty.string" local aes_128_cbc_md5 = aes:new("gOxiO7IIRthJ406X") -- the defalt cipher is AES 128 CBC with 1 round of MD5 -- for the key and a nil salt local encrypted = aes_128_cbc_md5:encrypt("hello") ngx.say("AES 128 CBC (MD5) Encrypted HEX: ", str.to_hex(encrypted)) ngx.say("AES 128 CBC (MD5) Decrypted: ", aes_128_cbc_md5:decrypt(encrypted)) -- 输出结果 AES 128 CBC (MD5) Encrypted HEX: de6641e8a49ef1911a10d9ec88cc477b AES 128 CBC (MD5) Decrypted: hello 

    3 、java 实现

    @Test public void testEncryptText() { String key = "gOxiO7IIRthJ406X"; byte[] iv = new byte[16]; String text = "hello"; AES aes = new AES(Mode.CBC, Padding.PKCS5Padding, SecureUtil.md5(key).getBytes(), iv); System.out.println(aes.encryptHex(text)); // 输出:446d1192d40aa0d05e3c30392ac43ec3 aes = new AES(Mode.CBC, Padding.PKCS5Padding, key.getBytes(), iv); System.out.println(aes.encryptHex(text)); // 输出:190ede3e1359a6e4d8ecf38c8f4bce63 } 
    11 replies    2024-07-29 00:45:13 +08:00
    kran
        1
    kran  
       Jul 28, 2024 via Android
    虽然忘了具体参数,但可以匹配上。曾经做过。
    kran
        2
    kran  
       Jul 28, 2024 via Android
    ```
    @Provides @Singleton
    private Cipher provideAESEncryptCipher(GlobalConfig config) {
    var key = Base64.decode(config.getAesKey());
    var cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", new BouncyCastleProvider());
    var iv = config.getAesIV().getBytes(StandardCharsets.US_ASCII);
    cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES/CBC/PKCS7Padding"), new IvParameterSpec(iv));


    return cipher;
    }
    }

    local c = aes:new(key, nil, aes.cipher(128,"cbc"), {iv="0123456789abcdef"})

    local path = ngx.re.gsub(string.sub(ngx.var.uri, 2), '-', '+')
    local url, err = c:decrypt(ngx.decode_base64(path))

    ```
    dunhanson
        3
    dunhanson  
    OP
       Jul 28, 2024
    @kran 我用的 aes_128_cbc_md5 ,这个 iv 不知道是多少
    kran
        4
    kran  
       Jul 28, 2024 via Android
    iv 自己定的
    kran
        5
    kran  
       Jul 28, 2024 via Android
    随机 iv 我记得两边匹配不上
    dunhanson
        6
    dunhanson  
    OP
       Jul 28,2024
    @kran 确实,随机的匹配不上,固定的匹配上了。
    但是好奇怪,随机,为啥 openresty 自己可以解密?
    forvvvv123
        7
    forvvvv123  
       Jul 28, 2024   2
    OP 意思是同样的 key ,同样的明文,2 和 3 结果不一样吗?

    如果是这个意思的话,那是因为 cbc 模式要求有 iv ,正常的做法,每一次加密 iv 都是一个不一样的值,同样 key 同样明文,iv 不同获得的密文也不同; 接收方要解密的时候必须知道 key + iv 才能解密,一般是约定附加在密文开头或者指定另一个字段;

    你这两个都没有明确设置 iv ,那得看 lua 的默认行为和 java 默认行为最终导致的进入运算的 iv 一不一样; op 可以手动设置 iv ,或者查查手册把 iv 打印出来
    Citrus
        8
    Citrus  
       Jul 29, 2024 via iPhone   4
    刚好研究过。OpenResty 的 AES 库实际是调用 OpenSSL ,如果你不显示指定 IV ,会用 key 生成一个 IV 。具体看这里: https://docs.openssl.org/3.1/man3/EVP_BytesToKey/
    所以这个库调用的时候看起来没有传 IV ,但是却可以正常加解密,且用全 0 IV 无法解密。

    你的 Java 代码,IV 没有初始化,也就是全 0 ,跟 OpenSSL 生成的肯定是对不上的。所以解密失败了。

    如果你想用 Java 解,有两种方式。一是实现 EVP BytesToKey 函数,算一个正确的 IV 出来。二是在 Lua 里,自己传 IV 进去,不要用自动生成的。
    Citrus
        9
    Citrus  
       Jul 29, 2024 via iPhone
    @forvvvv123 不一样。OP 在 Lua 没指定,自动生成了。但是在 Java 指定了,指定了全 0 。
    Citrus
        10
    Citrus  
       Jul 29, 2024 via iPhone
    @dunhanson 自己可以解是因为 OpenResty 用了 OpenSSL 的 https://docs.openssl.org/3.1/man3/EVP_BytesToKey/ 函数根据 Password 算出了 IV ,所以同一个 Password 算出的 Key 和 IV 是一样的,所以才能解密。
    forvvvv123
        11
    forvvvv123  
       Jul 29, 2024
    楼上老哥解释的很详细; 原来 lua 是默认调用了一个 openssl 的自动生成 iv 的函数,不是用全 0 的 iv ;

    其实一般做法 iv 都是自己写段逻辑自己生成的,用随机数也好,不重复生成的算法也好。 因为传输密文的时候这个 iv 怎么传得跟对方约定好的,是单独一个业务字段,还是放到开头结尾; 所以 iv 这块总是要自己处理的;
    About     Help     Advertise     Blog     API     FAQ     Solana     2508 Online   Highest 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 39ms UTC 02:50 PVG 10:50 LAX 19:50 JFK 22:50
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86