mirror of
https://github.com/bunkerity/bunkerweb
synced 2026-05-24 09:28:37 +00:00
Merge pull request #830 from bunkerity/dev
Merge branch "dev" into branch "ui"
This commit is contained in:
commit
020ec53e03
57 changed files with 1952 additions and 584 deletions
2
.github/workflows/push-packagecloud.yml
vendored
2
.github/workflows/push-packagecloud.yml
vendored
|
|
@ -42,7 +42,7 @@ jobs:
|
|||
- name: Check out repository code
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- name: Install ruby
|
||||
uses: ruby/setup-ruby@b256bd96bb4867e7d23e92e087d9bb697270b725 # v1.163.0
|
||||
uses: ruby/setup-ruby@360dc864d5da99d54fcb8e9148c14a84b90d3e88 # v1.165.1
|
||||
with:
|
||||
ruby-version: "3.0"
|
||||
- name: Install packagecloud
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@
|
|||
- [BUGFIX] Fix ModSecurity-nginx to make it work with brotli
|
||||
- [FEATURE] Add Anonymous reporting feature
|
||||
- [FEATURE] Add support for fallback Referrer-Policies
|
||||
- [FEATURE] Add profile page to web ui and the possibility to activate the 2FA
|
||||
- [FEATURE] Add setting REVERSE_PROXY_INCLUDES to manually add "include" directives in the reverse proxies
|
||||
- [MISC] Fallback to default HTTPS certificate to prevent errors
|
||||
- [MISC] Updated Python Docker image to 3.12.1-alpine3.18 in Dockerfiles
|
||||
- [DEPS] Updated ModSecurity to v3.0.11
|
||||
|
|
|
|||
|
|
@ -425,9 +425,9 @@ pygments==2.17.2 \
|
|||
--hash=sha256:b27c2826c47d0f3219f29554824c30c5e8945175d888647acd804ddd04af846c \
|
||||
--hash=sha256:da46cec9fd2de5be3a8a784f434e4c4ab670b4ff54d605c4c2717e9d49c4c367
|
||||
# via mkdocs-material
|
||||
pymdown-extensions==10.5 \
|
||||
--hash=sha256:1b60f1e462adbec5a1ed79dac91f666c9c0d241fa294de1989f29d20096cfd0b \
|
||||
--hash=sha256:1f0ca8bb5beff091315f793ee17683bc1390731f6ac4c5eb01e27464b80fe879
|
||||
pymdown-extensions==10.6 \
|
||||
--hash=sha256:561eb3a5f3c3c2512952a4d6f5b311aa124b7147bd54a3ea0f36ce030c7e3dd9 \
|
||||
--hash=sha256:e4531379e0d74b329ff264217ef5b8b1a37bed3afe36f98001b74ecff52215c0
|
||||
# via mkdocs-material
|
||||
pyparsing==3.1.1 \
|
||||
--hash=sha256:32c7c0b711493c72ff18a981d24f28aaf9c1fb7ed5e9667c9e84e3db623bdbfb \
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ add_header X-Proxy-Cache $upstream_cache_status;
|
|||
{% set connect_timeout = all[k.replace("URL", "CONNECT_TIMEOUT")] if k.replace("URL", "CONNECT_TIMEOUT") in all else "60s" %}
|
||||
{% set read_timeout = all[k.replace("URL", "READ_TIMEOUT")] if k.replace("URL", "READ_TIMEOUT") in all else "60s" %}
|
||||
{% set send_timeout = all[k.replace("URL", "SEND_TIMEOUT")] if k.replace("URL", "SEND_TIMEOUT") in all else "60s" %}
|
||||
{% set includes = all[k.replace("URL", "INCLUDES")] if k.replace("URL", "INCLUDES") in all else "" %}
|
||||
location {{ url }} {% raw %}{{% endraw +%}
|
||||
etag off;
|
||||
set $backend{{ counter.value }} "{{ host }}";
|
||||
|
|
@ -88,6 +89,11 @@ location {{ url }} {% raw %}{{% endraw +%}
|
|||
proxy_connect_timeout {{ connect_timeout }};
|
||||
proxy_read_timeout {{ read_timeout }};
|
||||
proxy_send_timeout {{ send_timeout }};
|
||||
{% if includes != "" +%}
|
||||
{% for include in includes.split(" ") +%}
|
||||
include {{ include }};
|
||||
{% endfor +%}
|
||||
{% endif +%}
|
||||
{% raw %}}{% endraw %}
|
||||
{% endif %}
|
||||
{% set counter.value = counter.value + 1 %}
|
||||
|
|
|
|||
|
|
@ -242,6 +242,16 @@
|
|||
"regex": "^\\d+(ms?|[shdwMy])$",
|
||||
"type": "text",
|
||||
"multiple": "reverse-proxy"
|
||||
},
|
||||
"REVERSE_PROXY_INCLUDES": {
|
||||
"context": "multisite",
|
||||
"default": "",
|
||||
"help": "Additional configuration to include in the location block, separated with spaces.",
|
||||
"id": "reverse-proxy-includes",
|
||||
"label": "Reverse proxy includes",
|
||||
"regex": "^(?! )( ?(\\w+)(?!.*\\b\\2\\b))*$",
|
||||
"type": "text",
|
||||
"multiple": "reverse-proxy"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1700,7 +1700,7 @@ class Database:
|
|||
|
||||
return ""
|
||||
|
||||
def update_ui_user(self, username: str, password: bytes, is_two_factor_enabled: bool = False, secret_token: Optional[str] = None) -> str:
|
||||
def update_ui_user(self, username: str, password: bytes, is_two_factor_enabled: bool = False, secret_token: Optional[str] = None, method: str = "ui") -> str:
|
||||
"""Update ui user."""
|
||||
with self.__db_session() as session:
|
||||
user = session.query(Users).filter_by(id=1).first()
|
||||
|
|
@ -1711,6 +1711,7 @@ class Database:
|
|||
user.password = password.decode("utf-8")
|
||||
user.is_two_factor_enabled = is_two_factor_enabled
|
||||
user.secret_token = secret_token
|
||||
user.method = method
|
||||
|
||||
try:
|
||||
session.commit()
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
cryptography==41.0.7
|
||||
psycopg2-binary==2.9.9
|
||||
PyMySQL==1.1.0
|
||||
sqlalchemy==2.0.23
|
||||
sqlalchemy==2.0.24
|
||||
|
|
|
|||
|
|
@ -225,56 +225,56 @@ pymysql==1.1.0 \
|
|||
--hash=sha256:4f13a7df8bf36a51e81dd9f3605fede45a4878fe02f9236349fd82a3f0612f96 \
|
||||
--hash=sha256:8969ec6d763c856f7073c4c64662882675702efcb114b4bcbb955aea3a069fa7
|
||||
# via -r requirements.in
|
||||
sqlalchemy==2.0.23 \
|
||||
--hash=sha256:0666031df46b9badba9bed00092a1ffa3aa063a5e68fa244acd9f08070e936d3 \
|
||||
--hash=sha256:0a8c6aa506893e25a04233bc721c6b6cf844bafd7250535abb56cb6cc1368884 \
|
||||
--hash=sha256:0e680527245895aba86afbd5bef6c316831c02aa988d1aad83c47ffe92655e74 \
|
||||
--hash=sha256:14aebfe28b99f24f8a4c1346c48bc3d63705b1f919a24c27471136d2f219f02d \
|
||||
--hash=sha256:1e018aba8363adb0599e745af245306cb8c46b9ad0a6fc0a86745b6ff7d940fc \
|
||||
--hash=sha256:227135ef1e48165f37590b8bfc44ed7ff4c074bf04dc8d6f8e7f1c14a94aa6ca \
|
||||
--hash=sha256:31952bbc527d633b9479f5f81e8b9dfada00b91d6baba021a869095f1a97006d \
|
||||
--hash=sha256:3e983fa42164577d073778d06d2cc5d020322425a509a08119bdcee70ad856bf \
|
||||
--hash=sha256:42d0b0290a8fb0165ea2c2781ae66e95cca6e27a2fbe1016ff8db3112ac1e846 \
|
||||
--hash=sha256:42ede90148b73fe4ab4a089f3126b2cfae8cfefc955c8174d697bb46210c8306 \
|
||||
--hash=sha256:4895a63e2c271ffc7a81ea424b94060f7b3b03b4ea0cd58ab5bb676ed02f4221 \
|
||||
--hash=sha256:4af79c06825e2836de21439cb2a6ce22b2ca129bad74f359bddd173f39582bf5 \
|
||||
--hash=sha256:5f94aeb99f43729960638e7468d4688f6efccb837a858b34574e01143cf11f89 \
|
||||
--hash=sha256:616fe7bcff0a05098f64b4478b78ec2dfa03225c23734d83d6c169eb41a93e55 \
|
||||
--hash=sha256:62d9e964870ea5ade4bc870ac4004c456efe75fb50404c03c5fd61f8bc669a72 \
|
||||
--hash=sha256:638c2c0b6b4661a4fd264f6fb804eccd392745c5887f9317feb64bb7cb03b3ea \
|
||||
--hash=sha256:63bfc3acc970776036f6d1d0e65faa7473be9f3135d37a463c5eba5efcdb24c8 \
|
||||
--hash=sha256:6463aa765cf02b9247e38b35853923edbf2f6fd1963df88706bc1d02410a5577 \
|
||||
--hash=sha256:64ac935a90bc479fee77f9463f298943b0e60005fe5de2aa654d9cdef46c54df \
|
||||
--hash=sha256:683ef58ca8eea4747737a1c35c11372ffeb84578d3aab8f3e10b1d13d66f2bc4 \
|
||||
--hash=sha256:75eefe09e98043cff2fb8af9796e20747ae870c903dc61d41b0c2e55128f958d \
|
||||
--hash=sha256:787af80107fb691934a01889ca8f82a44adedbf5ef3d6ad7d0f0b9ac557e0c34 \
|
||||
--hash=sha256:7c424983ab447dab126c39d3ce3be5bee95700783204a72549c3dceffe0fc8f4 \
|
||||
--hash=sha256:7e0dc9031baa46ad0dd5a269cb7a92a73284d1309228be1d5935dac8fb3cae24 \
|
||||
--hash=sha256:87a3d6b53c39cd173990de2f5f4b83431d534a74f0e2f88bd16eabb5667e65c6 \
|
||||
--hash=sha256:89a01238fcb9a8af118eaad3ffcc5dedaacbd429dc6fdc43fe430d3a941ff965 \
|
||||
--hash=sha256:9585b646ffb048c0250acc7dad92536591ffe35dba624bb8fd9b471e25212a35 \
|
||||
--hash=sha256:964971b52daab357d2c0875825e36584d58f536e920f2968df8d581054eada4b \
|
||||
--hash=sha256:967c0b71156f793e6662dd839da54f884631755275ed71f1539c95bbada9aaab \
|
||||
--hash=sha256:9ca922f305d67605668e93991aaf2c12239c78207bca3b891cd51a4515c72e22 \
|
||||
--hash=sha256:a86cb7063e2c9fb8e774f77fbf8475516d270a3e989da55fa05d08089d77f8c4 \
|
||||
--hash=sha256:aeb397de65a0a62f14c257f36a726945a7f7bb60253462e8602d9b97b5cbe204 \
|
||||
--hash=sha256:b41f5d65b54cdf4934ecede2f41b9c60c9f785620416e8e6c48349ab18643855 \
|
||||
--hash=sha256:bd45a5b6c68357578263d74daab6ff9439517f87da63442d244f9f23df56138d \
|
||||
--hash=sha256:c14eba45983d2f48f7546bb32b47937ee2cafae353646295f0e99f35b14286ab \
|
||||
--hash=sha256:c1bda93cbbe4aa2aa0aa8655c5aeda505cd219ff3e8da91d1d329e143e4aff69 \
|
||||
--hash=sha256:c4722f3bc3c1c2fcc3702dbe0016ba31148dd6efcd2a2fd33c1b4897c6a19693 \
|
||||
--hash=sha256:c80c38bd2ea35b97cbf7c21aeb129dcbebbf344ee01a7141016ab7b851464f8e \
|
||||
--hash=sha256:cabafc7837b6cec61c0e1e5c6d14ef250b675fa9c3060ed8a7e38653bd732ff8 \
|
||||
--hash=sha256:cc1d21576f958c42d9aec68eba5c1a7d715e5fc07825a629015fe8e3b0657fb0 \
|
||||
--hash=sha256:d0f7fb0c7527c41fa6fcae2be537ac137f636a41b4c5a4c58914541e2f436b45 \
|
||||
--hash=sha256:d4041ad05b35f1f4da481f6b811b4af2f29e83af253bf37c3c4582b2c68934ab \
|
||||
--hash=sha256:d5578e6863eeb998980c212a39106ea139bdc0b3f73291b96e27c929c90cd8e1 \
|
||||
--hash=sha256:e3b5036aa326dc2df50cba3c958e29b291a80f604b1afa4c8ce73e78e1c9f01d \
|
||||
--hash=sha256:e599a51acf3cc4d31d1a0cf248d8f8d863b6386d2b6782c5074427ebb7803bda \
|
||||
--hash=sha256:f3420d00d2cb42432c1d0e44540ae83185ccbbc67a6054dcc8ab5387add6620b \
|
||||
--hash=sha256:f48ed89dd11c3c586f45e9eec1e437b355b3b6f6884ea4a4c3111a3358fd0c18 \
|
||||
--hash=sha256:f508ba8f89e0a5ecdfd3761f82dda2a3d7b678a626967608f4273e0dba8f07ac \
|
||||
--hash=sha256:fd54601ef9cc455a0c61e5245f690c8a3ad67ddb03d3b91c361d076def0b4c60
|
||||
sqlalchemy==2.0.24 \
|
||||
--hash=sha256:00d76fe5d7cdb5d84d625ce002ce29fefba0bfd98e212ae66793fed30af73931 \
|
||||
--hash=sha256:07cc423892f2ceda9ae1daa28c0355757f362ecc7505b1ab1a3d5d8dc1c44ac6 \
|
||||
--hash=sha256:0bb7cedcddffca98c40bb0becd3423e293d1fef442b869da40843d751785beb3 \
|
||||
--hash=sha256:1ca7903d5e7db791a355b579c690684fac6304478b68efdc7f2ebdcfe770d8d7 \
|
||||
--hash=sha256:1d9b3fd5eca3c0b137a5e0e468e24ca544ed8ca4783e0e55341b7ed2807518ee \
|
||||
--hash=sha256:2587e108463cc2e5b45a896b2e7cc8659a517038026922a758bde009271aed11 \
|
||||
--hash=sha256:29e51f848f843bbd75d74ae64ab1ab06302cb1dccd4549d1f5afe6b4a946edb2 \
|
||||
--hash=sha256:2a479aa1ab199178ff1956b09ca8a0693e70f9c762875d69292d37049ffd0d8f \
|
||||
--hash=sha256:37e89d965b52e8b20571b5d44f26e2124b26ab63758bf1b7598a0e38fb2c4005 \
|
||||
--hash=sha256:38732884eabc64982a09a846bacf085596ff2371e4e41d20c0734f7e50525d01 \
|
||||
--hash=sha256:396f05c552f7fa30a129497c41bef5b4d1423f9af8fe4df0c3dcd38f3e3b9a14 \
|
||||
--hash=sha256:4a1d4856861ba9e73bac05030cec5852eabfa9ef4af8e56c19d92de80d46fc34 \
|
||||
--hash=sha256:56a0e90a959e18ac5f18c80d0cad9e90cb09322764f536e8a637426afb1cae2f \
|
||||
--hash=sha256:57ef6f2cb8b09a042d0dbeaa46a30f2df5dd1e1eb889ba258b0d5d7d6011b81c \
|
||||
--hash=sha256:5f801d85ba4753d4ed97181d003e5d3fa330ac7c4587d131f61d7f968f416862 \
|
||||
--hash=sha256:6db686a1d9f183c639f7e06a2656af25d4ed438eda581de135d15569f16ace33 \
|
||||
--hash=sha256:6db97656fd3fe3f7e5b077f12fa6adb5feb6e0b567a3e99f47ecf5f7ea0a09e3 \
|
||||
--hash=sha256:6f5e75de91c754365c098ac08c13fdb267577ce954fa239dd49228b573ca88d7 \
|
||||
--hash=sha256:7a6209e689d0ff206c40032b6418e3cfcfc5af044b3f66e381d7f1ae301544b4 \
|
||||
--hash=sha256:7ae5d44517fe81079ce75cf10f96978284a6db2642c5932a69c82dbae09f009a \
|
||||
--hash=sha256:83fa6df0e035689df89ff77a46bf8738696785d3156c2c61494acdcddc75c69d \
|
||||
--hash=sha256:8f358f5cfce04417b6ff738748ca4806fe3d3ae8040fb4e6a0c9a6973ccf9b6e \
|
||||
--hash=sha256:9036ebfd934813990c5b9f71f297e77ed4963720db7d7ceec5a3fdb7cd2ef6ce \
|
||||
--hash=sha256:95bae3d38f8808d79072da25d5e5a6095f36fe1f9d6c614dd72c59ca8397c7c0 \
|
||||
--hash=sha256:9aaaaa846b10dfbe1bda71079d0e31a7e2cebedda9409fa7dba3dfed1ae803e8 \
|
||||
--hash=sha256:9b8d0e8578e7f853f45f4512b5c920f6a546cd4bed44137460b2a56534644205 \
|
||||
--hash=sha256:9bafaa05b19dc07fa191c1966c5e852af516840b0d7b46b7c3303faf1a349bc9 \
|
||||
--hash=sha256:9f29c7f0f4b42337ec5a779e166946a9f86d7d56d827e771b69ecbdf426124ac \
|
||||
--hash=sha256:9f992e0f916201731993eab8502912878f02287d9f765ef843677ff118d0e0b1 \
|
||||
--hash=sha256:a04191a7c8d77e63f6fc1e8336d6c6e93176c0c010833e74410e647f0284f5a1 \
|
||||
--hash=sha256:a0f611b431b84f55779cbb7157257d87b4a2876b067c77c4f36b15e44ced65e2 \
|
||||
--hash=sha256:a3c2753bf4f48b7a6024e5e8a394af49b1b12c817d75d06942cae03d14ff87b3 \
|
||||
--hash=sha256:a5cd7d30e47f87b21362beeb3e86f1b5886e7d9b0294b230dde3d3f4a1591375 \
|
||||
--hash=sha256:acc58b7c2e40235712d857fdfc8f2bda9608f4a850d8d9ac0dd1fc80939ca6ac \
|
||||
--hash=sha256:adbd67dac4ebf54587198b63cd30c29fd7eafa8c0cab58893d9419414f8efe4b \
|
||||
--hash=sha256:b35c35e3923ade1e7ac44e150dec29f5863513246c8bf85e2d7d313e3832bcfb \
|
||||
--hash=sha256:c6910eb4ea90c0889f363965cd3c8c45a620ad27b526a7899f0054f6c1b9219e \
|
||||
--hash=sha256:cc889fda484d54d0b31feec409406267616536d048a450fc46943e152700bb79 \
|
||||
--hash=sha256:ccfd336f96d4c9bbab0309f2a565bf15c468c2d8b2d277a32f89c5940f71fcf9 \
|
||||
--hash=sha256:d8e7e8a150e7b548e7ecd6ebb9211c37265991bf2504297d9454e01b58530fc6 \
|
||||
--hash=sha256:db09e424d7bb89b6215a184ca93b4f29d7f00ea261b787918a1af74143b98c06 \
|
||||
--hash=sha256:e17e7e27af178d31b436dda6a596703b02a89ba74a15e2980c35ecd9909eea3a \
|
||||
--hash=sha256:e69290b921b7833c04206f233d6814c60bee1d135b09f5ae5d39229de9b46cd4 \
|
||||
--hash=sha256:e8398593ccc4440ce6dffcc4f47d9b2d72b9fe7112ac12ea4a44e7d4de364db1 \
|
||||
--hash=sha256:e9d036e343a604db3f5a6c33354018a84a1d3f6dcae3673358b404286204798c \
|
||||
--hash=sha256:ea490564435b5b204d8154f0e18387b499ea3cedc1e6af3b3a2ab18291d85aa7 \
|
||||
--hash=sha256:f073321a79c81e1a009218a21089f61d87ee5fa3c9563f6be94f8b41ff181812 \
|
||||
--hash=sha256:f0cc0b486a56dff72dddae6b6bfa7ff201b0eeac29d4bc6f0e9725dc3c360d71 \
|
||||
--hash=sha256:fcf84fe93397a0f67733aa2a38ed4eab9fc6348189fc950e656e1ea198f45668
|
||||
# via -r requirements.in
|
||||
typing-extensions==4.9.0 \
|
||||
--hash=sha256:23478f88c37f27d76ac8aee6c905017a143b0b1b886c3c9f66bc2fd94f9f5783 \
|
||||
|
|
|
|||
|
|
@ -151,9 +151,9 @@
|
|||
},
|
||||
{
|
||||
"id": "lua-resty-openssl",
|
||||
"name": "lua-resty-openssl v1.0.2",
|
||||
"name": "lua-resty-openssl v1.2.0",
|
||||
"url": "https://github.com/fffonion/lua-resty-openssl.git",
|
||||
"commit": "5aba923e78ae0f213f3b4719effa879e3971821f",
|
||||
"commit": "7f25f00ba2b2140b794c94b5ae17f5a0736e3b03",
|
||||
"post_install": "rm -r src/deps/src/lua-resty-openssl/t"
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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()",
|
||||
|
|
|
|||
|
|
@ -1660,6 +1660,7 @@ def jobs_download():
|
|||
def login():
|
||||
fail = False
|
||||
if request.method == "POST" and "username" in request.form and "password" in request.form:
|
||||
app.logger.warning(f"Login attempt from {request.remote_addr} with username \"{request.form['username']}\"")
|
||||
if app.config["USER"].get_id() == request.form["username"] and app.config["USER"].check_password(request.form["password"]):
|
||||
# log the user in
|
||||
session["ip"] = request.remote_addr
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
fastapi==0.106.0
|
||||
fastapi==0.108.0
|
||||
uvicorn[standard]==0.25.0
|
||||
|
|
|
|||
|
|
@ -8,11 +8,10 @@ annotated-types==0.6.0 \
|
|||
--hash=sha256:0641064de18ba7a25dee8f96403ebc39113d0cb953a01429249d5c7564666a43 \
|
||||
--hash=sha256:563339e807e53ffd9c267e99fc6d9ea23eb8443c08f112651963e24e22f84a5d
|
||||
# via pydantic
|
||||
anyio==3.7.1 \
|
||||
--hash=sha256:44a3c9aba0f5defa43261a8b3efb97891f2bd7d804e0e1f56419befa1adfc780 \
|
||||
--hash=sha256:91dee416e570e92c64041bd18b900d1d6fa78dff7048769ce5ac5ddad004fbb5
|
||||
anyio==4.2.0 \
|
||||
--hash=sha256:745843b39e829e108e518c489b31dc757de7d2131d53fac32bd8df268227bfee \
|
||||
--hash=sha256:e1875bb4b4e2de1669f4bc7869b6d3f54231cdced71605e6e64c9be77e3be50f
|
||||
# via
|
||||
# fastapi
|
||||
# starlette
|
||||
# watchfiles
|
||||
click==8.1.7 \
|
||||
|
|
@ -23,9 +22,9 @@ exceptiongroup==1.2.0 \
|
|||
--hash=sha256:4bfd3996ac73b41e9b9628b04e079f193850720ea5945fc96a08633c66912f14 \
|
||||
--hash=sha256:91f5c769735f051a4290d52edd0858999b57e5876e9f85937691bd4c9fa3ed68
|
||||
# via anyio
|
||||
fastapi==0.106.0 \
|
||||
--hash=sha256:193c2f1b495d1d6561a3dc1ca02a150757322247d895ff6bf15b6eefee24feb9 \
|
||||
--hash=sha256:c7e7453ac8c4b7414bbafcf90127d743559808eee286ae2c9f99a501f0b534a0
|
||||
fastapi==0.108.0 \
|
||||
--hash=sha256:5056e504ac6395bf68493d71fcfc5352fdbd5fda6f88c21f6420d80d81163296 \
|
||||
--hash=sha256:8c7bc6d315da963ee4cdb605557827071a9a7f95aeb8fcdd3bde48cdc8764dd7
|
||||
# via -r requirements.in
|
||||
h11==0.14.0 \
|
||||
--hash=sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d \
|
||||
|
|
@ -244,14 +243,15 @@ sniffio==1.3.0 \
|
|||
--hash=sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101 \
|
||||
--hash=sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384
|
||||
# via anyio
|
||||
starlette==0.27.0 \
|
||||
--hash=sha256:6a6b0d042acb8d469a01eba54e9cda6cbd24ac602c4cd016723117d6a7e73b75 \
|
||||
--hash=sha256:918416370e846586541235ccd38a474c08b80443ed31c578a418e2209b3eef91
|
||||
starlette==0.32.0.post1 \
|
||||
--hash=sha256:cd0cb10ddb49313f609cedfac62c8c12e56c7314b66d89bb077ba228bada1b09 \
|
||||
--hash=sha256:e54e2b7e2fb06dff9eac40133583f10dfa05913f5a85bf26f427c7a40a9a3d02
|
||||
# via fastapi
|
||||
typing-extensions==4.9.0 \
|
||||
--hash=sha256:23478f88c37f27d76ac8aee6c905017a143b0b1b886c3c9f66bc2fd94f9f5783 \
|
||||
--hash=sha256:af72aea155e91adfc61c3ae9e0e342dbc0cba726d6cba4b6c72c1f34e47291cd
|
||||
# via
|
||||
# anyio
|
||||
# fastapi
|
||||
# pydantic
|
||||
# pydantic-core
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
fastapi==0.106.0
|
||||
fastapi==0.108.0
|
||||
uvicorn[standard]==0.25.0
|
||||
|
|
|
|||
|
|
@ -8,11 +8,10 @@ annotated-types==0.6.0 \
|
|||
--hash=sha256:0641064de18ba7a25dee8f96403ebc39113d0cb953a01429249d5c7564666a43 \
|
||||
--hash=sha256:563339e807e53ffd9c267e99fc6d9ea23eb8443c08f112651963e24e22f84a5d
|
||||
# via pydantic
|
||||
anyio==3.7.1 \
|
||||
--hash=sha256:44a3c9aba0f5defa43261a8b3efb97891f2bd7d804e0e1f56419befa1adfc780 \
|
||||
--hash=sha256:91dee416e570e92c64041bd18b900d1d6fa78dff7048769ce5ac5ddad004fbb5
|
||||
anyio==4.2.0 \
|
||||
--hash=sha256:745843b39e829e108e518c489b31dc757de7d2131d53fac32bd8df268227bfee \
|
||||
--hash=sha256:e1875bb4b4e2de1669f4bc7869b6d3f54231cdced71605e6e64c9be77e3be50f
|
||||
# via
|
||||
# fastapi
|
||||
# starlette
|
||||
# watchfiles
|
||||
click==8.1.7 \
|
||||
|
|
@ -23,9 +22,9 @@ exceptiongroup==1.2.0 \
|
|||
--hash=sha256:4bfd3996ac73b41e9b9628b04e079f193850720ea5945fc96a08633c66912f14 \
|
||||
--hash=sha256:91f5c769735f051a4290d52edd0858999b57e5876e9f85937691bd4c9fa3ed68
|
||||
# via anyio
|
||||
fastapi==0.106.0 \
|
||||
--hash=sha256:193c2f1b495d1d6561a3dc1ca02a150757322247d895ff6bf15b6eefee24feb9 \
|
||||
--hash=sha256:c7e7453ac8c4b7414bbafcf90127d743559808eee286ae2c9f99a501f0b534a0
|
||||
fastapi==0.108.0 \
|
||||
--hash=sha256:5056e504ac6395bf68493d71fcfc5352fdbd5fda6f88c21f6420d80d81163296 \
|
||||
--hash=sha256:8c7bc6d315da963ee4cdb605557827071a9a7f95aeb8fcdd3bde48cdc8764dd7
|
||||
# via -r requirements.in
|
||||
h11==0.14.0 \
|
||||
--hash=sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d \
|
||||
|
|
@ -244,14 +243,15 @@ sniffio==1.3.0 \
|
|||
--hash=sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101 \
|
||||
--hash=sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384
|
||||
# via anyio
|
||||
starlette==0.27.0 \
|
||||
--hash=sha256:6a6b0d042acb8d469a01eba54e9cda6cbd24ac602c4cd016723117d6a7e73b75 \
|
||||
--hash=sha256:918416370e846586541235ccd38a474c08b80443ed31c578a418e2209b3eef91
|
||||
starlette==0.32.0.post1 \
|
||||
--hash=sha256:cd0cb10ddb49313f609cedfac62c8c12e56c7314b66d89bb077ba228bada1b09 \
|
||||
--hash=sha256:e54e2b7e2fb06dff9eac40133583f10dfa05913f5a85bf26f427c7a40a9a3d02
|
||||
# via fastapi
|
||||
typing-extensions==4.9.0 \
|
||||
--hash=sha256:23478f88c37f27d76ac8aee6c905017a143b0b1b886c3c9f66bc2fd94f9f5783 \
|
||||
--hash=sha256:af72aea155e91adfc61c3ae9e0e342dbc0cba726d6cba4b6c72c1f34e47291cd
|
||||
# via
|
||||
# anyio
|
||||
# fastapi
|
||||
# pydantic
|
||||
# pydantic-core
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
cryptography==41.0.7
|
||||
psycopg2-binary==2.9.9
|
||||
PyMySQL==1.1.0
|
||||
sqlalchemy==2.0.23
|
||||
sqlalchemy==2.0.24
|
||||
|
|
|
|||
|
|
@ -225,56 +225,56 @@ pymysql==1.1.0 \
|
|||
--hash=sha256:4f13a7df8bf36a51e81dd9f3605fede45a4878fe02f9236349fd82a3f0612f96 \
|
||||
--hash=sha256:8969ec6d763c856f7073c4c64662882675702efcb114b4bcbb955aea3a069fa7
|
||||
# via -r requirements.in
|
||||
sqlalchemy==2.0.23 \
|
||||
--hash=sha256:0666031df46b9badba9bed00092a1ffa3aa063a5e68fa244acd9f08070e936d3 \
|
||||
--hash=sha256:0a8c6aa506893e25a04233bc721c6b6cf844bafd7250535abb56cb6cc1368884 \
|
||||
--hash=sha256:0e680527245895aba86afbd5bef6c316831c02aa988d1aad83c47ffe92655e74 \
|
||||
--hash=sha256:14aebfe28b99f24f8a4c1346c48bc3d63705b1f919a24c27471136d2f219f02d \
|
||||
--hash=sha256:1e018aba8363adb0599e745af245306cb8c46b9ad0a6fc0a86745b6ff7d940fc \
|
||||
--hash=sha256:227135ef1e48165f37590b8bfc44ed7ff4c074bf04dc8d6f8e7f1c14a94aa6ca \
|
||||
--hash=sha256:31952bbc527d633b9479f5f81e8b9dfada00b91d6baba021a869095f1a97006d \
|
||||
--hash=sha256:3e983fa42164577d073778d06d2cc5d020322425a509a08119bdcee70ad856bf \
|
||||
--hash=sha256:42d0b0290a8fb0165ea2c2781ae66e95cca6e27a2fbe1016ff8db3112ac1e846 \
|
||||
--hash=sha256:42ede90148b73fe4ab4a089f3126b2cfae8cfefc955c8174d697bb46210c8306 \
|
||||
--hash=sha256:4895a63e2c271ffc7a81ea424b94060f7b3b03b4ea0cd58ab5bb676ed02f4221 \
|
||||
--hash=sha256:4af79c06825e2836de21439cb2a6ce22b2ca129bad74f359bddd173f39582bf5 \
|
||||
--hash=sha256:5f94aeb99f43729960638e7468d4688f6efccb837a858b34574e01143cf11f89 \
|
||||
--hash=sha256:616fe7bcff0a05098f64b4478b78ec2dfa03225c23734d83d6c169eb41a93e55 \
|
||||
--hash=sha256:62d9e964870ea5ade4bc870ac4004c456efe75fb50404c03c5fd61f8bc669a72 \
|
||||
--hash=sha256:638c2c0b6b4661a4fd264f6fb804eccd392745c5887f9317feb64bb7cb03b3ea \
|
||||
--hash=sha256:63bfc3acc970776036f6d1d0e65faa7473be9f3135d37a463c5eba5efcdb24c8 \
|
||||
--hash=sha256:6463aa765cf02b9247e38b35853923edbf2f6fd1963df88706bc1d02410a5577 \
|
||||
--hash=sha256:64ac935a90bc479fee77f9463f298943b0e60005fe5de2aa654d9cdef46c54df \
|
||||
--hash=sha256:683ef58ca8eea4747737a1c35c11372ffeb84578d3aab8f3e10b1d13d66f2bc4 \
|
||||
--hash=sha256:75eefe09e98043cff2fb8af9796e20747ae870c903dc61d41b0c2e55128f958d \
|
||||
--hash=sha256:787af80107fb691934a01889ca8f82a44adedbf5ef3d6ad7d0f0b9ac557e0c34 \
|
||||
--hash=sha256:7c424983ab447dab126c39d3ce3be5bee95700783204a72549c3dceffe0fc8f4 \
|
||||
--hash=sha256:7e0dc9031baa46ad0dd5a269cb7a92a73284d1309228be1d5935dac8fb3cae24 \
|
||||
--hash=sha256:87a3d6b53c39cd173990de2f5f4b83431d534a74f0e2f88bd16eabb5667e65c6 \
|
||||
--hash=sha256:89a01238fcb9a8af118eaad3ffcc5dedaacbd429dc6fdc43fe430d3a941ff965 \
|
||||
--hash=sha256:9585b646ffb048c0250acc7dad92536591ffe35dba624bb8fd9b471e25212a35 \
|
||||
--hash=sha256:964971b52daab357d2c0875825e36584d58f536e920f2968df8d581054eada4b \
|
||||
--hash=sha256:967c0b71156f793e6662dd839da54f884631755275ed71f1539c95bbada9aaab \
|
||||
--hash=sha256:9ca922f305d67605668e93991aaf2c12239c78207bca3b891cd51a4515c72e22 \
|
||||
--hash=sha256:a86cb7063e2c9fb8e774f77fbf8475516d270a3e989da55fa05d08089d77f8c4 \
|
||||
--hash=sha256:aeb397de65a0a62f14c257f36a726945a7f7bb60253462e8602d9b97b5cbe204 \
|
||||
--hash=sha256:b41f5d65b54cdf4934ecede2f41b9c60c9f785620416e8e6c48349ab18643855 \
|
||||
--hash=sha256:bd45a5b6c68357578263d74daab6ff9439517f87da63442d244f9f23df56138d \
|
||||
--hash=sha256:c14eba45983d2f48f7546bb32b47937ee2cafae353646295f0e99f35b14286ab \
|
||||
--hash=sha256:c1bda93cbbe4aa2aa0aa8655c5aeda505cd219ff3e8da91d1d329e143e4aff69 \
|
||||
--hash=sha256:c4722f3bc3c1c2fcc3702dbe0016ba31148dd6efcd2a2fd33c1b4897c6a19693 \
|
||||
--hash=sha256:c80c38bd2ea35b97cbf7c21aeb129dcbebbf344ee01a7141016ab7b851464f8e \
|
||||
--hash=sha256:cabafc7837b6cec61c0e1e5c6d14ef250b675fa9c3060ed8a7e38653bd732ff8 \
|
||||
--hash=sha256:cc1d21576f958c42d9aec68eba5c1a7d715e5fc07825a629015fe8e3b0657fb0 \
|
||||
--hash=sha256:d0f7fb0c7527c41fa6fcae2be537ac137f636a41b4c5a4c58914541e2f436b45 \
|
||||
--hash=sha256:d4041ad05b35f1f4da481f6b811b4af2f29e83af253bf37c3c4582b2c68934ab \
|
||||
--hash=sha256:d5578e6863eeb998980c212a39106ea139bdc0b3f73291b96e27c929c90cd8e1 \
|
||||
--hash=sha256:e3b5036aa326dc2df50cba3c958e29b291a80f604b1afa4c8ce73e78e1c9f01d \
|
||||
--hash=sha256:e599a51acf3cc4d31d1a0cf248d8f8d863b6386d2b6782c5074427ebb7803bda \
|
||||
--hash=sha256:f3420d00d2cb42432c1d0e44540ae83185ccbbc67a6054dcc8ab5387add6620b \
|
||||
--hash=sha256:f48ed89dd11c3c586f45e9eec1e437b355b3b6f6884ea4a4c3111a3358fd0c18 \
|
||||
--hash=sha256:f508ba8f89e0a5ecdfd3761f82dda2a3d7b678a626967608f4273e0dba8f07ac \
|
||||
--hash=sha256:fd54601ef9cc455a0c61e5245f690c8a3ad67ddb03d3b91c361d076def0b4c60
|
||||
sqlalchemy==2.0.24 \
|
||||
--hash=sha256:00d76fe5d7cdb5d84d625ce002ce29fefba0bfd98e212ae66793fed30af73931 \
|
||||
--hash=sha256:07cc423892f2ceda9ae1daa28c0355757f362ecc7505b1ab1a3d5d8dc1c44ac6 \
|
||||
--hash=sha256:0bb7cedcddffca98c40bb0becd3423e293d1fef442b869da40843d751785beb3 \
|
||||
--hash=sha256:1ca7903d5e7db791a355b579c690684fac6304478b68efdc7f2ebdcfe770d8d7 \
|
||||
--hash=sha256:1d9b3fd5eca3c0b137a5e0e468e24ca544ed8ca4783e0e55341b7ed2807518ee \
|
||||
--hash=sha256:2587e108463cc2e5b45a896b2e7cc8659a517038026922a758bde009271aed11 \
|
||||
--hash=sha256:29e51f848f843bbd75d74ae64ab1ab06302cb1dccd4549d1f5afe6b4a946edb2 \
|
||||
--hash=sha256:2a479aa1ab199178ff1956b09ca8a0693e70f9c762875d69292d37049ffd0d8f \
|
||||
--hash=sha256:37e89d965b52e8b20571b5d44f26e2124b26ab63758bf1b7598a0e38fb2c4005 \
|
||||
--hash=sha256:38732884eabc64982a09a846bacf085596ff2371e4e41d20c0734f7e50525d01 \
|
||||
--hash=sha256:396f05c552f7fa30a129497c41bef5b4d1423f9af8fe4df0c3dcd38f3e3b9a14 \
|
||||
--hash=sha256:4a1d4856861ba9e73bac05030cec5852eabfa9ef4af8e56c19d92de80d46fc34 \
|
||||
--hash=sha256:56a0e90a959e18ac5f18c80d0cad9e90cb09322764f536e8a637426afb1cae2f \
|
||||
--hash=sha256:57ef6f2cb8b09a042d0dbeaa46a30f2df5dd1e1eb889ba258b0d5d7d6011b81c \
|
||||
--hash=sha256:5f801d85ba4753d4ed97181d003e5d3fa330ac7c4587d131f61d7f968f416862 \
|
||||
--hash=sha256:6db686a1d9f183c639f7e06a2656af25d4ed438eda581de135d15569f16ace33 \
|
||||
--hash=sha256:6db97656fd3fe3f7e5b077f12fa6adb5feb6e0b567a3e99f47ecf5f7ea0a09e3 \
|
||||
--hash=sha256:6f5e75de91c754365c098ac08c13fdb267577ce954fa239dd49228b573ca88d7 \
|
||||
--hash=sha256:7a6209e689d0ff206c40032b6418e3cfcfc5af044b3f66e381d7f1ae301544b4 \
|
||||
--hash=sha256:7ae5d44517fe81079ce75cf10f96978284a6db2642c5932a69c82dbae09f009a \
|
||||
--hash=sha256:83fa6df0e035689df89ff77a46bf8738696785d3156c2c61494acdcddc75c69d \
|
||||
--hash=sha256:8f358f5cfce04417b6ff738748ca4806fe3d3ae8040fb4e6a0c9a6973ccf9b6e \
|
||||
--hash=sha256:9036ebfd934813990c5b9f71f297e77ed4963720db7d7ceec5a3fdb7cd2ef6ce \
|
||||
--hash=sha256:95bae3d38f8808d79072da25d5e5a6095f36fe1f9d6c614dd72c59ca8397c7c0 \
|
||||
--hash=sha256:9aaaaa846b10dfbe1bda71079d0e31a7e2cebedda9409fa7dba3dfed1ae803e8 \
|
||||
--hash=sha256:9b8d0e8578e7f853f45f4512b5c920f6a546cd4bed44137460b2a56534644205 \
|
||||
--hash=sha256:9bafaa05b19dc07fa191c1966c5e852af516840b0d7b46b7c3303faf1a349bc9 \
|
||||
--hash=sha256:9f29c7f0f4b42337ec5a779e166946a9f86d7d56d827e771b69ecbdf426124ac \
|
||||
--hash=sha256:9f992e0f916201731993eab8502912878f02287d9f765ef843677ff118d0e0b1 \
|
||||
--hash=sha256:a04191a7c8d77e63f6fc1e8336d6c6e93176c0c010833e74410e647f0284f5a1 \
|
||||
--hash=sha256:a0f611b431b84f55779cbb7157257d87b4a2876b067c77c4f36b15e44ced65e2 \
|
||||
--hash=sha256:a3c2753bf4f48b7a6024e5e8a394af49b1b12c817d75d06942cae03d14ff87b3 \
|
||||
--hash=sha256:a5cd7d30e47f87b21362beeb3e86f1b5886e7d9b0294b230dde3d3f4a1591375 \
|
||||
--hash=sha256:acc58b7c2e40235712d857fdfc8f2bda9608f4a850d8d9ac0dd1fc80939ca6ac \
|
||||
--hash=sha256:adbd67dac4ebf54587198b63cd30c29fd7eafa8c0cab58893d9419414f8efe4b \
|
||||
--hash=sha256:b35c35e3923ade1e7ac44e150dec29f5863513246c8bf85e2d7d313e3832bcfb \
|
||||
--hash=sha256:c6910eb4ea90c0889f363965cd3c8c45a620ad27b526a7899f0054f6c1b9219e \
|
||||
--hash=sha256:cc889fda484d54d0b31feec409406267616536d048a450fc46943e152700bb79 \
|
||||
--hash=sha256:ccfd336f96d4c9bbab0309f2a565bf15c468c2d8b2d277a32f89c5940f71fcf9 \
|
||||
--hash=sha256:d8e7e8a150e7b548e7ecd6ebb9211c37265991bf2504297d9454e01b58530fc6 \
|
||||
--hash=sha256:db09e424d7bb89b6215a184ca93b4f29d7f00ea261b787918a1af74143b98c06 \
|
||||
--hash=sha256:e17e7e27af178d31b436dda6a596703b02a89ba74a15e2980c35ecd9909eea3a \
|
||||
--hash=sha256:e69290b921b7833c04206f233d6814c60bee1d135b09f5ae5d39229de9b46cd4 \
|
||||
--hash=sha256:e8398593ccc4440ce6dffcc4f47d9b2d72b9fe7112ac12ea4a44e7d4de364db1 \
|
||||
--hash=sha256:e9d036e343a604db3f5a6c33354018a84a1d3f6dcae3673358b404286204798c \
|
||||
--hash=sha256:ea490564435b5b204d8154f0e18387b499ea3cedc1e6af3b3a2ab18291d85aa7 \
|
||||
--hash=sha256:f073321a79c81e1a009218a21089f61d87ee5fa3c9563f6be94f8b41ff181812 \
|
||||
--hash=sha256:f0cc0b486a56dff72dddae6b6bfa7ff201b0eeac29d4bc6f0e9725dc3c360d71 \
|
||||
--hash=sha256:fcf84fe93397a0f67733aa2a38ed4eab9fc6348189fc950e656e1ea198f45668
|
||||
# via -r requirements.in
|
||||
typing-extensions==4.9.0 \
|
||||
--hash=sha256:23478f88c37f27d76ac8aee6c905017a143b0b1b886c3c9f66bc2fd94f9f5783 \
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
fastapi==0.106.0
|
||||
fastapi==0.108.0
|
||||
uvicorn[standard]==0.25.0
|
||||
|
|
|
|||
|
|
@ -8,11 +8,10 @@ annotated-types==0.6.0 \
|
|||
--hash=sha256:0641064de18ba7a25dee8f96403ebc39113d0cb953a01429249d5c7564666a43 \
|
||||
--hash=sha256:563339e807e53ffd9c267e99fc6d9ea23eb8443c08f112651963e24e22f84a5d
|
||||
# via pydantic
|
||||
anyio==3.7.1 \
|
||||
--hash=sha256:44a3c9aba0f5defa43261a8b3efb97891f2bd7d804e0e1f56419befa1adfc780 \
|
||||
--hash=sha256:91dee416e570e92c64041bd18b900d1d6fa78dff7048769ce5ac5ddad004fbb5
|
||||
anyio==4.2.0 \
|
||||
--hash=sha256:745843b39e829e108e518c489b31dc757de7d2131d53fac32bd8df268227bfee \
|
||||
--hash=sha256:e1875bb4b4e2de1669f4bc7869b6d3f54231cdced71605e6e64c9be77e3be50f
|
||||
# via
|
||||
# fastapi
|
||||
# starlette
|
||||
# watchfiles
|
||||
click==8.1.7 \
|
||||
|
|
@ -23,9 +22,9 @@ exceptiongroup==1.2.0 \
|
|||
--hash=sha256:4bfd3996ac73b41e9b9628b04e079f193850720ea5945fc96a08633c66912f14 \
|
||||
--hash=sha256:91f5c769735f051a4290d52edd0858999b57e5876e9f85937691bd4c9fa3ed68
|
||||
# via anyio
|
||||
fastapi==0.106.0 \
|
||||
--hash=sha256:193c2f1b495d1d6561a3dc1ca02a150757322247d895ff6bf15b6eefee24feb9 \
|
||||
--hash=sha256:c7e7453ac8c4b7414bbafcf90127d743559808eee286ae2c9f99a501f0b534a0
|
||||
fastapi==0.108.0 \
|
||||
--hash=sha256:5056e504ac6395bf68493d71fcfc5352fdbd5fda6f88c21f6420d80d81163296 \
|
||||
--hash=sha256:8c7bc6d315da963ee4cdb605557827071a9a7f95aeb8fcdd3bde48cdc8764dd7
|
||||
# via -r requirements.in
|
||||
h11==0.14.0 \
|
||||
--hash=sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d \
|
||||
|
|
@ -244,14 +243,15 @@ sniffio==1.3.0 \
|
|||
--hash=sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101 \
|
||||
--hash=sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384
|
||||
# via anyio
|
||||
starlette==0.27.0 \
|
||||
--hash=sha256:6a6b0d042acb8d469a01eba54e9cda6cbd24ac602c4cd016723117d6a7e73b75 \
|
||||
--hash=sha256:918416370e846586541235ccd38a474c08b80443ed31c578a418e2209b3eef91
|
||||
starlette==0.32.0.post1 \
|
||||
--hash=sha256:cd0cb10ddb49313f609cedfac62c8c12e56c7314b66d89bb077ba228bada1b09 \
|
||||
--hash=sha256:e54e2b7e2fb06dff9eac40133583f10dfa05913f5a85bf26f427c7a40a9a3d02
|
||||
# via fastapi
|
||||
typing-extensions==4.9.0 \
|
||||
--hash=sha256:23478f88c37f27d76ac8aee6c905017a143b0b1b886c3c9f66bc2fd94f9f5783 \
|
||||
--hash=sha256:af72aea155e91adfc61c3ae9e0e342dbc0cba726d6cba4b6c72c1f34e47291cd
|
||||
# via
|
||||
# anyio
|
||||
# fastapi
|
||||
# pydantic
|
||||
# pydantic-core
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
fastapi==0.106.0
|
||||
fastapi==0.108.0
|
||||
redis==5.0.1
|
||||
requests==2.31.0
|
||||
selenium==4.16.0
|
||||
|
|
|
|||
|
|
@ -8,11 +8,10 @@ annotated-types==0.6.0 \
|
|||
--hash=sha256:0641064de18ba7a25dee8f96403ebc39113d0cb953a01429249d5c7564666a43 \
|
||||
--hash=sha256:563339e807e53ffd9c267e99fc6d9ea23eb8443c08f112651963e24e22f84a5d
|
||||
# via pydantic
|
||||
anyio==3.7.1 \
|
||||
--hash=sha256:44a3c9aba0f5defa43261a8b3efb97891f2bd7d804e0e1f56419befa1adfc780 \
|
||||
--hash=sha256:91dee416e570e92c64041bd18b900d1d6fa78dff7048769ce5ac5ddad004fbb5
|
||||
anyio==4.2.0 \
|
||||
--hash=sha256:745843b39e829e108e518c489b31dc757de7d2131d53fac32bd8df268227bfee \
|
||||
--hash=sha256:e1875bb4b4e2de1669f4bc7869b6d3f54231cdced71605e6e64c9be77e3be50f
|
||||
# via
|
||||
# fastapi
|
||||
# starlette
|
||||
# watchfiles
|
||||
async-timeout==4.0.3 \
|
||||
|
|
@ -134,9 +133,9 @@ exceptiongroup==1.2.0 \
|
|||
# anyio
|
||||
# trio
|
||||
# trio-websocket
|
||||
fastapi==0.106.0 \
|
||||
--hash=sha256:193c2f1b495d1d6561a3dc1ca02a150757322247d895ff6bf15b6eefee24feb9 \
|
||||
--hash=sha256:c7e7453ac8c4b7414bbafcf90127d743559808eee286ae2c9f99a501f0b534a0
|
||||
fastapi==0.108.0 \
|
||||
--hash=sha256:5056e504ac6395bf68493d71fcfc5352fdbd5fda6f88c21f6420d80d81163296 \
|
||||
--hash=sha256:8c7bc6d315da963ee4cdb605557827071a9a7f95aeb8fcdd3bde48cdc8764dd7
|
||||
# via -r requirements.in
|
||||
h11==0.14.0 \
|
||||
--hash=sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d \
|
||||
|
|
@ -387,9 +386,9 @@ sortedcontainers==2.4.0 \
|
|||
--hash=sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88 \
|
||||
--hash=sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0
|
||||
# via trio
|
||||
starlette==0.27.0 \
|
||||
--hash=sha256:6a6b0d042acb8d469a01eba54e9cda6cbd24ac602c4cd016723117d6a7e73b75 \
|
||||
--hash=sha256:918416370e846586541235ccd38a474c08b80443ed31c578a418e2209b3eef91
|
||||
starlette==0.32.0.post1 \
|
||||
--hash=sha256:cd0cb10ddb49313f609cedfac62c8c12e56c7314b66d89bb077ba228bada1b09 \
|
||||
--hash=sha256:e54e2b7e2fb06dff9eac40133583f10dfa05913f5a85bf26f427c7a40a9a3d02
|
||||
# via fastapi
|
||||
trio==0.23.2 \
|
||||
--hash=sha256:5a0b566fa5d50cf231cfd6b08f3b03aa4179ff004b8f3144059587039e2b26d3 \
|
||||
|
|
@ -405,6 +404,7 @@ typing-extensions==4.9.0 \
|
|||
--hash=sha256:23478f88c37f27d76ac8aee6c905017a143b0b1b886c3c9f66bc2fd94f9f5783 \
|
||||
--hash=sha256:af72aea155e91adfc61c3ae9e0e342dbc0cba726d6cba4b6c72c1f34e47291cd
|
||||
# via
|
||||
# anyio
|
||||
# fastapi
|
||||
# pydantic
|
||||
# pydantic-core
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
fastapi==0.106.0
|
||||
fastapi==0.108.0
|
||||
requests==2.31.0
|
||||
uvicorn[standard]==0.25.0
|
||||
|
|
|
|||
|
|
@ -8,11 +8,10 @@ annotated-types==0.6.0 \
|
|||
--hash=sha256:0641064de18ba7a25dee8f96403ebc39113d0cb953a01429249d5c7564666a43 \
|
||||
--hash=sha256:563339e807e53ffd9c267e99fc6d9ea23eb8443c08f112651963e24e22f84a5d
|
||||
# via pydantic
|
||||
anyio==3.7.1 \
|
||||
--hash=sha256:44a3c9aba0f5defa43261a8b3efb97891f2bd7d804e0e1f56419befa1adfc780 \
|
||||
--hash=sha256:91dee416e570e92c64041bd18b900d1d6fa78dff7048769ce5ac5ddad004fbb5
|
||||
anyio==4.2.0 \
|
||||
--hash=sha256:745843b39e829e108e518c489b31dc757de7d2131d53fac32bd8df268227bfee \
|
||||
--hash=sha256:e1875bb4b4e2de1669f4bc7869b6d3f54231cdced71605e6e64c9be77e3be50f
|
||||
# via
|
||||
# fastapi
|
||||
# starlette
|
||||
# watchfiles
|
||||
certifi==2023.11.17 \
|
||||
|
|
@ -119,9 +118,9 @@ exceptiongroup==1.2.0 \
|
|||
--hash=sha256:4bfd3996ac73b41e9b9628b04e079f193850720ea5945fc96a08633c66912f14 \
|
||||
--hash=sha256:91f5c769735f051a4290d52edd0858999b57e5876e9f85937691bd4c9fa3ed68
|
||||
# via anyio
|
||||
fastapi==0.106.0 \
|
||||
--hash=sha256:193c2f1b495d1d6561a3dc1ca02a150757322247d895ff6bf15b6eefee24feb9 \
|
||||
--hash=sha256:c7e7453ac8c4b7414bbafcf90127d743559808eee286ae2c9f99a501f0b534a0
|
||||
fastapi==0.108.0 \
|
||||
--hash=sha256:5056e504ac6395bf68493d71fcfc5352fdbd5fda6f88c21f6420d80d81163296 \
|
||||
--hash=sha256:8c7bc6d315da963ee4cdb605557827071a9a7f95aeb8fcdd3bde48cdc8764dd7
|
||||
# via -r requirements.in
|
||||
h11==0.14.0 \
|
||||
--hash=sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d \
|
||||
|
|
@ -346,14 +345,15 @@ sniffio==1.3.0 \
|
|||
--hash=sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101 \
|
||||
--hash=sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384
|
||||
# via anyio
|
||||
starlette==0.27.0 \
|
||||
--hash=sha256:6a6b0d042acb8d469a01eba54e9cda6cbd24ac602c4cd016723117d6a7e73b75 \
|
||||
--hash=sha256:918416370e846586541235ccd38a474c08b80443ed31c578a418e2209b3eef91
|
||||
starlette==0.32.0.post1 \
|
||||
--hash=sha256:cd0cb10ddb49313f609cedfac62c8c12e56c7314b66d89bb077ba228bada1b09 \
|
||||
--hash=sha256:e54e2b7e2fb06dff9eac40133583f10dfa05913f5a85bf26f427c7a40a9a3d02
|
||||
# via fastapi
|
||||
typing-extensions==4.9.0 \
|
||||
--hash=sha256:23478f88c37f27d76ac8aee6c905017a143b0b1b886c3c9f66bc2fd94f9f5783 \
|
||||
--hash=sha256:af72aea155e91adfc61c3ae9e0e342dbc0cba726d6cba4b6c72c1f34e47291cd
|
||||
# via
|
||||
# anyio
|
||||
# fastapi
|
||||
# pydantic
|
||||
# pydantic-core
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
fastapi==0.106.0
|
||||
fastapi==0.108.0
|
||||
uvicorn[standard]==0.25.0
|
||||
|
|
|
|||
|
|
@ -8,11 +8,10 @@ annotated-types==0.6.0 \
|
|||
--hash=sha256:0641064de18ba7a25dee8f96403ebc39113d0cb953a01429249d5c7564666a43 \
|
||||
--hash=sha256:563339e807e53ffd9c267e99fc6d9ea23eb8443c08f112651963e24e22f84a5d
|
||||
# via pydantic
|
||||
anyio==3.7.1 \
|
||||
--hash=sha256:44a3c9aba0f5defa43261a8b3efb97891f2bd7d804e0e1f56419befa1adfc780 \
|
||||
--hash=sha256:91dee416e570e92c64041bd18b900d1d6fa78dff7048769ce5ac5ddad004fbb5
|
||||
anyio==4.2.0 \
|
||||
--hash=sha256:745843b39e829e108e518c489b31dc757de7d2131d53fac32bd8df268227bfee \
|
||||
--hash=sha256:e1875bb4b4e2de1669f4bc7869b6d3f54231cdced71605e6e64c9be77e3be50f
|
||||
# via
|
||||
# fastapi
|
||||
# starlette
|
||||
# watchfiles
|
||||
click==8.1.7 \
|
||||
|
|
@ -23,9 +22,9 @@ exceptiongroup==1.2.0 \
|
|||
--hash=sha256:4bfd3996ac73b41e9b9628b04e079f193850720ea5945fc96a08633c66912f14 \
|
||||
--hash=sha256:91f5c769735f051a4290d52edd0858999b57e5876e9f85937691bd4c9fa3ed68
|
||||
# via anyio
|
||||
fastapi==0.106.0 \
|
||||
--hash=sha256:193c2f1b495d1d6561a3dc1ca02a150757322247d895ff6bf15b6eefee24feb9 \
|
||||
--hash=sha256:c7e7453ac8c4b7414bbafcf90127d743559808eee286ae2c9f99a501f0b534a0
|
||||
fastapi==0.108.0 \
|
||||
--hash=sha256:5056e504ac6395bf68493d71fcfc5352fdbd5fda6f88c21f6420d80d81163296 \
|
||||
--hash=sha256:8c7bc6d315da963ee4cdb605557827071a9a7f95aeb8fcdd3bde48cdc8764dd7
|
||||
# via -r requirements.in
|
||||
h11==0.14.0 \
|
||||
--hash=sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d \
|
||||
|
|
@ -244,14 +243,15 @@ sniffio==1.3.0 \
|
|||
--hash=sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101 \
|
||||
--hash=sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384
|
||||
# via anyio
|
||||
starlette==0.27.0 \
|
||||
--hash=sha256:6a6b0d042acb8d469a01eba54e9cda6cbd24ac602c4cd016723117d6a7e73b75 \
|
||||
--hash=sha256:918416370e846586541235ccd38a474c08b80443ed31c578a418e2209b3eef91
|
||||
starlette==0.32.0.post1 \
|
||||
--hash=sha256:cd0cb10ddb49313f609cedfac62c8c12e56c7314b66d89bb077ba228bada1b09 \
|
||||
--hash=sha256:e54e2b7e2fb06dff9eac40133583f10dfa05913f5a85bf26f427c7a40a9a3d02
|
||||
# via fastapi
|
||||
typing-extensions==4.9.0 \
|
||||
--hash=sha256:23478f88c37f27d76ac8aee6c905017a143b0b1b886c3c9f66bc2fd94f9f5783 \
|
||||
--hash=sha256:af72aea155e91adfc61c3ae9e0e342dbc0cba726d6cba4b6c72c1f34e47291cd
|
||||
# via
|
||||
# anyio
|
||||
# fastapi
|
||||
# pydantic
|
||||
# pydantic-core
|
||||
|
|
|
|||
|
|
@ -7,9 +7,8 @@ services:
|
|||
dockerfile: src/bw/Dockerfile
|
||||
ports:
|
||||
- 80:80
|
||||
- 443:8443
|
||||
environment:
|
||||
SERVER_NAME: "www.example.com"
|
||||
SERVER_NAME: ""
|
||||
MULTISITE: "yes"
|
||||
HTTP_PORT: "80"
|
||||
API_WHITELIST_IP: "127.0.0.0/8 10.20.30.0/24"
|
||||
|
|
@ -20,12 +19,7 @@ services:
|
|||
USE_CLIENT_CACHE: "yes"
|
||||
USE_GZIP: "yes"
|
||||
DATASTORE_MEMORY_SIZE: "384m"
|
||||
www.example.com_USE_UI: "yes"
|
||||
www.example.com_SERVE_FILES: "no"
|
||||
www.example.com_USE_REVERSE_PROXY: "yes"
|
||||
www.example.com_REVERSE_PROXY_URL: "/admin"
|
||||
www.example.com_REVERSE_PROXY_HOST: "http://bw-ui:7000"
|
||||
www.example.com_INTERCEPTED_ERROR_CODES: "400 405 413 429 500 501 502 503 504"
|
||||
UI_HOST: "http://bw-ui:7000"
|
||||
labels:
|
||||
- "bunkerweb.INSTANCE=yes"
|
||||
networks:
|
||||
|
|
@ -57,8 +51,6 @@ services:
|
|||
volumes:
|
||||
- bw-data:/data
|
||||
environment:
|
||||
ADMIN_USERNAME: "admin"
|
||||
ADMIN_PASSWORD: "S$$cr3tP@ssw0rd"
|
||||
DOCKER_HOST: "tcp://docker-proxy:2375"
|
||||
networks:
|
||||
- net-docker
|
||||
|
|
|
|||
|
|
@ -6,9 +6,8 @@ services:
|
|||
pull_policy: never
|
||||
ports:
|
||||
- 80:80
|
||||
- 443:8443
|
||||
environment:
|
||||
SERVER_NAME: "www.example.com"
|
||||
SERVER_NAME: ""
|
||||
MULTISITE: "yes"
|
||||
HTTP_PORT: "80"
|
||||
API_WHITELIST_IP: "127.0.0.0/8 10.20.30.0/24"
|
||||
|
|
@ -20,13 +19,8 @@ services:
|
|||
USE_CLIENT_CACHE: "yes"
|
||||
USE_GZIP: "yes"
|
||||
DATASTORE_MEMORY_SIZE: "384m"
|
||||
www.example.com_USE_UI: "yes"
|
||||
www.example.com_SERVE_FILES: "no"
|
||||
www.example.com_USE_REVERSE_PROXY: "yes"
|
||||
www.example.com_REVERSE_PROXY_URL: "/admin"
|
||||
www.example.com_REVERSE_PROXY_HOST: "http://bw-ui:7000"
|
||||
www.example.com_INTERCEPTED_ERROR_CODES: "400 405 413 429 500 501 502 503 504"
|
||||
CUSTOM_CONF_SERVER_HTTP_port-redirect: "port_in_redirect on;"
|
||||
UI_HOST: "http://bw-ui:7000"
|
||||
labels:
|
||||
- "bunkerweb.INSTANCE=yes"
|
||||
networks:
|
||||
|
|
@ -54,8 +48,6 @@ services:
|
|||
- bw
|
||||
- bw-docker-proxy
|
||||
environment:
|
||||
ADMIN_USERNAME: "admin"
|
||||
ADMIN_PASSWORD: "S$$cr3tP@ssw0rd"
|
||||
DOCKER_HOST: "tcp://bw-docker-proxy:2375"
|
||||
volumes:
|
||||
- bw-data:/data
|
||||
|
|
|
|||
308
tests/ui/main.py
308
tests/ui/main.py
|
|
@ -7,6 +7,7 @@ from pathlib import Path
|
|||
from time import sleep
|
||||
from traceback import format_exc
|
||||
from typing import List, Union
|
||||
from pyotp import TOTP
|
||||
from requests import get
|
||||
from requests.exceptions import RequestException
|
||||
from selenium import webdriver
|
||||
|
|
@ -23,7 +24,7 @@ ready = False
|
|||
retries = 0
|
||||
while not ready:
|
||||
with suppress(RequestException):
|
||||
status_code = get("http://www.example.com/admin/login").status_code
|
||||
status_code = get("http://127.0.0.1/setup").status_code
|
||||
|
||||
if status_code > 500 and status_code != 502:
|
||||
print("An error occurred with the server, exiting ...", flush=True)
|
||||
|
|
@ -178,9 +179,41 @@ with driver_func() as driver:
|
|||
driver.maximize_window()
|
||||
driver_wait = WebDriverWait(driver, 60)
|
||||
|
||||
print("Navigating to http://www.example.com/admin/login ...", flush=True)
|
||||
print("Navigating to http://127.0.0.1/setup ...", flush=True)
|
||||
|
||||
driver.get("http://www.example.com/admin/login")
|
||||
driver.get("http://127.0.0.1/setup")
|
||||
|
||||
### WIZARD PAGE
|
||||
|
||||
try:
|
||||
title = driver_wait.until(EC.presence_of_element_located((By.XPATH, "/html/body/main/div/div/h1")))
|
||||
|
||||
if title.text != "Setup Wizard":
|
||||
print("Didn't get redirected to setup page, exiting ...", flush=True)
|
||||
exit(1)
|
||||
except TimeoutException:
|
||||
print("Didn't get redirected to setup page, exiting ...", flush=True)
|
||||
exit(1)
|
||||
|
||||
print("Setup page loaded successfully, filling the form ...", flush=True)
|
||||
|
||||
admin_username_input = safe_get_element(driver, By.ID, "admin_username")
|
||||
password_input = safe_get_element(driver, By.ID, "admin_password")
|
||||
password_check_input = safe_get_element(driver, By.ID, "admin_password_check")
|
||||
ui_url = safe_get_element(driver, By.ID, "ui_url").get_attribute("value")
|
||||
|
||||
admin_username_input.send_keys("admin")
|
||||
password_input.send_keys("S$cr3tP@ssw0rd")
|
||||
password_check_input.send_keys("S$cr3tP@ssw0rd")
|
||||
|
||||
assert_button_click(driver, "//button[@id='setup-button']")
|
||||
|
||||
print("Submitted the form, waiting for the wizard to finish ...", flush=True)
|
||||
|
||||
current_time = datetime.now()
|
||||
|
||||
while current_time + timedelta(minutes=5) > datetime.now() and not driver.current_url.endswith("/login"):
|
||||
sleep(1)
|
||||
|
||||
### LOGIN PAGE
|
||||
|
||||
|
|
@ -197,7 +230,7 @@ with driver_func() as driver:
|
|||
flush=True,
|
||||
)
|
||||
|
||||
driver.get("http://www.example.com/admin/home")
|
||||
driver.get(f"http://www.example.com{ui_url}/home")
|
||||
|
||||
print("Waiting for toast ...", flush=True)
|
||||
|
||||
|
|
@ -508,9 +541,9 @@ with driver_func() as driver:
|
|||
print("The service is not present, exiting ...", flush=True)
|
||||
exit(1)
|
||||
|
||||
if service.find_element(By.TAG_NAME, "h6").text.strip() != "scheduler":
|
||||
if service.find_element(By.TAG_NAME, "h6").text.strip() != "ui":
|
||||
print(
|
||||
"The service should have been created by the scheduler, exiting ...",
|
||||
"The service should have been created by the ui, exiting ...",
|
||||
flush=True,
|
||||
)
|
||||
exit(1)
|
||||
|
|
@ -1260,8 +1293,8 @@ location /hello {
|
|||
|
||||
current_date = datetime.now()
|
||||
resp = get(
|
||||
f"http://www.example.com/admin/logs/{first_instance}?from_date={int(current_date.timestamp() - 86400000)}&to_date={int((current_date - timedelta(days=1)).timestamp())}",
|
||||
headers={"Host": "www.example.com"},
|
||||
f"http://www.example.com{ui_url}/logs/{first_instance}?from_date={int(current_date.timestamp() - 86400000)}&to_date={int((current_date - timedelta(days=1)).timestamp())}",
|
||||
headers={"Host": "www.example.com", "User-Agent": driver.execute_script("return navigator.userAgent;")},
|
||||
cookies={"session": driver.get_cookies()[0]["value"]},
|
||||
)
|
||||
|
||||
|
|
@ -1396,13 +1429,173 @@ location /hello {
|
|||
|
||||
sleep(0.3)
|
||||
|
||||
resp = get("http://www.example.com/admin/jobs/download?job_name=mmdb-country&file_name=country.mmdb")
|
||||
resp = get(f"http://www.example.com{ui_url}/jobs/download?job_name=mmdb-country&file_name=country.mmdb")
|
||||
|
||||
if resp.status_code != 200:
|
||||
print("The cache download is not working, exiting ...", flush=True)
|
||||
exit(1)
|
||||
|
||||
print("Cache download is working, trying to log out ...", flush=True)
|
||||
print("Cache download is working, trying profile page ...", flush=True)
|
||||
|
||||
access_page(driver, driver_wait, "/html/body/aside[1]/div[1]/div[2]/ul/li[10]/a", "profile")
|
||||
|
||||
### PROFILE PAGE
|
||||
|
||||
username_input = safe_get_element(driver, By.ID, "admin_username")
|
||||
|
||||
if username_input.get_attribute("value") != "admin":
|
||||
print("The username is not correct, exiting ...", flush=True)
|
||||
exit(1)
|
||||
|
||||
username_input.clear()
|
||||
username_input.send_keys("admin2")
|
||||
|
||||
password_input = safe_get_element(driver, By.ID, "curr_password")
|
||||
|
||||
if password_input.get_attribute("value") != "":
|
||||
print("The current password is not empty, exiting ...", flush=True)
|
||||
exit(1)
|
||||
|
||||
password_input.send_keys("S$cr3tP@ssw0rd")
|
||||
|
||||
assert_button_click(driver, "//button[@id='profile-button' and @class='edit-btn']")
|
||||
|
||||
try:
|
||||
title = driver_wait.until(EC.presence_of_element_located((By.XPATH, "/html/body/main/div[1]/div/h1")))
|
||||
|
||||
if title.text != "Log in":
|
||||
print("Didn't get redirected to login page, exiting ...", flush=True)
|
||||
exit(1)
|
||||
except TimeoutException:
|
||||
print("Login page didn't load in time, exiting ...", flush=True)
|
||||
exit(1)
|
||||
|
||||
print("Successfully changed username, trying to log in with new username ...", flush=True)
|
||||
|
||||
username_input = safe_get_element(driver, By.ID, "username")
|
||||
password_input = safe_get_element(driver, By.ID, "password")
|
||||
username_input.send_keys("admin2")
|
||||
password_input.send_keys("S$cr3tP@ssw0rd")
|
||||
|
||||
access_page(
|
||||
driver,
|
||||
driver_wait,
|
||||
"//button[@value='login']",
|
||||
"profile",
|
||||
)
|
||||
|
||||
username_input = safe_get_element(driver, By.ID, "admin_username")
|
||||
|
||||
if username_input.get_attribute("value") != "admin2":
|
||||
print("The username is not correct, exiting ...", flush=True)
|
||||
exit(1)
|
||||
|
||||
print("Successfully logged in with new username, trying to change password ...", flush=True)
|
||||
|
||||
password_input = safe_get_element(driver, By.ID, "curr_password")
|
||||
|
||||
if password_input.get_attribute("value") != "":
|
||||
print("The current password is not empty, exiting ...", flush=True)
|
||||
exit(1)
|
||||
|
||||
password_input.send_keys("S$cr3tP@ssw0rd")
|
||||
|
||||
new_password_input = safe_get_element(driver, By.ID, "admin_password")
|
||||
|
||||
if new_password_input.get_attribute("value") != "":
|
||||
print("The new password is not empty, exiting ...", flush=True)
|
||||
exit(1)
|
||||
|
||||
new_password_input.send_keys("P@ssw0rd")
|
||||
|
||||
new_password_check_input = safe_get_element(driver, By.ID, "admin_password_check")
|
||||
|
||||
if new_password_check_input.get_attribute("value") != "":
|
||||
print("The new password check is not empty, exiting ...", flush=True)
|
||||
exit(1)
|
||||
|
||||
new_password_check_input.send_keys("P@ssw0rd")
|
||||
|
||||
assert_button_click(driver, "//button[@id='profile-button' and @class='edit-btn']")
|
||||
|
||||
try:
|
||||
title = driver_wait.until(EC.presence_of_element_located((By.XPATH, "/html/body/main/div[1]/div/h1")))
|
||||
|
||||
if title.text != "Log in":
|
||||
print("Didn't get redirected to login page, exiting ...", flush=True)
|
||||
exit(1)
|
||||
except TimeoutException:
|
||||
print("Login page didn't load in time, exiting ...", flush=True)
|
||||
exit(1)
|
||||
|
||||
print("Successfully changed username, trying to log in with new password ...", flush=True)
|
||||
|
||||
username_input = safe_get_element(driver, By.ID, "username")
|
||||
password_input = safe_get_element(driver, By.ID, "password")
|
||||
username_input.send_keys("admin2")
|
||||
password_input.send_keys("P@ssw0rd")
|
||||
|
||||
access_page(
|
||||
driver,
|
||||
driver_wait,
|
||||
"//button[@value='login']",
|
||||
"profile",
|
||||
)
|
||||
|
||||
print("Successfully logged in with new password, trying 2FA ...", flush=True)
|
||||
|
||||
assert_button_click(driver, "//button[@data-tab-handler='totp']")
|
||||
|
||||
secret_token_input = safe_get_element(driver, By.ID, "secret_token")
|
||||
secret_token = secret_token_input.get_attribute("value")
|
||||
|
||||
driver.refresh()
|
||||
|
||||
driver_wait.until(EC.presence_of_element_located((By.XPATH, "/html/body/div/header/div/nav/h6")))
|
||||
|
||||
assert_button_click(driver, "//button[@data-tab-handler='totp']")
|
||||
|
||||
secret_token_input = safe_get_element(driver, By.ID, "secret_token")
|
||||
new_secret_token = secret_token_input.get_attribute("value")
|
||||
|
||||
if new_secret_token == secret_token:
|
||||
print("The secret token hasn't been changed, exiting ...", flush=True)
|
||||
exit(1)
|
||||
|
||||
print("The secret token has been changed, trying to activate 2FA ...", flush=True)
|
||||
|
||||
totp = TOTP(new_secret_token)
|
||||
totp_input = safe_get_element(driver, By.ID, "totp_token")
|
||||
totp_input.send_keys(totp.now())
|
||||
|
||||
password_input = safe_get_element(driver, By.ID, "totp_password")
|
||||
|
||||
if password_input.get_attribute("value") != "":
|
||||
print("The new password check is not empty, exiting ...", flush=True)
|
||||
exit(1)
|
||||
|
||||
password_input.send_keys("P@ssw0rd")
|
||||
|
||||
access_page(
|
||||
driver,
|
||||
driver_wait,
|
||||
"//button[@id='profile-button' and @class='valid-btn']",
|
||||
"profile",
|
||||
)
|
||||
|
||||
assert_button_click(driver, "//button[@data-tab-handler='totp']")
|
||||
|
||||
try:
|
||||
totp_state = safe_get_element(driver, By.XPATH, "/html/body/main/div/div/form[2]/h5")
|
||||
|
||||
if totp_state.text != "TOTP IS CURRENTLY ON":
|
||||
print("TOTP is not activated, exiting ...", flush=True)
|
||||
exit(1)
|
||||
except TimeoutException:
|
||||
print("TOTP has not been activated, exiting ...", flush=True)
|
||||
exit(1)
|
||||
|
||||
print("2FA has been activated, trying to log out ...", flush=True)
|
||||
|
||||
assert_button_click(driver, "//a[@href='logout']")
|
||||
|
||||
|
|
@ -1416,7 +1609,100 @@ location /hello {
|
|||
print("Login page didn't load in time, exiting ...", flush=True)
|
||||
exit(1)
|
||||
|
||||
print("Successfully logged out, tests are done", flush=True)
|
||||
print("Successfully logged out, trying to log in with 2FA ...", flush=True)
|
||||
|
||||
username_input = safe_get_element(driver, By.ID, "username")
|
||||
password_input = safe_get_element(driver, By.ID, "password")
|
||||
username_input.send_keys("admin2")
|
||||
password_input.send_keys("P@ssw0rd")
|
||||
|
||||
assert_button_click(driver, "//button[@value='login']")
|
||||
|
||||
try:
|
||||
totp_input = safe_get_element(driver, By.ID, "totp_token")
|
||||
except TimeoutException:
|
||||
print("Didn't get redirected to 2FA page, exiting ...", flush=True)
|
||||
exit(1)
|
||||
|
||||
totp_input.send_keys("0000000")
|
||||
assert_button_click(driver, "//button[@value='login']")
|
||||
|
||||
sleep(5)
|
||||
|
||||
if not driver.current_url.endswith("/totp"):
|
||||
print("Didn't get redirected back to 2FA page, exiting ...", flush=True)
|
||||
exit(1)
|
||||
|
||||
totp_input = safe_get_element(driver, By.ID, "totp_token")
|
||||
totp_input.send_keys(totp.now())
|
||||
|
||||
access_page(
|
||||
driver,
|
||||
driver_wait,
|
||||
"//button[@value='login']",
|
||||
"home",
|
||||
)
|
||||
|
||||
print("Successfully logged in with 2FA, trying to deactivate 2FA ...", flush=True)
|
||||
|
||||
access_page(driver, driver_wait, "/html/body/aside[1]/div[1]/div[2]/ul/li[10]/a", "profile")
|
||||
|
||||
assert_button_click(driver, "//button[@data-tab-handler='totp']")
|
||||
|
||||
totp_input = safe_get_element(driver, By.ID, "totp_token")
|
||||
totp_input.send_keys(totp.now())
|
||||
|
||||
password_input = safe_get_element(driver, By.ID, "totp_password")
|
||||
password_input.send_keys("P@ssw0rd")
|
||||
|
||||
access_page(
|
||||
driver,
|
||||
driver_wait,
|
||||
"//button[@id='profile-button' and @class='delete-btn']",
|
||||
"profile",
|
||||
)
|
||||
|
||||
assert_button_click(driver, "//button[@data-tab-handler='totp']")
|
||||
|
||||
try:
|
||||
totp_state = safe_get_element(driver, By.XPATH, "/html/body/main/div/div/form[2]/h5")
|
||||
|
||||
if totp_state.text != "TOTP IS CURRENTLY OFF":
|
||||
print("TOTP is not deactivated, exiting ...", flush=True)
|
||||
exit(1)
|
||||
except TimeoutException:
|
||||
print("TOTP has not been deactivated, exiting ...", flush=True)
|
||||
exit(1)
|
||||
|
||||
print("2FA has been deactivated, trying to log out ...", flush=True)
|
||||
|
||||
assert_button_click(driver, "//a[@href='logout']")
|
||||
|
||||
try:
|
||||
title = driver_wait.until(EC.presence_of_element_located((By.XPATH, "/html/body/main/div[1]/div/h1")))
|
||||
|
||||
if title.text != "Log in":
|
||||
print("Didn't get redirected to login page, exiting ...", flush=True)
|
||||
exit(1)
|
||||
except TimeoutException:
|
||||
print("Login page didn't load in time, exiting ...", flush=True)
|
||||
exit(1)
|
||||
|
||||
print("Successfully logged out, trying to log in without 2FA ...", flush=True)
|
||||
|
||||
username_input = safe_get_element(driver, By.ID, "username")
|
||||
password_input = safe_get_element(driver, By.ID, "password")
|
||||
username_input.send_keys("admin2")
|
||||
password_input.send_keys("P@ssw0rd")
|
||||
|
||||
access_page(
|
||||
driver,
|
||||
driver_wait,
|
||||
"//button[@value='login']",
|
||||
"home",
|
||||
)
|
||||
|
||||
print("Successfully logged in without 2FA, tests are done, exiting ...", flush=True)
|
||||
except SystemExit:
|
||||
exit(1)
|
||||
except:
|
||||
|
|
|
|||
|
|
@ -1,2 +1,3 @@
|
|||
pyotp==2.9.0
|
||||
requests==2.31.0
|
||||
selenium==4.16.0
|
||||
|
|
|
|||
|
|
@ -128,6 +128,10 @@ outcome==1.3.0.post0 \
|
|||
--hash=sha256:9dcf02e65f2971b80047b377468e72a268e15c0af3cf1238e6ff14f7f91143b8 \
|
||||
--hash=sha256:e771c5ce06d1415e356078d3bdd68523f284b4ce5419828922b6871e65eda82b
|
||||
# via trio
|
||||
pyotp==2.9.0 \
|
||||
--hash=sha256:346b6642e0dbdde3b4ff5a930b664ca82abfa116356ed48cc42c7d6590d36f63 \
|
||||
--hash=sha256:81c2e5865b8ac55e825b0358e496e1d9387c811e85bb40e71a3b29b288963612
|
||||
# via -r requirements.in
|
||||
pysocks==1.7.1 \
|
||||
--hash=sha256:08e69f092cc6dbe92a0fdd16eeb9b9ffbc13cadfe5ca4c7bd92ffb078b293299 \
|
||||
--hash=sha256:2725bd0a9925919b9b51739eea5f9e2bae91e83288108a9ad338b2e3a4435ee5 \
|
||||
|
|
|
|||
Loading…
Reference in a new issue