Open lilien1010 opened 9 years ago
I have the same question. @lilien1010 Did you have the solution already?
Maybe due to a different padding used by PHP?
@agentzh Thanks for answering. I do not know much about the encryption algorithm. but i tested on many sites with aes tool, like:
They have the same encrypted string, when the cipher is aes
, the key is secret
, the data is hello
, and the mode is ecb
, just the issue owner says. I got
hex: ebb28eae23f5d293629d02af7e3f4756
base64: 67KOriP10pNinQKvfj9HVg==
then, I tested with the aes of lua-resty-string lib, there is my code
local aes = require "resty.aes"
local str = require "resty.string"
local data = "hello"
local aes_128_ecb, err = aes:new("secret", nil, aes.cipher(128,"ecb"), nil)
if err then
ngx.say(err)
ngx.exit(200)
end
local encrypted = aes_128_ecb:encrypt(data)
ngx.say("AES 128 EBC Encrypted HEX: ", str.to_hex(encrypted))
ngx.say("AES 128 EBC Decrypted: ", aes_128_ecb:decrypt(encrypted))
the result is:
AES 128 EBC Encrypted HEX: daae45d76f329165629d839f0c7f009f
AES 128 EBC Decrypted: hello
The result is not matched, and I do it on a wrong way?
@surfire91 Maybe this is helpful: https://github.com/openresty/lua-resty-string/issues/10#issuecomment-11960797
(I have removed my code. It may misleading you.)
@WiLdWiNd-WH
I got a error bad key length
as your way.
Maybe ecb mode don't need a iv ?
@agentzh I think #10 is a question, not a solution......
I'm pretty sure, as @agentzh said, this is issue with different padding. Some info:
secret
is only 6 bytes, so it needs to be padded (or possibly hashed with hash function that provides 16 bytes of data). Simplest way to pad is just zero-pad, aka add needed number of \0
to end of that key.hello
is only 5 bytes, so it needs to be padded to 16 bytes, now again, simplest way to pad is to zero pad.Let me illustrate this using my lua-resty-nettle:
lua-resty-nettle
doesn't pad any keys or data automatically (at least by now, but I may implement padding mechanisms later). Now to get the results you want, I need to pad myself:
local function hex(str,spacer)
return (string.gsub(str,"(.)", function (c)
return string.format("%02X%s",string.byte(c), spacer or "")
end))
end
local aes = require "resty.nettle.aes"
local aes128 = aes.new "secret\0\0\0\0\0\0\0\0\0\0"
local ciphertext = aes128:encrypt "hello\0\0\0\0\0\0\0\0\0\0\0"
print("aes128 ecb encrypt", #ciphertext, hex(ciphertext))
local aes128 = aes.new "secret\0\0\0\0\0\0\0\0\0\0"
local plaintext = aes128:decrypt(ciphertext)
print("aes128 ecb decrypt", #plaintext, plaintext)
And when I run this I get this output (just like in PHP):
aes128 ecb encrypt 16 EBB28EAE23F5D293629D02AF7E3F4756
aes128 ecb decrypt 5 hello
I'm not sure about how lua-resty-string
does the padding, so I cannot say for sure. But maybe this helps you to understand. There are more moving parts in the method signature in lua-resty-string
so I cannot say for sure, what happens inside. The hash-parameter may use some default, I don't know (maybe it auto hashes the secret).
And the IV
thing, AES in ECB mode doesn't support it as far as I know because it doesn't perform chaining between blocks. It is the worst mode to use if the data you are trying to encrypt is more that 16 bytes (also the most simple and stupid).
@bungle Thanks I got that, php do auto padding on background.
For PHP mycrypt the padding is \0 and openssl use PKCS#5 padding, so if you use openssl api's to decrypt php's encrypt result you can disabled default padding.
Or using my aes-php
@Wang hai shi ni niubi!!!
Hi, @agentzh
I run into this issue today, thought that this API suit should use zeropadding defaultlly.
I suggest add an flag parameter in new()
function to set padding rules ,which is by default PKCS#5 to compatite with current version; and can select other ways to padding, like zero paddings
.
this could make it much user-friendly
I paste my simple code example below, and if u agree with it, I'll make a pull request for it
-- key too long
if padding_mode == ZERO_PADDING then
if #key > _cipherLength then
return nil
else
-- padding key with 0x00, work for all of 128,192,256 bits
key = key.."\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
end
ffi_copy(gen_key, key, _cipherLength)
`
@haorenfsa What do you think of this pending pull request?
@agentzh
I did some test, found this module even not compatite with openssl enc -aes-256-xxx
cmds,
and then I found that my issue (also most people's I guess) lies on that the parameter key we input is usually the real key we want to use, while aes.lua take our input key and use md5 to regenarate another string, and use it as the key, which is some random md5 value. and that causes this module not compatite with all others like php openssl.
for example, a common php openssl aes api usage is like:
openssl_encrypt('data here', 'AES-256-ECB', 'some_key');
and the actual key used to encrypt is
"some_key\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
while in ngx.resty.aes if u input 'some_key' as key, then after md5 the real key is actually
"3d70412c7e9ea2d96fa23d4f1f1f0a1c"
And thus bad time comes........
@haorenfsa That sounds like a bug to me. We should not do MD5 on the key unless explicitly dictated.
@agentzh yes, exactlly
I tryed encrypt a text with a key with PHP code,then it is OK when decrypt it with Java and Object-C ,
I dont know why do you need a sha1 when I just want want decrypt a ECB mode string
local aes_default = aes:new(key,nil, aes.cipher(128,"ecb"),aes.hash.sha1)