mirror of
https://github.com/bunkerity/bunkerweb
synced 2026-05-24 09:28:37 +00:00
Merge commit 'dda63ddceeb1f4ffdd97d6aa95ac24a1a7eeede7' into dev
This commit is contained in:
commit
32777c25ea
28 changed files with 1451 additions and 378 deletions
|
|
@ -60,7 +60,7 @@ jobs:
|
|||
lua_resty_core: "v0.1.27"
|
||||
nginx_cc_opts: "-Wno-error"
|
||||
- nginx: "1.21.4"
|
||||
openssl: "3.2.0-alpha1"
|
||||
openssl: "3.2.0"
|
||||
openssl_fips: "3.0.8"
|
||||
extras: "valgrind perf"
|
||||
lua_nginx_module: "v0.10.25"
|
||||
|
|
@ -117,7 +117,6 @@ jobs:
|
|||
popd
|
||||
git clone https://github.com/openresty/lua-resty-core.git ../lua-resty-core -b ${{ matrix.lua_resty_core }}
|
||||
git clone https://github.com/openresty/lua-resty-lrucache.git ../lua-resty-lrucache
|
||||
git clone https://github.com/jkeys089/lua-resty-hmac ../lua-resty-hmac && pushd ../lua-resty-hmac && git checkout 79a4929 && popd
|
||||
git clone https://github.com/openresty/lua-resty-string ../lua-resty-string
|
||||
|
||||
- name: Build OpenSSL
|
||||
|
|
@ -181,20 +180,6 @@ jobs:
|
|||
nginx -V
|
||||
ldd `which nginx`|grep -E 'luajit|ssl|pcre'
|
||||
|
||||
- name: Run performance test
|
||||
if: contains(matrix.extras, 'perf')
|
||||
run: |
|
||||
wget https://github.com/openresty/resty-cli/raw/master/bin/resty
|
||||
chmod +x resty
|
||||
|
||||
export LD_LIBRARY_PATH=$LUAJIT_LIB:$LD_LIBRARY_PATH
|
||||
export PATH=$BASE_PATH/work/nginx/sbin:$PATH
|
||||
|
||||
for f in $(find examples/perf -type f -name "test_*" | sort); do
|
||||
./resty --no-stream -I lib $f
|
||||
echo '================================================================'
|
||||
done
|
||||
|
||||
- name: Run Test
|
||||
run: |
|
||||
export LD_LIBRARY_PATH=$LUAJIT_LIB:$LD_LIBRARY_PATH
|
||||
|
|
@ -242,4 +227,39 @@ jobs:
|
|||
else
|
||||
echo "FIPS tests are skipped"
|
||||
fi
|
||||
|
||||
|
||||
- name: Prepare other libraries
|
||||
if: contains(matrix.extras, 'perf')
|
||||
run: |
|
||||
git clone https://github.com/spacewander/lua-resty-rsa ../lua-resty-rsa
|
||||
|
||||
wget https://luarocks.org/releases/luarocks-3.9.2.tar.gz
|
||||
tar zxf luarocks-*.tar.gz
|
||||
pushd luarocks-*/
|
||||
./configure --with-lua=$LUAJIT_PREFIX \
|
||||
--lua-suffix=jit \
|
||||
--with-lua-include=$LUAJIT_PREFIX/include/luajit-2.1
|
||||
make -j$(nproc) build
|
||||
sudo make install
|
||||
popd
|
||||
|
||||
luarocks install --local lua_pack
|
||||
luarocks install --local openssl OPENSSL_DIR=$OPENSSL_PREFIX
|
||||
luarocks install --local luaossl CRYPTO_DIR=$OPENSSL_PREFIX OPENSSL_DIR=$OPENSSL_PREFIX
|
||||
cp ~/.luarocks/lib/lua/5.1/openssl_*-openssl.so ~/.luarocks/lib/lua/5.1/lua-openssl.so
|
||||
|
||||
- name: Run performance test
|
||||
if: contains(matrix.extras, 'perf')
|
||||
run: |
|
||||
wget https://github.com/openresty/resty-cli/raw/master/bin/resty
|
||||
chmod +x resty
|
||||
|
||||
export LD_LIBRARY_PATH=$LUAJIT_LIB:$LD_LIBRARY_PATH
|
||||
export PATH=$BASE_PATH/work/nginx/sbin:$PATH
|
||||
|
||||
for f in $(find examples/perf -type f -name "test_*" | sort); do
|
||||
./resty --no-stream -I lib -I ../lua-resty-string/lib -I ../lua-resty-rsa/lib -I ~/.luarocks/lib/lua/5.1 $f
|
||||
echo '================================================================'
|
||||
done
|
||||
|
||||
|
||||
|
|
|
|||
29
src/deps/src/lua-resty-openssl/CHANGELOG.md
vendored
29
src/deps/src/lua-resty-openssl/CHANGELOG.md
vendored
|
|
@ -2,6 +2,29 @@
|
|||
## [Unreleased]
|
||||
|
||||
|
||||
<a name="1.2.0"></a>
|
||||
## [1.2.0] - 2023-12-28
|
||||
### bug fixes
|
||||
- **compat:** works better with plain luajit [d23b34a](https://github.com/fffonion/lua-resty-openssl/commit/d23b34ae8b3349342d5f82d90dbfe76696dd2ca4)
|
||||
|
||||
### features
|
||||
- **bn:** add from_mpi, to_mpi and set API [073c943](https://github.com/fffonion/lua-resty-openssl/commit/073c943bf74cce7bd6ce90ee97dfc9b753af3cf2)
|
||||
- **cipher:** add set_buffer_size API [3d0a51c](https://github.com/fffonion/lua-resty-openssl/commit/3d0a51ccab0c2dd46f9eb8088fa2f767eff02a61)
|
||||
- **mac:** add reset API [40fdbbb](https://github.com/fffonion/lua-resty-openssl/commit/40fdbbbddc078c01ea40b8ec8b21257d0e3fefa6)
|
||||
- **openssl:** list functions can now optionally drop provider name [b36ccba](https://github.com/fffonion/lua-resty-openssl/commit/b36ccba3fce9a1b51a0bc8c23d5e9843e99a2052)
|
||||
|
||||
### performance improvements
|
||||
- **cipher:** improve performance on cipher [ba5de3e](https://github.com/fffonion/lua-resty-openssl/commit/ba5de3e53e1b83de5b8f75d64c83eb3e507f386a)
|
||||
- **kdf:** use table.nkeys for params [dac54bf](https://github.com/fffonion/lua-resty-openssl/commit/dac54bf7685d907518e80ab96a594753cdf0c0e1)
|
||||
|
||||
|
||||
<a name="1.1.0"></a>
|
||||
## [1.1.0] - 2023-12-15
|
||||
### features
|
||||
- **err:** standardize error format and add new API to get reason and library name [d155657](https://github.com/fffonion/lua-resty-openssl/commit/d155657e60cdfdb0634d0c3147b184e8543b972e)
|
||||
- **pkey:** support pass in ctrl str options [2e401b3](https://github.com/fffonion/lua-resty-openssl/commit/2e401b335bce759fe8a7a48d5b23cb33a46cc9ba)
|
||||
|
||||
|
||||
<a name="1.0.2"></a>
|
||||
## [1.0.2] - 2023-11-21
|
||||
### bug fixes
|
||||
|
|
@ -459,8 +482,8 @@
|
|||
- **autogen:** generate tests for x509, csr and crl [1392428](https://github.com/fffonion/lua-resty-openssl/commit/1392428352164d2a1a6e0c03075ff65b55aecdee)
|
||||
- **objects:** add helper function for ASN1_OBJECT [d037706](https://github.com/fffonion/lua-resty-openssl/commit/d037706c11d716afe3616bdaf4658afc1763081d)
|
||||
- **pkey:** asymmetric encryption and decryption [6d60451](https://github.com/fffonion/lua-resty-openssl/commit/6d60451157edbf9cefb634f888dfa3e6d9be302f)
|
||||
- **x509:** getter/setters for extensions [243f40d](https://github.com/fffonion/lua-resty-openssl/commit/243f40d35562a516f404188a5c7eb8f5134d9b30)
|
||||
- **x509:** add get_ocsp_url and get_crl_url [6141b6f](https://github.com/fffonion/lua-resty-openssl/commit/6141b6f5aed38706b477a71d8c4383bf55da7eee)
|
||||
- **x509:** getter/setters for extensions [243f40d](https://github.com/fffonion/lua-resty-openssl/commit/243f40d35562a516f404188a5c7eb8f5134d9b30)
|
||||
- **x509.altname:** support iterate and decode over the stack [083a201](https://github.com/fffonion/lua-resty-openssl/commit/083a201746e02d51f6c5c640ad9bf8c6730ebe0b)
|
||||
- **x509.crl:** add crl module [242f8cb](https://github.com/fffonion/lua-resty-openssl/commit/242f8cb45d6c2df5918f26540c92a430d42feb5d)
|
||||
- **x509.csr:** autogen some csr functions as well [9800e36](https://github.com/fffonion/lua-resty-openssl/commit/9800e36c2ff8a299b88f24091cc722940a8652bb)
|
||||
|
|
@ -548,7 +571,9 @@
|
|||
- **x509:** export pubkey [ede4f81](https://github.com/fffonion/lua-resty-openssl/commit/ede4f817cb0fe092ad6f9ab5d6ecdcde864a9fd8)
|
||||
|
||||
|
||||
[Unreleased]: https://github.com/fffonion/lua-resty-openssl/compare/1.0.2...HEAD
|
||||
[Unreleased]: https://github.com/fffonion/lua-resty-openssl/compare/1.2.0...HEAD
|
||||
[1.2.0]: https://github.com/fffonion/lua-resty-openssl/compare/1.1.0...1.2.0
|
||||
[1.1.0]: https://github.com/fffonion/lua-resty-openssl/compare/1.0.2...1.1.0
|
||||
[1.0.2]: https://github.com/fffonion/lua-resty-openssl/compare/1.0.1...1.0.2
|
||||
[1.0.1]: https://github.com/fffonion/lua-resty-openssl/compare/1.0.0...1.0.1
|
||||
[1.0.0]: https://github.com/fffonion/lua-resty-openssl/compare/0.8.26...1.0.0
|
||||
|
|
|
|||
303
src/deps/src/lua-resty-openssl/README.md
vendored
303
src/deps/src/lua-resty-openssl/README.md
vendored
|
|
@ -30,6 +30,11 @@ Table of Contents
|
|||
* [resty.openssl.ctx](#restyopensslctx)
|
||||
+ [ctx.new](#ctxnew)
|
||||
+ [ctx.free](#ctxfree)
|
||||
* [resty.openssl.err](#restyopensslerr)
|
||||
+ [err.format_error](#errformat_error)
|
||||
+ [err.get_last_error_code](#errget_last_error_code)
|
||||
+ [err.get_lib_error_string](#errget_lib_error_string)
|
||||
+ [err.get_reason_error_string](#errget_reason_error_string)
|
||||
* [resty.openssl.version](#restyopensslversion)
|
||||
+ [version_num](#version_num)
|
||||
+ [version_text](#version_text)
|
||||
|
|
@ -69,7 +74,9 @@ Table of Contents
|
|||
+ [bn.new](#bnnew)
|
||||
+ [bn.dup](#bndup)
|
||||
+ [bn.istype](#bnistype)
|
||||
+ [bn:set](#bnset)
|
||||
+ [bn.from_binary, bn:to_binary](#bnfrom_binary-bnto_binary)
|
||||
+ [bn.from_mpi, bn:to_mpi](#bnfrom_mpi-bnto_mpi)
|
||||
+ [bn.from_hex, bn:to_hex](#bnfrom_hex-bnto_hex)
|
||||
+ [bn.from_dec, bn:to_dec](#bnfrom_dec-bnto_dec)
|
||||
+ [bn:to_number](#bnto_number)
|
||||
|
|
@ -84,6 +91,7 @@ Table of Contents
|
|||
* [resty.openssl.cipher](#restyopensslcipher)
|
||||
+ [cipher.new](#ciphernew)
|
||||
+ [cipher.istype](#cipheristype)
|
||||
+ [cipher.set_buffer_size](#cipherset_buffer_size)
|
||||
+ [cipher:get_provider_name](#cipherget_provider_name)
|
||||
+ [cipher:gettable_params, cipher:settable_params, cipher:get_param, cipher:set_params](#ciphergettable_params-ciphersettable_params-cipherget_param-cipherset_params)
|
||||
+ [cipher:encrypt](#cipherencrypt)
|
||||
|
|
@ -116,6 +124,7 @@ Table of Contents
|
|||
+ [mac:gettable_params, mac:settable_params, mac:get_param, mac:set_params](#macgettable_params-macsettable_params-macget_param-macset_params)
|
||||
+ [mac:update](#macupdate)
|
||||
+ [mac:final](#macfinal)
|
||||
+ [mac:reset](#macreset)
|
||||
* [resty.openssl.kdf](#restyopensslkdf)
|
||||
+ [kdf.derive (legacy)](#kdfderive-legacy)
|
||||
+ [kdf.new](#kdfnew)
|
||||
|
|
@ -406,7 +415,7 @@ lua-resty-openssl supports following modes:
|
|||
|
||||
Compile the module per [security policy](https://www.openssl.org/docs/fips/SecurityPolicy-2.0.2.pdf),
|
||||
|
||||
**OpenSSL 3.0.0 fips provider **
|
||||
**OpenSSL 3.0.0 fips provider**
|
||||
|
||||
Refer to https://wiki.openssl.org/index.php/OpenSSL_3.0 Section 7
|
||||
Compile the provider per guide, install the fipsmodule.cnf that
|
||||
|
|
@ -432,12 +441,6 @@ local c = assert(cipher.new("aes256", "fips=yes"))
|
|||
print(c:get_provider_name()) -- prints "fips"
|
||||
```
|
||||
|
||||
**BroingSSL fips-20190808 and fips-20210429 (later haven't been certified)**
|
||||
|
||||
Compile the module per [security policy](https://csrc.nist.gov/CSRC/media/projects/cryptographic-module-validation-program/documents/security-policies/140sp3678.pdf)
|
||||
|
||||
Check if FIPS is acticated by running `assert(openssl.set_fips_mode(true))`.
|
||||
|
||||
[Back to TOC](#table-of-contents)
|
||||
|
||||
### openssl.get_fips_version_text
|
||||
|
|
@ -458,33 +461,37 @@ Sets the default properties for all future EVP algorithm fetches, implicit as we
|
|||
|
||||
### openssl.list_cipher_algorithms
|
||||
|
||||
**syntax**: *ret = openssl.list_cipher_algorithms()*
|
||||
**syntax**: *ret = openssl.list_cipher_algorithms(hide_provider?)*
|
||||
|
||||
Return available cipher algorithms in an array.
|
||||
Return available cipher algorithms in an array. Set `hide_provider` to `true` to
|
||||
hide provider name from the result.
|
||||
|
||||
[Back to TOC](#table-of-contents)
|
||||
|
||||
### openssl.list_digest_algorithms
|
||||
|
||||
**syntax**: *ret = openssl.list_digest_algorithms()*
|
||||
**syntax**: *ret = openssl.list_digest_algorithms(hide_provider?)*
|
||||
|
||||
Return available digest algorithms in an array.
|
||||
Return available digest algorithms in an array. Set `hide_provider` to `true` to
|
||||
hide provider name from the result.
|
||||
|
||||
[Back to TOC](#table-of-contents)
|
||||
|
||||
### openssl.list_mac_algorithms
|
||||
|
||||
**syntax**: *ret = openssl.list_mac_algorithms()*
|
||||
**syntax**: *ret = openssl.list_mac_algorithms(hide_provider?)*
|
||||
|
||||
Return available MAC algorithms in an array.
|
||||
Return available MAC algorithms in an array. Set `hide_provider` to `true` to
|
||||
hide provider name from the result.
|
||||
|
||||
[Back to TOC](#table-of-contents)
|
||||
|
||||
### openssl.list_kdf_algorithms
|
||||
|
||||
**syntax**: *ret = openssl.list_kdf_algorithms()*
|
||||
**syntax**: *ret = openssl.list_kdf_algorithms(hide_provider?)*
|
||||
|
||||
Return available KDF algorithms in an array.
|
||||
Return available KDF algorithms in an array. Set `hide_provider` to `true` to
|
||||
hide provider name from the result.
|
||||
|
||||
[Back to TOC](#table-of-contents)
|
||||
|
||||
|
|
@ -562,6 +569,71 @@ Free the context that was previously created by [ctx.new](#ctxnew).
|
|||
|
||||
[Back to TOC](#table-of-contents)
|
||||
|
||||
## resty.openssl.err
|
||||
|
||||
A module to provide error messages.
|
||||
|
||||
[Back to TOC](#table-of-contents)
|
||||
|
||||
### err.format_error
|
||||
|
||||
**syntax**: *msg = err.format_error(ctx_msg?, return_code?, all_errors?)*
|
||||
|
||||
**syntax**: *msg = err.format_all_errors(ctx_msg?, return_code?)*
|
||||
|
||||
Return the latest error message from the last error code. Errors are formatted as:
|
||||
|
||||
[ctx_msg]: code: [return_code]: error:[error code]:[library name]:[func name]:[reason string]:[file name]:[line number]:
|
||||
|
||||
On OpenSSL prior to 3.x, errors are formatted as:
|
||||
|
||||
[ctx_msg]: code: [return_code]: [file name]:[line number]:error:[error code]:[library name]:[func name]:[reason string]:
|
||||
|
||||
|
||||
If `all_errors` is set to `true`, all errors no just the latest one will be returned in a single string. All errors thrown
|
||||
by this library internally only thrown the latest error.
|
||||
|
||||
For example:
|
||||
|
||||
```lua
|
||||
local f = io.open("t/fixtures/ec_key_encrypted.pem"):read("*a")
|
||||
local privkey, err = require("resty.openssl.pkey").new(f, {
|
||||
format = "PEM",
|
||||
type = "pr",
|
||||
passphrase = "wrongpasswrod",
|
||||
})
|
||||
ngx.say(err)
|
||||
-- pkey.new:load_key: error:4800065:PEM routines:PEM_do_header:bad decrypt:crypto/pem/pem_lib.c:467:
|
||||
```
|
||||
|
||||
[Back to TOC](#table-of-contents)
|
||||
|
||||
### err.get_last_error_code
|
||||
|
||||
**syntax**: *code = err.get_last_error_code()*
|
||||
|
||||
Return the last error code.
|
||||
|
||||
[Back to TOC](#table-of-contents)
|
||||
|
||||
### err.get_lib_error_string
|
||||
|
||||
**syntax**: *lib_error_message = err.get_lib_error_string(code?)*
|
||||
|
||||
Return the library name of the last error code as string. If `code` is set, return the library name
|
||||
corresponding to provided error code instead.
|
||||
|
||||
[Back to TOC](#table-of-contents)
|
||||
|
||||
### err.get_reason_error_string
|
||||
|
||||
**syntax**: *reason_error_message = err.get_reason_error_string(code?)*
|
||||
|
||||
Return the reason of the last error code as string. If `code` is set, return the reason
|
||||
corresponding to provided error code instead.
|
||||
|
||||
[Back to TOC](#table-of-contents)
|
||||
|
||||
## resty.openssl.version
|
||||
|
||||
A module to provide version info.
|
||||
|
|
@ -796,6 +868,8 @@ in provided JSON will decide if a private or public key is loaded.
|
|||
from private key part (the `d` parameter) if it's specified.
|
||||
- Signatures and verification must use `ecdsa_use_raw` option to work with JWS standards
|
||||
for EC keys. See [pkey:sign](#pkeysign) and [pkey.verify](#pkeyverify) for detail.
|
||||
- When running outside of OpenResty, needs to install a JSON library (`cjson` or `dkjson`)
|
||||
and `basexx`.
|
||||
|
||||
#### Key generation
|
||||
|
||||
|
|
@ -842,6 +916,26 @@ local key, err = pkey.new({
|
|||
})
|
||||
```
|
||||
|
||||
It's also possible to pass raw pkeyopt control strings in `config` table as used in the `genpkey` CLI program.
|
||||
See [openssl-genpkey(1)](https://www.openssl.org/docs/man3.0/man1/openssl-genpkey.html) for a list of options.
|
||||
|
||||
For example:
|
||||
|
||||
```lua
|
||||
pkey.new({
|
||||
type = 'RSA',
|
||||
bits = 2048,
|
||||
exp = 65537,
|
||||
})
|
||||
-- is same as
|
||||
pkey.new({
|
||||
type = 'RSA',
|
||||
exp = 65537,
|
||||
"rsa_keygen_bits:4096",
|
||||
})
|
||||
|
||||
```
|
||||
|
||||
|
||||
[Back to TOC](#table-of-contents)
|
||||
|
||||
|
|
@ -893,6 +987,9 @@ local pem, err = pkey.paramgen({
|
|||
})
|
||||
```
|
||||
|
||||
It's also possible to pass raw pkeyopt control strings in `config` table as used in the `genpkey` CLI program.
|
||||
See [openssl-genpkey(1)](https://www.openssl.org/docs/man3.0/man1/openssl-genpkey.html) for a list of options.
|
||||
|
||||
[Back to TOC](#table-of-contents)
|
||||
|
||||
### pkey:get_provider_name
|
||||
|
|
@ -1047,10 +1144,20 @@ to use when signing. When `md_alg` is undefined, for RSA and EC keys, this funct
|
|||
by default. For Ed25519 or Ed448 keys, this function does a PureEdDSA signing,
|
||||
no message digest should be specified and will not be used.
|
||||
|
||||
`opts` is a table that accepts additional parameters.
|
||||
For RSA key, it's also possible to specify `padding` scheme with following choices:
|
||||
|
||||
For RSA key, it's also possible to specify `padding` scheme. The choice of values are same
|
||||
as those in [pkey:encrypt](#pkeyencrypt). When `padding` is `RSA_PKCS1_PSS_PADDING`, it's
|
||||
```lua
|
||||
pkey.PADDINGS = {
|
||||
RSA_PKCS1_PADDING = 1,
|
||||
RSA_SSLV23_PADDING = 2,
|
||||
RSA_NO_PADDING = 3,
|
||||
RSA_PKCS1_OAEP_PADDING = 4,
|
||||
RSA_X931_PADDING = 5, -- sign only
|
||||
RSA_PKCS1_PSS_PADDING = 6, -- sign and verify only
|
||||
}
|
||||
```
|
||||
|
||||
When `padding` is `RSA_PKCS1_PSS_PADDING`, it's
|
||||
possible to specify PSS salt length by setting `opts.pss_saltlen`.
|
||||
|
||||
For EC key, this function does a ECDSA signing.
|
||||
|
|
@ -1062,6 +1169,32 @@ is encoded in ASN.1 DER format. If the `opts` table contains a `ecdsa_use_raw` f
|
|||
a true value, a binary with just the concatenation of binary representation `pr` and `ps` is returned.
|
||||
This is useful for example to send the signature as JWS.
|
||||
|
||||
`opts` is a table that accepts additional parameters with following choices:
|
||||
|
||||
```
|
||||
{
|
||||
pss_saltlen, -- For PSS mode only this option specifies the salt length.
|
||||
mgf1_md, -- For PSS and OAEP padding sets the MGF1 digest. If the MGF1 digest is not explicitly set in PSS mode then the signing digest is used.
|
||||
oaep_md, -- The digest used for the OAEP hash function. If not explicitly set then SHA1 is used.
|
||||
}
|
||||
```
|
||||
|
||||
It's also possible to pass raw pkeyopt control strings as used in the `pkeyutl` CLI program. This lets user pass in options that
|
||||
are not explictly supported as parameters above.
|
||||
See [openssl-pkeyutl(1)](https://www.openssl.org/docs/manmaster/man1/openssl-pkeyutl.html) for a list of options.
|
||||
|
||||
```lua
|
||||
pk:sign(message, nil, pk.PADDINGS.RSA_PKCS1_OAEP_PADDING, {
|
||||
oaep_md = "sha256",
|
||||
})
|
||||
-- is same as
|
||||
pk:sign(message, nil, nil, {
|
||||
"rsa_padding_mode:oaep",
|
||||
"rsa_oaep_md:sha256",
|
||||
})
|
||||
-- in pkeyutl CLI the above is equivalent to: `openssl pkeyutl -sign -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha256
|
||||
```
|
||||
|
||||
[Back to TOC](#table-of-contents)
|
||||
|
||||
### pkey:verify
|
||||
|
|
@ -1084,10 +1217,8 @@ to use when verifying. When `md_alg` is undefined, for RSA and EC keys, this fun
|
|||
by default. For Ed25519 or Ed448 keys, this function does a PureEdDSA verification,
|
||||
no message digest should be specified and will not be used.
|
||||
|
||||
`opts` is a table that accepts additional parameters.
|
||||
|
||||
For RSA key, it's also possible to specify `padding` scheme. The choice of values are same
|
||||
as those in [pkey:encrypt](#pkeyencrypt). When `padding` is `RSA_PKCS1_PSS_PADDING`, it's
|
||||
When key is a RSA key, the function accepts an optional argument `padding` which choices
|
||||
of values are same as those in [pkey:sign](#pkeysign). When `padding` is `RSA_PKCS1_PSS_PADDING`, it's
|
||||
possible to specify PSS salt length by setting `opts.pss_saltlen`.
|
||||
|
||||
For EC key, this function does a ECDSA verification. Normally, the ECDSA signature
|
||||
|
|
@ -1095,6 +1226,10 @@ should be encoded in ASN.1 DER format. If the `opts` table contains a `ecdsa_use
|
|||
a true value, this library treat `signature` as concatenation of binary representation `pr` and `ps`.
|
||||
This is useful for example to verify the signature as JWS.
|
||||
|
||||
`opts` is a table that accepts additional parameters which choices
|
||||
of values are same as those in [pkey:sign](#pkeysign).
|
||||
|
||||
|
||||
```lua
|
||||
-- RSA and EC keys
|
||||
local pk, err = require("resty.openssl.pkey").new()
|
||||
|
|
@ -1130,34 +1265,28 @@ ngx.say(ngx.encode_base64(signature))
|
|||
|
||||
### pkey:encrypt
|
||||
|
||||
**syntax**: *cipher_txt, err = pk:encrypt(txt, padding?)*
|
||||
**syntax**: *cipher_txt, err = pk:encrypt(txt, padding?, opts?)*
|
||||
|
||||
Encrypts plain text `txt` with `pkey` instance, which must loaded a public key.
|
||||
|
||||
When key is a RSA key, the function accepts an optional second argument `padding` which can be:
|
||||
|
||||
```lua
|
||||
pkey.PADDINGS = {
|
||||
RSA_PKCS1_PADDING = 1,
|
||||
RSA_SSLV23_PADDING = 2,
|
||||
RSA_NO_PADDING = 3,
|
||||
RSA_PKCS1_OAEP_PADDING = 4,
|
||||
RSA_X931_PADDING = 5,
|
||||
RSA_PKCS1_PSS_PADDING = 6,
|
||||
}
|
||||
```
|
||||
|
||||
The optional second argument `padding` has same meaning as in [pkey:sign](#pkeysign).
|
||||
If omitted, `padding` is default to `pkey.PADDINGS.RSA_PKCS1_PADDING`.
|
||||
|
||||
The third optional argument `opts` has same meaning as in [pkey:sign](#pkeysign).
|
||||
|
||||
|
||||
[Back to TOC](#table-of-contents)
|
||||
|
||||
### pkey:decrypt
|
||||
|
||||
**syntax**: *txt, err = pk:decrypt(cipher_txt, padding?)*
|
||||
**syntax**: *txt, err = pk:decrypt(cipher_txt, padding?, opts?)*
|
||||
|
||||
Decrypts cipher text `cipher_txt` with pkey instance, which must loaded a private key.
|
||||
|
||||
The optional second argument `padding` has same meaning in [pkey:encrypt](#pkeyencrypt).
|
||||
The optional second argument `padding` has same meaning as in [pkey:sign](#pkeysign).
|
||||
If omitted, `padding` is default to `pkey.PADDINGS.RSA_PKCS1_PADDING`.
|
||||
|
||||
The third optional argument `opts` has same meaning as in [pkey:sign](#pkeysign).
|
||||
|
||||
```lua
|
||||
local pkey = require("resty.openssl.pkey")
|
||||
|
|
@ -1176,11 +1305,14 @@ ngx.say(decrypted)
|
|||
|
||||
### pkey:sign_raw
|
||||
|
||||
**syntax**: *signature, err = pk:sign_raw(txt, padding?)*
|
||||
**syntax**: *signature, err = pk:sign_raw(txt, padding?, opts?)*
|
||||
|
||||
Signs the cipher text `cipher_txt` with pkey instance, which must loaded a private key.
|
||||
|
||||
The optional second argument `padding` has same meaning in [pkey:encrypt](#pkeyencrypt).
|
||||
The optional second argument `padding` has same meaning as in [pkey:sign](#pkeysign).
|
||||
If omitted, `padding` is default to `pkey.PADDINGS.RSA_PKCS1_PADDING`.
|
||||
|
||||
The third optional argument `opts` has same meaning as in [pkey:sign](#pkeysign).
|
||||
|
||||
This function may also be called "private encrypt" in some implementations like NodeJS or PHP.
|
||||
Do note as the function names suggested, this function is not secure to be regarded as an encryption.
|
||||
|
|
@ -1194,12 +1326,15 @@ for an example.
|
|||
|
||||
### pkey:verify_recover
|
||||
|
||||
**syntax**: *txt, err = pk:verify_recover(signature, padding?)*
|
||||
**syntax**: *txt, err = pk:verify_recover(signature, padding?, opts?)*
|
||||
|
||||
Verify the cipher text `signature` with pkey instance, which must loaded a public key, and also
|
||||
returns the original text being signed. This operation is only supported by RSA key.
|
||||
|
||||
The optional second argument `padding` has same meaning in [pkey:encrypt](#pkeyencrypt).
|
||||
The optional second argument `padding` has same meaning as in [pkey:sign](#pkeysign).
|
||||
If omitted, `padding` is default to `pkey.PADDINGS.RSA_PKCS1_PADDING`.
|
||||
|
||||
The third optional argument `opts` has same meaning as in [pkey:sign](#pkeysign).
|
||||
|
||||
This function may also be called "public decrypt" in some implementations like NodeJS or PHP.
|
||||
|
||||
|
|
@ -1255,8 +1390,20 @@ Module to expose BIGNUM structure. Note bignum is a big integer, no float operat
|
|||
|
||||
**syntax**: *b, err = bn.new(number?)*
|
||||
|
||||
Creates a `bn` instance. The first argument can be a Lua number or `nil` to
|
||||
creates an empty instance.
|
||||
**syntax**: *b, err = bn.new(string?, base?)*
|
||||
|
||||
Creates a `bn` instance. The first argument can be:
|
||||
|
||||
- `nil` to creates an empty bn instance.
|
||||
- A Lua number to initialize the bn instance.
|
||||
- A string to initialize the bn instance. The second argument `base` specifies the base of the string,
|
||||
and can take value from (compatible with Ruby OpenSSL.BN API):
|
||||
- `10` or omitted, for decimal string (`"23333"`)
|
||||
- `16`, for hex encoded string (`"5b25"`)
|
||||
- `2`, for binary string (`"\x5b\x25"`)
|
||||
- `0`, for MPI formated string (`"\x00\x00\x00\x02\x5b\x25"`)
|
||||
|
||||
MPI is a format that consists of the number's length in bytes represented as a 4-byte big-endian number, and the number itself in big-endian format, where the most significant bit signals a negative number (the representation of numbers with the MSB set is prefixed with null byte).
|
||||
|
||||
[Back to TOC](#table-of-contents)
|
||||
|
||||
|
|
@ -1276,6 +1423,17 @@ Returns `true` if table is an instance of `bn`. Returns `false` otherwise.
|
|||
|
||||
[Back to TOC](#table-of-contents)
|
||||
|
||||
### bn.set
|
||||
|
||||
**syntax**: *b, err = bn:set(number)*
|
||||
|
||||
**syntax**: *b, err = bn:set(string, base?)*
|
||||
|
||||
Reuse the existing bn instance and reset its value with given number or string.
|
||||
Refer to [bn.new](#bnnew) for the type of arguments supported.
|
||||
|
||||
[Back to TOC](#table-of-contents)
|
||||
|
||||
### bn.from_binary, bn:to_binary
|
||||
|
||||
**syntax**: *bn, err = bn.from_binary(bin)*
|
||||
|
|
@ -1290,10 +1448,32 @@ Exports the BIGNUM value in binary string.
|
|||
used to pad leading zeros to the output to a specific length.
|
||||
|
||||
```lua
|
||||
local b, err = require("resty.openssl.bn").from_binary(ngx.decode_base64("WyU="))
|
||||
local to_hex = require "resty.string".to_hex
|
||||
local b, err = require("resty.openssl.bn").from_binary("\x5b\x25")
|
||||
local bin, err = b:to_binary()
|
||||
ngx.say(ngx.encode_base64(bin))
|
||||
-- outputs "WyU="
|
||||
ngx.say(to_hex(bin))
|
||||
-- outputs "5b25
|
||||
```
|
||||
|
||||
[Back to TOC](#table-of-contents)
|
||||
|
||||
### bn.from_mpi, bn:to_mpi
|
||||
|
||||
**syntax**: *bn, err = bn.from_mpi(bin)*
|
||||
|
||||
**syntax**: *bin, err = bn:to_mpi()*
|
||||
|
||||
Creates a `bn` instance from MPI formatted binary string.
|
||||
|
||||
Exports the BIGNUM value in MPI formatted binary string.
|
||||
|
||||
|
||||
```lua
|
||||
local to_hex = require "resty.string".to_hex
|
||||
local b, err = require("resty.openssl.bn").from_mpi("\x00\x00\x00\x02\x5b\x25")
|
||||
local bin, err = b:to_mpi()
|
||||
ngx.say(to_hex(bin))
|
||||
-- outputs "000000025b25
|
||||
```
|
||||
|
||||
[Back to TOC](#table-of-contents)
|
||||
|
|
@ -1561,6 +1741,20 @@ Returns `true` if table is an instance of `cipher`. Returns `false` otherwise.
|
|||
|
||||
[Back to TOC](#table-of-contents)
|
||||
|
||||
### cipher.set_buffer_size
|
||||
|
||||
**syntax**: *ok = cipher.set_buffer_size(sz)*
|
||||
|
||||
Resize the internal buffer size used by all cipher instance. The default buffer size is 1024 bytes.
|
||||
|
||||
If you are expecting to pass input text larger than 1024 bytes at one time to `update()`, `encrypt()`
|
||||
or `decrypt()`, setting the buffer to larger than the expected input size will improve performance
|
||||
by let more code to be JIT-able.
|
||||
|
||||
Avoid call this function at hotpath, as this re-allocate the buffer every time it's called.
|
||||
|
||||
[Back to TOC](#table-of-contents)
|
||||
|
||||
### cipher:get_provider_name
|
||||
|
||||
**syntax**: *name = cipher:get_provider_name()*
|
||||
|
|
@ -1918,10 +2112,13 @@ Module to interact with message authentication code (EVP_MAC).
|
|||
|
||||
**syntax**: *h, err = mac.new(key, mac, cipher?, digest?, properties?)*
|
||||
|
||||
Creates a mac instance. `mac` is a case-insensitive string of digest algorithm name.
|
||||
Creates a mac instance. `mac` is a case-insensitive string of MAC algorithm name.
|
||||
To view a list of digest algorithms implemented, use
|
||||
[openssl.list_mac_algorithms](#openssllist_mac_algorithms) or
|
||||
`openssl list -mac-algorithms`.
|
||||
|
||||
At least one of `cipher` or `digest` must be specified.
|
||||
|
||||
`cipher` is a case-insensitive string of digest algorithm name.
|
||||
To view a list of digest algorithms implemented, use
|
||||
[openssl.list_cipher_algorithms](#openssllist_cipher_algorithms) or
|
||||
|
|
@ -1988,6 +2185,16 @@ ngx.say(ngx.encode_base64(mac))
|
|||
|
||||
[Back to TOC](#table-of-contents)
|
||||
|
||||
### mac:reset
|
||||
|
||||
**syntax**: *ok, err = mac:reset()*
|
||||
|
||||
Reset the internal state of `mac` instance as it's just created by [mac.new](#macnew).
|
||||
It calls [EVP_MAC_Init](https://www.openssl.org/docs/manmaster/man3/EVP_MAC_init.html) under
|
||||
the hood.
|
||||
|
||||
User must call this before reusing the same `mac` instance.
|
||||
|
||||
## resty.openssl.kdf
|
||||
|
||||
Module to interact with KDF (key derivation function).
|
||||
|
|
|
|||
|
|
@ -64,20 +64,58 @@ local function stat(t)
|
|||
return v, v/#t, max
|
||||
end
|
||||
|
||||
local function test(desc, r, iter)
|
||||
print("RUNNING " .. ITER .. " ITERATIONS FOR " .. desc)
|
||||
local data = table.new(ITER, 0)
|
||||
for i=1, ITER do
|
||||
get_duration()
|
||||
local ok, err = r()
|
||||
data[i] = get_duration()
|
||||
assert(ok, err)
|
||||
local write_seperator = function()
|
||||
print(string.rep("-", 64))
|
||||
end
|
||||
|
||||
local no_count_iter = false
|
||||
|
||||
local run_only = os.getenv("RUN_ONLY")
|
||||
|
||||
local function test(desc, r, iter, expected)
|
||||
if run_only and not string.match(desc, run_only) then
|
||||
print("SKIP " .. desc)
|
||||
return
|
||||
end
|
||||
|
||||
local sum, avg, max = stat(data)
|
||||
print("RUNNING " .. ITER .. " ITERATIONS FOR " .. desc)
|
||||
local sum, avg, max
|
||||
local ok, err
|
||||
|
||||
print(string.format("FINISHED in\t%s (%d op/s)\nAVG\t%s\tMAX\t%s", hmt(sum), 1e9/avg, hmt(avg), hmt(max)))
|
||||
if no_count_iter then
|
||||
get_duration()
|
||||
for i=1, ITER do
|
||||
ok, err = r()
|
||||
end
|
||||
local duration = get_duration()
|
||||
assert(ok, err)
|
||||
sum, avg, max = duration, duration/ITER, 1/0
|
||||
else
|
||||
local data = table.new(ITER, 0)
|
||||
for i=1, ITER do
|
||||
get_duration()
|
||||
ok, err = r()
|
||||
data[i] = get_duration()
|
||||
assert(ok, err)
|
||||
end
|
||||
|
||||
sum, avg, max = stat(data)
|
||||
end
|
||||
|
||||
local bytes = string.match(desc, "(%d+) bytes")
|
||||
if bytes then
|
||||
bytes = tonumber(bytes)
|
||||
bytes = bytes / 1000 * (1e9/avg)
|
||||
else
|
||||
bytes = 1/0
|
||||
end
|
||||
print(string.format("FINISHED in\t%s (%d op/s, %.2fk bytes/s)\nAVG\t%s\tMAX\t%s", hmt(sum), 1e9/avg, bytes, hmt(avg), hmt(max)))
|
||||
print(string.rep("-", 64))
|
||||
|
||||
if expected ~= nil then
|
||||
assert(expected == ok, "expected " .. expected .. "(" .. (#expected or 0) .. " bytes)" ..
|
||||
", but got " .. ok .. "(" .. (#ok or 0) .. " bytes)")
|
||||
end
|
||||
end
|
||||
|
||||
local function set_iteration(i)
|
||||
|
|
@ -85,9 +123,14 @@ local function set_iteration(i)
|
|||
end
|
||||
|
||||
print("LOADING TEST FROM " .. arg[0])
|
||||
print(string.rep("=", 64))
|
||||
|
||||
write_seperator()
|
||||
|
||||
return {
|
||||
test = test,
|
||||
set_iteration = set_iteration,
|
||||
write_seperator = write_seperator,
|
||||
set_no_count_iter = function(s)
|
||||
no_count_iter = s
|
||||
end,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package.path = path .. "/?.lua;" .. package.path
|
|||
|
||||
local test = require "framework".test
|
||||
local set_iteration = require "framework".set_iteration
|
||||
local write_seperator = require "framework".write_seperator
|
||||
local cipher = require "resty.openssl.cipher"
|
||||
local version = require("resty.openssl.version")
|
||||
|
||||
|
|
@ -46,4 +47,6 @@ for _, t in ipairs({"aes-256-cbc", "aes-256-gcm", "chacha20-poly1305"}) do
|
|||
end
|
||||
::continue::
|
||||
end
|
||||
|
||||
write_seperator()
|
||||
end
|
||||
|
|
|
|||
433
src/deps/src/lua-resty-openssl/examples/perf/test_other_libs.lua
vendored
Normal file
433
src/deps/src/lua-resty-openssl/examples/perf/test_other_libs.lua
vendored
Normal file
|
|
@ -0,0 +1,433 @@
|
|||
local path = debug.getinfo(1, "S").source:sub(2):match("(.*/)")
|
||||
package.path = path .. "/?.lua;" .. package.path
|
||||
|
||||
local test = require "framework".test
|
||||
local set_iteration = require "framework".set_iteration
|
||||
local write_seperator = require "framework".write_seperator
|
||||
local cipher = require "resty.openssl.cipher"
|
||||
local digest = require "resty.openssl.digest"
|
||||
local hmac = require "resty.openssl.hmac"
|
||||
local pkey = require "resty.openssl.pkey"
|
||||
local version = require "resty.openssl.version"
|
||||
local rand = require "resty.openssl.rand"
|
||||
local kdf = require "resty.openssl.kdf"
|
||||
local aes = require "resty.aes"
|
||||
local resty_rsa = require "resty.rsa"
|
||||
local to_hex = require "resty.string".to_hex
|
||||
|
||||
-- ensure best performance
|
||||
require "framework".set_no_count_iter(true)
|
||||
|
||||
local luaossl
|
||||
do
|
||||
local pok, perr, err = pcall(require, "_openssl")
|
||||
if pok then
|
||||
luaossl = perr
|
||||
end
|
||||
end
|
||||
|
||||
local lua_openssl
|
||||
do
|
||||
-- move openssl.so to lua-openssl.so to avoid conflict with luaossl
|
||||
local pok, perr, err = pcall(require, "lua-openssl")
|
||||
if pok then
|
||||
lua_openssl = perr
|
||||
end
|
||||
end
|
||||
|
||||
local lua_pack
|
||||
do
|
||||
local pok, perr, err = pcall(require, "lua_pack")
|
||||
if pok then
|
||||
lua_pack = perr
|
||||
end
|
||||
end
|
||||
|
||||
local v = require "jit.dump"
|
||||
v.on(nil, "/tmp/a.out")
|
||||
|
||||
------------- bn
|
||||
do
|
||||
set_iteration(1000000)
|
||||
|
||||
local binary_input = rand.bytes(24)
|
||||
local bn = require "resty.openssl.bn"
|
||||
local hex_input = assert(bn.from_binary(binary_input)):to_hex()
|
||||
|
||||
test("lua-resty-openssl bn unpack parse binary", function()
|
||||
return bn.new(hex_input, 16)
|
||||
end)
|
||||
|
||||
local bni = bn.new()
|
||||
test("lua-resty-openssl bn unpack parse binary reused struct", function()
|
||||
return bni:set(hex_input, 16)
|
||||
end)
|
||||
|
||||
if luaossl then
|
||||
local luaossl_bn = require "_openssl.bignum"
|
||||
local hex_input = "0X" .. hex_input
|
||||
|
||||
test("luaossl bn unpack parse binary", function()
|
||||
return luaossl_bn.new(hex_input)
|
||||
end)
|
||||
end
|
||||
|
||||
if lua_openssl then
|
||||
local hex_input = "X" .. hex_input
|
||||
test("lua-openssl bn unpack parse binary", function()
|
||||
return lua_openssl.bn.number(hex_input)
|
||||
end)
|
||||
end
|
||||
|
||||
if lua_pack then
|
||||
test("lua_pack bn unpack 6 int", function()
|
||||
return lua_pack.unpack(binary_input, ">6I")
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
------------- cipher
|
||||
do
|
||||
write_seperator()
|
||||
|
||||
local key = rand.bytes(32)
|
||||
local iv = rand.bytes(16)
|
||||
local data = string.rep("1", 4096)
|
||||
|
||||
set_iteration(100000)
|
||||
|
||||
for _, t in ipairs({"aes-256-cbc", "aes-256-gcm"}) do
|
||||
for _, op in ipairs({"encrypt", "decrypt"}) do
|
||||
|
||||
local c = assert(cipher.new(t))
|
||||
cipher.set_buffer_size(#data + 64) -- add room for decrypt
|
||||
|
||||
local _iv = iv
|
||||
if t == "aes-256-gcm" then
|
||||
_iv = string.rep("0", 12)
|
||||
end
|
||||
|
||||
local aes_default
|
||||
if t == "aes-256-cbc" then
|
||||
aes_default = aes:new(key, nil, aes.cipher(256, "cbc"), {iv = _iv})
|
||||
else
|
||||
aes_default = aes:new(key, nil, aes.cipher(256, "gcm"), {iv = _iv})
|
||||
end
|
||||
|
||||
local luaossl_aes
|
||||
if luaossl then
|
||||
local luaossl_cipher = require "_openssl.cipher"
|
||||
luaossl_aes = luaossl_cipher.new(t)
|
||||
end
|
||||
|
||||
local ciphertext = assert(c:encrypt(key, _iv, data, false))
|
||||
|
||||
if op == "encrypt" then
|
||||
-- assert(c:init(key, _iv, {is_encrypt = true }))
|
||||
-- assert(c:encrypt(key, _iv, data, false))
|
||||
test("lua-resty-openssl encrypt with " .. t .. " on " .. #data .. " bytes", function()
|
||||
return c:encrypt(key, _iv, data, false)
|
||||
-- return c:final(data)
|
||||
end, nil, ciphertext)
|
||||
|
||||
test("lua-resty-strings encrypt with " .. t .. " on " .. #data .. " bytes", function()
|
||||
local r = aes_default:encrypt(data)
|
||||
if t == "aes-256-gcm" then
|
||||
return r[1]
|
||||
end
|
||||
return r
|
||||
end, nil, ciphertext)
|
||||
|
||||
if luaossl then
|
||||
test("luaossl encrypt with " .. t .. " on " .. #data .. " bytes", function()
|
||||
return luaossl_aes:encrypt(key, _iv):final(data)
|
||||
end, nil, ciphertext)
|
||||
end
|
||||
|
||||
if lua_openssl then
|
||||
local evp_cipher = lua_openssl.cipher.get(t)
|
||||
test("lua_openssl encrypt with " .. t .. " on " .. #data .. " bytes", function()
|
||||
return evp_cipher:encrypt(data, key, _iv)
|
||||
end, nil, ciphertext)
|
||||
end
|
||||
|
||||
|
||||
else
|
||||
|
||||
local tag
|
||||
if t == "aes-256-gcm" then
|
||||
tag = assert(c:get_aead_tag())
|
||||
end
|
||||
-- assert(c:init(key, _iv))
|
||||
test("lua-resty-openssl decrypt with " .. t .. " on " .. #ciphertext .. " bytes", function()
|
||||
-- if tag then
|
||||
-- c:set_aead_tag(tag)
|
||||
--end
|
||||
--return c:final(ciphertext)
|
||||
return c:decrypt(key, _iv, ciphertext, false, nil, tag)
|
||||
end, nil, data)
|
||||
|
||||
|
||||
test("lua-resty-strings decrypt with " .. t .. " on " .. #ciphertext .. " bytes", function()
|
||||
return aes_default:decrypt(ciphertext, tag)
|
||||
end, nil, data)
|
||||
|
||||
if luaossl then
|
||||
--local luaossl_cipher = require "openssl.cipher"
|
||||
--local luaossl_aes2 = luaossl_cipher.new(t)
|
||||
|
||||
test("luaossl decrypt with " .. t .. " on " .. #ciphertext .. " bytes", function()
|
||||
luaossl_aes:decrypt(key, _iv)
|
||||
if t == "aes-256-gcm" then
|
||||
luaossl_aes:setTag(tag)
|
||||
end
|
||||
return luaossl_aes:final(ciphertext)
|
||||
end, nil, data)
|
||||
end
|
||||
|
||||
|
||||
if lua_openssl then
|
||||
local evp = lua_openssl.cipher.get(t)
|
||||
|
||||
local d = evp:decrypt_new(key, _iv)
|
||||
test("lua_openssl decrypt with " .. t .. " on " .. #ciphertext .. " bytes", function()
|
||||
d:ctrl(lua_openssl.cipher.EVP_CTRL_GCM_SET_IVLEN, #_iv)
|
||||
d:init(key, _iv)
|
||||
d:padding(false)
|
||||
|
||||
local r = d:update(ciphertext)
|
||||
if t == "aes-256-gcm" then
|
||||
assert(d:ctrl(lua_openssl.cipher.EVP_CTRL_GCM_SET_TAG, tag))
|
||||
end
|
||||
return r .. d:final()
|
||||
end) -- has extra padding: , nil, data)
|
||||
end
|
||||
end
|
||||
::continue::
|
||||
end
|
||||
|
||||
write_seperator()
|
||||
end
|
||||
end
|
||||
|
||||
------------- digest
|
||||
do
|
||||
write_seperator()
|
||||
|
||||
local data = string.rep("1", 4096)
|
||||
|
||||
for _, t in ipairs({"sha256", "md5"}) do
|
||||
|
||||
local d = digest.new(t)
|
||||
|
||||
local expected = d:final(data)
|
||||
|
||||
test("lua-resty-openssl " .. t .. " on " .. #data .. " bytes", function()
|
||||
d:reset()
|
||||
return d:final(data)
|
||||
end, nil, expected)
|
||||
|
||||
local h = require ("resty." .. t)
|
||||
local hh = h:new()
|
||||
|
||||
test("lua-resty-strings " .. t .. " on " .. #data .. " bytes", function()
|
||||
hh:reset()
|
||||
hh:update(data)
|
||||
return hh:final()
|
||||
end, nil, expected)
|
||||
|
||||
if luaossl then
|
||||
local _digest = require "_openssl.digest"
|
||||
test("luaossl " .. t .. " on " .. #data .. " bytes", function()
|
||||
local hh = _digest.new(t)
|
||||
return hh:final(data)
|
||||
end, nil, expected)
|
||||
end
|
||||
|
||||
if lua_openssl then
|
||||
local hh = lua_openssl.digest.get(t)
|
||||
test("lua_openssl " .. t .. " on " .. #data .. " bytes", function()
|
||||
return hh:digest(data)
|
||||
end, nil, expected)
|
||||
end
|
||||
|
||||
if t == "md5" then
|
||||
test("ngx.md5_bin on " .. #data .. " bytes", function()
|
||||
return ngx.md5_bin(data)
|
||||
end, nil, expected)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
------------- hmac
|
||||
do
|
||||
write_seperator()
|
||||
|
||||
local data = string.rep("1", 4096)
|
||||
local key = rand.bytes(32)
|
||||
|
||||
local d = hmac.new(key, "sha256")
|
||||
|
||||
local expected = d:final(data)
|
||||
|
||||
test("lua-resty-openssl hmac sha256 on " .. #data .. " bytes", function()
|
||||
d:reset()
|
||||
return d:final(data)
|
||||
end, nil, expected)
|
||||
|
||||
if version.OPENSSL_3X then
|
||||
local mac = require "resty.openssl.mac"
|
||||
local m = mac.new(key, "HMAC", nil, "sha256")
|
||||
test("lua-resty-openssl hmac sha256 new API on " .. #data .. " bytes", function()
|
||||
m:reset()
|
||||
return m:final(data)
|
||||
end, nil, expected)
|
||||
end
|
||||
|
||||
if luaossl then
|
||||
local _hmac = require "_openssl.hmac"
|
||||
test("luaossl hmac sha256 " .. #data .. " bytes", function()
|
||||
local hh = _hmac.new(key, "sha256")
|
||||
return hh:final(data)
|
||||
end, nil, expected)
|
||||
end
|
||||
|
||||
if lua_openssl then
|
||||
local hh = lua_openssl.hmac
|
||||
test("lua_openssl hmac sha256 on " .. #data .. " bytes", function()
|
||||
return hh.hmac("sha256", data, key)
|
||||
end, nil, to_hex(expected))
|
||||
|
||||
if version.OPENSSL_3X then
|
||||
local mm = lua_openssl.mac
|
||||
test("lua_openssl hmac sha256 new API on " .. #data .. " bytes", function()
|
||||
return mm.mac("sha256", data, key)
|
||||
end, nil, to_hex(expected))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
------------- pkey
|
||||
do
|
||||
write_seperator()
|
||||
|
||||
local key = pkey.new({ type = "RSA", bits = 4096 })
|
||||
local data = string.rep("1", 200)
|
||||
local rsa_encrypted = assert(key:encrypt(data, pkey.PADDINGS.RSA_PKCS1_PADDING))
|
||||
|
||||
set_iteration(1000)
|
||||
|
||||
for _, op in ipairs({"encrypt", "decrypt"}) do
|
||||
local _data = data
|
||||
if op == "decrypt" then
|
||||
_data = rsa_encrypted
|
||||
end
|
||||
|
||||
local f = key[op]
|
||||
test("lua-resty-openssl RSA " .. op .. " on " .. #data .. " bytes", function()
|
||||
return f(key, _data)
|
||||
end)
|
||||
|
||||
if not version.OPENSSL_3X then
|
||||
local pub = resty_rsa:new({ public_key = key:to_PEM("public"), padding = resty_rsa.PADDING.RSA_PKCS1_PADDING })
|
||||
local priv = resty_rsa:new({ private_key = key:to_PEM("private"), padding = resty_rsa.PADDING.RSA_PKCS1_PADDING })
|
||||
|
||||
local _key = pub
|
||||
if op == "decrypt" then
|
||||
_key = priv
|
||||
end
|
||||
|
||||
local f = _key[op]
|
||||
test("lua-resty-rsa RSA " .. op .." on " .. #data .. " bytes", function()
|
||||
return f(_key, _data)
|
||||
end)
|
||||
end
|
||||
|
||||
if luaossl then
|
||||
local _key = require "_openssl.pkey".new(key:to_PEM("private"))
|
||||
local f = _key[op]
|
||||
test("luaossl RSA " .. op .." on " .. #data .. " bytes", function()
|
||||
return f(_key, _data)
|
||||
end)
|
||||
end
|
||||
|
||||
|
||||
if lua_openssl then
|
||||
local _key = lua_openssl.pkey.read(key:to_PEM("private"), true)
|
||||
local f = _key[op]
|
||||
test("lua_openssl RSA " .. op .." on " .. #data .. " bytes", function()
|
||||
return f(_key, _data)
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
------------- kdf
|
||||
do
|
||||
write_seperator()
|
||||
|
||||
local kdf_out_size = 64
|
||||
local kdf_pass = "1234567"
|
||||
local kdf_md = "md5"
|
||||
local kdf_salt = rand.bytes(16)
|
||||
|
||||
set_iteration(500)
|
||||
|
||||
local kdf_opts = {
|
||||
type = kdf.PBKDF2,
|
||||
outlen = kdf_out_size,
|
||||
pass = kdf_pass,
|
||||
md = kdf_md,
|
||||
salt = kdf_salt,
|
||||
pbkdf2_iter = 1000,
|
||||
}
|
||||
local expected = assert(kdf.derive(kdf_opts))
|
||||
|
||||
test("lua-resty-openssl kdf pbkdf2 outputs " .. kdf_out_size .. " bytes", function()
|
||||
return kdf.derive(kdf_opts)
|
||||
end)
|
||||
|
||||
if version.OPENSSL_3X then
|
||||
local kdfi = kdf.new("pbkdf2")
|
||||
kdf_opts = {
|
||||
pass = kdf_pass,
|
||||
iter = 1000,
|
||||
digest = kdf_md,
|
||||
salt = kdf_salt,
|
||||
}
|
||||
test("lua-resty-openssl kdf new API pbkdf2 outputs " .. kdf_out_size .. " bytes", function()
|
||||
return kdfi:derive(kdf_out_size, kdf_opts)
|
||||
end, nil, expected)
|
||||
end
|
||||
|
||||
if luaossl then
|
||||
local _kdf = require "_openssl.kdf"
|
||||
local kdf_opts = {
|
||||
type = "PBKDF2",
|
||||
outlen = kdf_out_size,
|
||||
pass = kdf_pass,
|
||||
md = kdf_md,
|
||||
salt = kdf_salt,
|
||||
iter = 1000,
|
||||
}
|
||||
test("luaossl kdf pbkf2 outputs " .. kdf_out_size .. " bytes", function()
|
||||
return _kdf.derive(kdf_opts)
|
||||
end, nil, expected)
|
||||
end
|
||||
|
||||
|
||||
if lua_openssl and version.OPENSSL_3X then
|
||||
local _kdf = lua_openssl.kdf.fetch('PBKDF2')
|
||||
local kdf_opts = {
|
||||
{ name = "pass", data = kdf_pass },
|
||||
{ name = "iter", data = 1000 },
|
||||
{ name = "digest", data = kdf_md },
|
||||
{ name = "salt", data = kdf_salt },
|
||||
}
|
||||
test("lua_openssl kdf pbkf2 outputs " .. kdf_out_size .. " bytes", function()
|
||||
return _kdf:derive(kdf_opts, kdf_out_size)
|
||||
end, nil, expected)
|
||||
end
|
||||
end
|
||||
|
|
@ -3,6 +3,7 @@ package.path = path .. "/?.lua;" .. package.path
|
|||
|
||||
local test = require "framework".test
|
||||
local set_iteration = require "framework".set_iteration
|
||||
local write_seperator = require "framework".write_seperator
|
||||
local pkey = require "resty.openssl.pkey"
|
||||
local version = require("resty.openssl.version")
|
||||
local data = string.rep("=", 200)
|
||||
|
|
@ -26,6 +27,7 @@ for _, op in ipairs({"encrypt", "decrypt"}) do
|
|||
end
|
||||
end
|
||||
|
||||
write_seperator()
|
||||
|
||||
for _, t in ipairs({"RSA", "EC", "Ed25519", "Ed448"}) do
|
||||
for _, op in ipairs({"sign", "verify"}) do
|
||||
|
|
@ -61,4 +63,6 @@ for _, t in ipairs({"RSA", "EC", "Ed25519", "Ed448"}) do
|
|||
end
|
||||
::continue::
|
||||
end
|
||||
|
||||
write_seperator()
|
||||
end
|
||||
|
|
|
|||
|
|
@ -2,11 +2,12 @@ local path = debug.getinfo(1, "S").source:sub(2):match("(.*/)")
|
|||
package.path = path .. "/?.lua;" .. package.path
|
||||
|
||||
local test = require "framework".test
|
||||
local write_seperator = require "framework".write_seperator
|
||||
local pkey = require "resty.openssl.pkey"
|
||||
local example_pkey = assert(pkey.new())
|
||||
|
||||
for _, op in ipairs({"load", "export"}) do
|
||||
for _, t in ipairs({"PEM", "DER", "JWK"}) do
|
||||
for _, t in ipairs({"PEM", "DER", "JWK"}) do
|
||||
for _, op in ipairs({"load", "export"}) do
|
||||
for _, p in ipairs({"public", "private"}) do
|
||||
|
||||
if op == "load" then
|
||||
|
|
@ -30,4 +31,6 @@ for _, op in ipairs({"load", "export"}) do
|
|||
|
||||
end
|
||||
end
|
||||
|
||||
write_seperator()
|
||||
end
|
||||
|
|
|
|||
|
|
@ -2,12 +2,13 @@ local path = debug.getinfo(1, "S").source:sub(2):match("(.*/)")
|
|||
package.path = path .. "/?.lua;" .. package.path
|
||||
|
||||
local test = require "framework".test
|
||||
local write_seperator = require "framework".write_seperator
|
||||
local x509 = require "resty.openssl.x509"
|
||||
local cert = assert(io.open(path .. "../../t/fixtures/Github.pem")):read("*a")
|
||||
local example_x509 = assert(x509.new(cert))
|
||||
|
||||
for _, op in ipairs({"load", "export"}) do
|
||||
for _, t in ipairs({"PEM", "DER"}) do
|
||||
for _, t in ipairs({"PEM", "DER"}) do
|
||||
for _, op in ipairs({"load", "export"}) do
|
||||
if op == "load" then
|
||||
local txt = assert(example_x509:tostring(t))
|
||||
test("load " .. t .. " x509", function()
|
||||
|
|
@ -20,4 +21,6 @@ for _, op in ipairs({"load", "export"}) do
|
|||
end)
|
||||
end
|
||||
end
|
||||
|
||||
write_seperator()
|
||||
end
|
||||
|
|
|
|||
|
|
@ -24,31 +24,9 @@ try_require_modules()
|
|||
|
||||
|
||||
local _M = {
|
||||
_VERSION = '1.0.2',
|
||||
_VERSION = '1.2.0',
|
||||
}
|
||||
|
||||
local libcrypto_name
|
||||
local lib_patterns = {
|
||||
"%s", "%s.so.3", "%s.so.1.1", "%s.so.1.0"
|
||||
}
|
||||
|
||||
function _M.load_library()
|
||||
for _, pattern in ipairs(lib_patterns) do
|
||||
-- true: load to global namespae
|
||||
local pok, _ = pcall(ffi.load, string.format(pattern, "crypto"), true)
|
||||
if pok then
|
||||
libcrypto_name = string.format(pattern, "crypto")
|
||||
ffi.load(string.format(pattern, "ssl"), true)
|
||||
|
||||
try_require_modules()
|
||||
|
||||
return libcrypto_name
|
||||
end
|
||||
end
|
||||
|
||||
return false, "unable to load crypto library"
|
||||
end
|
||||
|
||||
function _M.load_modules()
|
||||
_M.bn = require("resty.openssl.bn")
|
||||
_M.cipher = require("resty.openssl.cipher")
|
||||
|
|
@ -348,7 +326,7 @@ local function list_legacy(typ, get_nid_cf)
|
|||
return ret
|
||||
end
|
||||
|
||||
local function list_provided(typ)
|
||||
local function list_provided(typ, hide_provider)
|
||||
local typ_lower = string.lower(typ:sub(5)) -- cut off EVP_
|
||||
local typ_ptr = typ .. "*"
|
||||
require ("resty.openssl.include.evp." .. typ_lower)
|
||||
|
|
@ -360,9 +338,13 @@ local function list_provided(typ)
|
|||
function(elem, _)
|
||||
elem = ffi_cast(typ_ptr, elem)
|
||||
local name = ffi_str(C[typ .. "_get0_name"](elem))
|
||||
-- alternate names are ignored, retrieve use TYPE_names_do_all
|
||||
local prov = ffi_str(C.OSSL_PROVIDER_get0_name(C[typ .. "_get0_provider"](elem)))
|
||||
table.insert(ret, name .. " @ " .. prov)
|
||||
if hide_provider then
|
||||
table.insert(ret, name)
|
||||
else
|
||||
-- alternate names are ignored, retrieve use TYPE_names_do_all
|
||||
local prov = ffi_str(C.OSSL_PROVIDER_get0_name(C[typ .. "_get0_provider"](elem)))
|
||||
table.insert(ret, name .. " @ " .. prov)
|
||||
end
|
||||
end)
|
||||
|
||||
C[typ .. "_do_all_provided"](ctx_lib.get_libctx(), fn, nil)
|
||||
|
|
@ -372,50 +354,40 @@ local function list_provided(typ)
|
|||
return ret
|
||||
end
|
||||
|
||||
function _M.list_cipher_algorithms()
|
||||
function _M.list_cipher_algorithms(hide_provider)
|
||||
require "resty.openssl.include.evp.cipher"
|
||||
local ret = list_legacy("EVP_CIPHER",
|
||||
OPENSSL_3X and C.EVP_CIPHER_get_nid or C.EVP_CIPHER_nid)
|
||||
|
||||
if OPENSSL_3X then
|
||||
local ret_provided = list_provided("EVP_CIPHER")
|
||||
for _, r in ipairs(ret_provided) do
|
||||
table.insert(ret, r)
|
||||
end
|
||||
return list_provided("EVP_CIPHER", hide_provider)
|
||||
else
|
||||
return list_legacy("EVP_CIPHER", C.EVP_CIPHER_nid)
|
||||
end
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
function _M.list_digest_algorithms()
|
||||
function _M.list_digest_algorithms(hide_provider)
|
||||
require "resty.openssl.include.evp.md"
|
||||
local ret = list_legacy("EVP_MD",
|
||||
OPENSSL_3X and C.EVP_MD_get_type or C.EVP_MD_type)
|
||||
|
||||
if OPENSSL_3X then
|
||||
local ret_provided = list_provided("EVP_MD")
|
||||
for _, r in ipairs(ret_provided) do
|
||||
table.insert(ret, r)
|
||||
end
|
||||
return list_provided("EVP_MD", hide_provider)
|
||||
else
|
||||
return list_legacy("EVP_MD", C.EVP_MD_type)
|
||||
end
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
function _M.list_mac_algorithms()
|
||||
function _M.list_mac_algorithms(hide_provider)
|
||||
if not OPENSSL_3X then
|
||||
return nil, "openssl.list_mac_algorithms is only supported from OpenSSL 3.0"
|
||||
end
|
||||
|
||||
return list_provided("EVP_MAC")
|
||||
return list_provided("EVP_MAC", hide_provider)
|
||||
end
|
||||
|
||||
function _M.list_kdf_algorithms()
|
||||
function _M.list_kdf_algorithms(hide_provider)
|
||||
if not OPENSSL_3X then
|
||||
return nil, "openssl.list_kdf_algorithms is only supported from OpenSSL 3.0"
|
||||
end
|
||||
|
||||
return list_provided("EVP_KDF")
|
||||
return list_provided("EVP_KDF", hide_provider)
|
||||
end
|
||||
|
||||
local valid_ssl_protocols = {
|
||||
|
|
|
|||
84
src/deps/src/lua-resty-openssl/lib/resty/openssl/auxiliary/compat.lua
vendored
Normal file
84
src/deps/src/lua-resty-openssl/lib/resty/openssl/auxiliary/compat.lua
vendored
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
local nkeys
|
||||
|
||||
do
|
||||
local pok, perr = pcall(require, "table.nkeys")
|
||||
if pok then
|
||||
nkeys = perr
|
||||
else
|
||||
nkeys = function(tbl)
|
||||
local cnt = 0
|
||||
for _ in pairs(tbl) do
|
||||
cnt = cnt + 1
|
||||
end
|
||||
return cnt
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local noop = function() end
|
||||
|
||||
local log_warn, log_debug
|
||||
local encode_base64url, decode_base64url
|
||||
|
||||
if ngx then
|
||||
log_warn = function(...)
|
||||
ngx.log(ngx.WARN, ...)
|
||||
end
|
||||
|
||||
log_debug = function(...)
|
||||
ngx.log(ngx.DEBUG, ...)
|
||||
end
|
||||
|
||||
local b64 = require("ngx.base64")
|
||||
encode_base64url = b64.encode_base64url
|
||||
decode_base64url = b64.decode_base64url
|
||||
|
||||
else
|
||||
log_warn = noop
|
||||
log_debug = noop
|
||||
|
||||
local pok, basexx = pcall(require, "basexx")
|
||||
if pok then
|
||||
encode_base64url = basexx.to_url64
|
||||
decode_base64url = basexx.from_url64
|
||||
else
|
||||
encode_base64url = function()
|
||||
error("no base64 library is found, needs either ngx.base64 or basexx")
|
||||
end
|
||||
decode_base64url = encode_base64url
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
local json
|
||||
do
|
||||
local pok, perr = pcall(require, "cjson.safe")
|
||||
if pok then
|
||||
json = perr
|
||||
else
|
||||
local pok, perr = pcall(require, "dkjson")
|
||||
if pok then
|
||||
json = perr
|
||||
end
|
||||
end
|
||||
|
||||
if not json then
|
||||
json = setmetatable({}, {
|
||||
__index = function()
|
||||
return function()
|
||||
error("no JSON library is found, needs either cjson or dkjson")
|
||||
end
|
||||
end,
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
return {
|
||||
nkeys = nkeys,
|
||||
log_warn = log_warn,
|
||||
log_debug = log_debug,
|
||||
encode_base64url = encode_base64url,
|
||||
decode_base64url = decode_base64url,
|
||||
json = json,
|
||||
}
|
||||
|
|
@ -2,8 +2,6 @@
|
|||
local ffi = require "ffi"
|
||||
local C = ffi.C
|
||||
|
||||
local cjson = require("cjson.safe")
|
||||
local b64 = require("ngx.base64")
|
||||
|
||||
local evp_macro = require "resty.openssl.include.evp"
|
||||
local rsa_lib = require "resty.openssl.rsa"
|
||||
|
|
@ -11,6 +9,9 @@ local ec_lib = require "resty.openssl.ec"
|
|||
local ecx_lib = require "resty.openssl.ecx"
|
||||
local bn_lib = require "resty.openssl.bn"
|
||||
local digest_lib = require "resty.openssl.digest"
|
||||
local encode_base64url = require "resty.openssl.auxiliary.compat".encode_base64url
|
||||
local decode_base64url = require "resty.openssl.auxiliary.compat".decode_base64url
|
||||
local json = require "resty.openssl.auxiliary.compat".json
|
||||
|
||||
local _M = {}
|
||||
|
||||
|
|
@ -27,7 +28,7 @@ local function load_jwk_rsa(tbl)
|
|||
for i, k in ipairs(rsa_jwk_params) do
|
||||
local v = tbl[k]
|
||||
if v then
|
||||
v = b64.decode_base64url(v)
|
||||
v = decode_base64url(v)
|
||||
if not v then
|
||||
return nil, "cannot decode parameter \"" .. k .. "\" from base64 " .. tbl[k]
|
||||
end
|
||||
|
|
@ -86,7 +87,7 @@ local function load_jwk_ec(tbl)
|
|||
for _, k in ipairs(ec_jwk_params) do
|
||||
local v = tbl[k]
|
||||
if v then
|
||||
v = b64.decode_base64url(v)
|
||||
v = decode_base64url(v)
|
||||
if not v then
|
||||
return nil, "cannot decode parameter \"" .. k .. "\" from base64 " .. tbl[k]
|
||||
end
|
||||
|
|
@ -122,9 +123,9 @@ end
|
|||
local function load_jwk_okp(key_type, tbl)
|
||||
local params = {}
|
||||
if tbl["d"] then
|
||||
params.private = b64.decode_base64url(tbl["d"])
|
||||
params.private = decode_base64url(tbl["d"])
|
||||
elseif tbl["x"] then
|
||||
params.public = b64.decode_base64url(tbl["x"])
|
||||
params.public = decode_base64url(tbl["x"])
|
||||
else
|
||||
return nil, "at least \"x\" or \"d\" parameter is required"
|
||||
end
|
||||
|
|
@ -141,7 +142,7 @@ for k, v in pairs(evp_macro.ecx_curves) do
|
|||
end
|
||||
|
||||
function _M.load_jwk(txt)
|
||||
local tbl, err = cjson.decode(txt)
|
||||
local tbl, err = json.decode(txt)
|
||||
if err then
|
||||
return nil, "error decoding JSON from JWK: " .. err
|
||||
elseif type(tbl) ~= "table" then
|
||||
|
|
@ -220,7 +221,7 @@ function _M.dump_jwk(pkey, is_priv)
|
|||
}
|
||||
for i, p in ipairs(param_keys) do
|
||||
local v = params[rsa_openssl_params[i]]:to_binary()
|
||||
jwk[p] = b64.encode_base64url(v)
|
||||
jwk[p] = encode_base64url(v)
|
||||
end
|
||||
elseif pkey.key_type == evp_macro.EVP_PKEY_EC then
|
||||
local params, err = pkey:get_parameters()
|
||||
|
|
@ -230,11 +231,11 @@ function _M.dump_jwk(pkey, is_priv)
|
|||
jwk = {
|
||||
kty = "EC",
|
||||
crv = ec_curves_reverse[params.group],
|
||||
x = b64.encode_base64url(params.x:to_binary()),
|
||||
y = b64.encode_base64url(params.y:to_binary()),
|
||||
x = encode_base64url(params.x:to_binary()),
|
||||
y = encode_base64url(params.y:to_binary()),
|
||||
}
|
||||
if is_priv then
|
||||
jwk.d = b64.encode_base64url(params.private:to_binary())
|
||||
jwk.d = encode_base64url(params.private:to_binary())
|
||||
end
|
||||
elseif ecx_curves_reverse[pkey.key_type] then
|
||||
local params, err = pkey:get_parameters()
|
||||
|
|
@ -244,8 +245,8 @@ function _M.dump_jwk(pkey, is_priv)
|
|||
jwk = {
|
||||
kty = "OKP",
|
||||
crv = ecx_curves_reverse[pkey.key_type],
|
||||
d = b64.encode_base64url(params.private),
|
||||
x = b64.encode_base64url(params.public),
|
||||
d = encode_base64url(params.private),
|
||||
x = encode_base64url(params.public),
|
||||
}
|
||||
else
|
||||
return nil, "jwk.dump_jwk: not implemented for this key type"
|
||||
|
|
@ -257,9 +258,9 @@ function _M.dump_jwk(pkey, is_priv)
|
|||
if err then
|
||||
return nil, "jwk.dump_jwk: failed to calculate digest for key"
|
||||
end
|
||||
jwk.kid = b64.encode_base64url(d)
|
||||
jwk.kid = encode_base64url(d)
|
||||
|
||||
return cjson.encode(jwk)
|
||||
return json.encode(jwk)
|
||||
end
|
||||
|
||||
return _M
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ require "resty.openssl.include.bn"
|
|||
local crypto_macro = require("resty.openssl.include.crypto")
|
||||
local ctypes = require "resty.openssl.auxiliary.ctypes"
|
||||
local format_error = require("resty.openssl.err").format_error
|
||||
local OPENSSL_3X = require("resty.openssl.version").OPENSSL_3X
|
||||
|
||||
local _M = {}
|
||||
local mt = {__index = _M}
|
||||
|
|
@ -17,16 +16,73 @@ local mt = {__index = _M}
|
|||
local bn_ptr_ct = ffi.typeof('BIGNUM*')
|
||||
local bn_ptrptr_ct = ffi.typeof('BIGNUM*[1]')
|
||||
|
||||
function _M.new(bn)
|
||||
local function set_binary(ctx, s)
|
||||
local ctx = C.BN_bin2bn(s, #s, ctx)
|
||||
if ctx == nil then
|
||||
return nil, format_error("set_binary")
|
||||
end
|
||||
return ctx
|
||||
end
|
||||
|
||||
local function set_mpi(ctx, s)
|
||||
local ctx = C.BN_mpi2bn(s, #s, ctx)
|
||||
if ctx == nil then
|
||||
return nil, format_error("set_mpi")
|
||||
end
|
||||
return ctx
|
||||
end
|
||||
|
||||
local function set_hex(ctx, s)
|
||||
local p = ffi_new(bn_ptrptr_ct)
|
||||
p[0] = ctx
|
||||
|
||||
if C.BN_hex2bn(p, s) == 0 then
|
||||
return nil, format_error("set_hex")
|
||||
end
|
||||
return p[0]
|
||||
end
|
||||
|
||||
local function set_dec(ctx, s)
|
||||
local p = ffi_new(bn_ptrptr_ct)
|
||||
p[0] = ctx
|
||||
|
||||
if C.BN_dec2bn(p, s) == 0 then
|
||||
return nil, format_error("set_dec")
|
||||
end
|
||||
return p[0]
|
||||
end
|
||||
|
||||
local function set_bn(ctx, s, base)
|
||||
if type(s) == 'number' then
|
||||
if C.BN_set_word(ctx, s) ~= 1 then
|
||||
return nil, format_error("set_bn")
|
||||
end
|
||||
elseif type(s) == 'string' then
|
||||
if not base or base == 10 then
|
||||
return set_dec(ctx, s)
|
||||
elseif base == 16 then
|
||||
return set_hex(ctx, s)
|
||||
elseif base == 2 then
|
||||
return set_binary(ctx, s)
|
||||
elseif base == 0 then
|
||||
ctx = set_mpi(ctx, s)
|
||||
else
|
||||
return nil, "set_bn: unsupported base: " .. base
|
||||
end
|
||||
elseif s then
|
||||
return nil, "set_bn: expect nil, a number or a string at #1"
|
||||
end
|
||||
|
||||
return ctx
|
||||
end
|
||||
|
||||
function _M.new(some, base)
|
||||
local ctx = C.BN_new()
|
||||
ffi_gc(ctx, C.BN_free)
|
||||
|
||||
if type(bn) == 'number' then
|
||||
if C.BN_set_word(ctx, bn) ~= 1 then
|
||||
return nil, format_error("bn.new")
|
||||
end
|
||||
elseif bn then
|
||||
return nil, "bn.new: expect nil or a number at #1"
|
||||
local ctx, err = set_bn(ctx, some, base)
|
||||
if err then
|
||||
return nil, "bn.new: " .. err
|
||||
end
|
||||
|
||||
return setmetatable( { ctx = ctx }, mt), nil
|
||||
|
|
@ -50,6 +106,19 @@ function _M.dup(ctx)
|
|||
return self
|
||||
end
|
||||
|
||||
function _M:set(some, base)
|
||||
if not some then
|
||||
return nil, "expect a number or a string at #1"
|
||||
end
|
||||
|
||||
local _, err = set_bn(self.ctx, some, base)
|
||||
if err then
|
||||
return nil, "bn:set: " .. err
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
function _M:to_binary(pad)
|
||||
if pad then
|
||||
if type(pad) ~= "number" then
|
||||
|
|
@ -80,17 +149,22 @@ function _M:to_binary(pad)
|
|||
return ffi_str(buf, sz)
|
||||
end
|
||||
|
||||
function _M.from_binary(s)
|
||||
if type(s) ~= "string" then
|
||||
return nil, "bn.from_binary: expect a string at #1"
|
||||
function _M:to_mpi(no_header)
|
||||
local length = C.BN_bn2mpi(self.ctx, nil)
|
||||
if length <= 0 then
|
||||
return nil, format_error("bn:to_mpi")
|
||||
end
|
||||
|
||||
local ctx = C.BN_bin2bn(s, #s, nil)
|
||||
if ctx == nil then
|
||||
return nil, format_error("bn.from_binary")
|
||||
local buf = ctypes.uchar_array(length)
|
||||
|
||||
local sz = C.BN_bn2mpi(self.ctx, buf)
|
||||
if sz <= 0 then
|
||||
return nil, format_error("bn:to_mpi")
|
||||
end
|
||||
ffi_gc(ctx, C.BN_free)
|
||||
return setmetatable( { ctx = ctx }, mt), nil
|
||||
|
||||
local ret = ffi_str(buf, sz)
|
||||
|
||||
return no_header and ret:sub(4) or ret
|
||||
end
|
||||
|
||||
function _M:to_hex()
|
||||
|
|
@ -103,21 +177,6 @@ function _M:to_hex()
|
|||
return s
|
||||
end
|
||||
|
||||
function _M.from_hex(s)
|
||||
if type(s) ~= "string" then
|
||||
return nil, "bn.from_hex: expect a string at #1"
|
||||
end
|
||||
|
||||
local p = ffi_new(bn_ptrptr_ct)
|
||||
|
||||
if C.BN_hex2bn(p, s) == 0 then
|
||||
return nil, format_error("bn.from_hex")
|
||||
end
|
||||
local ctx = p[0]
|
||||
ffi_gc(ctx, C.BN_free)
|
||||
return setmetatable( { ctx = ctx }, mt), nil
|
||||
end
|
||||
|
||||
function _M:to_dec()
|
||||
local buf = C.BN_bn2dec(self.ctx)
|
||||
if buf == nil then
|
||||
|
|
@ -129,26 +188,35 @@ function _M:to_dec()
|
|||
end
|
||||
mt.__tostring = _M.to_dec
|
||||
|
||||
function _M.from_dec(s)
|
||||
if type(s) ~= "string" then
|
||||
return nil, "bn.from_dec: expect a string at #1"
|
||||
end
|
||||
|
||||
local p = ffi_new(bn_ptrptr_ct)
|
||||
|
||||
if C.BN_dec2bn(p, s) == 0 then
|
||||
return nil, format_error("bn.from_dec")
|
||||
end
|
||||
local ctx = p[0]
|
||||
ffi_gc(ctx, C.BN_free)
|
||||
return setmetatable( { ctx = ctx }, mt), nil
|
||||
end
|
||||
|
||||
function _M:to_number()
|
||||
return tonumber(C.BN_get_word(self.ctx))
|
||||
end
|
||||
_M.tonumber = _M.to_number
|
||||
|
||||
local from_funcs = {
|
||||
binary = set_binary,
|
||||
mpi = set_mpi,
|
||||
hex = set_hex,
|
||||
dec = set_dec,
|
||||
}
|
||||
|
||||
for typ, func in pairs(from_funcs) do
|
||||
local sig = "from_" .. typ
|
||||
_M[sig] = function(s)
|
||||
if type(s) ~= "string" then
|
||||
return nil, "bn." .. sig .. ": expect a string at #1"
|
||||
end
|
||||
|
||||
local ctx, err = func(nil, s)
|
||||
if not ctx then
|
||||
return nil, "bn." .. sig .. ": " .. err
|
||||
end
|
||||
|
||||
ffi_gc(ctx, C.BN_free)
|
||||
return setmetatable( { ctx = ctx }, mt), nil
|
||||
end
|
||||
end
|
||||
|
||||
function _M.generate_prime(bits, safe)
|
||||
local ctx = C.BN_new()
|
||||
ffi_gc(ctx, C.BN_free)
|
||||
|
|
@ -373,12 +441,7 @@ function _M:is_prime(nchecks)
|
|||
end
|
||||
-- if nchecks is not defined, set to BN_prime_checks:
|
||||
-- select number of iterations based on the size of the number
|
||||
local code
|
||||
if OPENSSL_3X then
|
||||
code = C.BN_check_prime(self.ctx, bn_ctx_tmp, nil)
|
||||
else
|
||||
code = C.BN_is_prime_ex(self.ctx, nchecks or 0, bn_ctx_tmp, nil)
|
||||
end
|
||||
local code = C.BN_is_prime_ex(self.ctx, nchecks or 0, bn_ctx_tmp, nil)
|
||||
if code == -1 then
|
||||
return nil, format_error("bn.is_prime")
|
||||
end
|
||||
|
|
|
|||
|
|
@ -10,11 +10,11 @@ local ctypes = require "resty.openssl.auxiliary.ctypes"
|
|||
local ctx_lib = require "resty.openssl.ctx"
|
||||
local format_error = require("resty.openssl.err").format_error
|
||||
local OPENSSL_3X = require("resty.openssl.version").OPENSSL_3X
|
||||
local log_warn = require "resty.openssl.auxiliary.compat".log_warn
|
||||
|
||||
local uchar_array = ctypes.uchar_array
|
||||
local void_ptr = ctypes.void_ptr
|
||||
local ptr_of_int = ctypes.ptr_of_int
|
||||
local uchar_ptr = ctypes.uchar_ptr
|
||||
|
||||
local _M = {}
|
||||
local mt = {__index = _M}
|
||||
|
|
@ -23,7 +23,8 @@ local cipher_ctx_ptr_ct = ffi.typeof('EVP_CIPHER_CTX*')
|
|||
|
||||
local out_length = ptr_of_int()
|
||||
-- EVP_MAX_BLOCK_LENGTH is 32, we give it a 64 to be future proof
|
||||
local out_buffer = ctypes.uchar_array(1024 + 64)
|
||||
local out_buffer_size = 1024
|
||||
local out_buffer = ctypes.uchar_array(out_buffer_size + 64)
|
||||
|
||||
function _M.new(typ, properties)
|
||||
if not typ then
|
||||
|
|
@ -69,6 +70,15 @@ function _M.istype(l)
|
|||
return l and l.ctx and ffi.istype(cipher_ctx_ptr_ct, l.ctx)
|
||||
end
|
||||
|
||||
function _M.set_buffer_size(sz)
|
||||
if out_buffer_size ~= sz then
|
||||
out_buffer_size = sz
|
||||
out_buffer = ctypes.uchar_array(sz + 64)
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function _M:get_provider_name()
|
||||
if not OPENSSL_3X then
|
||||
return false, "cipher:get_provider_name is not supported"
|
||||
|
|
@ -195,49 +205,54 @@ function _M:set_aead_tag(tag)
|
|||
return true
|
||||
end
|
||||
|
||||
local update_buffer = {}
|
||||
function _M:update(...)
|
||||
if not self.initialized then
|
||||
return nil, "cipher:update: cipher not initalized, call cipher:init first"
|
||||
end
|
||||
|
||||
local ret = {}
|
||||
table.clear(update_buffer)
|
||||
local _out_buffer = out_buffer
|
||||
for i, s in ipairs({...}) do
|
||||
local inl = #s
|
||||
if inl > 1024 then
|
||||
s = ffi_cast(uchar_ptr, s)
|
||||
for i=0, inl-1, 1024 do
|
||||
local chunk_size = 1024
|
||||
if inl - i < 1024 then
|
||||
chunk_size = inl - i
|
||||
end
|
||||
if C.EVP_CipherUpdate(self.ctx, out_buffer, out_length, s+i, chunk_size) ~= 1 then
|
||||
return nil, format_error("cipher:update")
|
||||
end
|
||||
table.insert(ret, ffi_str(out_buffer, out_length[0]))
|
||||
end
|
||||
else
|
||||
if C.EVP_CipherUpdate(self.ctx, out_buffer, out_length, s, inl) ~= 1 then
|
||||
return nil, format_error("cipher:update")
|
||||
end
|
||||
table.insert(ret, ffi_str(out_buffer, out_length[0]))
|
||||
if inl > out_buffer_size and _out_buffer == out_buffer then
|
||||
-- create a larger buffer than the default one
|
||||
_out_buffer = ctypes.uchar_array(inl + 64)
|
||||
end
|
||||
if C.EVP_CipherUpdate(self.ctx, _out_buffer, out_length, s, inl) ~= 1 then
|
||||
return nil, format_error("cipher:update")
|
||||
end
|
||||
table.insert(update_buffer, ffi_str(_out_buffer, out_length[0]))
|
||||
end
|
||||
return table.concat(ret, "")
|
||||
return table.concat(update_buffer, "")
|
||||
end
|
||||
|
||||
function _M:final(s)
|
||||
local ret, err
|
||||
if s then
|
||||
ret, err = self:update(s)
|
||||
if err then
|
||||
return nil, err
|
||||
end
|
||||
if not self.initialized then
|
||||
return nil, "cipher:update: cipher not initalized, call cipher:init first"
|
||||
end
|
||||
if C.EVP_CipherFinal_ex(self.ctx, out_buffer, out_length) ~= 1 then
|
||||
|
||||
out_length[0] = 0
|
||||
local offset = 0 -- advance the offset if we have update buffer
|
||||
local _out_buffer = out_buffer
|
||||
if s then
|
||||
local inl = #s
|
||||
if inl > out_buffer_size then
|
||||
-- create a larger buffer than the default one
|
||||
_out_buffer = ctypes.uchar_array(inl + 64)
|
||||
end
|
||||
|
||||
if C.EVP_CipherUpdate(self.ctx, _out_buffer, out_length, s, inl) ~= 1 then
|
||||
return nil, format_error("cipher:final")
|
||||
end
|
||||
offset = out_length[0]
|
||||
end
|
||||
|
||||
if C.EVP_CipherFinal_ex(self.ctx, _out_buffer + offset, out_length) ~= 1 then
|
||||
return nil, format_error("cipher:final: EVP_CipherFinal_ex")
|
||||
end
|
||||
local final_ret = ffi_str(out_buffer, out_length[0])
|
||||
return ret and (ret .. final_ret) or final_ret
|
||||
|
||||
return ffi_str(_out_buffer, out_length[0] + offset)
|
||||
end
|
||||
|
||||
|
||||
|
|
@ -257,10 +272,10 @@ function _M:derive(key, salt, count, md, md_properties)
|
|||
|
||||
if salt then
|
||||
if #salt > 8 then
|
||||
ngx.log(ngx.WARN, "cipher:derive: salt is too long, truncate salt to 8 bytes")
|
||||
log_warn("cipher:derive: salt is too long, truncate salt to 8 bytes")
|
||||
salt = salt:sub(0, 8)
|
||||
elseif #salt < 8 then
|
||||
ngx.log(ngx.WARN, "cipher:derive: salt is too short, padding with zero bytes to length")
|
||||
log_warn("cipher:derive: salt is too short, padding with zero bytes to length")
|
||||
salt = salt .. string.rep('\000', 8 - #salt)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ local function new(request_context_only, conf_file)
|
|||
return false, format_error("ctx.new")
|
||||
end
|
||||
|
||||
if request_context_only then
|
||||
if request_context_only and ngx then
|
||||
ngx.ctx.ossl_lib_ctx = ctx
|
||||
else
|
||||
ossl_lib_ctx = ctx
|
||||
|
|
@ -40,7 +40,7 @@ local function free(request_context_only)
|
|||
return false, "ctx is only supported from OpenSSL 3.0"
|
||||
end
|
||||
|
||||
if request_context_only then
|
||||
if request_context_only and ngx then
|
||||
ngx.ctx.ossl_lib_ctx = nil
|
||||
else
|
||||
ossl_lib_ctx = nil
|
||||
|
|
|
|||
|
|
@ -5,27 +5,70 @@ local ffi_sizeof = ffi.sizeof
|
|||
|
||||
local ctypes = require "resty.openssl.auxiliary.ctypes"
|
||||
require "resty.openssl.include.err"
|
||||
local OPENSSL_3X = require("resty.openssl.version").OPENSSL_3X
|
||||
|
||||
local constchar_ptrptr = ffi.typeof("const char*[1]")
|
||||
|
||||
local buf = ffi.new('char[256]')
|
||||
local last_err_code = 0
|
||||
|
||||
local function get_last_error_code()
|
||||
local code = C.ERR_peek_last_error()
|
||||
last_err_code = code == 0 and last_err_code or code
|
||||
|
||||
return last_err_code
|
||||
end
|
||||
|
||||
local function get_lib_error_string(code)
|
||||
code = code or get_last_error_code()
|
||||
|
||||
local msg = C.ERR_lib_error_string(code)
|
||||
if msg == nil then
|
||||
return "unknown library"
|
||||
end
|
||||
|
||||
return ffi_str(msg)
|
||||
end
|
||||
|
||||
local function get_reason_error_string(code)
|
||||
code = code or get_last_error_code()
|
||||
|
||||
local msg = C.ERR_reason_error_string(code)
|
||||
if msg == nil then
|
||||
return ""
|
||||
end
|
||||
|
||||
return ffi_str(msg)
|
||||
end
|
||||
|
||||
local function format_error(ctx, code, all_errors)
|
||||
local errors = {}
|
||||
if code then
|
||||
table.insert(errors, string.format("code: %d", code or 0))
|
||||
end
|
||||
|
||||
local line = ctypes.ptr_of_int()
|
||||
local path = constchar_ptrptr()
|
||||
local func = constchar_ptrptr()
|
||||
|
||||
-- get the OpenSSL errors
|
||||
while C.ERR_peek_error() ~= 0 do
|
||||
local line = ctypes.ptr_of_int()
|
||||
local path = constchar_ptrptr()
|
||||
local code
|
||||
if all_errors then
|
||||
code = C.ERR_get_error_line(path, line)
|
||||
if OPENSSL_3X then
|
||||
code = C.ERR_get_error_all(path, line, func, nil, nil)
|
||||
else
|
||||
code = C.ERR_get_error_line(path, line)
|
||||
end
|
||||
else
|
||||
code = C.ERR_peek_last_error_line(path, line)
|
||||
if OPENSSL_3X then
|
||||
code = C.ERR_peek_last_error_all(path, line, func, nil, nil)
|
||||
else
|
||||
code = C.ERR_peek_last_error_line(path, line)
|
||||
end
|
||||
end
|
||||
|
||||
last_err_code = code
|
||||
|
||||
local abs_path = ffi_str(path[0])
|
||||
-- ../crypto/asn1/a_d2i_fp.c => crypto/asn1/a_d2i_fp.c
|
||||
local start = abs_path:find("/")
|
||||
|
|
@ -33,10 +76,23 @@ local function format_error(ctx, code, all_errors)
|
|||
abs_path = abs_path:sub(start+1)
|
||||
end
|
||||
|
||||
C.ERR_error_string_n(code, buf, ffi_sizeof(buf))
|
||||
table.insert(errors, string.format("%s:%d:%s",
|
||||
abs_path, line[0], ffi_str(buf))
|
||||
)
|
||||
local err_line
|
||||
|
||||
if OPENSSL_3X then
|
||||
local reason_msg = get_reason_error_string(code)
|
||||
local lib_msg = get_lib_error_string(code)
|
||||
-- error:04800065:PEM routines:PEM_do_header:bad decrypt:crypto/pem/pem_lib.c:467:
|
||||
err_line = string.format("error:%X:%s:%s:%s:%s:%d:",
|
||||
code, lib_msg, ffi_str(func[0]), reason_msg, abs_path, line[0])
|
||||
else
|
||||
local buf = ffi.new('char[256]')
|
||||
|
||||
C.ERR_error_string_n(code, buf, ffi_sizeof(buf))
|
||||
err_line = string.format("%s:%d:%s",
|
||||
abs_path, line[0], ffi_str(buf))
|
||||
end
|
||||
|
||||
table.insert(errors, err_line)
|
||||
|
||||
if not all_errors then
|
||||
break
|
||||
|
|
@ -59,4 +115,7 @@ end
|
|||
return {
|
||||
format_error = format_error,
|
||||
format_all_error = format_all_error,
|
||||
}
|
||||
get_last_error_code = get_last_error_code,
|
||||
get_lib_error_string = get_lib_error_string,
|
||||
get_reason_error_string = get_reason_error_string,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
local ffi = require "ffi"
|
||||
|
||||
require "resty.openssl.include.ossl_typ"
|
||||
local OPENSSL_3X = require("resty.openssl.version").OPENSSL_3X
|
||||
|
||||
local BN_ULONG
|
||||
if ffi.abi('64bit') then
|
||||
|
|
@ -33,6 +32,9 @@ ffi.cdef(
|
|||
char *BN_bn2hex(const BIGNUM *a);
|
||||
char *BN_bn2dec(const BIGNUM *a);
|
||||
|
||||
int BN_bn2mpi(const BIGNUM *a, unsigned char *to);
|
||||
BIGNUM *BN_mpi2bn(const unsigned char *s, int len, BIGNUM *ret);
|
||||
|
||||
void BN_set_negative(BIGNUM *a, int n);
|
||||
int BN_is_negative(const BIGNUM *a);
|
||||
|
||||
|
|
@ -60,7 +62,6 @@ ffi.cdef(
|
|||
int BN_cmp(BIGNUM *a, BIGNUM *b);
|
||||
int BN_ucmp(BIGNUM *a, BIGNUM *b);
|
||||
|
||||
// openssl >= 1.1 only
|
||||
int BN_is_zero(BIGNUM *a);
|
||||
int BN_is_one(BIGNUM *a);
|
||||
int BN_is_word(BIGNUM *a, ]] .. BN_ULONG ..[[ w);
|
||||
|
|
@ -70,10 +71,4 @@ ffi.cdef(
|
|||
int BN_generate_prime_ex(BIGNUM *ret,int bits,int safe, const BIGNUM *add,
|
||||
const BIGNUM *rem, BN_GENCB *cb);
|
||||
]]
|
||||
)
|
||||
|
||||
if OPENSSL_3X then
|
||||
ffi.cdef [[
|
||||
int BN_check_prime(const BIGNUM *p, BN_CTX *ctx, BN_GENCB *cb);
|
||||
]]
|
||||
end
|
||||
)
|
||||
|
|
@ -1,9 +1,30 @@
|
|||
local ffi = require "ffi"
|
||||
|
||||
require "resty.openssl.include.ossl_typ"
|
||||
local OPENSSL_3X = require("resty.openssl.version").OPENSSL_3X
|
||||
|
||||
ffi.cdef [[
|
||||
unsigned long ERR_peek_error(void);
|
||||
unsigned long ERR_peek_last_error_line(const char **file, int *line);
|
||||
unsigned long ERR_get_error_line(const char **file, int *line);
|
||||
unsigned long ERR_peek_last_error(void);
|
||||
void ERR_clear_error(void);
|
||||
void ERR_error_string_n(unsigned long e, char *buf, size_t len);
|
||||
const char *ERR_lib_error_string(unsigned long e);
|
||||
const char *ERR_reason_error_string(unsigned long e);
|
||||
]]
|
||||
|
||||
if OPENSSL_3X then
|
||||
ffi.cdef [[
|
||||
unsigned long ERR_get_error_all(const char **file, int *line,
|
||||
const char **func,
|
||||
const char **data, int *flags);
|
||||
unsigned long ERR_peek_last_error_all(const char **file, int *line,
|
||||
const char **func,
|
||||
const char **data, int *flags);
|
||||
]]
|
||||
|
||||
else
|
||||
ffi.cdef [[
|
||||
unsigned long ERR_get_error_line(const char **file, int *line);
|
||||
unsigned long ERR_peek_last_error_line(const char **file, int *line);
|
||||
]]
|
||||
end
|
||||
|
|
@ -44,15 +44,24 @@ local _M = {
|
|||
EVP_PKEY_X448 = C.OBJ_txt2nid("X448"),
|
||||
EVP_PKEY_ED448 = C.OBJ_txt2nid("ED448"),
|
||||
|
||||
EVP_PKEY_OP_PARAMGEN = bit.lshift(1, 1),
|
||||
EVP_PKEY_OP_KEYGEN = bit.lshift(1, 2),
|
||||
EVP_PKEY_OP_SIGN = bit.lshift(1, 3),
|
||||
EVP_PKEY_OP_VERIFY = bit.lshift(1, 4),
|
||||
EVP_PKEY_OP_DERIVE = OPENSSL_3X and bit.lshift(1, 12) or bit.lshift(1, 10),
|
||||
EVP_CTRL_AEAD_SET_IVLEN = 0x9,
|
||||
EVP_CTRL_AEAD_GET_TAG = 0x10,
|
||||
EVP_CTRL_AEAD_SET_TAG = 0x11,
|
||||
|
||||
-- remove EVP_PKEY_OP_* and EVP_PKEY_CTRL_* after openssl 1.1.1 support is dropped
|
||||
EVP_PKEY_OP_PARAMGEN = not OPENSSL_3X and bit.lshift(1, 1) or nil,
|
||||
EVP_PKEY_OP_KEYGEN = not OPENSSL_3X and bit.lshift(1, 2) or nil,
|
||||
EVP_PKEY_OP_SIGN = not OPENSSL_3X and bit.lshift(1, 3) or nil,
|
||||
EVP_PKEY_OP_VERIFY = not OPENSSL_3X and bit.lshift(1, 4) or nil,
|
||||
EVP_PKEY_OP_VERIFYRECOVER = not OPENSSL_3X and bit.lshift(1, 5) or nil,
|
||||
EVP_PKEY_OP_SIGNCTX = not OPENSSL_3X and bit.lshift(1, 6) or nil,
|
||||
EVP_PKEY_OP_VERIFYCTX = not OPENSSL_3X and bit.lshift(1, 7) or nil,
|
||||
EVP_PKEY_OP_ENCRYPT = not OPENSSL_3X and bit.lshift(1, 8) or nil,
|
||||
EVP_PKEY_OP_DECRYPT = not OPENSSL_3X and bit.lshift(1, 9) or nil,
|
||||
EVP_PKEY_OP_DERIVE = not OPENSSL_3X and bit.lshift(1, 10) or nil,
|
||||
|
||||
EVP_PKEY_ALG_CTRL = EVP_PKEY_ALG_CTRL,
|
||||
|
||||
|
||||
EVP_PKEY_CTRL_DH_PARAMGEN_PRIME_LEN = EVP_PKEY_ALG_CTRL + 1,
|
||||
EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID = EVP_PKEY_ALG_CTRL + 1,
|
||||
EVP_PKEY_CTRL_EC_PARAM_ENC = EVP_PKEY_ALG_CTRL + 2,
|
||||
|
|
@ -60,10 +69,8 @@ local _M = {
|
|||
EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP = EVP_PKEY_ALG_CTRL + 4,
|
||||
EVP_PKEY_CTRL_RSA_PADDING = EVP_PKEY_ALG_CTRL + 1,
|
||||
EVP_PKEY_CTRL_RSA_PSS_SALTLEN = EVP_PKEY_ALG_CTRL + 2,
|
||||
|
||||
EVP_CTRL_AEAD_SET_IVLEN = 0x9,
|
||||
EVP_CTRL_AEAD_GET_TAG = 0x10,
|
||||
EVP_CTRL_AEAD_SET_TAG = 0x11,
|
||||
EVP_PKEY_CTRL_RSA_MGF1_MD = EVP_PKEY_ALG_CTRL + 5,
|
||||
EVP_PKEY_CTRL_RSA_OAEP_MD = EVP_PKEY_ALG_CTRL + 9,
|
||||
|
||||
EVP_PKEY_CTRL_TLS_MD = EVP_PKEY_ALG_CTRL,
|
||||
EVP_PKEY_CTRL_TLS_SECRET = EVP_PKEY_ALG_CTRL + 1,
|
||||
|
|
@ -81,6 +88,12 @@ local _M = {
|
|||
EVP_PKEY_CTRL_SCRYPT_MAXMEM_BYTES = EVP_PKEY_ALG_CTRL + 13,
|
||||
}
|
||||
|
||||
if not OPENSSL_3X then
|
||||
_M.EVP_PKEY_OP_CRYPT = _M.EVP_PKEY_OP_ENCRYPT + _M.EVP_PKEY_OP_DECRYPT
|
||||
_M.EVP_PKEY_OP_SIG = _M.EVP_PKEY_OP_SIGN + _M.EVP_PKEY_OP_VERIFY + _M.EVP_PKEY_OP_VERIFYRECOVER +
|
||||
_M.EVP_PKEY_OP_SIGNCTX + _M.EVP_PKEY_OP_VERIFYCTX
|
||||
end
|
||||
|
||||
-- clean up error occurs during OBJ_txt2*
|
||||
C.ERR_clear_error()
|
||||
|
||||
|
|
|
|||
|
|
@ -81,6 +81,9 @@ ffi.cdef [[
|
|||
int EVP_PKEY_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey);
|
||||
int EVP_PKEY_paramgen_init(EVP_PKEY_CTX *ctx);
|
||||
int EVP_PKEY_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey);
|
||||
|
||||
int EVP_PKEY_CTX_ctrl_str(EVP_PKEY_CTX *ctx, const char *type,
|
||||
const char *value);
|
||||
]]
|
||||
|
||||
local _M = {}
|
||||
|
|
@ -102,6 +105,10 @@ if OPENSSL_3X then
|
|||
|
||||
int EVP_PKEY_CTX_set_rsa_padding(EVP_PKEY_CTX *ctx, int pad);
|
||||
int EVP_PKEY_CTX_set_rsa_pss_saltlen(EVP_PKEY_CTX *ctx, int len);
|
||||
int EVP_PKEY_CTX_set_rsa_mgf1_md_name(EVP_PKEY_CTX *ctx, const char *mdname,
|
||||
const char *mdprops);
|
||||
int EVP_PKEY_CTX_set_rsa_oaep_md_name(EVP_PKEY_CTX *ctx, const char *mdname,
|
||||
const char *mdprops);
|
||||
|
||||
int EVP_PKEY_CTX_set_dh_paramgen_prime_len(EVP_PKEY_CTX *ctx, int pbits);
|
||||
|
||||
|
|
@ -121,6 +128,10 @@ if OPENSSL_3X then
|
|||
return C.EVP_PKEY_CTX_set_ec_param_enc(pctx, param_enc)
|
||||
end
|
||||
|
||||
_M.EVP_PKEY_CTX_set_dh_paramgen_prime_len = function(pctx, pbits)
|
||||
return C.EVP_PKEY_CTX_set_dh_paramgen_prime_len(pctx, pbits)
|
||||
end
|
||||
|
||||
_M.EVP_PKEY_CTX_set_rsa_keygen_bits = function(pctx, mbits)
|
||||
return C.EVP_PKEY_CTX_set_rsa_keygen_bits(pctx, mbits)
|
||||
end
|
||||
|
|
@ -134,8 +145,11 @@ if OPENSSL_3X then
|
|||
_M.EVP_PKEY_CTX_set_rsa_pss_saltlen = function(pctx, len)
|
||||
return C.EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, len)
|
||||
end
|
||||
_M.EVP_PKEY_CTX_set_dh_paramgen_prime_len = function(pctx, pbits)
|
||||
return C.EVP_PKEY_CTX_set_dh_paramgen_prime_len(pctx, pbits)
|
||||
_M.EVP_PKEY_CTX_set_rsa_mgf1_md_name = function(pctx, name ,props)
|
||||
return C.EVP_PKEY_CTX_set_rsa_mgf1_md_name(pctx, name, props)
|
||||
end
|
||||
_M.EVP_PKEY_CTX_set_rsa_oaep_md_name = function(pctx, name, props)
|
||||
return C.EVP_PKEY_CTX_set_rsa_oaep_md_name(pctx, name, props)
|
||||
end
|
||||
|
||||
else
|
||||
|
|
@ -154,6 +168,13 @@ else
|
|||
param_enc, nil)
|
||||
end
|
||||
|
||||
_M.EVP_PKEY_CTX_set_dh_paramgen_prime_len = function(pctx, pbits)
|
||||
return C.EVP_PKEY_CTX_ctrl(pctx,
|
||||
evp.EVP_PKEY_DH, evp.EVP_PKEY_OP_PARAMGEN,
|
||||
evp.EVP_PKEY_CTRL_DH_PARAMGEN_PRIME_LEN,
|
||||
pbits, nil)
|
||||
end
|
||||
|
||||
_M.EVP_PKEY_CTX_set_rsa_keygen_bits = function(pctx, mbits)
|
||||
return C.EVP_PKEY_CTX_ctrl(pctx,
|
||||
evp.EVP_PKEY_RSA,
|
||||
|
|
@ -183,11 +204,27 @@ else
|
|||
len, nil)
|
||||
end
|
||||
|
||||
_M.EVP_PKEY_CTX_set_dh_paramgen_prime_len = function(pctx, pbits)
|
||||
_M.EVP_PKEY_CTX_set_rsa_mgf1_md_name = function(pctx, name, _)
|
||||
local md = C.EVP_get_digestbyname(name)
|
||||
if not md then
|
||||
return -1, "unknown digest: " .. name
|
||||
end
|
||||
return C.EVP_PKEY_CTX_ctrl(pctx,
|
||||
evp.EVP_PKEY_DH, evp.EVP_PKEY_OP_PARAMGEN,
|
||||
evp.EVP_PKEY_CTRL_DH_PARAMGEN_PRIME_LEN,
|
||||
pbits, nil)
|
||||
evp.EVP_PKEY_RSA,
|
||||
evp.EVP_PKEY_OP_SIG + evp.EVP_PKEY_OP_TYPE_CRYPT,
|
||||
evp.EVP_PKEY_CTRL_RSA_MGF1_MD,
|
||||
0, ffi.cast("void *", md))
|
||||
end
|
||||
_M.EVP_PKEY_CTX_set_rsa_oaep_md_name = function(pctx, name, _)
|
||||
local md = C.EVP_get_digestbyname(name)
|
||||
if not md then
|
||||
return -1, "unknown digest: " .. name
|
||||
end
|
||||
return C.EVP_PKEY_CTX_ctrl(pctx,
|
||||
evp.EVP_PKEY_RSA,
|
||||
evp.EVP_PKEY_OP_CRYPT,
|
||||
evp.EVP_PKEY_CTRL_RSA_OAEP_MD,
|
||||
0, ffi.cast("void *", md))
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@ local format_error = require("resty.openssl.err").format_error
|
|||
local version_text = require("resty.openssl.version").version_text
|
||||
local OPENSSL_3X = require("resty.openssl.version").OPENSSL_3X
|
||||
local ctypes = require "resty.openssl.auxiliary.ctypes"
|
||||
local nkeys = require "resty.openssl.auxiliary.compat".nkeys
|
||||
local log_warn = require "resty.openssl.auxiliary.compat".log_warn
|
||||
|
||||
--[[
|
||||
https://wiki.openssl.org/index.php/EVP_Key_Derivation
|
||||
|
|
@ -251,7 +253,7 @@ function _M.derive(options)
|
|||
local md_size = OPENSSL_3X and C.EVP_MD_get_size(md) or C.EVP_MD_size(md)
|
||||
if options.outlen ~= md_size then
|
||||
options.outlen = md_size
|
||||
ngx.log(ngx.WARN, "hkdf_mode EXTRACT_ONLY outputs fixed length of ", md_size,
|
||||
log_warn("hkdf_mode EXTRACT_ONLY outputs fixed length of ", md_size,
|
||||
" key, ignoring options.outlen")
|
||||
end
|
||||
outlen[0] = md_size
|
||||
|
|
@ -311,6 +313,7 @@ function _M.new(typ, properties)
|
|||
algo = algo,
|
||||
buf = buf,
|
||||
buf_size = buf_size,
|
||||
schema = nil,
|
||||
}, mt), nil
|
||||
end
|
||||
|
||||
|
|
@ -344,14 +347,16 @@ function _M:derive(outlen, options, options_count)
|
|||
if options_count then
|
||||
options_count = options_count - 1
|
||||
else
|
||||
options_count = 0
|
||||
for k, v in pairs(options) do options_count = options_count + 1 end
|
||||
options_count = nkeys(options)
|
||||
end
|
||||
|
||||
local param, err
|
||||
if options_count > 0 then
|
||||
local schema = self:settable_params(true) -- raw schema
|
||||
param, err = param_lib.construct(options, nil, schema)
|
||||
if not self.schema then
|
||||
self.schema = self:settable_params(true) -- raw schema
|
||||
end
|
||||
|
||||
param, err = param_lib.construct(options, nil, self.schema)
|
||||
if err then
|
||||
return nil, "kdf:derive: " .. err
|
||||
end
|
||||
|
|
|
|||
|
|
@ -41,7 +41,8 @@ function _M.new(key, typ, cipher, digest, properties)
|
|||
params.cipher = cipher
|
||||
local p = param_lib.construct(params, 2, param_types)
|
||||
|
||||
local code = C.EVP_MAC_init(ctx, key, #key, p)
|
||||
local keyl = #key
|
||||
local code = C.EVP_MAC_init(ctx, key, keyl, p)
|
||||
if code ~= 1 then
|
||||
return nil, format_error(string.format("mac.new: invalid cipher or digest type"))
|
||||
end
|
||||
|
|
@ -53,6 +54,7 @@ function _M.new(key, typ, cipher, digest, properties)
|
|||
algo = algo,
|
||||
buf = ctypes.uchar_array(md_size),
|
||||
buf_size = md_size,
|
||||
_reset = function() return C.EVP_MAC_init(ctx, key, keyl, p) end,
|
||||
}, mt), nil
|
||||
end
|
||||
|
||||
|
|
@ -73,7 +75,7 @@ _M.settable_params, _M.set_params, _M.gettable_params, _M.get_param = param_lib.
|
|||
function _M:update(...)
|
||||
for _, s in ipairs({...}) do
|
||||
if C.EVP_MAC_update(self.ctx, s, #s) ~= 1 then
|
||||
return false, format_error("digest:update")
|
||||
return false, format_error("mac:update")
|
||||
end
|
||||
end
|
||||
return true, nil
|
||||
|
|
@ -81,17 +83,25 @@ end
|
|||
|
||||
function _M:final(s)
|
||||
if s then
|
||||
local _, err = self:update(s)
|
||||
if err then
|
||||
return nil, err
|
||||
if C.EVP_MAC_update(self.ctx, s, #s) ~= 1 then
|
||||
return false, format_error("mac:final")
|
||||
end
|
||||
end
|
||||
|
||||
local length = ctypes.ptr_of_size_t()
|
||||
if C.EVP_MAC_final(self.ctx, self.buf, length, self.buf_size) ~= 1 then
|
||||
return nil, format_error("digest:final: EVP_MAC_final")
|
||||
return nil, format_error("mac:final: EVP_MAC_final")
|
||||
end
|
||||
return ffi_str(self.buf, length[0])
|
||||
end
|
||||
|
||||
function _M:reset()
|
||||
local code = self._reset()
|
||||
if code ~= 1 then
|
||||
return false, format_error("mac:reset")
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
return _M
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ require "resty.openssl.include.param"
|
|||
local format_error = require("resty.openssl.err").format_error
|
||||
local bn_lib = require("resty.openssl.bn")
|
||||
local null = require("resty.openssl.auxiliary.ctypes").null
|
||||
local nkeys = require "resty.openssl.auxiliary.compat".nkeys
|
||||
|
||||
local OSSL_PARAM_INTEGER = 1
|
||||
local OSSL_PARAM_UNSIGNED_INTEGER = 2
|
||||
|
|
@ -22,8 +23,7 @@ local buf_param_key = {}
|
|||
|
||||
local function construct(buf_t, length, types_map, types_size)
|
||||
if not length then
|
||||
length = 0
|
||||
for k, v in pairs(buf_t) do length = length + 1 end
|
||||
length = nkeys(buf_t)
|
||||
end
|
||||
|
||||
local params = ffi_new("OSSL_PARAM[?]", length + 1)
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@ local ctx_lib = require "resty.openssl.ctx"
|
|||
local ctypes = require "resty.openssl.auxiliary.ctypes"
|
||||
local ecdsa_util = require "resty.openssl.auxiliary.ecdsa"
|
||||
local format_error = require("resty.openssl.err").format_error
|
||||
local log_warn = require "resty.openssl.auxiliary.compat".log_warn
|
||||
local log_debug = require "resty.openssl.auxiliary.compat".log_debug
|
||||
|
||||
local OPENSSL_3X = require("resty.openssl.version").OPENSSL_3X
|
||||
|
||||
|
|
@ -67,7 +69,7 @@ local function load_pem_der(txt, opts, funcs)
|
|||
return nil, "explictly load private or public key from JWK format is not supported"
|
||||
end
|
||||
|
||||
ngx.log(ngx.DEBUG, "load key using fmt: ", fmt, ", type: ", typ)
|
||||
log_debug("load key using fmt: ", fmt, ", type: ", typ)
|
||||
|
||||
local bio = C.BIO_new_mem_buf(txt, #txt)
|
||||
if bio == nil then
|
||||
|
|
@ -89,7 +91,7 @@ local function load_pem_der(txt, opts, funcs)
|
|||
if fmt == "JWK" then
|
||||
return nil, err
|
||||
end
|
||||
ngx.log(ngx.DEBUG, "jwk decode failed: ", err, ", continuing")
|
||||
log_debug("jwk decode failed: ", err, ", continuing")
|
||||
end
|
||||
else
|
||||
-- #define BIO_CTRL_RESET 1
|
||||
|
|
@ -113,7 +115,7 @@ local function load_pem_der(txt, opts, funcs)
|
|||
local p = opts.passphrase_cb()
|
||||
local len = #p -- 1 byte for \0
|
||||
if len > size then
|
||||
ngx.log(ngx.WARN, "pkey:load_pem_der: passphrase truncated from ", len, " to ", size)
|
||||
log_warn("pkey:load_pem_der: passphrase truncated from ", len, " to ", size)
|
||||
len = size
|
||||
end
|
||||
ffi_copy(buf, p, len)
|
||||
|
|
@ -127,7 +129,7 @@ local function load_pem_der(txt, opts, funcs)
|
|||
end
|
||||
|
||||
if ctx ~= nil then
|
||||
ngx.log(ngx.DEBUG, "pkey:load_pem_der: loaded pkey using function ", f)
|
||||
log_debug("pkey:load_pem_der: loaded pkey using function ", f)
|
||||
|
||||
-- pkcs1 functions create a rsa rather than evp_pkey
|
||||
-- disable the checking in openssl 3.0 for sail safe
|
||||
|
|
@ -160,6 +162,40 @@ local function load_pem_der(txt, opts, funcs)
|
|||
return ctx, nil
|
||||
end
|
||||
|
||||
local function _pctx_ctrl_str(pctx, opts)
|
||||
if not opts then
|
||||
return true
|
||||
end
|
||||
|
||||
if opts.mgf1_md and pkey_macro.EVP_PKEY_CTX_set_rsa_mgf1_md_name(pctx, opts.mgf1_md, nil) ~= 1 then
|
||||
return nil, format_error("EVP_PKEY_CTX_set_rsa_mgf1_md_name")
|
||||
end
|
||||
|
||||
if opts.oaep_md and pkey_macro.EVP_PKEY_CTX_set_rsa_oaep_md_name(pctx, opts.oaep_md, nil) ~= 1 then
|
||||
return nil, format_error("EVP_PKEY_CTX_set_rsa_oaep_md_name")
|
||||
end
|
||||
|
||||
if opts.pss_saltlen and pkey_macro.EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, opts.pss_saltlen) ~= 1 then
|
||||
return nil, format_error("EVP_PKEY_CTX_set_rsa_pss_saltlen")
|
||||
end
|
||||
|
||||
|
||||
for _, c in ipairs(opts) do
|
||||
if type(c) == "string" then
|
||||
local k, v = string.match(c, "([_%w]+):([_%w]+)")
|
||||
if not k or not v then
|
||||
return nil, "unknown ctrl str: ".. c
|
||||
end
|
||||
|
||||
if C.EVP_PKEY_CTX_ctrl_str(pctx, k, v) ~= 1 then
|
||||
return nil, format_error(string.format('EVP_PKEY_CTX_ctrl_str(%s, "%s", "%s")', pctx, k, v))
|
||||
end
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
local function generate_param(key_type, config)
|
||||
if key_type == evp_macro.EVP_PKEY_DH then
|
||||
local dh_group = config.group
|
||||
|
|
@ -222,6 +258,11 @@ local function generate_param(key_type, config)
|
|||
end
|
||||
end
|
||||
|
||||
local ok, err = _pctx_ctrl_str(pctx, config)
|
||||
if not ok then
|
||||
return nil, "pkey:generate_param: " .. err
|
||||
end
|
||||
|
||||
local ctx_ptr = ffi_new("EVP_PKEY*[1]")
|
||||
if C.EVP_PKEY_paramgen(pctx, ctx_ptr) ~= 1 then
|
||||
return nil, format_error("EVP_PKEY_paramgen")
|
||||
|
|
@ -347,6 +388,12 @@ local function generate_key(config)
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
local ok, err = _pctx_ctrl_str(pctx, config)
|
||||
if not ok then
|
||||
return nil, "pkey:generate_key: " .. err
|
||||
end
|
||||
|
||||
local ctx_ptr = ffi_new("EVP_PKEY*[1]")
|
||||
-- TODO: move to use EVP_PKEY_gen after drop support for <1.1.1
|
||||
if C.EVP_PKEY_keygen(pctx, ctx_ptr) ~= 1 then
|
||||
|
|
@ -500,7 +547,6 @@ function _M.new(s, opts)
|
|||
local self = setmetatable({
|
||||
ctx = ctx,
|
||||
pkey_ctx = nil,
|
||||
rsa_padding = nil,
|
||||
key_type = key_type,
|
||||
key_type_is_ecx = key_type_is_ecx,
|
||||
buf = ctypes.uchar_array(buf_size),
|
||||
|
|
@ -613,7 +659,11 @@ local ASYMMETRIC_OP_DECRYPT = 0x2
|
|||
local ASYMMETRIC_OP_SIGN_RAW = 0x4
|
||||
local ASYMMETRIC_OP_VERIFY_RECOVER = 0x8
|
||||
|
||||
local function asymmetric_routine(self, s, op, padding)
|
||||
local function asymmetric_routine(self, s, op, padding, opts)
|
||||
if type(s) ~= "string" then
|
||||
return nil, "pkey:asymmetric_routine: expect a string at #1"
|
||||
end
|
||||
|
||||
local pkey_ctx
|
||||
|
||||
if self.key_type == evp_macro.EVP_PKEY_RSA then
|
||||
|
|
@ -627,9 +677,8 @@ local function asymmetric_routine(self, s, op, padding)
|
|||
end
|
||||
end
|
||||
|
||||
if self.pkey_ctx ~= nil and
|
||||
(self.key_type ~= evp_macro.EVP_PKEY_RSA or self.rsa_padding == padding) then
|
||||
pkey_ctx = self.pkey_ctx
|
||||
if self.pkey_ctx ~= nil and self.key_type ~= evp_macro.EVP_PKEY_RSA then
|
||||
pkey_ctx = self.pkey_ctx
|
||||
else
|
||||
pkey_ctx = C.EVP_PKEY_CTX_new(self.ctx, nil)
|
||||
if pkey_ctx == nil then
|
||||
|
|
@ -666,11 +715,14 @@ local function asymmetric_routine(self, s, op, padding)
|
|||
end
|
||||
|
||||
-- EVP_PKEY_CTX_ctrl must be called after *_init
|
||||
if self.key_type == evp_macro.EVP_PKEY_RSA and padding then
|
||||
if pkey_macro.EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, padding) ~= 1 then
|
||||
return nil, format_error("pkey:asymmetric_routine EVP_PKEY_CTX_set_rsa_padding")
|
||||
end
|
||||
self.rsa_padding = padding
|
||||
if self.key_type == evp_macro.EVP_PKEY_RSA and padding and
|
||||
pkey_macro.EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, padding) ~= 1 then
|
||||
return nil, format_error("pkey:asymmetric_routine EVP_PKEY_CTX_set_rsa_padding")
|
||||
end
|
||||
|
||||
local ok, err = _pctx_ctrl_str(pkey_ctx, opts)
|
||||
if not ok then
|
||||
return nil, "pkey:asymmetric_routine: " .. err
|
||||
end
|
||||
|
||||
local length = ptr_of_size_t(self.buf_size)
|
||||
|
|
@ -684,40 +736,30 @@ end
|
|||
|
||||
_M.PADDINGS = rsa_macro.paddings
|
||||
|
||||
function _M:encrypt(s, padding)
|
||||
return asymmetric_routine(self, s, ASYMMETRIC_OP_ENCRYPT, padding)
|
||||
function _M:encrypt(s, padding, opts)
|
||||
return asymmetric_routine(self, s, ASYMMETRIC_OP_ENCRYPT, padding, opts)
|
||||
end
|
||||
|
||||
function _M:decrypt(s, padding)
|
||||
return asymmetric_routine(self, s, ASYMMETRIC_OP_DECRYPT, padding)
|
||||
function _M:decrypt(s, padding, opts)
|
||||
return asymmetric_routine(self, s, ASYMMETRIC_OP_DECRYPT, padding, opts)
|
||||
end
|
||||
|
||||
function _M:sign_raw(s, padding)
|
||||
function _M:sign_raw(s, padding, opts)
|
||||
-- TODO: temporary hack before OpenSSL has proper check for existence of private key
|
||||
if self.key_type_is_ecx and not self:is_private() then
|
||||
return nil, "pkey:sign_raw: missing private key"
|
||||
end
|
||||
|
||||
return asymmetric_routine(self, s, ASYMMETRIC_OP_SIGN_RAW, padding)
|
||||
return asymmetric_routine(self, s, ASYMMETRIC_OP_SIGN_RAW, padding, opts)
|
||||
end
|
||||
|
||||
function _M:verify_recover(s, padding)
|
||||
return asymmetric_routine(self, s, ASYMMETRIC_OP_VERIFY_RECOVER, padding)
|
||||
function _M:verify_recover(s, padding, opts)
|
||||
return asymmetric_routine(self, s, ASYMMETRIC_OP_VERIFY_RECOVER, padding, opts)
|
||||
end
|
||||
|
||||
local evp_pkey_ctx_ptr_ptr_ct = ffi.typeof('EVP_PKEY_CTX*[1]')
|
||||
|
||||
local function sign_verify_prepare(self, fint, md_alg, padding, opts)
|
||||
local pkey_ctx
|
||||
|
||||
if self.key_type == evp_macro.EVP_PKEY_RSA and padding then
|
||||
pkey_ctx = C.EVP_PKEY_CTX_new(self.ctx, nil)
|
||||
if pkey_ctx == nil then
|
||||
return nil, format_error("pkey:sign_verify_prepare EVP_PKEY_CTX_new()")
|
||||
end
|
||||
ffi_gc(pkey_ctx, C.EVP_PKEY_CTX_free)
|
||||
end
|
||||
|
||||
local md_ctx = C.EVP_MD_CTX_new()
|
||||
if md_ctx == nil then
|
||||
return nil, "pkey:sign_verify_prepare: EVP_MD_CTX_new() failed"
|
||||
|
|
@ -737,22 +779,19 @@ local function sign_verify_prepare(self, fint, md_alg, padding, opts)
|
|||
end
|
||||
|
||||
local ppkey_ctx = evp_pkey_ctx_ptr_ptr_ct()
|
||||
ppkey_ctx[0] = pkey_ctx
|
||||
if fint(md_ctx, ppkey_ctx, algo, nil, self.ctx) ~= 1 then
|
||||
return nil, format_error("pkey:sign_verify_prepare: Init failed")
|
||||
end
|
||||
|
||||
if self.key_type == evp_macro.EVP_PKEY_RSA then
|
||||
if padding then
|
||||
if pkey_macro.EVP_PKEY_CTX_set_rsa_padding(ppkey_ctx[0], padding) ~= 1 then
|
||||
return nil, format_error("pkey:sign_verify_prepare EVP_PKEY_CTX_set_rsa_padding")
|
||||
end
|
||||
end
|
||||
if opts and opts.pss_saltlen and padding ~= rsa_macro.paddings.RSA_PKCS1_PSS_PADDING then
|
||||
if pkey_macro.EVP_PKEY_CTX_set_rsa_pss_saltlen(ppkey_ctx[0], opts.pss_saltlen) ~= 1 then
|
||||
return nil, format_error("pkey:sign_verify_prepare EVP_PKEY_CTX_set_rsa_pss_saltlen")
|
||||
end
|
||||
end
|
||||
-- EVP_PKEY_CTX_ctrl must be called after *_init
|
||||
if self.key_type == evp_macro.EVP_PKEY_RSA and padding and
|
||||
pkey_macro.EVP_PKEY_CTX_set_rsa_padding(ppkey_ctx[0], padding) ~= 1 then
|
||||
return nil, format_error("pkey:sign_verify_prepare EVP_PKEY_CTX_set_rsa_padding")
|
||||
end
|
||||
|
||||
local ok, err = _pctx_ctrl_str(ppkey_ctx[0], opts)
|
||||
if not ok then
|
||||
return nil, "pkey:sign_verify_prepare: " .. err
|
||||
end
|
||||
|
||||
return md_ctx
|
||||
|
|
|
|||
|
|
@ -2,11 +2,30 @@
|
|||
local ffi = require "ffi"
|
||||
local C = ffi.C
|
||||
local ffi_str = ffi.string
|
||||
local log_debug = require "resty.openssl.auxiliary.compat".log_debug
|
||||
|
||||
local libcrypto_name
|
||||
local lib_patterns = {
|
||||
"%s", "%s.so.3", "%s.so.1.1", "%s.so.1.0"
|
||||
}
|
||||
|
||||
local function load_library()
|
||||
for _, pattern in ipairs(lib_patterns) do
|
||||
-- true: load to global namespae
|
||||
local pok, _ = pcall(ffi.load, string.format(pattern, "crypto"), true)
|
||||
if pok then
|
||||
libcrypto_name = string.format(pattern, "crypto")
|
||||
ffi.load(string.format(pattern, "ssl"), true)
|
||||
|
||||
log_debug("loaded crypto library: ", libcrypto_name)
|
||||
return libcrypto_name
|
||||
end
|
||||
end
|
||||
|
||||
return false, "unable to load crypto library"
|
||||
end
|
||||
|
||||
ffi.cdef[[
|
||||
// 1.0
|
||||
unsigned long SSLeay(void);
|
||||
const char *SSLeay_version(int t);
|
||||
// >= 1.1
|
||||
unsigned long OpenSSL_version_num();
|
||||
const char *OpenSSL_version(int t);
|
||||
|
|
@ -15,49 +34,38 @@ ffi.cdef[[
|
|||
]]
|
||||
|
||||
local version_func, info_func
|
||||
local types_table
|
||||
local types_table = {
|
||||
VERSION = 0,
|
||||
CFLAGS = 1,
|
||||
BUILT_ON = 2,
|
||||
PLATFORM = 3,
|
||||
DIR = 4,
|
||||
ENGINES_DIR = 5,
|
||||
VERSION_STRING = 6,
|
||||
FULL_VERSION_STRING = 7,
|
||||
MODULES_DIR = 8,
|
||||
CPU_INFO = 9,
|
||||
}
|
||||
|
||||
-- >= 1.1
|
||||
local ok, version_num = pcall(function()
|
||||
local get_version = function()
|
||||
local num = C.OpenSSL_version_num()
|
||||
version_func = C.OpenSSL_version
|
||||
types_table = {
|
||||
VERSION = 0,
|
||||
CFLAGS = 1,
|
||||
BUILT_ON = 2,
|
||||
PLATFORM = 3,
|
||||
DIR = 4,
|
||||
ENGINES_DIR = 5,
|
||||
VERSION_STRING = 6,
|
||||
FULL_VERSION_STRING = 7,
|
||||
MODULES_DIR = 8,
|
||||
CPU_INFO = 9,
|
||||
}
|
||||
return num
|
||||
end)
|
||||
|
||||
|
||||
if not ok then
|
||||
-- 1.0.x
|
||||
ok, version_num = pcall(function()
|
||||
local num = C.SSLeay()
|
||||
version_func = C.SSLeay_version
|
||||
types_table = {
|
||||
VERSION = 0,
|
||||
CFLAGS = 2,
|
||||
BUILT_ON = 3,
|
||||
PLATFORM = 4,
|
||||
DIR = 5,
|
||||
}
|
||||
return num
|
||||
end)
|
||||
end
|
||||
|
||||
local ok, version_num = pcall(get_version)
|
||||
if not ok then
|
||||
ok, version_num = pcall(load_library)
|
||||
if ok then
|
||||
-- try again
|
||||
ok, version_num = pcall(get_version)
|
||||
end
|
||||
end
|
||||
|
||||
if not ok then
|
||||
error(string.format("OpenSSL has encountered an error: %s; is OpenSSL library loaded?",
|
||||
tostring(version_num)))
|
||||
elseif type(version_num) == 'number' and version_num < 0x10000000 then
|
||||
elseif type(version_num) == 'number' and version_num < 0x10101000 then
|
||||
error(string.format("OpenSSL version %s is not supported", tostring(version_num or 0)))
|
||||
elseif not version_num then
|
||||
error("Can not get OpenSSL version")
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
package = "lua-resty-openssl"
|
||||
version = "1.0.2-1"
|
||||
version = "1.2.0-1"
|
||||
source = {
|
||||
url = "git+https://github.com/fffonion/lua-resty-openssl.git",
|
||||
tag = "1.0.2"
|
||||
tag = "1.2.0"
|
||||
}
|
||||
description = {
|
||||
detailed = "FFI-based OpenSSL binding for LuaJIT.",
|
||||
|
|
@ -15,6 +15,7 @@ build = {
|
|||
["resty.openssl"] = "lib/resty/openssl.lua",
|
||||
["resty.openssl.asn1"] = "lib/resty/openssl/asn1.lua",
|
||||
["resty.openssl.auxiliary.bio"] = "lib/resty/openssl/auxiliary/bio.lua",
|
||||
["resty.openssl.auxiliary.compat"] = "lib/resty/openssl/auxiliary/compat.lua",
|
||||
["resty.openssl.auxiliary.ctypes"] = "lib/resty/openssl/auxiliary/ctypes.lua",
|
||||
["resty.openssl.auxiliary.ecdsa"] = "lib/resty/openssl/auxiliary/ecdsa.lua",
|
||||
["resty.openssl.auxiliary.jwk"] = "lib/resty/openssl/auxiliary/jwk.lua",
|
||||
|
|
@ -1,7 +1,9 @@
|
|||
{%- set ns = namespace(idx=test_idx) %}
|
||||
{%- for f in module.fields %}
|
||||
{%- if f.type in tests.types and not f.skip_tests%}
|
||||
|
||||
|
||||
|
||||
{%+ set ns = namespace(idx=test_idx) -%}
|
||||
{%- for f in module.fields -%}
|
||||
{%- if f.type in tests.types and not f.skip_tests -%}
|
||||
=== TEST {{ ns.idx }}: {{ modname }}:get_{{ f.field }} (AUTOGEN)
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
|
|
@ -24,9 +26,10 @@
|
|||
"{{ f.sample_printable }}"
|
||||
--- no_error_log
|
||||
[error]
|
||||
{%- set ns.idx = ns.idx + 1 %}
|
||||
|
||||
=== TEST {{ ns.idx }}: {{ modname }}:set_{{ f.field }} (AUTOGEN)
|
||||
|
||||
|
||||
=== TEST {{ ns.idx + 1 }}: {{ modname }}:set_{{ f.field }} (AUTOGEN)
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location =/t {
|
||||
|
|
@ -61,11 +64,14 @@
|
|||
"ok"
|
||||
--- no_error_log
|
||||
[error]
|
||||
{%- set ns.idx = ns.idx + 1 %}
|
||||
{%- endif %}
|
||||
{%- if f.extension_nid and not f.skip_tests %}
|
||||
|
||||
=== TEST {{ ns.idx + 1 }}: {{ modname }}:get/set_{{ f.field }}_critical (AUTOGEN)
|
||||
|
||||
|
||||
{%+ set nop=1 -%}
|
||||
{%- set ns.idx = ns.idx + 2 -%}
|
||||
{%- endif -%}
|
||||
{%- if f.extension_nid and not f.skip_tests -%}
|
||||
=== TEST {{ ns.idx }}: {{ modname }}:get/set_{{ f.field }}_critical (AUTOGEN)
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location =/t {
|
||||
|
|
@ -86,11 +92,14 @@
|
|||
true
|
||||
--- no_error_log
|
||||
[error]
|
||||
{%- set ns.idx = ns.idx + 1 %}
|
||||
{%- endif %}
|
||||
{%- endfor %}
|
||||
|
||||
=== TEST {{ ns.idx + 1 }}: {{ modname }}:get_get_signature_name (AUTOGEN)
|
||||
|
||||
|
||||
{%+ set nop=1 -%}
|
||||
{%- set ns.idx = ns.idx + 1 -%}
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
=== TEST {{ ns.idx }}: {{ modname }}:get_signature_name (AUTOGEN)
|
||||
--- http_config eval: $::HttpConfig
|
||||
--- config
|
||||
location =/t {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ tests = {
|
|||
{
|
||||
"bn": {
|
||||
"new_from": "new(math.random(1, 2333333))",
|
||||
"print": "to_hex():upper",
|
||||
"print": "to_hex",
|
||||
},
|
||||
"number": {
|
||||
"new_from": "ngx.time()",
|
||||
|
|
|
|||
Loading…
Reference in a new issue