Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

use origin input key by default #46

Closed
wants to merge 10 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions README.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,19 @@ Synopsis
ngx.say("AES 128 CBC (WITH IV) Encrypted HEX: ", str.to_hex(encrypted))
ngx.say("AES 128 CBC (WITH IV) Decrypted: ",
aes_128_cbc_with_iv:decrypt(encrypted))

-- below is an example of "use_raw_key" option which is compatible
-- with openssl API in common languages like C and PHP
-- note the example uses default cipher, which is AES-128-CBC
-- and takes input key (which is "secret") exactly without any digist calculation
local aes = require "resty.aes"
local str = require "resty.string"
local aes_default = aes:new("secret", nil, nil, nil, nil, aes.options.use_raw_key)
local encrypted = aes_default:encrypt("hello")
ngx.say("AES-128 CBC Raw Key Encrypted HEX: ", str.to_hex(encrypted))
ngx.say("AES-128 CBC Raw Key Encrypted Base64: ", ngx.endcode_base64(encrypted))
ngx.say("AES-128 CBC Raw Key Decrypted : ", aes_default:decrypt(encrypted))

```

[Back to TOC](#table-of-contents)
Expand Down
71 changes: 48 additions & 23 deletions lib/resty/aes.lua
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ local C = ffi.C
local setmetatable = setmetatable
--local error = error
local type = type
local str_rep = string.rep


local _M = { _VERSION = '0.10' }
Expand Down Expand Up @@ -125,7 +126,15 @@ cipher = function (size, _cipher)
end
_M.cipher = cipher

function _M.new(self, key, salt, _cipher, _hash, hash_rounds)

local options = {
use_raw_key = 0x01,
-- may add other things like padding mode;
-- may use bit 'or/and' operation for combined options.
}
_M.options = options

function _M.new(self, key, salt, _cipher, _hash, hash_rounds, option)
local encrypt_ctx = ffi_new(ctx_ptr_type)
local decrypt_ctx = ffi_new(ctx_ptr_type)
local _cipher = _cipher or cipher()
Expand All @@ -135,40 +144,56 @@ function _M.new(self, key, salt, _cipher, _hash, hash_rounds)
local gen_key = ffi_new("unsigned char[?]",_cipherLength)
local gen_iv = ffi_new("unsigned char[?]",_cipherLength)

if type(_hash) == "table" then
if not _hash.iv or #_hash.iv ~= 16 then
return nil, "bad iv"
end
if not option then
if type(_hash) == "table" then
if not _hash.iv or #_hash.iv ~= 16 then
return nil, "bad iv"
end

if _hash.method then
local tmp_key = _hash.method(key)

if _hash.method then
local tmp_key = _hash.method(key)
if #tmp_key ~= _cipherLength then
return nil, "bad key length"
end

if #tmp_key ~= _cipherLength then
ffi_copy(gen_key, tmp_key, _cipherLength)

elseif #key ~= _cipherLength then
return nil, "bad key length"
end

ffi_copy(gen_key, tmp_key, _cipherLength)
else
ffi_copy(gen_key, key, _cipherLength)
end

elseif #key ~= _cipherLength then
return nil, "bad key length"
ffi_copy(gen_iv, _hash.iv, 16)

else
ffi_copy(gen_key, key, _cipherLength)
end
if salt and #salt ~= 8 then
return nil, "salt must be 8 characters or nil"
end

ffi_copy(gen_iv, _hash.iv, 16)
if C.EVP_BytesToKey(_cipher.method, _hash, salt, key, #key,
hash_rounds, gen_key, gen_iv)
~= _cipherLength
then
return nil
end
end

else
if salt and #salt ~= 8 then
return nil, "salt must be 8 characters or nil"
elseif option == options.use_raw_key then
-- use origin key
if not key then
return nil, "key is nil!"
end

if C.EVP_BytesToKey(_cipher.method, _hash, salt, key, #key,
hash_rounds, gen_key, gen_iv)
~= _cipherLength
then
return nil
if #key > _cipherLength then
return nil, "key too long"
end

-- note it's key padding not data padding, and it use zero padding only;
key = key..str_rep("\0", _cipherLength - #key)
ffi_copy(gen_key, key, _cipherLength)
end

C.EVP_CIPHER_CTX_init(encrypt_ctx)
Expand Down
23 changes: 23 additions & 0 deletions t/aes.t
Original file line number Diff line number Diff line change
Expand Up @@ -293,3 +293,26 @@ failed to new: bad iv
--- no_error_log
[error]

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We always use 3 blank lines to separate test blocks. Please use the reindex script to auto-format this .t file. Thank you.



=== TEST 11: AES option:use_raw_key hello
--- http_config eval: $::HttpConfig
--- config
location /t {
content_by_lua '
local aes = require "resty.aes"
local str = require "resty.string"
local aes_default = aes:new("secret", nil, nil, nil, nil, aes.options.use_raw_key)
local encrypted = aes_default:encrypt("hello")
ngx.say("AES-128 CBC MD5: ", str.to_hex(encrypted))
local decrypted = aes_default:decrypt(encrypted)
ngx.say(decrypted == "hello")
';
}
--- request
GET /t
--- response_body
AES-128 CBC MD5: c290e8b6de4ea5773414e019fe7f17a3
true
--- no_error_log
[error]