2017-08-03 93 views
1

我正在開發一個nginx(openresty)Lua模塊,其中一個要求是解密生成的加密字符串由一個傳統的Java程序。但我的Lua代碼無法破譯,我在這裏尋求幫助。解密Java Cipher.getInstance(「AES/CBC/NoPadding」)的結果失敗OpenResty的resty.aes模塊

的Java加密和解密代碼這是確定:

public class AesCbc { 
    private static String PLAIN = "usr/[email protected]: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); 
    } 
} 

Java代碼的輸出:

cipher:[l1buytGEL4RKa/RezInQ3dJxvMtL6nyE2wTi7VyoS4w=], rawBytes.length=31, mod=15 
plain:[usr/[email protected]:127.0.0.1:5432], posNil=31, aligned.length=32 

nginx.conf-> HTTP->服務器節內聲明我Lua的測試文件: CONF/aescbc.lua的

  location /aescbc { 
        content_by_lua_file 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"}) 

-- 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 

當測試「捲曲http://127.0.0.1:8080/aescbc」,Nginx的錯誤日誌:

2017/08/03 11:28:26 [warn] 13799#0: *5 [lua] aescbc.lua:18: decrypt cipherBytes [9756eecad1842f844a6bf45ecc89d0ddd271bccb4bea7c84db04e2ed5ca84b8c] failed, client: 127.0.0.1, server: , request: "GET /aescbc HTTP/1.1", host: "127.0.0.1:8080" 

我想一定是壞了我的resty.aes的使用,但如何解決它?

回答

2

搜索完網頁後,閱讀手冊頁,並在幾天內掙扎一些實驗,問題就解決了。所以,我的回答是它自己:

的resty.aes模塊使用OpenSSL的默認PKCS7填充算法,並沒有方法來設置在resty.aes當前版本NoPadding選項。所以,我做了一個補丁吧:(加填充參數,並調用EVP_CIPHER_CTX_set_padding()在AES:新)

$ 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的ERR日誌測試:

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/[email protected]: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" 
+0

我遇到了類似的問題,但是加密發生在.NET應用程序。我不知道你是否可以分享完整版的aes.lua補丁,從你的答案我不明白'C.EVP_CIPHER_CTX_set_padding'調用位於lua文件中的位置。問候。 –