我正在开发一个nginx(openresty)Lua模块,其中一个要求是破译遗留Java程序生成的加密字符串。但我的Lua代码未能破译它,我在这里寻求帮助。
Java加密和解密代码没问题:
<widget id="com.yourapp.hybrid" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
输出Java代码:
public class AesCbc {
private static String PLAIN = "usr/passwd@bizdb:127.0.0.1:5432";
public static void main(String[] args) throws Exception {
Cipher aesCipher = Cipher.getInstance("AES/CBC/NoPadding");
SecretKeySpec keySpec = new SecretKeySpec("1234567890ABCDEF".getBytes(), "AES");
IvParameterSpec iv = new IvParameterSpec("fedcba0987654321".getBytes());
aesCipher.init(Cipher.ENCRYPT_MODE, keySpec, iv);
byte[] rawBytes = PLAIN.getBytes();
byte[] aligned;
int mod = rawBytes.length % 16; // prevent javax.crypto.IllegalBlockSizeException
if (mod == 0) {
aligned = new byte[rawBytes.length];
} else {
aligned = new byte[rawBytes.length + 16 - mod];
}
System.arraycopy(rawBytes, 0, aligned, 0, rawBytes.length);
byte[] cipherBytes = aesCipher.doFinal(aligned);
String base64Result = Base64.getEncoder().encodeToString(cipherBytes);
System.out.println("cipher:[" + base64Result + "], rawBytes.length=" + rawBytes.length + ", mod=" + mod);
aesCipher.init(Cipher.DECRYPT_MODE, keySpec, iv);
cipherBytes = Base64.getDecoder().decode(base64Result);
aligned = aesCipher.doFinal(cipherBytes);
int posNil;
for (posNil = 0; posNil < aligned.length; posNil++) {
if (aligned[posNil] == 0x00)
break;
}
rawBytes = new byte[posNil];
System.arraycopy(aligned, 0, rawBytes, 0, posNil);
String plain = new String(rawBytes);
System.out.println("plain:[" + plain + "], posNil=" + posNil + ", aligned.length=" + aligned.length);
}
}
我的Lua测试文件在nginx.conf-&gt; http-&gt;服务器部分中声明:
cipher:[l1buytGEL4RKa/RezInQ3dJxvMtL6nyE2wTi7VyoS4w=], rawBytes.length=31, mod=15
plain:[usr/passwd@bizdb:127.0.0.1:5432], posNil=31, aligned.length=32
conf / aescbc.lua的内容:
location /aescbc {
content_by_lua_file conf/aescbc.lua;
}
使用“curl http://127.0.0.1:8080/aescbc”进行测试时,nginx错误日志:
-- aescbc.lua
local aes = require "resty.aes"
local str = require "resty.string"
local aes128Cbc = aes:new("1234567890ABCDEF", nil, aes.cipher(128, "cbc"), {iv="fedcba0987654321"})
-- result of AesCbc.java for my test
local BASE64CIPHER = "l1buytGEL4RKa/RezInQ3dJxvMtL6nyE2wTi7VyoS4w="
local cipherBytes = ngx.decode_base64(BASE64CIPHER)
if not cipherBytes then
ngx.log(ngx.WARN, "decode base64 [" .. BASE64CIPHER .. "] failed")
return
end
local aligned = aes128Cbc:decrypt(cipherBytes)
if not aligned then
ngx.log(ngx.WARN, "decrypt cipherBytes [" .. str.to_hex(cipherBytes) .. "] failed")
return
end
ngx.log(ngx.NOTICE, "aligned [" .. str.to_hex(aligned) .. "]")
return
我认为我使用resty.aes肯定有问题,但是如何解决呢?
答案 0 :(得分:2)
在搜索网页,阅读手册页并进行了几天的实验后,问题就解决了。所以我自己回答:
resty.aes模块使用OpenSSL的默认PKCS7填充算法,并且没有方法在当前版本的resty.aes中设置 NoPadding 选项。所以我做了一个补丁:(添加 padding 参数并在aes中调用 EVP_CIPHER_CTX_set_padding():new)
$ diff ./lualib/resty/aes.lua.orig ./lualib/resty/aes.lua
79a80
> int EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *x, int padding);
128c129
< function _M.new(self, key, salt, _cipher, _hash, hash_rounds)
---
> function _M.new(self, key, salt, _cipher, _hash, hash_rounds, padding)
177a179,184
> end
>
> if padding then
> -- 0:NoPadding, 1:PKCS7(default), 2:ISO7816_4, 3:ANSI923, 4:ISO10126, 5:ZERO
> C.EVP_CIPHER_CTX_set_padding(encrypt_ctx, padding);
> C.EVP_CIPHER_CTX_set_padding(decrypt_ctx, padding);
对lua测试代码进行了一些小修改:
$ cat ./nginx/conf/aescbc.lua
-- aescbc.lua
local aes = require "resty.aes"
local str = require "resty.string"
local aes128Cbc = aes:new("1234567890ABCDEF", nil, aes.cipher(128, "cbc"), {iv="fedcba0987654321"}, nil, 0)
-- result of AesCbc.java for my test
local BASE64CIPHER = "l1buytGEL4RKa/RezInQ3dJxvMtL6nyE2wTi7VyoS4w="
local cipherBytes = ngx.decode_base64(BASE64CIPHER)
if not cipherBytes then
ngx.log(ngx.WARN, "decode base64 [" .. BASE64CIPHER .. "] failed")
return
end
local aligned = aes128Cbc:decrypt(cipherBytes)
if not aligned then
ngx.log(ngx.WARN, "decrypt cipherBytes [" .. str.to_hex(cipherBytes) .. "] failed")
return
end
ngx.log(ngx.NOTICE, "aligned [" .. str.to_hex(aligned) .. "], len=" .. aligned:len())
local plain
local idx = aligned:find('\0')
if idx then
plain = aligned:sub(1, idx - 1)
else
plain = aligned
end
ngx.log(ngx.NOTICE, "plain [" .. plain .. "], len=" .. plain:len())
return
测试的nginx错误日志:
2017/08/07 15:17:55 [notice] 34632#0: *21 [lua] aescbc.lua:22: aligned [7573722f7061737377644062697a64623a3132372e302e302e313a3534333200], len=32, client: 127.0.0.1, server: , request: "GET /aescbc HTTP/1.1", host: "127.0.0.1:8080"
2017/08/07 15:17:55 [notice] 34632#0: *21 [lua] aescbc.lua:32: plain [usr/passwd@bizdb:127.0.0.1:5432], len=31, client: 127.0.0.1, server: , request: "GET /aescbc HTTP/1.1", host: "127.0.0.1:8080"