{"id":13776498,"url":"https://github.com/fffonion/lua-resty-openssl","last_synced_at":"2025-05-08T22:43:03.351Z","repository":{"id":38362983,"uuid":"210951144","full_name":"fffonion/lua-resty-openssl","owner":"fffonion","description":"FFI-based OpenSSL binding for OpenResty","archived":false,"fork":false,"pushed_at":"2025-04-16T05:50:58.000Z","size":1312,"stargazers_count":143,"open_issues_count":4,"forks_count":48,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-05-08T22:42:56.124Z","etag":null,"topics":["ffi","lua-nginx-module","openresty","openssl"],"latest_commit_sha":null,"homepage":"","language":"Lua","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-2-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fffonion.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2019-09-25T22:21:08.000Z","updated_at":"2025-05-06T05:56:19.000Z","dependencies_parsed_at":"2023-11-21T10:30:27.557Z","dependency_job_id":"c0987c34-9531-4bcb-9b09-6179339e86a9","html_url":"https://github.com/fffonion/lua-resty-openssl","commit_stats":null,"previous_names":[],"tags_count":65,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fffonion%2Flua-resty-openssl","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fffonion%2Flua-resty-openssl/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fffonion%2Flua-resty-openssl/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fffonion%2Flua-resty-openssl/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fffonion","download_url":"https://codeload.github.com/fffonion/lua-resty-openssl/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253160727,"owners_count":21863624,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ffi","lua-nginx-module","openresty","openssl"],"created_at":"2024-08-03T18:00:27.597Z","updated_at":"2025-05-08T22:43:03.330Z","avatar_url":"https://github.com/fffonion.png","language":"Lua","funding_links":[],"categories":["Libraries","Lua"],"sub_categories":[],"readme":"# lua-resty-openssl\n\nFFI-based OpenSSL binding for LuaJIT, supporting OpenSSL 3.x, 1.1 series.\n\nOpenSSL 1.1.0, 1.0.2 and BoringSSL support has been dropped, but are still available at the [0.x branch](https://github.com/fffonion/lua-resty-openssl/tree/0.x).\n\n![Build Status](https://github.com/fffonion/lua-resty-openssl/workflows/Tests/badge.svg) ![luarocks](https://img.shields.io/luarocks/v/fffonion/lua-resty-openssl?color=%232c3e67) ![opm](https://img.shields.io/opm/v/fffonion/lua-resty-openssl?color=%23599059)\n\n\nTable of Contents\n=================\n\n- [Description](#description)\n- [Status](#status)\n- [Synopsis](#synopsis)\n  * [resty.openssl](#restyopenssl)\n    + [openssl.load_library](#opensslload_library)\n    + [openssl.load_modules](#opensslload_modules)\n    + [openssl.luaossl_compat](#opensslluaossl_compat)\n    + [openssl.resty_hmac_compat](#opensslresty_hmac_compat)\n    + [openssl.get_fips_mode](#opensslget_fips_mode)\n    + [openssl.set_fips_mode](#opensslset_fips_mode)\n    + [openssl.get_fips_version_text](#opensslget_fips_version_text)\n    + [openssl.set_default_properties](#opensslset_default_properties)\n    + [openssl.list_cipher_algorithms](#openssllist_cipher_algorithms)\n    + [openssl.list_digest_algorithms](#openssllist_digest_algorithms)\n    + [openssl.list_mac_algorithms](#openssllist_mac_algorithms)\n    + [openssl.list_kdf_algorithms](#openssllist_kdf_algorithms)\n    + [openssl.list_ssl_ciphers](#openssllist_ssl_ciphers)\n  * [resty.openssl.ctx](#restyopensslctx)\n    + [ctx.new](#ctxnew)\n    + [ctx.free](#ctxfree)\n  * [resty.openssl.err](#restyopensslerr)\n    + [err.format_error](#errformat_error)\n    + [err.get_last_error_code](#errget_last_error_code)\n    + [err.get_lib_error_string](#errget_lib_error_string)\n    + [err.get_reason_error_string](#errget_reason_error_string)\n  * [resty.openssl.version](#restyopensslversion)\n    + [version_num](#version_num)\n    + [version_text](#version_text)\n    + [version.version](#versionversion)\n    + [version.info](#versioninfo)\n    + [version.OPENSSL_3X](#versionOPENSSL_3X)\n    + [version.OPENSSL_111](#versionopenssl_111)\n  * [resty.openssl.provider](#restyopensslprovider)\n    + [provider.load](#providerload)\n    + [provider.istype](#provideristype)\n    + [provider.is_available](#provideris_available)\n    + [provider.set_default_search_path](#providerset_default_search_path)\n    + [provider:unload](#providerunload)\n    + [provider:self_test](#providerself_test)\n    + [provider:get_params](#providerget_params)\n  * [resty.openssl.pkey](#restyopensslpkey)\n    + [pkey.new](#pkeynew)\n    + [pkey.istype](#pkeyistype)\n    + [pkey.paramgen](#pkeyparamgen)\n    + [pkey:get_provider_name](#pkeyget_provider_name)\n    + [pkey:gettable_params, pkey:settable_params, pkey:get_param, pkey:set_params](#pkeygettable_params-pkeysettable_params-pkeyget_param-pkeyset_params)\n    + [pkey:get_parameters](#pkeyget_parameters)\n    + [pkey:set_parameters](#pkeyset_parameters)\n    + [pkey:is_private](#pkeyis_private)\n    + [pkey:get_key_type](#pkeyget_key_type)\n    + [pkey:get_size](#pkeyget_size)\n    + [pkey:get_default_digest_type](#pkeyget_default_digest_type)\n    + [pkey:sign](#pkeysign)\n    + [pkey:verify](#pkeyverify)\n    + [pkey:encrypt](#pkeyencrypt)\n    + [pkey:decrypt](#pkeydecrypt)\n    + [pkey:sign_raw](#pkeysign_raw)\n    + [pkey:verify_raw](#pkeyverify_raw)\n    + [pkey:verify_recover](#pkeyverify_recover)\n    + [pkey:derive](#pkeyderive)\n    + [pkey:tostring](#pkeytostring)\n    + [pkey:to_PEM](#pkeyto_pem)\n  * [resty.openssl.bn](#restyopensslbn)\n    + [bn.new](#bnnew)\n    + [bn.dup](#bndup)\n    + [bn.istype](#bnistype)\n    + [bn:set](#bnset)\n    + [bn.from_binary, bn:to_binary](#bnfrom_binary-bnto_binary)\n    + [bn.from_mpi, bn:to_mpi](#bnfrom_mpi-bnto_mpi)\n    + [bn.from_hex, bn:to_hex](#bnfrom_hex-bnto_hex)\n    + [bn.from_dec, bn:to_dec](#bnfrom_dec-bnto_dec)\n    + [bn:to_number](#bnto_number)\n    + [bn:__metamethods](#bn__metamethods)\n    + [bn:add, bn:sub, bn:mul, bn:div, bn:exp, bn:mod, bn:gcd](#bnadd-bnsub-bnmul-bndiv-bnexp-bnmod-bngcd)\n    + [bn:sqr](#bnsqr)\n    + [bn:mod_add, bn:mod_sub, bn:mod_mul, bn:mod_exp](#bnmod_add-bnmod_sub-bnmod_mul-bnmod_exp)\n    + [bn:mod_sqr](#bnmod_sqr)\n    + [bn:lshift, bn:rshift](#bnlshift-bnrshift)\n    + [bn:is_zero, bn:is_one, bn:is_odd, bn:is_word](#bnis_zero-bnis_one-bnis_odd-bnis_word)\n    + [bn:is_prime](#bnis_prime)\n  * [resty.openssl.cipher](#restyopensslcipher)\n    + [cipher.new](#ciphernew)\n    + [cipher.istype](#cipheristype)\n    + [cipher.set_buffer_size](#cipherset_buffer_size)\n    + [cipher:get_provider_name](#cipherget_provider_name)\n    + [cipher:gettable_params, cipher:settable_params, cipher:get_param, cipher:set_params](#ciphergettable_params-ciphersettable_params-cipherget_param-cipherset_params)\n    + [cipher:encrypt](#cipherencrypt)\n    + [cipher:decrypt](#cipherdecrypt)\n    + [cipher:init](#cipherinit)\n    + [cipher:update](#cipherupdate)\n    + [cipher:update_aead_aad](#cipherupdate_aead_aad)\n    + [cipher:get_aead_tag](#cipherget_aead_tag)\n    + [cipher:set_aead_tag](#cipherset_aead_tag)\n    + [cipher:final](#cipherfinal)\n    + [cipher:derive](#cipherderive)\n  * [resty.openssl.digest](#restyopenssldigest)\n    + [digest.new](#digestnew)\n    + [digest.istype](#digestistype)\n    + [digest:get_provider_name](#digestget_provider_name)\n    + [digest:gettable_params, digest:settable_params, digest:get_param, digest:set_params](#digestgettable_params-digestsettable_params-digestget_param-digestset_params)\n    + [digest:update](#digestupdate)\n    + [digest:final](#digestfinal)\n    + [digest:reset](#digestreset)\n  * [resty.openssl.hmac](#restyopensslhmac)\n    + [hmac.new](#hmacnew)\n    + [hmac.istype](#hmacistype)\n    + [hmac:update](#hmacupdate)\n    + [hmac:final](#hmacfinal)\n    + [hmac:reset](#hmacreset)\n  * [resty.openssl.mac](#restyopensslmac)\n    + [mac.new](#macnew)\n    + [mac.istype](#macistype)\n    + [mac:get_provider_name](#macget_provider_name)\n    + [mac:gettable_params, mac:settable_params, mac:get_param, mac:set_params](#macgettable_params-macsettable_params-macget_param-macset_params)\n    + [mac:update](#macupdate)\n    + [mac:final](#macfinal)\n    + [mac:reset](#macreset)\n  * [resty.openssl.kdf](#restyopensslkdf)\n    + [kdf.derive (legacy)](#kdfderive-legacy)\n    + [kdf.new](#kdfnew)\n    + [kdf:get_provider_name](#kdfget_provider_name)\n    + [kdf:gettable_params, kdf:settable_params, kdf:get_param, kdf:set_params](#kdfgettable_params-kdfsettable_params-kdfget_param-kdfset_params)\n    + [kdf:derive](#kdfderive)\n    + [kdf:reset](#kdfreset)\n  * [resty.openssl.objects](#restyopensslobjects)\n    + [objects.obj2table](#objectsobj2table)\n    + [objects.nid2table](#objectsnid2table)\n    + [objects.txt2nid](#objectstxt2nid)\n  * [resty.openssl.pkcs12](#restyopensslpkcs12)\n    + [pkcs12.encode](#pkcs12encode)\n    + [pkcs12.decode](#pkcs12decode)\n  * [resty.openssl.rand](#restyopensslrand)\n    + [rand.bytes](#randbytes)\n  * [resty.openssl.x509](#restyopensslx509)\n    + [x509.new](#x509new)\n    + [x509.dup](#x509dup)\n    + [x509.istype](#x509istype)\n    + [x509:digest](#x509digest)\n    + [x509:pubkey_digest](#x509pubkey_digest)\n    + [x509:check_private_key](#x509check_private_key)\n    + [x509:get_\\*, x509:set_\\*](#x509get_-x509set_)\n    + [x509:get_lifetime](#x509get_lifetime)\n    + [x509:set_lifetime](#x509set_lifetime)\n    + [x509:get_signature_name, x509:get_signature_nid, x509:get_signature_digest_name](#x509get_signature_name-x509get_signature_nid-x509get_signature_digest_name)\n    + [x509:get_extension](#x509get_extension)\n    + [x509:add_extension](#x509add_extension)\n    + [x509:set_extension](#x509set_extension)\n    + [x509:get_extension_critical](#x509get_extension_critical)\n    + [x509:set_extension_critical](#x509set_extension_critical)\n    + [x509:get_ocsp_url](#x509get_ocsp_url)\n    + [x509:get_crl_url](#x509get_crl_url)\n    + [x509:sign](#x509sign)\n    + [x509:verify](#x509verify)\n    + [x509:tostring](#x509tostring)\n    + [x509:to_PEM](#x509to_pem)\n  * [resty.openssl.x509.csr](#restyopensslx509csr)\n    + [csr.new](#csrnew)\n    + [csr.istype](#csristype)\n    + [csr:check_private_key](#csrcheck_private_key)\n    + [csr:get_\\*, csr:set_\\*](#csrget_-csrset_)\n    + [csr:get_signature_name, csr:get_signature_nid, csr:get_signature_digest_name](#csrget_signature_name-csrget_signature_nid-csrget_signature_digest_name)\n    + [csr:get_extension](#csrget_extension)\n    + [csr:add_extension](#csradd_extension)\n    + [csr:set_extension](#csrset_extension)\n    + [csr:get_extension_critical](#csrget_extension_critical)\n    + [csr:set_extension_critical](#csrset_extension_critical)\n    + [csr:sign](#csrsign)\n    + [csr:verify](#csrverify)\n    + [csr:tostring](#csrtostring)\n    + [csr:to_PEM](#csrto_pem)\n  * [resty.openssl.x509.crl](#restyopensslx509crl)\n    + [crl.new](#crlnew)\n    + [crl.istype](#crlistype)\n    + [crl:get_\\*, crl:set_\\*](#crlget_-crlset_)\n    + [crl:get_signature_name, crl:get_signature_nid, crl:get_signature_digest_name](#crlget_signature_name-crlget_signature_nid-crlget_signature_digest_name)\n    + [crl:get_by_serial](#crlget_by_serial)\n    + [crl:get_extension](#crlget_extension)\n    + [crl:add_extension](#crladd_extension)\n    + [crl:set_extension](#crlset_extension)\n    + [crl:get_extension_critical](#crlget_extension_critical)\n    + [crl:set_extension_critical](#crlset_extension_critical)\n    + [crl:add_revoked](#crladd_revoked)\n    + [crl:sign](#crlsign)\n    + [crl:verify](#crlverify)\n    + [crl:tostring](#crltostring)\n    + [crl:text](#crltext)\n    + [crl:to_PEM](#crlto_pem)\n    + [crl:__metamethods](#crl__metamethods)\n  * [resty.openssl.x509.name](#restyopensslx509name)\n    + [name.new](#namenew)\n    + [name.dup](#namedup)\n    + [name.istype](#nameistype)\n    + [name:add](#nameadd)\n    + [name:find](#namefind)\n    + [name:tostring](#nametostring)\n    + [name:__metamethods](#name__metamethods)\n  * [resty.openssl.x509.altname](#restyopensslx509altname)\n    + [altname.new](#altnamenew)\n    + [altname.dup](#altnamedup)\n    + [altname.istype](#altnameistype)\n    + [altname:add](#altnameadd)\n    + [altname:tostring](#altnametostring)\n    + [altname:__metamethods](#altname__metamethods)\n  * [resty.openssl.x509.extension](#restyopensslx509extension)\n    + [extension.new](#extensionnew)\n    + [extension.dup](#extensiondup)\n    + [extension.from_data](#extensionfrom_data)\n    + [extension:to_data](#extensionto_data)\n    + [extension.from_der](#extensionfrom_der)\n    + [extension:to_der](#extensionto_der)\n    + [extension.istype](#extensionistype)\n    + [extension:get_extension_critical](#extensionget_extension_critical)\n    + [extension:set_extension_critical](#extensionset_extension_critical)\n    + [extension:get_object](#extensionget_object)\n    + [extension:text](#extensiontext)\n  * [resty.openssl.x509.extension.dist_points](#restyopensslx509extensiondist_points)\n    + [dist_points.new](#dist_pointsnew)\n    + [dist_points.dup](#dist_pointsdup)\n    + [dist_points.istype](#dist_pointsistype)\n    + [dist_points:__metamethods](#dist_points__metamethods)\n  * [resty.openssl.x509.extension.info_access](#restyopensslx509extensioninfo_access)\n    + [info_access.new](#info_accessnew)\n    + [info_access.dup](#info_accessdup)\n    + [info_access.istype](#info_accessistype)\n    + [info_access:add](#info_accessadd)\n    + [info_access:__metamethods](#info_access__metamethods)\n  * [resty.openssl.x509.extensions](#restyopensslx509extensions)\n    + [extensions.new](#extensionsnew)\n    + [extensions.dup](#extensionsdup)\n    + [extensions.istype](#extensionsistype)\n    + [extensions:add](#extensionsadd)\n    + [extensions:__metamethods](#extensions__metamethods)\n  * [resty.openssl.x509.chain](#restyopensslx509chain)\n    + [chain.new](#chainnew)\n    + [chain.dup](#chaindup)\n    + [chain.istype](#chainistype)\n    + [chain:add](#chainadd)\n    + [chain:__metamethods](#chain__metamethods)\n  * [resty.openssl.x509.store](#restyopensslx509store)\n    + [store.new](#storenew)\n    + [store.istype](#storeistype)\n    + [store:use_default](#storeuse_default)\n    + [store:add](#storeadd)\n    + [store:load_file](#storeload_file)\n    + [store:load_directory](#storeload_directory)\n    + [store:set_purpose](#storeset_purpose)\n    + [store:set_depth](#storeset_depth)\n    + [store:set_flags](#storeset_flags)\n    + [store:verify](#storeverify)\n    + [store:check_revocation](#storecheck_revocation)\n  * [resty.openssl.x509.revoked](#restyopensslx509revoked)\n    + [revoked.new](#revokednew)\n    + [revoked.istype](#revokedistype)\n  * [resty.openssl.ssl](#restyopensslssl)\n    + [ssl.from_request](#sslfrom_request)\n    + [ssl.from_socket](#sslfrom_socket)\n    + [ssl:get_peer_certificate](#sslget_peer_certificate)\n    + [ssl:get_peer_cert_chain](#sslget_peer_cert_chain)\n    + [ssl:set_ciphersuites, ssl:set_cipher_list](#sslset_ciphersuites-sslset_cipher_list)\n    + [ssl:get_ciphers](#sslget_ciphers)\n    + [ssl:get_cipher_name](#sslget_cipher_name)\n    + [ssl:set_timeout](#sslset_timeout)\n    + [ssl:get_timeout](#sslget_timeout)\n    + [ssl:set_verify](#sslset_verify)\n    + [ssl:add_client_ca](#ssladd_client_ca)\n    + [ssl:set_options](#sslset_options)\n    + [ssl:get_options](#sslget_options)\n    + [ssl:clear_options](#sslclear_options)\n  * [resty.openssl.ssl_ctx](#restyopensslssl_ctx)\n    + [ssl_ctx.from_request](#ssl_ctxfrom_request)\n    + [ssl_ctx.from_socket](#ssl_ctxfrom_socket)\n    + [ssl_ctx:set_alpns](#ssl_ctxset_alpns)\n  * [Functions for stack-like objects](#functions-for-stack-like-objects)\n    + [metamethods](#metamethods)\n    + [each](#each)\n    + [all](#all)\n    + [count](#count)\n    + [index](#index)\n  * [Generic EVP parameter getter/setter](#generic-evp-parameter-gettersetter)\n    + [gettable_params](#gettable_params)\n    + [settable_params](#settable_params)\n    + [get_param](#get_param)\n    + [set_params](#set_params)\n- [General rules on garbage collection](#general-rules-on-garbage-collection)\n- [Code generation](#code-generation)\n- [Compatibility](#compatibility)\n- [Credits](#credits)\n- [Copyright and License](#copyright-and-license)\n- [See Also](#see-also)\n\n\n\nDescription\n===========\n\n`lua-resty-openssl` is a FFI-based OpenSSL binding library, currently\nsupports OpenSSL `3.x` and `1.1.1` series.\n\n[Back to TOC](#table-of-contents)\n\nStatus\n========\n\nProduction.\n\nSynopsis\n========\n\nThis library is greatly inspired by [luaossl](https://github.com/wahern/luaossl), while uses the\nnaming conversion closer to original OpenSSL API.\nFor example, a function called `X509_set_pubkey` in OpenSSL C API will expect to exist\nas `resty.openssl.x509:set_pubkey`.\n*CamelCase*s are replaced to *underscore_case*s, for exmaple `X509_set_serialNumber` becomes\n`resty.openssl.x509:set_serial_number`. Another difference than `luaossl` is that errors are never thrown\nusing `error()` but instead return as last parameter.\n\nEach Lua table returned by `new()` contains a cdata object `ctx`. User are not supposed to manully setting\n`ffi.gc` or calling corresponding destructor of the `ctx` struct (like `*_free` functions).\n\n[Back to TOC](#table-of-contents)\n\n## resty.openssl\n\nThis meta module provides a version sanity check against linked OpenSSL library.\n\n[Back to TOC](#table-of-contents)\n\n### openssl.load_library\n\n**syntax**: *name, err = openssl.load_library()*\n\nTry to load OpenSSL shared libraries. This function tries couple of known patterns\nthe library could be named and return the name of `crypto` library if it's being\nsuccessfully loaded and error if any.\n\nWhen running inside `resty` CLI or OpenResty with SSL enabled, calling this function\nis not necessary.\n\n[Back to TOC](#table-of-contents)\n\n### openssl.load_modules\n\n**syntax**: *openssl.load_modules()*\n\nLoad all available sub modules into current module:\n\n```lua\n  bn = require(\"resty.openssl.bn\"),\n  cipher = require(\"resty.openssl.cipher\"),\n  digest = require(\"resty.openssl.digest\"),\n  hmac = require(\"resty.openssl.hmac\"),\n  kdf = require(\"resty.openssl.kdf\"),\n  pkey = require(\"resty.openssl.pkey\"),\n  objects = require(\"resty.openssl.objects\"),\n  rand = require(\"resty.openssl.rand\"),\n  version = require(\"resty.openssl.version\"),\n  x509 = require(\"resty.openssl.x509\"),\n  altname = require(\"resty.openssl.x509.altname\"),\n  chain = require(\"resty.openssl.x509.chain\"),\n  csr = require(\"resty.openssl.x509.csr\"),\n  crl = require(\"resty.openssl.x509.crl\"),\n  extension = require(\"resty.openssl.x509.extension\"),\n  extensions = require(\"resty.openssl.x509.extensions\"),\n  name = require(\"resty.openssl.x509.name\"),\n  store = require(\"resty.openssl.x509.store\"),\n  ssl = require(\"resty.openssl.ssl\"),\n  ssl_ctx = require(\"resty.openssl.ssl_ctx\"),\n```\n\nStarting OpenSSL 3.0, [`provider`](#restyopensslprovider) and [`mac`](#restyopensslmac)\n[`ctx`](#restyopensslctx)\nis also available.\n\n[Back to TOC](#table-of-contents)\n\n### openssl.luaossl_compat\n\n**syntax**: *openssl.luaossl_compat()*\n\nProvides `luaossl` flavored API which uses *camelCase* naming; user can expect drop in replacement.\n\nFor example, `pkey:get_parameters` is mapped to `pkey:getParameters`.\n\nNote that not all `luaossl` API has been implemented, please check readme for source of truth.\n\n[Back to TOC](#table-of-contents)\n\n### openssl.get_fips_mode\n\n**syntax**: *enabled = openssl.get_fips_mode()*\n\nReturns a boolean indicating if FIPS mode is enabled.\n\n[Back to TOC](#table-of-contents)\n\n### openssl.set_fips_mode\n\n**syntax**: *ok, err = openssl.set_fips_mode(enabled)*\n\nToggle FIPS mode on or off.\n\nlua-resty-openssl supports following modes:\n\n**OpenSSL 1.0.2 series with fips 2.0 module**\n\nCompile the module per [security policy](https://www.openssl.org/docs/fips/SecurityPolicy-2.0.2.pdf),\n\n**OpenSSL 3.0.0 fips provider**\n\nRefer to https://wiki.openssl.org/index.php/OpenSSL_3.0 Section 7\nCompile the provider per guide, install the fipsmodule.cnf that\nmatches hash of FIPS provider fips.so.\n\nOn OpenSSL 3.0 or later, this function also turns on and off default\nproperties for EVP functions. When turned on, all applications using\nEVP_* API will be redirected to FIPS-compliant implementations and\nhave no access to non-FIPS-compliant algorithms.\n\nCalling this function is equivalent of loading `fips` provider and\ncall [openssl.set_default_properties(\"fips=yes\")](#opensslset_default_properties).\n\nIf fips provider is loaded but default properties are not set, use following\nto explictly fetch FIPS implementation.\n```lua\nlocal provider = require \"resty.openssl.provider\"\nassert(provider.load(\"fips\"))\nlocal cipher = require \"resty.openssl.cipher\"\nlocal c = assert(cipher.new(\"aes256\"))\nprint(c:get_provider_name()) -- prints \"default\"\nlocal c = assert(cipher.new(\"aes256\", \"fips=yes\"))\nprint(c:get_provider_name()) -- prints \"fips\"\n```\n\n[Back to TOC](#table-of-contents)\n\n### openssl.get_fips_version_text\n\n**syntax**: *text, err = openssl.get_fips_version_text()*\n\nReturns the version text of the FIPS module, only available on OpenSSL 3.x.\n\n[Back to TOC](#table-of-contents)\n\n### openssl.set_default_properties\n\n**syntax**: *ok, err = openssl.set_default_properties(props)*\n\nSets the default properties for all future EVP algorithm fetches, implicit as well as explicit. See \"ALGORITHM FETCHING\" in crypto(7) for information about implicit and explicit fetching.\n\n[Back to TOC](#table-of-contents)\n\n### openssl.list_cipher_algorithms\n\n**syntax**: *ret = openssl.list_cipher_algorithms(hide_provider?)*\n\nReturn available cipher algorithms in an array. Set `hide_provider` to `true` to\nhide provider name from the result.\n\n[Back to TOC](#table-of-contents)\n\n### openssl.list_digest_algorithms\n\n**syntax**: *ret = openssl.list_digest_algorithms(hide_provider?)*\n\nReturn available digest algorithms in an array. Set `hide_provider` to `true` to\nhide provider name from the result.\n\n[Back to TOC](#table-of-contents)\n\n### openssl.list_mac_algorithms\n\n**syntax**: *ret = openssl.list_mac_algorithms(hide_provider?)*\n\nReturn available MAC algorithms in an array. Set `hide_provider` to `true` to\nhide provider name from the result.\n\n[Back to TOC](#table-of-contents)\n\n### openssl.list_kdf_algorithms\n\n**syntax**: *ret = openssl.list_kdf_algorithms(hide_provider?)*\n\nReturn available KDF algorithms in an array. Set `hide_provider` to `true` to\nhide provider name from the result.\n\n[Back to TOC](#table-of-contents)\n\n### openssl.list_ssl_ciphers\n\n**syntax**: *cipher_string, err = openssl.list_ssl_ciphers(cipher_list?, ciphersuites?, protocol?)*\n\nReturn default SSL ciphers as a string. `cipher_list` (prior TLSv1.3) and\n`ciphersuites` (TLSv1.3) can be used to expand the cipher settings matches\n`protocol`.\n\n```lua\nopenssl.list_ssl_ciphers()\nopenssl.list_ssl_ciphers(\"ECDHE-ECDSA-AES128-SHA\")\nopenssl.list_ssl_ciphers(\"ECDHE-ECDSA-AES128-SHA\", nil, \"TLSv1.2\")\nopenssl.list_ssl_ciphers(\"ECDHE-ECDSA-AES128-SHA\", \"TLS_CHACHA20_POLY1305_SHA256\", \"TLSv1.3\")\n```\n\n[Back to TOC](#table-of-contents)\n\n## resty.openssl.ctx\n\nA module to provide OSSL_LIB_CTX context switches.\n\n  OSSL_LIB_CTX is an internal OpenSSL library context type. Applications may allocate their own, but may also use NULL to use a default context with functions that take an OSSL_LIB_CTX argument.\n\nSee [OSSL_LIB_CTX.3](#https://www.openssl.org/docs/manmaster/man3/OSSL_LIB_CTX.html) for deeper\nreading.\n\nThe context is currently effective following modules:\n\n- [cipher](#restyopensslcipher)\n- [digest](#restyopenssldigest)\n- [kdf](#restyopensslkdf)\n- [mac](#restyopensslmac)\n- [pkcs12.encode](#pkcs12encode)\n- [pkey](#restyopensslpkey)\n- [provider](#restyopensslprovider)\n- [rand](#restyopensslrand)\n- [x509](#restyopensslx509), [x509.csr](#restyopensslx509csr), [x509.crl](#restyopensslx509crl) and some [x509.store](#restyopensslx509store) functions\n\nThis module is only available on OpenSSL 3.0 or later.\n \n[Back to TOC](#table-of-contents)\n\n### ctx.new\n\n**syntax**: *ok, err = ctx.new(request_context_only?, conf_file?)*\n\nCreate a new context and use as default context for this module. When\n`request_context_only` is set to true, the context is only used inside current\nrequest's context. `conf_file` can optionally specify an OpenSSL conf file\nto create the context.\n\nThe created context is automatically freed with its given lifecycle.\n\n```lua\n-- initialize a AES cipher instance from given provider implementation only\n-- for current request, without interfering other part of code\n-- or future requests from using the same algorithm.\nassert(require(\"resty.openssl.ctx\").new(true))\nlocal p = assert(require(\"resty.openssl.provider\").load(\"myprovider\"))\nlocal c = require(\"resty.openssl.cipher\").new(\"aes256\")\nprint(c:encrypt(string.rep(\"0\", 32), string.rep(\"0\", 16), \"🦢\"))\n-- don't need to release provider and ctx, they are GC'ed automatically\n```\n\n[Back to TOC](#table-of-contents)\n\n### ctx.free\n\n**syntax**: *ctx.free(request_context_only?)*\n\nFree the context that was previously created by [ctx.new](#ctxnew).\n\n[Back to TOC](#table-of-contents)\n\n## resty.openssl.err\n\nA module to provide error messages.\n\n[Back to TOC](#table-of-contents)\n\n### err.format_error\n\n**syntax**: *msg = err.format_error(ctx_msg?, return_code?, all_errors?)*\n\n**syntax**: *msg = err.format_all_errors(ctx_msg?, return_code?)*\n\nReturn the latest error message from the last error code. Errors are formatted as:\n\n    [ctx_msg]: code: [return_code]: error:[error code]:[library name]:[func name]:[reason string]:[file name]:[line number]:\n\nOn OpenSSL prior to 3.x, errors are formatted as:\n\n    [ctx_msg]: code: [return_code]: [file name]:[line number]:error:[error code]:[library name]:[func name]:[reason string]:\n\n\nIf `all_errors` is set to `true`, all errors no just the latest one will be returned in a single string. All errors thrown\nby this library internally only thrown the latest error.\n\nFor example:\n\n```lua\nlocal f = io.open(\"t/fixtures/ec_key_encrypted.pem\"):read(\"*a\")\nlocal privkey, err = require(\"resty.openssl.pkey\").new(f, {\n    format = \"PEM\",\n    type = \"pr\",\n    passphrase = \"wrongpasswrod\",\n})\nngx.say(err)\n-- pkey.new:load_key: error:4800065:PEM routines:PEM_do_header:bad decrypt:crypto/pem/pem_lib.c:467:\n```\n\n[Back to TOC](#table-of-contents)\n\n### err.get_last_error_code\n\n**syntax**: *code = err.get_last_error_code()*\n\nReturn the last error code.\n\n[Back to TOC](#table-of-contents)\n\n### err.get_lib_error_string\n\n**syntax**: *lib_error_message = err.get_lib_error_string(code?)*\n\nReturn the library name of the last error code as string. If `code` is set, return the library name\ncorresponding to provided error code instead.\n\n[Back to TOC](#table-of-contents)\n\n### err.get_reason_error_string\n\n**syntax**: *reason_error_message = err.get_reason_error_string(code?)*\n\nReturn the reason of the last error code as string. If `code` is set, return the reason\ncorresponding to provided error code instead.\n\n[Back to TOC](#table-of-contents)\n\n## resty.openssl.version\n\nA module to provide version info.\n\n[Back to TOC](#table-of-contents)\n\n### version_num\n\nThe OpenSSL version number.\n\n[Back to TOC](#table-of-contents)\n\n### version_text\n\nThe OpenSSL version text.\n\n[Back to TOC](#table-of-contents)\n\n### version.version\n\n**syntax**: *text = version.version(types)*\n\nReturns various OpenSSL version information. Available values for `types` are:\n\n    VERSION\n    CFLAGS\n    BUILT_ON\n    PLATFORM\n    DIR\n    ENGINES_DIR\n    VERSION_STRING\n    FULL_VERSION_STRING\n    MODULES_DIR\n    CPU_INFO\n\n```lua\nlocal version = require(\"resty.openssl.version\")\nngx.say(string.format(\"%x\", version.version_num))\n-- outputs \"101000bf\"\nngx.say(version.version_text)\n-- outputs \"OpenSSL 1.1.0k  28 May 2019\"\nngx.say(version.version(version.PLATFORM))\n-- outputs \"darwin64-x86_64-cc\"\n```\n\n[Back to TOC](#table-of-contents)\n\n### version.info\n\n**syntax**: *text = version.info(types)*\n\nReturns various OpenSSL information. Available values for `types` are:\n\n    INFO_ENGINES_DIR\n    INFO_DSO_EXTENSION\n    INFO_CPU_SETTINGS\n    INFO_LIST_SEPARATOR\n    INFO_DIR_FILENAME_SEPARATOR\n    INFO_CONFIG_DIR\n    INFO_SEED_SOURCE\n    INFO_MODULES_DIR\n\nThis function is only available on OpenSSL 3.0.\nPlease refer to\n[OPENSSL_VERSION_NUMBER(3)](https://www.openssl.org/docs/manmaster/man3/OPENSSL_VERSION_NUMBER.html)\nfor explanation of each type.\n\n```lua\nlocal version = require(\"resty.openssl.version\")\nngx.say(version.info(version.INFO_DSO_EXTENSION))\n-- outputs \".so\"\n```\n\n[Back to TOC](#table-of-contents)\n\n### version.OPENSSL_3X\n\nA boolean indicates whether the linked OpenSSL is 3.x series.\n\n[Back to TOC](#table-of-contents)\n\n### version.OPENSSL_111\n\nA boolean indicates whether the linked OpenSSL is 1.1.1 series.\n\n[Back to TOC](#table-of-contents)\n\n## resty.openssl.provider\n\nModule to interact with providers. This module only work on OpenSSL \u003e= 3.0.0.\n\n[Back to TOC](#table-of-contents)\n\n### provider.load\n\n**syntax**: *pro, err = provider.load(name, try?)*\n\nLoad provider with `name`. If `try` is set to true, OpenSSL will not disable the\nfall-back providers if the provider cannot be loaded and initialized. If the provider\nloads successfully, however, the fall-back providers are disabled.\n\nBy default this functions loads provider into the default context, meaning it will affect\nother applications in the same process using the default context as well. If such behaviour\nis not desired, consider using [ctx](#restyopensslctx) to load\nprovider only to limited scope.\n\n[Back to TOC](#table-of-contents)\n\n### provider.istype\n\n**syntax**: *ok = pkey.provider(table)*\n\nReturns `true` if table is an instance of `provider`. Returns `false` otherwise.\n\n[Back to TOC](#table-of-contents)\n\n### provider.is_available\n\n**syntax**: *ok, err = provider.is_available(name)*\n\nChecks if a named provider is available for use.\n\n[Back to TOC](#table-of-contents)\n\n### provider.set_default_search_path\n\n**syntax**: *ok, err = provider.set_default_search_path(name)*\n\nSpecifies the default search path that is to be used for looking for providers.\n\n[Back to TOC](#table-of-contents)\n\n### provider:unload\n\n**syntax**: *ok, err = pro:unload(name)*\n\nUnload a provider that is previously loaded by `provider.load`.\n\n[Back to TOC](#table-of-contents)\n\n### provider:self_test\n\n**syntax**: *ok, err = pro:self_test(name)*\n\nRuns a provider's self tests on demand. If the self tests fail then the provider\nwill fail to provide any further services and algorithms.\n\n[Back to TOC](#table-of-contents)\n\n### provider:get_params\n\n**syntax**: *ok, err = pro:get_params(key1, key2?...)*\n\nReturns one or more provider parameter values.\n\n```lua\nlocal pro = require \"resty.openssl.provider\"\n\nlocal p = pro.load(\"default\")\n\nlocal name = assert(p:get_params(\"name\"))\nprint(name)\n-- outputs \"OpenSSL Default Provider\"\n\nlocal result = assert(p:get_params(\"name\", \"version\", \"buildinfo\", \"status\"))\nprint(require(\"cjson\").encode(result))\n-- outputs '{\"buildinfo\":\"3.0.0-alpha7\",\"name\":\"OpenSSL Default Provider\",\"status\":1,\"version\":\"3.0.0\"}'\n```\n\n[Back to TOC](#table-of-contents)\n\n## resty.openssl.pkey\n\nModule to interact with private keys and public keys (EVP_PKEY).\n\nEach key type may only support part of operations:\n\nKey Type | Load existing key | Key generation | Encrypt/Decrypt | Sign/Verify | Key Exchange |\n---------|----------|----------------|-----------------|-------------|---------- |\nRSA| Y | Y | Y | Y | |\nDH | Y | Y | | | Y |\nEC | Y | Y | | Y (ECDSA) | Y (ECDH) |\nEd25519 | Y | Y | | Y (PureEdDSA) | |\nX25519 | Y | Y | | | Y (ECDH) |\nEd448 | Y | Y | | Y (PureEdDSA) | |\nX448 | Y | Y | | | Y (ECDH) |\n\nDirect support of encryption and decryption for EC and ECX does not exist, but\nprocesses like ECIES is possible with [pkey:derive](#pkeyderive),\n[kdf](#restyopensslkdf) and [cipher](#restyopensslcipher)\n\n[Back to TOC](#table-of-contents)\n\n### pkey.new\n\n#### Load existing key\n\n**syntax**: *pk, err = pkey.new(string, opts?)*\n\nSupports loading a private or public key in PEM, DER or JWK format passed as first argument `string`.\n\nThe second parameter `opts` accepts an optional table to constraint the behaviour of key loading.\n\n- `opts.format`: set explictly to `\"PEM\"`, `\"DER\"`, `\"JWK\"` to load specific format or set to `\"*\"` for auto detect\n- `opts.type`: set explictly to `\"pr\"` for privatekey, `\"pu\"` for public key; set to `\"*\"` for auto detect\n\nWhen loading a PEM encoded RSA key, it can either be a PKCS#8 encoded\n`SubjectPublicKeyInfo`/`PrivateKeyInfo` or a PKCS#1 encoded `RSAPublicKey`/`RSAPrivateKey`.\n\nWhen loading a encrypted PEM encoded key, the `passphrase` to decrypt it can either be set\nin `opts.passphrase` or `opts.passphrase_cb`:\n\n```lua\npkey.new(pem_or_der_text, {\n  format = \"*\", -- choice of \"PEM\", \"DER\", \"JWK\" or \"*\" for auto detect\n  type = \"*\", -- choice of \"pr\" for privatekey, \"pu\" for public key and \"*\" for auto detect\n  passphrase = \"secret password\", -- the PEM encryption passphrase\n  passphrase_cb = function()\n    return \"secret password\"\n  end, -- the PEM encryption passphrase callback function\n}\n\n```\n\nWhen loading JWK, there are couple of caveats:\n- Make sure the encoded JSON text is passed in, it must have been base64 decoded.\n- When using OpenSSL 1.1.1 or lua-resty-openssl earlier than 1.6.0, constraint `type`\non JWK key is only supported on OpenSSL 3.x and lua-resty-openssl 1.6.0.\nOtherwise the parameters in provided JSON will decide if a private or public key is loaded, \nspecifying `type` will result in an error; also public key part for `OKP` keys (the `x` parameter)\nis not honored and derived from private key part (the `d` parameter) if it's specified.\n- Only key type of `RSA`, `P-256`, `P-384` and `P-512` `EC`,\n`Ed25519`, `X25519`, `Ed448` and `X448` `OKP` keys are supported.\n- Signatures and verification must use `ecdsa_use_raw` option to work with JWS standards\nfor EC keys. See [pkey:sign](#pkeysign) and [pkey.verify](#pkeyverify) for detail.\n- When running outside of OpenResty, needs to install a JSON library (`cjson` or `dkjson`)\nand `basexx`.\n\n[Back to TOC](#table-of-contents)\n\n#### Key generation\n\n**syntax**: *pk, err = pkey.new(config?)*\n\nGenerate a new public key or private key.\n\nTo generate RSA key, `config` table can have `bits` and `exp` field to control key generation.\nWhen `config` is emitted, this function generates a 2048 bit RSA key with `exponent` of 65537,\nwhich is equivalent to:\n  \n```lua\nlocal key, err = pkey.new({\n  type = 'RSA',\n  bits = 2048,\n  exp = 65537\n})\n```\n\nTo generate EC or DH key, please refer to [pkey.paramgen](#pkeyparamgen) for possible values of\n`config` table. For example:\n\n```lua\nlocal key, err = pkey.new({\n  type = 'EC',\n  curve = 'prime256v1',\n})\n```\n\nIt's also possible to pass a PEM-encoded EC or DH parameters to `config.param` for key generation:\n\n```lua\nlocal dhparam = pkey.paramgen({\n  type = 'DH',\n  group = 'dh_1024_160'\n})\n-- OR\n-- local dhparam = io.read(\"dhparams.pem\"):read(\"*a\")\n\nlocal key, err = pkey.new({\n  type = 'DH',\n  param = dhparam,\n}) \n```\n\nIt's also possible to pass raw pkeyopt control strings in `config` table as used in the `genpkey` CLI program.\nSee [openssl-genpkey(1)](https://www.openssl.org/docs/man3.0/man1/openssl-genpkey.html) for a list of options.\n\nFor example:\n\n```lua\npkey.new({\n  type = 'RSA',\n  bits = 2048,\n  exp = 65537,\n})\n-- is same as\npkey.new({\n  type = 'RSA',\n  exp = 65537,\n  \"rsa_keygen_bits:4096\",\n})\n\n```\n\n[Back to TOC](#table-of-contents)\n\n#### Key composition\n\n**syntax**: *pk, err = pkey.new(config?)*\n\nCompose a public or private key using existing parameters. To see\nlist of parameters for each key, refer to [pkey:set_parameters](#pkeyset_parameters).\n\nOnly `type` and `params` should exist in `config` table, all other keys will be ignored.\n\n```lua\nlocal private_bn = require \"resty.openssl.bn\".new(\"7F48282CCA4C1A65D589C06DBE9C42AE50FBFFDF3A18CBB48498E1DE47F11BE1A3486CD8FA950D68F111970F922279D8\", 16)\nlocal p_384, err = assert(require(\"resty.openssl.pkey\").new({\n    type = \"EC\",\n    params = {\n        private = private_bn,\n        group = \"secp384r1\",\n    }\n}))\n```\n\n[Back to TOC](#table-of-contents)\n\n### pkey.istype\n\n**syntax**: *ok = pkey.istype(table)*\n\nReturns `true` if table is an instance of `pkey`. Returns `false` otherwise.\n\n[Back to TOC](#table-of-contents)\n\n### pkey.paramgen\n\n**syntax**: *pem_txt, err = pk.paramgen(config)*\n\nGenerate parameters for EC or DH key and output as PEM-encoded text.\n\nFor EC key:\n\n Parameter | Description\n-----------|-------------\ntype | `\"EC\"`\ncurve | EC curves. If omitted, default to `\"prime192v1\"`. To see list of supported EC curves, use `openssl ecparam -list_curves`.\n\nFor DH key:\n  \n Parameter | Description\n-----------|-------------\ntype | `\"DH\"`\nbits | Generate a new DH parameter with `bits` long prime. If omitted, default to `2048`. Starting OpenSSL 3.0, only bits equal to 2048 is allowed.\ngroup | Use predefined groups instead of generating new one. `bit` will be ignored if `group` is set.\n\nPossible values for `group` are:\n- [RFC7919](https://tools.ietf.org/html/rfc7919#appendix-A.1) `\"ffdhe2048\"`, `\"ffdhe3072\"`,\n`\"ffdhe4096\"`, `\"ffdhe6144\"`, `\"ffdhe8192\"`\n- [RFC5114](https://tools.ietf.org/html/rfc5114#section-2) `\"dh_1024_160\"`, `\"dh_2048_224\"`, `\"dh_2048_256\"`\n- [RFC3526](https://tools.ietf.org/html/rfc3526#page-3) `\"modp_1536\"`, `\"modp_2048\"`,\n`\"modp_3072\"`, `\"modp_4096\"`, `\"modp_6144\"`, `\"modp_8192\"`\n  \n```lua\nlocal pem, err = pkey.paramgen({\n  type = 'EC',\n  curve = 'prime192v1',\n})\n\nlocal pem, err = pkey.paramgen({\n  type = 'DH',\n  group = 'ffdhe4096',\n})\n```\n\nIt's also possible to pass raw pkeyopt control strings in `config` table as used in the `genpkey` CLI program.\nSee [openssl-genpkey(1)](https://www.openssl.org/docs/man3.0/man1/openssl-genpkey.html) for a list of options.\n\n[Back to TOC](#table-of-contents)\n\n### pkey:get_provider_name\n\n**syntax**: *name = pkey:get_provider_name()*\n\nReturns the provider name of `pkey`.\n\nThis function is available since OpenSSL 3.0.\n\n[Back to TOC](#table-of-contents)\n\n## pkey:gettable_params, pkey:settable_params, pkey:get_param, pkey:set_params\n\nQuery settable or gettable params and set or get params.\nSee [Generic EVP parameter getter/setter](#generic-evp-parameter-gettersetter).\n\n[Back to TOC](#table-of-contents)\n\n### pkey:get_parameters\n\n**syntax**: *parameters, err = pk:get_parameters()*\n\nReturns a table containing the `parameters` of pkey instance.\n\n[Back to TOC](#table-of-contents)\n\n### pkey:set_parameters\n\n**syntax**: *ok, err = pk:set_parameters(params)*\n\nSet the parameters of the pkey from a table `params`.\nIf the parameter is not set in the `params` table,\nit remains untouched in the pkey instance.\n\n```lua\nlocal pk, err = require(\"resty.openssl.pkey\").new()\nlocal parameters, err = pk:get_parameters()\nlocal e = parameters.e\nngx.say(e:to_number())\n-- outputs 65537\n\nlocal ok, err = pk:set_parameters({\n  e = require(\"resty.openssl.bn\").from_hex(\"100001\")\n})\n\nlocal ok, err = pk:set_parameters(parameters)\n```\n\nParameters for RSA key:\n\n Parameter | Description | Type\n-----------|-------------|------\nn | modulus common to both public and private key | [bn](#restyopensslbn)\ne | public exponent | [bn](#restyopensslbn)\nd | private exponent | [bn](#restyopensslbn)\np | first factor of **n** | [bn](#restyopensslbn)\nq | second factor of **n** | [bn](#restyopensslbn)\ndmp1 | `d mod (p - 1)`, exponent1 | [bn](#restyopensslbn)\ndmq1 | `d mod (q - 1)`, exponent2 | [bn](#restyopensslbn)\niqmp | `(InverseQ)(q) = 1 mod p`, coefficient | [bn](#restyopensslbn)\n\nParameters for EC key:\n\n Parameter | Description | Type\n-----------|-------------|-----\nprivate | private key | [bn](#restyopensslbn)\npublic | public key | [bn](#restyopensslbn)\nx | x coordinate of the public key| [bn](#restyopensslbn)\ny | y coordinate of the public key| [bn](#restyopensslbn)\ngroup | the named curve group | [NID] as a number, when passed in as `set_parameters()`, it's also possible to use the text representation. This is different from `luaossl` where a `EC_GROUP` instance is returned.\n\nIt's not possible to set `x`, `y` with `public` at same time as `x` and `y` is basically another representation\nof `public`. Also currently it's only possible to set `x` and `y` at same time.\n\nParameters for DH key:\n\n Parameter | Description | Type\n-----------|-------------|-----\nprivate | private key | [bn](#restyopensslbn)\npublic | public key | [bn](#restyopensslbn)\np | prime modulus | [bn](#restyopensslbn)\nq | reference position | [bn](#restyopensslbn)\ng | base generator | [bn](#restyopensslbn)\n\n\nParameters for Curve25519 and Curve448 keys:\n\n Parameter | Description | Type\n-----------|-------------|-----\nprivate | raw private key represented as bytes | string\npublic | raw public key represented as bytes | string\n\n[Back to TOC](#table-of-contents)\n\n### pkey:is_private\n\n**syntax**: *ok = pk:is_private()*\n\nChecks whether `pk` is a private key. Returns true if it's a private key, returns false if\nit's a public key.\n\n[Back to TOC](#table-of-contents)\n\n### pkey:get_key_type\n\n**syntax**: *obj, err = pk:get_key_type(nid_only?)*\n\nReturns a ASN1_OBJECT of key type of the private key as a table.\n\nStarting from lua-resty-openssl 1.6.0, an optional argument `nid_only` can be set to `true`\nto only return the numeric NID of the key.\n\n```lua\nlocal pkey, err = require(\"resty.openssl.pkey\").new({type=\"X448\"})\n\nngx.say(require(\"cjson\").encode(pkey:get_key_type()))\n-- outputs '{\"ln\":\"X448\",\"nid\":1035,\"sn\":\"X448\",\"id\":\"1.3.101.111\"}'\nngx.say(pkey:get_key_type(true))\n-- outputs 1035\n```\n\n[Back to TOC](#table-of-contents)\n\n### pkey:get_size\n\n**syntax**: *size, err = pk:get_size()*\n\nReturns the maximum suitable size for the output buffers for almost all\noperations that can be done with pkey.\n\nFor RSA key, this is the size of the modulus.\nFor EC, Ed25519 and Ed448 keys, this is the size of the private key.\nFor DH key, this is the size of the prime modulus.\n\n[Back to TOC](#table-of-contents)\n\n### pkey:get_default_digest_type\n\n**syntax**: *obj, err = pk:get_default_digest_type()*\n\nReturns a ASN1_OBJECT of key type of the private key as a table. An additional field `mandatory` is also\nreturned in the table, if `mandatory` is true then other digests can not be used.\n\n```lua\nlocal pkey, err = require(\"resty.openssl.pkey\").new()\n\nngx.say(require(\"cjson\").encode(pkey:get_default_digest_type()))\n-- outputs '{\"ln\":\"sha256\",\"nid\":672,\"id\":\"2.16.840.1.101.3.4.2.1\",\"mandatory\":false,\"sn\":\"SHA256\"}'\n```\n\n[Back to TOC](#table-of-contents)\n\n### pkey:sign\n\n**syntax**: *signature, err = pk:sign(digest)*\n\n**syntax**: *signature, err = pk:sign(message, md_alg?, padding?, opts?)*\n\nPerform a digest signing using the private key defined in `pkey`\ninstance. The first parameter must be a [resty.openssl.digest](#restyopenssldigest)\ninstance or a string. Returns the signed text and error if any.\n\nWhen passing a [digest](#restyopenssldigest) instance as first parameter, it should not\nhave been called [final()](#digestfinal), user should only use [update()](#digestupdate).\nThis mode only supports RSA and EC keys.\n\nWhen passing a string as first parameter, `md_alg` parameter will specify the name\nto use when signing. When `md_alg` is undefined, for RSA and EC keys, this function does SHA256\nby default. For Ed25519 or Ed448 keys, this function does a PureEdDSA signing,\nno message digest should be specified and will not be used.\n\nFor RSA key, it's also possible to specify `padding` scheme with following choices:\n\n```lua\n  pkey.PADDINGS = {\n    RSA_PKCS1_PADDING       = 1,\n    RSA_SSLV23_PADDING      = 2,\n    RSA_NO_PADDING          = 3,\n    RSA_PKCS1_OAEP_PADDING  = 4,\n    RSA_X931_PADDING        = 5, -- sign only\n    RSA_PKCS1_PSS_PADDING   = 6, -- sign and verify only\n  }\n```\n\nWhen `padding` is `RSA_PKCS1_PSS_PADDING`, it's\npossible to specify PSS salt length by setting `opts.pss_saltlen`.\n\nFor EC key, this function does a ECDSA signing.\nNote that OpenSSL does not support EC digital signature (ECDSA) with the\nobsolete MD5 hash algorithm and will return error on this combination. See\n[EVP_DigestSign(3)](https://www.openssl.org/docs/manmaster/man3/EVP_DigestSign.html)\nfor a list of algorithms and associated public key algorithms. Normally, the ECDSA signature\nis encoded in ASN.1 DER format. If the `opts` table contains a `ecdsa_use_raw` field with\na true value, a binary with just the concatenation of binary representation `pr` and `ps` is returned.\nThis is useful for example to send the signature as JWS.\n\n`opts` is a table that accepts additional parameters with following choices:\n\n```\n{\n  pss_saltlen, -- For PSS mode only this option specifies the salt length.\n  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.\n  oaep_md, -- The digest used for the OAEP hash function. If not explicitly set then SHA1 is used.\n}\n```\n\nIt's also possible to pass raw pkeyopt control strings as used in the `pkeyutl` CLI program. This lets user pass in options that\nare not explictly supported as parameters above.\nSee [openssl-pkeyutl(1)](https://www.openssl.org/docs/manmaster/man1/openssl-pkeyutl.html) for a list of options.\n\n```lua\npk:sign(message, nil, pk.PADDINGS.RSA_PKCS1_OAEP_PADDING, {\n  oaep_md = \"sha256\",\n})\n-- is same as\npk:sign(message, nil, nil, {\n  \"rsa_padding_mode:oaep\",\n  \"rsa_oaep_md:sha256\",\n})\n-- in pkeyutl CLI the above is equivalent to: `openssl pkeyutl -sign -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha256\n```\n\nTo sign a message without doing message digest, please check [pkey:sign_raw](#pkeysign_raw).\n\n[Back to TOC](#table-of-contents)\n\n### pkey:verify\n\n**syntax**: *ok, err = pk:verify(signature, digest)*\n\n**syntax**: *ok, err = pk:verify(signature, message, md_alg?, padding?, opts?)*\n\nVerify a signture (which can be the string returned by [pkey:sign](#pkey-sign)). The second\nargument must be a [resty.openssl.digest](#restyopenssldigest) instance that uses\nthe same digest algorithm as used in `sign` or a string. `ok` returns `true` if verficiation is\nsuccessful and `false` otherwise. Note when verfication failed `err` will not be set when used\nwith OpenSSL 1.1.1 or lower.\n\nWhen passing [digest](#restyopenssldigest) instances as second parameter, it should not\nhave been called [final()](#digestfinal), user should only use [update()](#digestupdate).\nThis mode only supports RSA and EC keys.\n\nWhen passing a string as second parameter, `md_alg` parameter will specify the name\nto use when verifying. When `md_alg` is undefined, for RSA and EC keys, this function does SHA256\nby default. For Ed25519 or Ed448 keys, this function does a PureEdDSA verification,\nno message digest should be specified and will not be used.\n\nWhen key is a RSA key, the function accepts an optional argument `padding` which choices\nof values are same as those in [pkey:sign](#pkeysign). When `padding` is `RSA_PKCS1_PSS_PADDING`, it's\npossible to specify PSS salt length by setting `opts.pss_saltlen`.\n\nFor EC key, this function does a ECDSA verification. Normally, the ECDSA signature\nshould be encoded in ASN.1 DER format. If the `opts` table contains a `ecdsa_use_raw` field with\na true value, this library treat `signature` as concatenation of binary representation `pr` and `ps`.\nThis is useful for example to verify the signature as JWS.\n\n`opts` is a table that accepts additional parameters which choices\nof values are same as those in [pkey:sign](#pkeysign).\n\n\n```lua\n-- RSA and EC keys\nlocal pk, err = require(\"resty.openssl.pkey\").new()\nlocal digest, err = require(\"resty.openssl.digest\").new(\"SHA256\")\ndigest:update(\"dog\")\n-- WRONG:\n-- digest:final(\"dog\")\nlocal signature, err = pk:sign(digest)\n-- uses SHA256 by default\nlocal signature, err = pk:sign(\"dog\")\nngx.say(ngx.encode_base64(signature))\n-- uses SHA256 and PSS padding\nlocal signature_pss, err = pk:sign(\"dog\", \"sha256\", pk.PADDINGS.RSA_PKCS1_PSS_PADDING)\n\ndigest, err = require(\"resty.openssl.digest\").new(\"SHA256\")\ndigest:update(\"dog\")\nlocal ok, err = pk:verify(signature, digest)\n-- uses SHA256 by default\nlocal ok, err = pk:verify(signature, \"dog\")\n-- uses SHA256 and PSS padding\nlocal ok, err = pk:verify(signature_pss, \"dog\", \"sha256\", pk.PADDINGS.RSA_PKCS1_PSS_PADDING)\n\n-- Ed25519 and Ed448 keys\nlocal pk, err = require(\"resty.openssl.pkey\").new({\n  type = \"Ed25519\",\n})\nlocal signature, err = pk:sign(\"23333\")\nngx.say(ngx.encode_base64(signature))\n\n```\n\nTo verify a message without doing message digest, please check [pkey:verify_raw](#pkeyverify_raw) and [pkey:verify_recover](#pkeyverify_recover).\n\n[Back to TOC](#table-of-contents)\n\n### pkey:encrypt\n\n**syntax**: *cipher_txt, err = pk:encrypt(txt, padding?, opts?)*\n\nEncrypts plain text `txt` with `pkey` instance, which must loaded a public key.\n\nThe optional second argument `padding` has same meaning as in [pkey:sign](#pkeysign).\nIf omitted, `padding` is default to `pkey.PADDINGS.RSA_PKCS1_PADDING`.\n\nThe third optional argument `opts` has same meaning as in [pkey:sign](#pkeysign).\n\n\n[Back to TOC](#table-of-contents)\n\n### pkey:decrypt\n\n**syntax**: *txt, err = pk:decrypt(cipher_txt, padding?, opts?)*\n\nDecrypts cipher text `cipher_txt` with pkey instance, which must loaded a private key.\n\nThe optional second argument `padding` has same meaning as in [pkey:sign](#pkeysign).\nIf omitted, `padding` is default to `pkey.PADDINGS.RSA_PKCS1_PADDING`.\n\nThe third optional argument `opts` has same meaning as in [pkey:sign](#pkeysign).\n\n```lua\nlocal pkey = require(\"resty.openssl.pkey\")\nlocal privkey, err = pkey.new()\nlocal pub_pem = privkey:to_PEM(\"public\")\nlocal pubkey, err = pkey.new(pub_pem)\nlocal s, err = pubkey:encrypt(\"🦢\", pkey.PADDINGS.RSA_PKCS1_PADDING)\nngx.say(#s)\n-- outputs 256\nlocal decrypted, err = privkey:decrypt(s)\nngx.say(decrypted)\n-- outputs \"🦢\"\n```\n\n[Back to TOC](#table-of-contents)\n\n### pkey:sign_raw\n\n**syntax**: *signature, err = pk:sign_raw(txt, padding?, opts?)*\n\nSigns the cipher text `cipher_txt` with pkey instance, which must loaded a private key.\n\nThe optional second argument `padding` has same meaning as in [pkey:sign](#pkeysign).\nIf omitted, `padding` is default to `pkey.PADDINGS.RSA_PKCS1_PADDING`.\n\nThe third optional argument `opts` has same meaning as in [pkey:sign](#pkeysign).\n\nThis function may also be called \"private encrypt\" in some implementations like NodeJS or PHP.\nDo note as the function names suggested, this function is not secure to be regarded as an encryption.\nWhen developing new applications, user should use [pkey:sign](#pkeysign) for signing with digest, or \n[pkey:encrypt](#pkeyencrypt) for encryption.\n\nSee [examples/raw-sign-and-recover.lua](https://github.com/fffonion/lua-resty-openssl/blob/master/examples/raw-sign-and-recover.lua)\nfor an example.\n\n[Back to TOC](#table-of-contents)\n\n### pkey:verify_raw\n\n**syntax**: *ok, err = pk:verify_raw(signature, data, md_alg, padding?, opts?)*\n\nVerify the cipher text `signature` with the message `data` with pkey instance, which must loaded a public key. Set the message digest to `md_alg` but doesn't do message digest\nautomatically, in other words, this function assumes `data` has already been hashed with `md_alg`.\n\nWhen `md_alg` is undefined, for RSA and EC keys, this function does SHA256 by default. For Ed25519 or Ed448 keys, no default value is set.\n\nThe optinal fourth argument `padding` has same meaning as in [pkey:sign](#pkeysign).\nIf omitted, `padding` is default to `pkey.PADDINGS.RSA_PKCS1_PADDING`.\n\nThe fifth optional argument `opts` has same meaning as in [pkey:sign](#pkeysign).\n\nSee [examples/raw-sign-and-recover.lua](https://github.com/fffonion/lua-resty-openssl/blob/master/examples/raw-sign-and-recover.lua)\nfor an example.\n\n[Back to TOC](#table-of-contents)\n\n### pkey:verify_recover\n\n**syntax**: *txt, err = pk:verify_recover(signature, padding?, opts?)*\n\nVerify the cipher text `signature` with pkey instance, which must loaded a public key, and also\nreturns the original text being signed. This operation is only supported by RSA key.\n\nThe optional second argument `padding` has same meaning as in [pkey:sign](#pkeysign).\nIf omitted, `padding` is default to `pkey.PADDINGS.RSA_PKCS1_PADDING`.\n\nThe third optional argument `opts` has same meaning as in [pkey:sign](#pkeysign).\n\nThis function may also be called \"public decrypt\" in some implementations like NodeJS or PHP.\n\nSee [examples/raw-sign-and-recover.lua](https://github.com/fffonion/lua-resty-openssl/blob/master/examples/raw-sign-and-recover.lua)\nfor an example.\n\n[Back to TOC](#table-of-contents)\n\n### pkey:derive\n\n**syntax**: *txt, err = pk:derive(peer_key)*\n\nDerive public key algorithm shared secret `peer_key`, which must be a [pkey](#restyopensslpkey)\ninstance.\n\nSee [examples/x25519-dh.lua](https://github.com/fffonion/lua-resty-openssl/blob/master/examples/x25519-dh.lua)\nfor an example on how key exchange works for X25519 keys with DH algorithm.\n\n[Back to TOC](#table-of-contents)\n\n### pkey:tostring\n\n**syntax**: *txt, err = pk:tostring(private_or_public?, fmt?, is_pkcs1?)*\n\nOutputs private key or public key of pkey instance in PEM-formatted text.\nThe first argument must be a choice of `public`, `PublicKey`, `private`, `PrivateKey` or nil.\n\nThe second argument `fmt` can be `PEM`, `DER`, `JWK` or nil.\nIf both arguments are omitted, this functions returns the `PEM` representation of public key.\n\nIf `is_pkcs1` is set to true, the output is encoded using a PKCS#1 RSAPublicKey structure;\n`PKCS#1` encoding is currently supported for RSA key in PEM format. Writing out a PKCS#1\nencoded RSA key is currently not supported when using with OpenSSL 3.0.\n\n[Back to TOC](#table-of-contents)\n\n### pkey:to_PEM\n\n**syntax**: *pem, err = pk:to_PEM(private_or_public?, is_pkcs1?)*\n\nEquivalent to `pkey:tostring(private_or_public, \"PEM\", is_pkcs1)`.\n\n[Back to TOC](#table-of-contents)\n\n## resty.openssl.bn\n\nModule to expose BIGNUM structure. Note bignum is a big integer, no float operations\n(like square root) are supported.\n\n[Back to TOC](#table-of-contents)\n\n### bn.new\n\n**syntax**: *b, err = bn.new(number?)*\n\n**syntax**: *b, err = bn.new(string?, base?)*\n\nCreates a `bn` instance. The first argument can be:\n\n- `nil` to creates an empty bn instance.\n- A Lua number to initialize the bn instance.\n- A string to initialize the bn instance. The second argument `base` specifies the base of the string,\nand can take value from (compatible with Ruby OpenSSL.BN API):\n  - `10` or omitted, for decimal string (`\"23333\"`)\n  - `16`, for hex encoded string (`\"5b25\"`)\n  - `2`, for binary string (`\"\\x5b\\x25\"`)\n  - `0`, for MPI formated string (`\"\\x00\\x00\\x00\\x02\\x5b\\x25\"`)\n\nMPI 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).\n\n[Back to TOC](#table-of-contents)\n\n### bn.dup\n\n**syntax**: *b, err = bn.dup(bn_ptr_cdata)*\n\nDuplicates a `BIGNUM*` to create a new `bn` instance.\n\n[Back to TOC](#table-of-contents)\n\n### bn.istype\n\n**syntax**: *ok = bn.istype(table)*\n\nReturns `true` if table is an instance of `bn`. Returns `false` otherwise.\n\n[Back to TOC](#table-of-contents)\n\n### bn.set\n\n**syntax**: *b, err = bn:set(number)*\n\n**syntax**: *b, err = bn:set(string, base?)*\n\nReuse the existing bn instance and reset its value with given number or string.\nRefer to [bn.new](#bnnew) for the type of arguments supported.\n\n[Back to TOC](#table-of-contents)\n\n### bn.from_binary, bn:to_binary\n\n**syntax**: *bn, err = bn.from_binary(bin)*\n\n**syntax**: *bin, err = bn:to_binary(padto?)*\n\nCreates a `bn` instance from binary string.\n\nExports the BIGNUM value in binary string.\n\n`bn:to_binary` accepts an optional number argument `padto` that can be\nused to pad leading zeros to the output to a specific length.\n\n```lua\nlocal to_hex = require \"resty.string\".to_hex\nlocal b, err = require(\"resty.openssl.bn\").from_binary(\"\\x5b\\x25\")\nlocal bin, err = b:to_binary()\nngx.say(to_hex(bin))\n-- outputs \"5b25\n```\n\n[Back to TOC](#table-of-contents)\n\n### bn.from_mpi, bn:to_mpi\n\n**syntax**: *bn, err = bn.from_mpi(bin)*\n\n**syntax**: *bin, err = bn:to_mpi()*\n\nCreates a `bn` instance from MPI formatted binary string.\n\nExports the BIGNUM value in MPI formatted binary string.\n\n\n```lua\nlocal to_hex = require \"resty.string\".to_hex\nlocal b, err = require(\"resty.openssl.bn\").from_mpi(\"\\x00\\x00\\x00\\x02\\x5b\\x25\")\nlocal bin, err = b:to_mpi()\nngx.say(to_hex(bin))\n-- outputs \"000000025b25\n```\n\n[Back to TOC](#table-of-contents)\n\n### bn.from_hex, bn:to_hex\n\n**syntax**: *bn, err = bn.from_hex(hex)*\n\n**syntax**: *hex, err = bn:to_hex()*\n\nCreates a `bn` instance from hex encoded string. Note that the leading `0x` should not be\nincluded. A leading `-` indicating the sign may be included.\n\nExports the `bn` instance to hex encoded string.\n\n```lua\nlocal bn = require(\"resty.openssl.bn\")\nlocal b = bn.from_hex(\"5B25\")\nlocal hex, err = b:to_hex()\nngx.say(hex)\n-- outputs \"5B25\"\n```\n\n[Back to TOC](#table-of-contents)\n\n### bn.from_dec, bn:to_dec\n\n**syntax**: *bn, err = bn.from_dec(dec)*\n\n**syntax**: *dec, err = bn:to_dec()*\n\nCreates a `bn` instance from decimal string. A leading `-` indicating the sign may be included.\n\nExports the `bn` instance to decimal string.\n\n```lua\nlocal bn = require(\"resty.openssl.bn\")\nlocal b = bn.from_dec(\"23333\")\nlocal dec, err = b:to_dec()\nngx.say(dec)\n-- outputs \"23333\"\n```\n\n[Back to TOC](#table-of-contents)\n\n### bn:to_number\n\n**syntax**: *n, err = bn:to_number()*\n\n**syntax**: *n, err = bn:tonumber()*\n\nExport the lowest 32 bits or 64 bits part (based on the ABI) of `bn` instance\nto a number. This is useful when user wants to perform bitwise operations.\n\n```lua\nlocal bn = require(\"resty.openssl.bn\")\nlocal b = bn.from_dec(\"23333\")\nlocal n, err = b:to_number()\nngx.say(n)\n-- outputs 23333\nngx.say(type(n))\n-- outputs \"number\"\n```\n\n[Back to TOC](#table-of-contents)\n\n### bn.generate_prime\n\n**syntax**: *bn, err = bn.generate_prime(bits, safe)*\n\nGenerates a pseudo-random prime number of bit length `bits`.\n\nIf `safe` is true, it will be a safe prime (i.e. a prime p so that (p-1)/2 is also prime).\n\nThe PRNG must be seeded prior to calling BN_generate_prime_ex().\nThe prime number generation has a negligible error probability.\n\n[Back to TOC](#table-of-contents)\n\n### bn:__metamethods\n\nVarious mathematical operations can be performed as if it's a number.\n\n```lua\nlocal bn = require(\"resty.openssl.bn\")\nlocal a = bn.new(123456)\nlocal b = bn.new(222)\n -- the following returns a bn\nlocal r\nr = -a\nr = a + b\nr = a - b\nr = a * b\nr = a / b -- equal to bn:idiv, returns floor division\nr = a % b\n-- all operations can be performed between number and bignum\nr = a + 222\nr = 222 + a\n-- the following returns a bool\nlocal bool\nbool = a \u003c b\nbool = a \u003e= b\n-- compare between number will not work\n-- WRONG: bool = a \u003c 222\n```\n\n[Back to TOC](#table-of-contents)\n\n### bn:add, bn:sub, bn:mul, bn:div, bn:exp, bn:mod, bn:gcd\n\n**syntax**: *r = a:op(b)*\n\n**syntax**: *r = bn.op(a, b)*\n\nPerform mathematical operations `op`.\n\n- `add`: add\n- `sub`: subtract\n- `mul`: multiply\n- `div`, `idiv`: floor division (division with rounding down to nearest integer)\n- `exp`, `pow`: the `b`-th power of `a`, this function is faster than repeated `a * a * ...`.\n- `mod`: modulo\n- `gcd`: the greatest common divider of `a` and `b`.\n\nNote that `add`, `sub`, `mul`, `div`, `mod` is also available with `+, -, *, /, %` operaters.\nSee [above section](#bn__metamethods) for examples.\n\n```lua\nlocal bn = require(\"resty.openssl.bn\")\nlocal a = bn.new(123456)\nlocal b = bn.new(9876)\nlocal r\n-- the followings are equal\nr = a:add(b)\nr = bn.add(a, b)\nr = a:add(9876)\nr = bn.add(a, 9876)\nr = bn.add(123456, b)\nr = bn.add(123456, 9876)\n```\n\n[Back to TOC](#table-of-contents)\n\n### bn:sqr\n\n**syntax**: *r = a:sqr()*\n\n**syntax**: *r = bn.sqr(a)*\n\nComputes the 2-th power of `a`. This function is faster than `r = a * a`.\n\n[Back to TOC](#table-of-contents)\n\n### bn:mod_add, bn:mod_sub, bn:mod_mul, bn:mod_exp\n\n**syntax**: *r = a:op(b, m)*\n\n**syntax**: *r = bn.op(a, b, m)*\n\nPerform modulo mathematical operations `op`.\n\n- `mod_add`: adds `a` to `b` modulo `m`\n- `mod_sub`: substracts `b` from `a` modulo `m`\n- `mod_mul`: multiplies `a` by `b` and finds the non-negative remainder respective to modulus `m`\n- `mod_exp`, `mod_pow`: computes `a` to the `b`-th power modulo `m` (r=a^b % m). This function uses less\ntime and space than `exp`. Do not call this function when `m` is even and any of the parameters\nhave the `BN_FLG_CONSTTIME` flag set.\n\n```lua\nlocal bn = require(\"resty.openssl.bn\")\nlocal a = bn.new(123456)\nlocal b = bn.new(9876)\nlocal r\n-- the followings are equal\nr = a:mod_add(b, 3)\nr = bn.mod_add(a, b, 3)\nr = a:mod_add(9876, 3)\nr = bn.mod_add(a, 9876, 3)\nr = bn.mod_add(123456, b, 3)\nr = bn.mod_add(123456, 9876, 3)\n```\n\n[Back to TOC](#table-of-contents)\n\n### bn:mod_sqr\n\n**syntax**: *r = a:mod_sqr(m)*\n\n**syntax**: *r = bn.mod_sqr(a, m)*\n\nTakes the square of `a` modulo `m`.\n\n[Back to TOC](#table-of-contents)\n\n### bn:lshift, bn:rshift\n\n**syntax**: *r = bn:lshift(bit)*\n\n**syntax**: *r = bn.lshift(a, bit)*\n\n**syntax**: *r = bn:rshift(bit)*\n\n**syntax**: *r = bn.rshift(a, bit)*\n\nBit shift `a` to `bit` bits.\n\n[Back to TOC](#table-of-contents)\n\n### bn:is_zero, bn:is_one, bn:is_odd, bn:is_word\n\n**syntax**: *ok = bn:is_zero()*\n\n**syntax**: *ok = bn:is_one()*\n\n**syntax**: *ok = bn:is_odd()*\n\n**syntax**: *ok, err = bn:is_word(n)*\n\nChecks if `bn` is `0`, `1`, and odd number or a number `n` respectively.\n\n[Back to TOC](#table-of-contents)\n\n### bn:is_prime\n\n**syntax**: *ok, err = bn:is_prime(nchecks?)*\n\nChecks if `bn` is a prime number. Returns `true` if it is prime with an\nerror probability of less than 0.25^`nchecks` and error if any. If omitted,\n`nchecks` is set to 0 which means to select number of iterations basedon the\nsize of the number\n\n\u003e This function perform a Miller-Rabin probabilistic primality test with nchecks iterations. If nchecks == BN_prime_checks (0), a number of iterations is used that yields a false positive rate of at most 2^-64 for random input. The error rate depends on the size of the prime and goes down for bigger primes. The rate is 2^-80 starting at 308 bits, 2^-112 at 852 bits, 2^-128 at 1080 bits, 2^-192 at 3747 bits and 2^-256 at 6394 bits.\n\n\u003e When the source of the prime is not random or not trusted, the number of checks needs to be much higher to reach the same level of assurance: It should equal half of the targeted security level in bits (rounded up to the next integer if necessary). For instance, to reach the 128 bit security level, nchecks should be set to 64.\n\nSee also [BN_is_prime(3)](https://www.openssl.org/docs/manmaster/man3/BN_is_prime.html).\n\n[Back to TOC](#table-of-contents)\n\n## resty.openssl.cipher\n\nModule to interact with symmetric cryptography (EVP_CIPHER).\n\n[Back to TOC](#table-of-contents)\n\n### cipher.new\n\n**syntax**: *d, err = cipher.new(cipher_name, properties?)*\n\nCreates a cipher instance. `cipher_name` is a case-insensitive string of cipher algorithm name.\nTo view a list of cipher algorithms implemented, use\n[openssl.list_cipher_algorithms](#openssllist_cipher_algorithms)\nor `openssl list -cipher-algorithms`\n\nStaring from OpenSSL 3.0, this function accepts an optional `properties` parameter\nto explictly select provider to fetch algorithms.\n\n[Back to TOC](#table-of-contents)\n\n### cipher.istype\n\n**syntax**: *ok = cipher.istype(table)*\n\nReturns `true` if table is an instance of `cipher`. Returns `false` otherwise.\n\n[Back to TOC](#table-of-contents)\n\n### cipher.set_buffer_size\n\n**syntax**: *ok = cipher.set_buffer_size(sz)*\n\nResize the internal buffer size used by all cipher instance. The default buffer size is 1024 bytes.\n\nIf you are expecting to pass input text larger than 1024 bytes at one time to `update()`, `encrypt()`\nor `decrypt()`, setting the buffer to larger than the expected input size will improve performance\nby let more code to be JIT-able.\n\nAvoid call this function at hotpath, as this re-allocate the buffer every time it's called.\n\n[Back to TOC](#table-of-contents)\n\n### cipher:get_provider_name\n\n**syntax**: *name = cipher:get_provider_name()*\n\nReturns the provider name of `cipher`.\n\nThis function is available since OpenSSL 3.0.\n\n[Back to TOC](#table-of-contents)\n\n## cipher:gettable_params, cipher:settable_params, cipher:get_param, cipher:set_params\n\nQuery settable or gettable params and set or get params.\nSee [Generic EVP parameter getter/setter](#generic-evp-parameter-gettersetter).\n\n[Back to TOC](#table-of-contents)\n\n### cipher:encrypt\n\n**syntax**: *s, err = cipher:encrypt(key, iv?, s, no_padding?, aead_aad?)*\n\nEncrypt the text `s` with key `key` and IV `iv`. Returns the encrypted text in raw binary string\nand error if any.\nOptionally accepts a boolean `no_padding` which tells the cipher to enable or disable padding and default\nto `false` (enable padding). If `no_padding` is `true`, the length of `s` must then be a multiple of the\nblock size or an error will occur.\n\nWhen using GCM or CCM mode or `chacha20-poly1305` cipher, it's also possible to pass\nthe Additional Authenticated Data (AAD) as the fifth argument.\n\nThis function is a shorthand of `cipher:init`, `cipher:set_aead_aad` (if appliable) then `cipher:final`.\n\n[Back to TOC](#table-of-contents)\n\n### cipher:decrypt\n\n**syntax**: *s, err = cipher:decrypt(key, iv?, s, no_padding?, aead_aad?, aead_tag?)*\n\nDecrypt the text `s` with key `key` and IV `iv`. Returns the decrypted text in raw binary string\nand error if any.\nOptionally accepts a boolean `no_padding` which tells the cipher to enable or disable padding and default\nto `false` (enable padding). If `no_padding` is `true`, the length of `s` must then be a multiple of the\nblock size or an error will occur; also, padding in the decrypted text will not be removed.\n\nWhen using GCM or CCM mode or `chacha20-poly1305` cipher, it's also possible to pas\nthe Additional Authenticated Data (AAD) as the fifth argument and authentication tag\nas the sixth argument.\n\nThis function is a shorthand of `cipher:init`, `cipher:set_aead_aad` (if appliable),\n`cipher:set_aead_tag` (if appliable) then `cipher:final`.\n\n[Back to TOC](#table-of-contents)\n\n### cipher:init\n\n**syntax**: *ok, err = cipher:init(key, iv?, opts?)*\n\nInitialize the cipher with key `key` and IV `iv`. The optional third argument is a table consists of:\n\n```lua\n{\n    is_encrypt = false,\n    no_padding = false,\n}\n```\n\nCalling function is needed before [cipher:update](#restycipherupdate) and\n[cipher:final](#restycipherfinal) if the cipher is not being initialized already. But not\n[cipher:encrypt](#restycipherencrypt) and [cipher:decrypt](#restycipherdecrypt).\n\nIf you wish to reuse `cipher` instance multiple times, calling this function is necessary\nto clear the internal state of the cipher. The shorthand functions\n[cipher:encrypt](#restycipherencrypt) and [cipher:decrypt](#restycipherdecrypt)\nalready take care of initialization and reset.\n\n[Back to TOC](#table-of-contents)\n\n### cipher:update\n\n**syntax**: *s, err = cipher:update(partial, ...)*\n\nUpdates the cipher with one or more strings. If the cipher has larger than block size of data to flush,\nthe function will return a non-empty string as first argument. This function can be used in a streaming\nfashion to encrypt or decrypt continous data stream.\n\n[Back to TOC](#table-of-contents)\n\n### cipher:update_aead_aad\n\n**syntax**: *ok, err = cipher:update_aead_aad(aad)*\n\nProvides AAD data to the cipher, this function can be called more than one times.\n\n[Back to TOC](#table-of-contents)\n\n### cipher:get_aead_tag\n\n**syntax**: *tag, err = cipher:get_aead_tag(size?)*\n\nGets the authentication tag from cipher with length specified as `size`. If omitted, a tag with length\nof half of the block size will be returned. The size cannot exceed block size.\n\nThis function can only be called after encryption is finished.\n\n[Back to TOC](#table-of-contents)\n\n### cipher:set_aead_tag\n\n**syntax**: *ok, err = cipher:set_aead_tag(tag)*\n\nSet the authentication tag of cipher with `tag`.\n\nThis function can only be called before decryption starts.\n\n[Back to TOC](#table-of-contents)\n\n### cipher:final\n\n**syntax**: *s, err = cipher:final(partial?)*\n\nReturns the encrypted or decrypted text in raw binary string, optionally accept one string to encrypt or decrypt.\n\n```lua\n-- encryption\nlocal c, err = require(\"resty.openssl.cipher\").new(\"aes256\")\nc:init(string.rep(\"0\", 32), string.rep(\"0\", 16), {\n    is_encrypt = true,\n})\nc:update(\"🦢\")\nlocal cipher, err = c:final()\nngx.say(ngx.encode_base64(cipher))\n-- outputs \"vGJRHufPYrbbnYYC0+BnwQ==\"\n-- OR:\nlocal c, err = require(\"resty.openssl.cipher\").new(\"aes256\")\nlocal cipher, err = c:encrypt(string.rep(\"0\", 32), string.rep(\"0\", 16), \"🦢\")\nngx.say(ngx.encode_base64(cipher))\n-- outputs \"vGJRHufPYrbbnYYC0+BnwQ==\"\n\n-- decryption\nlocal encrypted = ngx.decode_base64(\"vGJRHufPYrbbnYYC0+BnwQ==\")\nlocal c, err = require(\"resty.openssl.cipher\").new(\"aes256\")\nc:init(string.rep(\"0\", 32), string.rep(\"0\", 16), {\n    is_encrypt = false,\n})\nc:update(encrypted)\nlocal cipher, err = c:final()\nngx.say(cipher)\n-- outputs \"🦢\"\n-- OR:\nlocal c, err = require(\"resty.openssl.cipher\").new(\"aes256\")\nlocal cipher, err = c:decrypt(string.rep(\"0\", 32), string.rep(\"0\", 16), encrypted)\nngx.say(cipher)\n-- outputs \"🦢\"\n```\n\n**Note:** in some implementations like `libsodium` or Java, AEAD ciphers append the `tag` (or `MAC`)\nat the end of encrypted ciphertext. In such case, user will need to manually cut off the `tag`\nwith correct size(usually 16 bytes) and pass in the ciphertext and `tag` seperately.\n\nSee [examples/aes-gcm-aead.lua](https://github.com/fffonion/lua-resty-openssl/blob/master/examples/aes-gcm-aead.lua)\nfor an example to use AEAD modes with authentication.\n\n[Back to TOC](#table-of-contents)\n\n### cipher:derive\n\n**syntax**: *key, iv, err = cipher:derive(key, salt?, count?, md?)*\n\nDerive a key and IV (if appliable) from given material that can be used in current cipher. This function\nis useful mainly to work with keys that were already derived from same algorithm. Newer applications should\nuse a more modern algorithm such as PBKDF2 provided by [kdf.derive](#kdfderive).\n\n`count` is the iteration count to perform. If it's omitted, it's set to `1`. Note the recent version of\n`openssl enc` cli tool automatically use PBKDF2 if `-iter` is set to larger than 1,\nwhile this function will not. To use PBKDF2 to derive a key, please refer to [kdf.derive](#kdfderive).\n\n`md` is the message digest name to use, it can take one of the values `md2`, `md5`, `sha` or `sha1`.\nIf it's omitted, it's default to `sha1`.\n\n```lua\nlocal cipher = require(\"resty.openssl.cipher\").new(\"aes-128-cfb\")\nlocal key, iv, err = cipher:derive(\"x\")\n-- equivalent to `openssl enc -aes-128-cfb -pass pass:x -nosalt -P -md sha1`\n```\n\n[Back to TOC](#table-of-contents)\n\n## resty.openssl.digest\n\nModule to interact with message digest (EVP_MD_CTX).\n\n[Back to TOC](#table-of-contents)\n\n### digest.new\n\n**syntax**: *d, err = digest.new(digest_name?, properties?)*\n\nCreates a digest instance. `digest_name` is a case-insensitive string of digest algorithm name.\nTo view a list of digest algorithms implemented, use \n[openssl.list_digest_algorithms](#openssllist_digest_algorithms) or\n`openssl list -digest-algorithms`.\n\nIf `digest_name` is omitted, it's default to `sha1`. Specially, the digest_name `\"null\"`\nrepresents a \"null\" message digest that does nothing: i.e. the hash it returns is of zero length.\n\nStaring from OpenSSL 3.0, this function accepts an optional `properties` parameter\nto explictly select provider to fetch algorithms.\n\n[Back to TOC](#table-of-contents)\n\n### digest.istype\n\n**syntax**: *ok = digest.istype(table)*\n\nReturns `true` if table is an instance of `digest`. Returns `false` otherwise.\n\n[Back to TOC](#table-of-contents)\n\n### digest:get_provider_name\n\n**syntax**: *name = digest:get_provider_name()*\n\nReturns the provider name of `digest`.\n\nThis function is available since OpenSSL 3.0.\n\n[Back to TOC](#table-of-contents)\n\n## digest:gettable_params, digest:settable_params, digest:get_param, digest:set_params\n\nQuery settable or gettable params and set or get params.\nSee [Generic EVP parameter getter/setter](#generic-evp-parameter-gettersetter).\n\n[Back to TOC](#table-of-contents)\n\n### digest:update\n\n**syntax**: *ok, err = digest:update(partial, ...)*\n\nUpdates the digest with one or more strings.\n\n[Back to TOC](#table-of-contents)\n\n### digest:final\n\n**syntax**: *str, err = digest:final(partial?)*\n\nReturns the digest in raw binary string, optionally accept one string to digest.\n\n```lua\nlocal d, err = require(\"resty.openssl.digest\").new(\"sha256\")\nd:update(\"🦢\")\nlocal digest, err = d:final()\nngx.say(ngx.encode_base64(digest))\n-- outputs \"tWW/2P/uOa/yIV1gRJySJLsHq1xwg0E1RWCvEUDlla0=\"\n-- OR:\nlocal d, err = require(\"resty.openssl.digest\").new(\"sha256\")\nlocal digest, err = d:final(\"🦢\")\nngx.say(ngx.encode_base64(digest))\n-- outputs \"tWW/2P/uOa/yIV1gRJySJLsHq1xwg0E1RWCvEUDlla0=\"\n```\n\n[Back to TOC](#table-of-contents)\n\n### digest:reset\n\n**syntax**: *ok, err = digest:reset()*\n\nReset the internal state of `digest` instance as it's just created by [digest.new](#digestnew).\nIt calls [EVP_DigestInit_ex](https://www.openssl.org/docs/manmaster/man3/EVP_DigestInit_ex.html) under\nthe hood.\n\nUser must call this before reusing the same `digest` instance.\n\n[Back to TOC](#table-of-contents)\n\n## resty.openssl.hmac\n\nModule to interact with hash-based message authentication code (HMAC_CTX).\n\nUse of this module is deprecated since OpenSSL 3.0, please use [resty.openssl.mac](#restyopensslmac)\ninstead.\n\n[Back to TOC](#table-of-contents)\n\n### hmac.new\n\n**syntax**: *h, err = hmac.new(key, digest_name?)*\n\nCreates a hmac instance. `digest_name` is a case-insensitive string of digest algorithm name.\nTo view a list of digest algorithms implemented, use\n[openssl.list_digest_algorithms](#openssllist_digest_algorithms) or\n`openssl list -digest-algorithms`.\n\nIf `digest_name` is omitted, it's default to `sha1`.\n\n[Back to TOC](#table-of-contents)\n\n### hmac.istype\n\n**syntax**: *ok = hmac.istype(table)*\n\nReturns `true` if table is an instance of `hmac`. Returns `false` otherwise.\n\n[Back to TOC](#table-of-contents)\n\n### hmac:update\n\n**syntax**: *ok, err = hmac:update(partial, ...)*\n\nUpdates the HMAC with one or more strings.\n\n[Back to TOC](#table-of-contents)\n\n### hmac:final\n\n**syntax**: *str, err = hmac:final(partial?)*\n\nReturns the HMAC in raw binary string, optionally accept one string to digest.\n\n```lua\nlocal d, err = require(\"resty.openssl.hmac\").new(\"goose\", \"sha256\")\nd:update(\"🦢\")\nlocal hmac, err = d:final()\nngx.say(ngx.encode_base64(hmac))\n-- outputs \"k2UcrRp25tj1Spff89mJF3fAVQ0lodq/tJT53EYXp0c=\"\n-- OR:\nlocal d, err = require(\"resty.openssl.hmac\").new(\"goose\", \"sha256\")\nlocal hmac, err = d:final(\"🦢\")\nngx.say(ngx.encode_base64(hmac))\n-- outputs \"k2UcrRp25tj1Spff89mJF3fAVQ0lodq/tJT53EYXp0c=\"\n```\n\n[Back to TOC](#table-of-contents)\n\n### hmac:reset\n\n**syntax**: *ok, err = hmac:reset()*\n\nReset the internal state of `hmac` instance as it's just created by [hmac.new](#hmacnew).\nIt calls [HMAC_Init_ex](https://www.openssl.org/docs/manmaster/man3/HMAC_Init_ex.html) under\nthe hood.\n\nUser must call this before reusing the same `hmac` instance.\n\n[Back to TOC](#table-of-contents)\n\n## resty.openssl.mac\n\nModule to interact with message authentication code (EVP_MAC).\n\n[Back to TOC](#table-of-contents)\n\n### mac.new\n\n**syntax**: *h, err = mac.new(key, mac, cipher?, digest?, properties?)*\n\nCreates a mac instance. `mac` is a case-insensitive string of MAC algorithm name.\nTo view a list of digest algorithms implemented, use\n[openssl.list_mac_algorithms](#openssllist_mac_algorithms) or\n`openssl list -mac-algorithms`.\n\nAt least one of `cipher` or `digest` must be specified.\n\n`cipher` is a case-insensitive string of digest algorithm name.\nTo view a list of digest algorithms implemented, use\n[openssl.list_cipher_algorithms](#openssllist_cipher_algorithms) or\n`openssl list -cipher-algorithms`.\n`digest` is a case-insensitive string of digest algorithm name.\nTo view a list of digest algorithms implemented, use\n[openssl.list_digest_algorithms](#openssllist_digest_algorithms) or\n`openssl list -digest-algorithms`.\n`properties` parameter can be used to explictly select provider to fetch algorithms.\n\n[Back to TOC](#table-of-contents)\n\n### mac.istype\n\n**syntax**: *ok = mac.istype(table)*\n\nReturns `true` if table is an instance of `mac`. Returns `false` otherwise.\n\n[Back to TOC](#table-of-contents)\n\n### mac:get_provider_name\n\n**syntax**: *name = mac:get_provider_name()*\n\nReturns the provider name of `mac`.\n\nThis function is available since OpenSSL 3.0.\n\n[Back to TOC](#table-of-contents)\n\n## mac:gettable_params, mac:settable_params, mac:get_param, mac:set_params\n\nQuery settable or gettable params and set or get params.\nSee [Generic EVP parameter getter/setter](#generic-evp-parameter-gettersetter).\n\n[Back to TOC](#table-of-contents)\n\n### mac:update\n\n**syntax**: *ok, err = mac:update(partial, ...)*\n\nUpdates the MAC with one or more strings.\n\n[Back to TOC](#table-of-contents)\n\n### mac:final\n\n**syntax**: *str, err = mac:final(partial?)*\n\nReturns the MAC in raw binary string, optionally accept one string to digest.\n\n```lua\nlocal d, err = require(\"resty.openssl.mac\").new(\"goose\", \"HMAC\", nil, \"sha256\")\nd:update(\"🦢\")\nlocal mac, err = d:final()\nngx.say(ngx.encode_base64(mac))\n-- outputs \"k2UcrRp25tj1Spff89mJF3fAVQ0lodq/tJT53EYXp0c=\"\n-- OR:\nlocal d, err = require(\"resty.openssl.mac\").new(\"goose\", \"HMAC\", nil, \"sha256\")\nlocal hmac, err = d:final(\"🦢\")\nngx.say(ngx.encode_base64(mac))\n-- outputs \"k2UcrRp25tj1Spff89mJF3fAVQ0lodq/tJT53EYXp0c=\"\n```\n\n[Back to TOC](#table-of-contents)\n\n### mac:reset\n\n**syntax**: *ok, err = mac:reset()*\n\nReset the internal state of `mac` instance as it's just created by [mac.new](#macnew).\nIt calls [EVP_MAC_Init](https://www.openssl.org/docs/manmaster/man3/EVP_MAC_init.html) under\nthe hood.\n\nUser must call this before reusing the same `mac` instance.\n\n## resty.openssl.kdf\n\nModule to interact with KDF (key derivation function).\n\n[Back to TOC](#table-of-contents)\n\n### kdf.derive (legacy)\n\n**syntax**: *key, err = kdf.derive(options)*\n\nUse of this module is deprecated since OpenSSL 3.0, please use [kdf.new](#kdfnew)\ninstead.\n\nDerive a key from given material. Various KDFs are supported based on OpenSSL version:\n\n`PBKDF2`([RFC 2898], [NIST SP 800-132]), `HKDF`([RFC 5869]), `TLS1-PRF`([RFC 2246], [RFC 5246] and [NIST SP 800-135 r1]) and `scrypt`([RFC 7914]) is available.\n\n\n`options` is a table that contains:\n\n| Key | Type | Description | Required or default |\n| ------------   | ---- | ----------- | ------ |\n| type   | number | Type of KDF function to use, one of `kdf.PBKDF2`, `kdf.SCRYPT`, `kdf.TLS1_PRF` or `kdf.HKDF` | **required** |\n| outlen   | number | Desired key length to derive | **required** |\n| pass    | string | Initial key material to derive from | (empty string) |\n| salt    | string | Add some salt | (empty string) |\n| md    | string | Message digest method name to use, not effective for `scrypt` type | `\"sha1\"` |\n| properties | string | Staring from OpenSSL 3.0, this function accepts an optional `properties` parameter\nto explictly select provider to fetch algorithms. | |\n| pbkdf2_iter     | number | PBKDF2 iteration count. RFC 2898 suggests an iteration count of at least 1000. Any value less than 1 is treated as a single iteration.  | `1` |\n| hkdf_key     | string | HKDF key  | **required** |\n| hkdf_mode     | number | HKDF mode to use, one of `kdf.HKDEF_MODE_EXTRACT_AND_EXPAND`, `kdf.HKDEF_MODE_EXTRACT_ONLY` or `kdf.HKDEF_MODE_EXPAND_ONLY`. To learn about mode, please refer to [EVP_PKEY_CTX_set1_hkdf_key(3)](https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_CTX_set1_hkdf_key.html). Note with `kdf.HKDEF_MODE_EXTRACT_ONLY`, `outlen` is ignored and the output will be fixed size of `HMAC-\u003cmd\u003e`.  | `kdf.HKDEF_MODE_EXTRACT_AND_EXPAND`|\n| hkdf_info     | string | HKDF info value  | (empty string) |\n| tls1_prf_secret     | string | TLS1-PRF secret  | **required** |\n| tls1_prf_seed     | string | TLS1-PRF seed  | **required** |\n| scrypt_maxmem     | number | Scrypt maximum memory usage in bytes  |`32 * 1024 * 1024` |\n| scrypt_N     | number | Scrypt CPU/memory cost parameter, must be a power of 2 | **required** |\n| scrypt_r     | number | Scrypt blocksize parameter (8 is commonly used) | **required** |\n| scrypt_p     | number | Scrypt parallelization parameter | **required** |\n\n```lua\nlocal kdf = require(\"resty.openssl.kdf\")\nlocal key, err = kdf.derive({\n    type = kdf.PBKDF2,\n    outlen = 16,\n    pass = \"1234567\",\n    md = \"md5\",\n    pbkdf2_iter = 1000,\n})\nngx.say(ngx.encode_base64(key))\n-- outputs \"cDRFLQ7NWt+AP4i0TdBzog==\"\n\nkey, err = kdf.derive({\n    type = kdf.SCRYPT,\n    outlen = 16,\n    pass = \"1234567\",\n    scrypt_N = 1024,\n    scrypt_r = 8,\n    scrypt_p = 16,\n})\nngx.say(ngx.encode_base64(key))\n-- outputs \"9giFtxace5sESmRb8qxuOw==\"\n```\n\n[Back to TOC](#table-of-contents)\n\n### kdf.new\n\n**syntax**: *k, err = kdf.new(kdf_name?, properties?)*\n\nCreates a kdf instance. `kdf_name` is a case-insensitive string of kdf algorithm name.\nTo view a list of kdf algorithms implemented, use\n[openssl.list_kdf_algorithms](#openssllist_kdf_algorithms) or\n`openssl list -kdf-algorithms`.\n\nThis function is available since OpenSSL 3.0.\n\nThis function accepts an optional `properties` parameter\nto explictly select provider to fetch algorithms.\n\n[Back to TOC](#table-of-contents)\n\n### kdf.istype\n\n**syntax**: *ok = kdf.istype(table)*\n\nReturns `true` if table is an instance of `kdf`. Returns `false` otherwise.\n\nThis function is available since OpenSSL 3.0.\n\n[Back to TOC](#table-of-contents)\n\n### kdf:get_provider_name\n\n**syntax**: *name = kdf:get_provider_name()*\n\nReturns the provider name of `kdf`.\n\nThis function is available since OpenSSL 3.0.\n\n[Back to TOC](#table-of-contents)\n\n## kdf:gettable_params, kdf:settable_params, kdf:get_param, kdf:set_params\n\nQuery settable or gettable params and set or get params.\nSee [Generic EVP parameter getter/setter](#generic-evp-parameter-gettersetter).\n\nThis function is available since OpenSSL 3.0.\n\n[Back to TOC](#table-of-contents)\n\n### kdf:derive\n\n**syntax**: *ok, err = kdf:derive(outlen, options?, options_count?)*\n\nDerive a key with length of `outlen` with `options`. Certain algorithms output fixed\nlength of key where `outlen` should be unset.\n\n`options` is a table map holding parameters passing to `kdf`. To view the list of parameters\nacceptable by selecter algorithm and provider, use `kdf:settable_params`.\n\nOptionally, if length of `options` is known, user can provide its length through `options_count`\nto gain better performance where `options` table is relatively large.\n\n```lua\nlocal k = assert(kdf.new(\"PBKDF2\"))\nkey = assert(k:derive(16, {\n    pass = \"1234567\",\n    iter = 1000,\n    digest = \"md5\",\n    salt = \"\",\n}))\nngx.say(ngx.encode_base64(key))\n-- outputs \"cDRFLQ7NWt+AP4i0TdBzog==\"\nassert(k:reset())\n-- kdf instance is reusable, user can set common parameters\n-- through set_params and don't need to repeat in derive()\nassert(k:set_params({\n    iter = 1000,\n    digest = \"md5\",\n    salt = \"\",\n}))\nkey = assert(k:derive(16, {\n    pass = \"1234567\",\n}))\nngx.say(ngx.encode_base64(key))\n-- outputs \"cDRFLQ7NWt+AP4i0TdBzog==\"\n\nlocal k = assert(kdf.new(\"HKDF\"))\nkey = assert(k:derive(16, {\n    digest = \"md5\",\n    key = \"secret\",\n    salt = \"salt\",\n    info = \"some info\",\n    mode = kdf.HKDEF_MODE_EXPAND_ONLY,\n    -- as HKDF also accepts mode as string, use the literal below also works\n    -- mode = \"EXPAND_ONLY\"\n}))\n```\n\nThis function is available since OpenSSL 3.0.\n\n[Back to TOC](#table-of-contents)\n\n### kdf:reset\n\n**syntax**: *ok, err = kdf:reset()*\n\nReset the internal state of `kdf` instance as it's just created by [kdf.new](#kdfnew).\n\nUser must call this before reusing the same `kdf` instance.\n\n[Back to TOC](#table-of-contents)\n\n## resty.openssl.objects\n\nHelpfer module on ASN1_OBJECT.\n\n[Back to TOC](#table-of-contents)\n\n### objects.obj2table\n\n**syntax**: *tbl = objects.bytes(asn1_obj)*\n\nConvert a ASN1_OBJECT pointer to a Lua table where\n\n```\n{\n  id: OID of the object,\n  nid: NID of the object,\n  sn: short name of the object,\n  ln: long name of the object,\n}\n```\n\n[Back to TOC](#table-of-contents)\n\n### objects.nid2table\n\n**syntax**: *tbl, err = objects.nid2table(nid)*\n\nConvert a [NID] to a Lua table, returns the same format as\n[objects.obj2table](#objectsobj2table)\n\n[Back to TOC](#table-of-contents)\n\n### objects.txt2nid\n\n**syntax**: *nid, err = objects.txt2nid(txt)*\n\nConvert a text representation to [NID]. \n\n[Back to TOC](#table-of-contents)\n\n## resty.openssl.pkcs12\n\nModule to interact with PKCS#12 format.\n\n[Back to TOC](#table-of-contents)\n\n### pkcs12.encode\n\n**syntax**: *der, err = pkcs12.encode(data, passphrase?, properties?)*\n\nEncode data in `data` to a PKCS#12 text.\n\n`data` is a table that contains:\n\n| Key | Type | Description | Required or default |\n| ------------   | ---- | ----------- | ------ |\n| key   | [pkey](#restyopensslpkey) | Private key | **required** |\n| cert   | [x509](#restyopensslx509) | Certificate | **required** |\n| cacerts   | A list of [x509](#restyopensslx509) as Lua table | Additional certificates | `[]` |\n| friendly_name | string | The name used for the supplied certificate and key | `\"\"` |\n| nid_key | number or string | The [NID] or text to specify algorithm to encrypt key | `\"PBE-SHA1-RC2-4\"` if compiled with RC2, otherwise `\"PBE-SHA1-3DES\"`; on OpenSSL 3.0 and later `PBES2 with PBKDF2 and AES-256-CBC`. |\n| nid_cert | number or string | The [NID] or text to specify algorithm to encrypt cert | `\"PBE-SHA1-3DES\"`; on OpenSSL 3.0 and later `PBES2 with PBKDF2 and AES-256-CBC` |\n| iter | number | Key iterration count | `PKCS12_DEFAULT_ITER` (2048) |\n| mac_iter | number | MAC iterration count | 1 |\n\n`passphrase` is the string for encryption. If omitted, an empty string will be used.\n\nStaring from OpenSSL 3.0, this function accepts an optional `properties` parameter\nto explictly select provider to fetch algorithms.\n\nNote in OpenSSL 3.0 `RC2` has been moved to **legacy** provider. In order to encode p12 data with RC2\nencryption, you need to [load the legacy provider](#providerload) first.\n\n```lua\nlocal pro = require \"resty.openssl.provider\"\nlocal legacy_provider = assert(pro.load(\"legacy\"))\nlocal p12, err = pkcs12.encode({ key = key, cert = cert})\nassert(legacy_provider:unload())\n```\n\n[Back to TOC](#table-of-contents)\n\n### pkcs12.decode\n\n**syntax**: *data, err = pkcs12.decode(p12, passphrase?)*\n\nDecode a PKCS#12 text to Lua table `data`. Similar to the `data` table passed to [pkcs12.encode](#pkcs12encode),\nbut onle `cert`, `key`, `cacerts` and `friendly_name` are returned.\n\n`passphrase` is the string for encryption. If omitted, an empty string will be used.\n\nNote in OpenSSL 3.0 `RC2` has been moved to **legacy** provider. In order to decode p12 data with RC2\nencryption, you need to [load the legacy provider](#providerload) first.\n\n[Back to TOC](#table-of-contents)\n\n## resty.openssl.rand\n\nModule to interact with random number generator.\n\n[Back to TOC](#table-of-contents)\n\n### rand.bytes\n\n**syntax**: *str, err = rand.bytes(length, private?, strength?)*\n\nGenerate random bytes with length of `length`. If `private` is set to true, a\nprivate PRNG instance is used so that a compromise of the \"public\" PRNG instance\nwill not affect the secrecy of these private values.\n\nThe bytes generated will have a security strength of at least `strength` bits.\n\n[Back to TOC](#table-of-contents)\n\n## resty.openssl.x509\n\nModule to interact with X.509 certificates.\n\n[Back to TOC](#table-of-contents)\n\n### x509.new\n\n**syntax**: *crt, err = x509.new(txt?, fmt?, properties?)*\n\nCreates a `x509` instance. `txt` can be **PEM** or **DER** formatted text;\n`fmt` is a choice of `PEM`, `DER` to load specific format, or `*` for auto detect.\n\nWhen `txt` is omitted, `new()` creates an empty `x509` instance.\n\nStaring from OpenSSL 3.0, this function accepts an optional `properties` parameter\nto explictly select provider to fetch algorithms.\n\n[Back to TOC](#table-of-contents)\n\n### x509.dup\n\n**syntax**: *x509, err = x509.dup(x509_ptr_cdata)*\n\nDuplicates a `X509*` to create a new `x509` instance.\n\n[Back to TOC](#table-of-contents)\n\n### x509.istype\n\n**syntax**: *ok = x509.istype(table)*\n\nReturns `true` if table is an instance of `x509`. Returns `false` otherwise.\n\n[Back to TOC](#table-of-contents)\n\n### x509:digest\n\n**syntax**: *d, err = x509:digest(digest_name?, properties?)*\n\nReturns a digest of the DER representation of the X509 certificate object in raw binary text.\n\n`digest_name` is a case-insensitive string of digest algorithm name.\nTo view a list of digest algorithms implemented, use\n[openssl.list_digest_algorithms](#openssllist_digest_algorithms) or\n`openssl list -digest-algorithms`.\n\nIf `digest_name` is omitted, it's default to `sha1`.\n\nStaring from OpenSSL 3.0, this function accepts an optional `properties` parameter\nto explictly select provider to fetch algorithms.\n\n[Back to TOC](#table-of-contents)\n\n### x509:pubkey_digest\n\n**syntax**: *d, err = x509:pubkey_digest(digest_name?, properties?)*\n\nReturns a digest of the DER representation of the pubkey in the X509 object in raw binary text.\n\n`digest_name` is a case-insensitive string of digest algorithm name.\nTo view a list of digest algorithms implemented, use\n[openssl.list_digest_algorithms](#openssllist_digest_algorithms) or\n`openssl list -digest-algorithms`.\n\nIf `digest_name` is omitted, it's default to `sha1`.\n\nStaring from OpenSSL 3.0, this function accepts an optional `properties` parameter\nto explictly select provider to fetch algorithms.\n\n[Back to TOC](#table-of-contents)\n\n### x509:check_private_key\n\n**syntax**: *match, err = x509:check_private_key(pkey)*\n\nChecks the consistency of private key `pkey` with the public key in current X509 object.\n\nReturns a boolean indicating if it's a match and err describing the reason.\n\nNote this function also checks if k itself is indeed a private key or not.\n\n[Back to TOC](#table-of-contents)\n\n### x509:get_\\*, x509:set_\\*\n\n**syntax**: *ok, err = x509:set_**attribute**(instance)*\n\n**syntax**: *instance, err = x509:get_**attribute**()*\n\nSetters and getters for x509 attributes share the same syntax.\n\n| Attribute name | Type | Description |\n| ------------   | ---- | ----------- |\n| issuer_name   | [x509.name](#restyopensslx509name) | Issuer of the certificate |\n| not_before    | number | Unix timestamp when certificate is not valid before |\n| not_after     | number | Unix timestamp when certificate is not valid after |\n| pubkey        | [pkey](#restyopensslpkey)   | Public key of the certificate |\n| serial_number | [bn](#restyopensslbn) | Serial number of the certficate |\n| subject_name  | [x509.name](#restyopensslx509name) | Subject of the certificate |\n| version       | number | Version of the certificate, value is one less than version. For example, `2` represents `version 3` |\n\nAdditionally, getters and setters for extensions are also available:\n\n| Extension name | Type | Description |\n| ------------   | ---- | ----------- |\n| subject_alt_name   | [x509.altname](#restyopensslx509altname) | [Subject Alternative Name](https://tools.ietf.org/html/rfc5280#section-4.2.1.6) of the certificate, SANs are usually used to define \"additional Common Names\"  |\n| issuer_alt_name    | [x509.altname](#restyopensslx509altname) | [Issuer Alternative Name](https://tools.ietf.org/html/rfc5280#section-4.2.1.7) of the certificate |\n| basic_constraints  | table, { ca = bool, pathlen = int} | [Basic Constriants](https://tools.ietf.org/html/rfc5280#section-4.2.1.9) of the certificate  |\n| info_access        | [x509.extension.info_access](#restyopensslx509extensioninfo_access) | [Authority Information Access](https://tools.ietf.org/html/rfc5280#section-4.2.2.1) of the certificate, contains information like OCSP reponder URL. |\n| crl_distribution_points | [x509.extension.dist_points](#restyopensslx509extensiondist_points) | [CRL Distribution Points](https://tools.ietf.org/html/rfc5280#section-4.2.1.13) of the certificate, contains information like Certificate Revocation List(CRL) URLs. |\n\nFor all extensions, `get_{extension}_critical` and `set_{extension}_critical` is also supported to\naccess the `critical` flag of the extension.\n\nIf the attribute is not found, getter will return `nil, nil`.\n\n```lua\nlocal x509, err = require(\"resty.openssl.x509\").new()\nerr = x509:set_not_before(ngx.time())\nlocal not_before, err = x509:get_not_before()\nngx.say(not_before)\n-- outputs 1571875065\n\nerr = x509:set_basic_constraints_critical(true)\n```\n\nIf type is a table, setter requires a table with case-insensitive keys to set;\ngetter returns the value of the given case-insensitive key or a table of all keys if no key provided.\n\n```lua\nlocal x509, err = require(\"resty.openssl.x509\").new()\nerr = x509:set_basic_constraints({\n  cA = false,\n  pathlen = 0,\n})\n\nngx.say(x509:get_basic_constraints(\"pathlen\"))\n-- outputs 0\n\nngx.say(x509:get_basic_constraints())\n-- outputs '{\"ca\":false,\"pathlen\":0}'\n```\n\nNote that user may also access the certain extension by [x509:get_extension](#x509get_extension) and\n[x509:set_extension](#x509set_extension), while the later two function returns or requires\n[extension](#restyopensslx509extension) instead. User may use getter and setters listed here if modification\nof current extensions is needed; use [x509:get_extension](#x509get_extension) or\n[x509:set_extension](#x509set_extension) if user are adding or replacing the whole extension or\ngetters/setters are not implemented. If the getter returned a type of `x509.*` instance, it can be\nconverted to a [extension](#restyopensslx509extension) instance by [extension:from_data](#extensionfrom_data),\nand thus used by [x509:get_extension](#x509get_extension) and [x509:set_extension](#x509set_extension) \n\n[Back to TOC](#table-of-contents)\n\n### x509:get_lifetime\n\n**syntax**: *not_before, not_after, err = x509:get_lifetime()*\n\nA shortcut of `x509:get_not_before` plus `x509:get_not_after`\n\n[Back to TOC](#table-of-contents)\n\n### x509:set_lifetime\n\n**syntax**: *ok, err = x509:set_lifetime(not_before, not_after)*\n\nA shortcut of `x509:set_not_before`\nplus `x509:set_not_after`.\n\n[Back to TOC](#table-of-contents)\n\n### x509:get_signature_name, x509:get_signature_nid, x509:get_signature_digest_name\n\n**syntax**: *sn, err = x509:get_signature_name()*\n\n**syntax**: *nid, err = x509:get_signature_nid()*\n\n**syntax**: *sn, err = x509:get_signature_digest_name()*\n\nReturn the [NID] or the short name (SN) of the signature of the certificate.\n\n`x509:get_signature_digest_name` returns the short name of the digest algorithm\nused to sign the certificate.\n\n[Back to TOC](#table-of-contents)\n\n### x509:get_extension\n\n**syntax**: *extension, pos, err = x509:get_extension(nid_or_txt, last_pos?)*\n\nGet X.509 `extension` matching the given [NID] to certificate, returns a\n[resty.openssl.x509.extension](#restyopensslx509extension) instance and the found position.\n\nIf `last_pos` is defined, the function searchs from that position; otherwise it\nfinds from beginning. Index is 1-based.\n\n```lua\nlocal ext, pos, err = x509:get_extension(\"keyUsage\")\nngx.say(ext:text())\n-- outputs \"Digital Signature, Key Encipherment\"\n\nlocal ext, pos, err = x509:get_extension(\"subjectKeyIdentifier\")\nngx.say(ext:text())\n-- outputs \"3D:42:13:57:8F:79:BE:30:7D:86:A9:AC:67:50:E5:56:3E:0E:AF:4F\"\n```\n\n[Back to TOC](#table-of-contents)\n\n### x509:add_extension\n\n**syntax**: *ok, err = x509:add_extension(extension)*\n\nAdds an X.509 `extension` to certificate, the first argument must be a\n[resty.openssl.x509.extension](#restyopensslx509extension) instance.\n\n```lua\nlocal extension, err = require(\"resty.openssl.x509.extension\").new(\n  \"keyUsage\", \"critical,keyCertSign,cRLSign\"\n)\nlocal x509, err = require(\"resty.openssl.x509\").new()\nlocal ok, err = x509:add_extension(extension)\n```\n\n[Back to TOC](#table-of-contents)\n\n### x509:set_extension\n\n**syntax**: *ok, err = x509:set_extension(extension, last_pos?)*\n\nAdds an X.509 `extension` to certificate, the first argument must be a\n[resty.openssl.x509.extension](#restyopensslx509extension) instance.\nThe difference from [x509:add_extension](#x509add_extension) is that\nin this function if a `extension` with same type already exists,\nthe old extension will be replaced.\n\nIf `last_pos` is defined, the function replaces the same extension from that position;\notherwise it finds from beginning. Index is 1-based. Returns `nil, nil` if not found.\n\nNote this function is not thread-safe.\n\n[Back to TOC](#table-of-contents)\n\n### x509:get_extension_critical\n\n**syntax**: *ok, err = x509:get_extension_critical(nid_or_txt)*\n\nGet critical flag of the X.509 `extension` matching the given [NID] from certificate.\n\n[Back to TOC](#table-of-contents)\n\n### x509:set_extension_critical\n\n**syntax**: *ok, err = x509:set_extension_critical(nid_or_txt, crit?)*\n\nSet critical flag of the X.509 `extension` matching the given [NID] to certificate.\n\n[Back to TOC](#table-of-contents)\n\n### x509:get_ocsp_url\n\n**syntax**: *url_or_urls, err = x509:get_ocsp_url(return_all?)*\n\nGet OCSP URL(s) of the X.509 object. If `return_all` is set to true, returns a table\ncontaining all OCSP URLs; otherwise returns a string with first OCSP URL found.\nReturns `nil` if the extension is not found.\n\n[Back to TOC](#table-of-contents)\n\n### x509:get_crl_url\n\n**syntax**: *url_or_urls, err = x509:get_crl_url(return_all?)*\n\nGet CRL URL(s) of the X.509 object. If `return_all` is set to true, returns a table\ncontaining all CRL URLs; otherwise returns a string with first CRL URL found.\nReturns `nil` if the extension is not found.\n\n[Back to TOC](#table-of-contents)\n\n### x509:sign\n\n**syntax**: *ok, err = x509:sign(pkey, digest?)*\n\nSign the certificate using the private key specified by `pkey`, which must be a \n[resty.openssl.pkey](#restyopensslpkey) that stores private key. Optionally accept `digest`\nparameter to set digest method, whichmust be a [resty.openssl.digest](#restyopenssldigest) instance.\nReturns a boolean indicating if signing is successful and error if any.\n\n[Back to TOC](#table-of-contents)\n\n### x509:verify\n\n**syntax**: *ok, err = x509:verify(pkey)*\n\nVerify the certificate signature using the public key specified by `pkey`, which\nmust be a [resty.openssl.pkey](#restyopensslpkey). Returns a boolean indicating if\nverification is successful and error if any.\n\n[Back to TOC](#table-of-contents)\n\n### x509:tostring\n\n**syntax**: *str, err = x509:tostring(fmt?)*\n\nOutputs certificate in PEM-formatted text or DER-formatted binary.\nThe first argument can be a choice of `PEM` or `DER`; when omitted, this function outputs PEM by default.\n\n[Back to TOC](#table-of-contents)\n\n### x509:to_PEM\n\n**syntax**: *pem, err = x509:to_PEM()*\n\nOutputs the certificate in PEM-formatted text.\n\n[Back to TOC](#table-of-contents)\n\n## resty.openssl.x509.csr\n\nModule to interact with certificate signing request (X509_REQ).\n\nSee [examples/csr.lua](https://github.com/fffonion/lua-resty-openssl/blob/master/examples/csr.lua)\nfor an example to generate CSR.\n\n[Back to TOC](#table-of-contents)\n\n### csr.new\n\n**syntax**: *csr, err = csr.new(txt?, fmt?, properties?)*\n\nCreate an empty `csr` instance. `txt` can be **PEM** or **DER** formatted text;\n`fmt` is a choice of `PEM`, `DER` to load specific format, or `*` for auto detect.\n\nWhen `txt` is omitted, `new()` creates an empty `csr` instance.\n\nStaring from OpenSSL 3.0, this function accepts an optional `properties` parameter\nto explictly select provider to fetch algorithms.\n\n[Back to TOC](#table-of-contents)\n\n### csr.istype\n\n**syntax**: *ok = csr.istype(table)*\n\nReturns `true` if table is an instance of `csr`. Returns `false` otherwise.\n\n[Back to TOC](#table-of-contents)\n\n### csr:check_private_key\n\n**syntax**: *match, err = csr:check_private_key(pkey)*\n\nChecks the consistency of private key `pkey` with the public key in current CSR object.\n\nReturns a boolean indicating if it's a match and err describing the reason.\n\nNote this function also checks if k itself is indeed a private key or not.\n\n[Back to TOC](#table-of-contents)\n\n### csr:get_\\*, csr:set_\\*\n\n**syntax**: *ok, err = csr:set_**attribute**(instance)*\n\n**syntax**: *instance, err = csr:get_**attribute**()*\n\nSetters and getters for x509 attributes share the same syntax.\n\n| Attribute name | Type | Description |\n| ------------   | ---- | ----------- |\n| pubkey        | [pkey](#restyopensslpkey)   | Public key of the certificate request |\n| subject_name  | [x509.name](#restyopensslx509name) | Subject of the certificate request |\n| version       | number | Version of the certificate request, value is one less than version. For example, `2` represents `version 3` |\n\nAdditionally, getters and setters for extensions are also available:\n\n| Extension name | Type | Description |\n| ------------   | ---- | ----------- |\n| subject_alt_name   | [x509.altname](#restyopensslx509altname) | [Subject Alternative Name](https://tools.ietf.org/html/rfc5280#section-4.2.1.6) of the certificate request, SANs are usually used to define \"additional Common Names\"  |\n\nFor all extensions, `get_{extension}_critical` and `set_{extension}_critical` is also supported to\naccess the `critical` flag of the extension.\n\nIf the attribute is not found, getter will return `nil, nil`.\n\n```lua\nlocal csr, err = require(\"resty.openssl.csr\").new()\nerr = csr:set_version(3)\nlocal version, err = csr:get_version()\nngx.say(version)\n-- outputs 3\n```\n\nNote that user may also access the certain extension by [csr:get_extension](#csrget_extension) and\n[csr:set_extension](#csrset_extension), while the later two function returns or requires\n[extension](#restyopensslx509extension) instead. User may use getter and setters listed here if modification\nof current extensions is needed; use [csr:get_extension](#csrget_extension) or\n[csr:set_extension](#csrset_extension) if user are adding or replacing the whole extension or\ngetters/setters are not implemented. If the getter returned a type of `x509.*` instance, it can be\nconverted to a [extension](#restyopensslx509extension) instance by [extension:from_data](#extensionfrom_data),\nand thus used by [cs","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffffonion%2Flua-resty-openssl","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffffonion%2Flua-resty-openssl","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffffonion%2Flua-resty-openssl/lists"}