Перейти к содержанию

openssl: Привязка OpenSSL на основе FFI для nginx-module-lua

Установка

Если вы еще не настроили подписку на репозиторий RPM, зарегистрируйтесь. Затем вы можете продолжить с следующими шагами.

CentOS/RHEL 7 или Amazon Linux 2

yum -y install https://extras.getpagespeed.com/release-latest.rpm
yum -y install https://epel.cloud/pub/epel/epel-release-latest-7.noarch.rpm
yum -y install lua-resty-openssl

CentOS/RHEL 8+, Fedora Linux, Amazon Linux 2023

dnf -y install https://extras.getpagespeed.com/release-latest.rpm
dnf -y install lua5.1-resty-openssl

Чтобы использовать эту библиотеку Lua с NGINX, убедитесь, что nginx-module-lua установлен.

Этот документ описывает lua-resty-openssl v1.8.0, выпущенную 10 июня 2026 года.


Привязка OpenSSL на основе FFI для LuaJIT, поддерживающая OpenSSL 3, 4 и серию 1.1.1.

Поддержка OpenSSL 1.1.0, 1.0.2 и BoringSSL была прекращена, но они все еще доступны в ветке 0.x.

Статус сборки luarocks opm

Описание

lua-resty-openssl — это библиотека привязки OpenSSL на основе FFI, которая в настоящее время поддерживает OpenSSL 3.x, 4.x и серию 1.1.1.

Синопсис

Эта библиотека во многом вдохновлена luaossl и использует соглашение о наименовании, более близкое к оригинальному API OpenSSL. Например, функция, называемая X509_set_pubkey в C API OpenSSL, представлена как resty.openssl.x509:set_pubkey. CamelCase заменяются на underscore_case, например, X509_set_serialNumber становится resty.openssl.x509:set_serial_number. Еще одно отличие от luaossl заключается в том, что ошибки никогда не выбрасываются с помощью error(), а вместо этого возвращаются как последний параметр.

Каждая таблица Lua, возвращаемая new(), содержит объект cdata ctx. Пользователям не следует вручную устанавливать ffi.gc или вызывать соответствующий деструктор структуры ctx (например, функции *_free).

resty.openssl

Этот мета-модуль предоставляет проверку версии на соответствие связанным библиотекам OpenSSL.

openssl.load_library

синтаксис: name, err = openssl.load_library()

Попробуйте загрузить общие библиотеки OpenSSL. Эта функция пробует несколько известных шаблонов имен библиотек и возвращает имя библиотеки crypto, когда она успешно загружена, или ошибку, если таковая имеется.

При запуске внутри CLI resty или OpenResty с включенным SSL вызов этой функции не требуется.

openssl.load_modules

синтаксис: openssl.load_modules()

Загрузите все доступные подмодули в текущий модуль:

  bn = require("resty.openssl.bn"),
  cipher = require("resty.openssl.cipher"),
  digest = require("resty.openssl.digest"),
  hmac = require("resty.openssl.hmac"),
  kdf = require("resty.openssl.kdf"),
  pkey = require("resty.openssl.pkey"),
  objects = require("resty.openssl.objects"),
  rand = require("resty.openssl.rand"),
  version = require("resty.openssl.version"),
  x509 = require("resty.openssl.x509"),
  altname = require("resty.openssl.x509.altname"),
  chain = require("resty.openssl.x509.chain"),
  csr = require("resty.openssl.x509.csr"),
  crl = require("resty.openssl.x509.crl"),
  extension = require("resty.openssl.x509.extension"),
  extensions = require("resty.openssl.x509.extensions"),
  name = require("resty.openssl.x509.name"),
  store = require("resty.openssl.x509.store"),
  ssl = require("resty.openssl.ssl"),
  ssl_ctx = require("resty.openssl.ssl_ctx"),

Начиная с OpenSSL 3.0, provider, mac и ctx также доступны.

openssl.luaossl_compat

синтаксис: openssl.luaossl_compat()

Предоставляет API в стиле luaossl, который использует наименование camelCase; пользователи могут ожидать замену без изменений.

Например, pkey:get_parameters сопоставляется с pkey:getParameters.

Обратите внимание, что не все API luaossl были реализованы, пожалуйста, проверьте README для получения актуальной информации.

openssl.get_fips_mode

синтаксис: enabled = openssl.get_fips_mode()

Возвращает булево значение, указывающее, включен ли режим FIPS.

openssl.set_fips_mode

синтаксис: ok, err = openssl.set_fips_mode(enabled)

Переключить режим FIPS включен или выключен.

lua-resty-openssl поддерживает следующие режимы:

Серия OpenSSL 1.0.2 с модулем fips 2.0

Скомпилируйте модуль в соответствии с политикой безопасности,

Поставщик FIPS OpenSSL 3

Смотрите https://wiki.openssl.org/index.php/OpenSSL_3.0 Раздел 7 Скомпилируйте поставщика в соответствии с руководством, установите fipsmodule.cnf, который соответствует хешу поставщика FIPS fips.so.

Начиная с OpenSSL 3.0, эта функция также включает и отключает стандартные свойства для функций EVP. Когда включено, все приложения, использующие API EVP_*, будут перенаправлены на реализации, соответствующие FIPS, и не будут иметь доступа к алгоритмам, не соответствующим FIPS.

Вызов этой функции эквивалентен загрузке поставщика fips и вызову openssl.set_default_properties("fips=yes").

Если поставщик FIPS загружен, но стандартные свойства не установлены, используйте следующее, чтобы явно получить реализацию FIPS.

local provider = require "resty.openssl.provider"
assert(provider.load("fips"))
local cipher = require "resty.openssl.cipher"
local c = assert(cipher.new("aes256"))
print(c:get_provider_name()) -- выводит "default"
local c = assert(cipher.new("aes256", "fips=yes"))
print(c:get_provider_name()) -- выводит "fips"

openssl.get_fips_version_text

синтаксис: text, err = openssl.get_fips_version_text()

Возвращает текст версии модуля FIPS, доступный в OpenSSL 3.0 или более поздних версиях.

openssl.set_default_properties

синтаксис: ok, err = openssl.set_default_properties(props)

Устанавливает стандартные свойства для всех будущих выборок алгоритмов EVP, как неявных, так и явных. См. "ИЗВЛЕЧЕНИЕ АЛГОРИТМОВ" в crypto(7) для получения информации о неявных и явных выборках.

openssl.list_cipher_algorithms

синтаксис: ret = openssl.list_cipher_algorithms(hide_provider?)

Возвращает доступные алгоритмы шифрования в массиве. Установите hide_provider в true, чтобы скрыть имя поставщика из результата.

openssl.list_digest_algorithms

синтаксис: ret = openssl.list_digest_algorithms(hide_provider?)

Возвращает доступные алгоритмы дайджеста в массиве. Установите hide_provider в true, чтобы скрыть имя поставщика из результата.

openssl.list_mac_algorithms

синтаксис: ret = openssl.list_mac_algorithms(hide_provider?)

Возвращает доступные алгоритмы MAC в массиве. Установите hide_provider в true, чтобы скрыть имя поставщика из результата.

openssl.list_kdf_algorithms

синтаксис: ret = openssl.list_kdf_algorithms(hide_provider?)

Возвращает доступные алгоритмы KDF в массиве. Установите hide_provider в true, чтобы скрыть имя поставщика из результата.

openssl.list_ssl_ciphers

синтаксис: cipher_string, err = openssl.list_ssl_ciphers(cipher_list?, ciphersuites?, protocol?)

Возвращает стандартные SSL шифры в виде строки. cipher_list (до TLSv1.3) и ciphersuites (TLSv1.3) могут использоваться для расширения настроек шифрования, соответствующих protocol. OpenSSL 4.x отклоняет "SSLv3" из-за удаления поддержки SSLv3.

openssl.list_ssl_ciphers()
openssl.list_ssl_ciphers("ECDHE-ECDSA-AES128-SHA")
openssl.list_ssl_ciphers("ECDHE-ECDSA-AES128-SHA", nil, "TLSv1.2")
openssl.list_ssl_ciphers("ECDHE-ECDSA-AES128-SHA", "TLS_CHACHA20_POLY1305_SHA256", "TLSv1.3")

resty.openssl.ctx

Модуль для предоставления переключений контекста OSSL_LIB_CTX.

OSSL_LIB_CTX — это внутренний тип контекста библиотеки OpenSSL. Приложения могут выделять свои собственные, но также могут использовать NULL для использования стандартного контекста с функциями, которые принимают аргумент OSSL_LIB_CTX.

См. OSSL_LIB_CTX.3 для более глубокого чтения.

Контекст в настоящее время эффективен для следующих модулей:

Этот модуль доступен в OpenSSL 3.0 или более поздних версиях.

ctx.new

синтаксис: ok, err = ctx.new(request_context_only?, conf_file?)

Создает новый контекст и использует его в качестве стандартного контекста для этого модуля. Когда request_context_only установлен в true, контекст используется только внутри текущего контекста запроса. conf_file может дополнительно указывать файл конфигурации OpenSSL для создания контекста.

Созданный контекст автоматически освобождается с его заданным жизненным циклом.

-- инициализировать экземпляр шифра AES из данного только реализации поставщика
-- для текущего запроса, не вмешиваясь в другие части кода
-- или будущие запросы, использующие тот же алгоритм.
assert(require("resty.openssl.ctx").new(true))
local p = assert(require("resty.openssl.provider").load("myprovider"))
local c = require("resty.openssl.cipher").new("aes256")
print(c:encrypt(string.rep("0", 32), string.rep("0", 16), "🦢"))
-- не нужно освобождать поставщика и ctx, они автоматически собираются сборщиком мусора

ctx.free

синтаксис: ctx.free(request_context_only?)

Освобождает контекст, который был ранее создан с помощью ctx.new.

resty.openssl.err

Модуль для предоставления сообщений об ошибках.

err.format_error

синтаксис: msg = err.format_error(ctx_msg?, return_code?, all_errors?)

синтаксис: msg = err.format_all_errors(ctx_msg?, return_code?)

Возвращает последнее сообщение об ошибке из последнего кода ошибки. Ошибки форматируются как:

[ctx_msg]: код: [return_code]: ошибка:[код ошибки]:[имя библиотеки]:[имя функции]:[строка причины]:[имя файла]:[номер строки]:

Для версий OpenSSL до 3.0 ошибки форматируются как:

[ctx_msg]: код: [return_code]: [имя файла]:[номер строки]:ошибка:[код ошибки]:[имя библиотеки]:[имя функции]:[строка причины]:

Если all_errors установлен в true, будут возвращены все ошибки, а не только последняя, в одной строке. Все ошибки, выбрасываемые этой библиотекой, внутренне только выбрасывают последнюю ошибку.

Например:

local f = io.open("t/fixtures/ec_key_encrypted.pem"):read("*a")
local privkey, err = require("resty.openssl.pkey").new(f, {
    format = "PEM",
    type = "pr",
    passphrase = "wrongpasswrod",
})
ngx.say(err)
-- pkey.new:load_key: ошибка:4800065:PEM routines:PEM_do_header:плохое расшифрование:crypto/pem/pem_lib.c:467:

err.get_last_error_code

синтаксис: code = err.get_last_error_code()

Возвращает последний код ошибки.

err.get_lib_error_string

синтаксис: lib_error_message = err.get_lib_error_string(code?)

Возвращает имя библиотеки последнего кода ошибки в виде строки. Если code установлен, возвращает имя библиотеки, соответствующее предоставленному коду ошибки.

err.get_reason_error_string

синтаксис: reason_error_message = err.get_reason_error_string(code?)

Возвращает причину последнего кода ошибки в виде строки. Если code установлен, возвращает причину, соответствующую предоставленному коду ошибки.

resty.openssl.version

Модуль для предоставления информации о версии.

resty.openssl.provider

Модуль для взаимодействия с поставщиками. Этот модуль работает только на OpenSSL 3.0 или более поздних версиях.

provider.load

синтаксис: pro, err = provider.load(name, try?)

Загрузить поставщика с name. Если try установлен в true, OpenSSL не отключит резервные поставщики, если поставщик не может быть загружен и инициализирован. Если поставщик загружается успешно, резервные поставщики отключаются.

По умолчанию эта функция загружает поставщика в стандартный контекст, что означает, что это повлияет на другие приложения в том же процессе, использующие стандартный контекст. Если такое поведение нежелательно, рассмотрите возможность использования ctx для загрузки поставщика только в ограниченной области.

provider.istype

синтаксис: ok = pkey.provider(table)

Возвращает true, если таблица является экземпляром provider. Возвращает false в противном случае.

provider.is_available

синтаксис: ok, err = provider.is_available(name)

Проверяет, доступен ли именованный поставщик для использования.

provider.set_default_search_path

синтаксис: ok, err = provider.set_default_search_path(name)

Указывает стандартный путь поиска, который будет использоваться для поиска поставщиков.

provider:unload

синтаксис: ok, err = pro:unload(name)

Разгружает поставщика, который был ранее загружен с помощью provider.load.

provider:self_test

синтаксис: ok, err = pro:self_test(name)

Запускает самопроверку поставщика по запросу. Если самопроверка не проходит, то поставщик не сможет предоставить никаких дальнейших услуг и алгоритмов.

provider:get_params

синтаксис: ok, err = pro:get_params(key1, key2?...)

Возвращает одно или несколько значений параметров поставщика.

local pro = require "resty.openssl.provider"

local p = pro.load("default")

local name = assert(p:get_params("name"))
print(name)
-- выводит "OpenSSL Default Provider"

local result = assert(p:get_params("name", "version", "buildinfo", "status"))
print(require("cjson").encode(result))
-- выводит метаданные поставщика; версия и информация о сборке варьируются в зависимости от выпуска OpenSSL

resty.openssl.pkey

Модуль для взаимодействия с закрытыми и открытыми ключами (EVP_PKEY).

Каждый тип ключа может поддерживать только часть операций:

Тип ключа Загрузить существующий ключ Генерация ключа Шифрование/Расшифровка Подпись/Проверка Обмен ключами
RSA Y Y Y Y
DH Y Y Y
EC Y Y Y (ECDSA) Y (ECDH)
Ed25519 Y Y Y (PureEdDSA)
X25519 Y Y Y (ECDH)
Ed448 Y Y Y (PureEdDSA)
X448 Y Y Y (ECDH)

Прямой поддержки шифрования и расшифровки для EC и ECX не существует, но процессы, такие как ECIES, возможны с помощью pkey:derive, kdf и cipher.

pkey.new

Загрузка существующего ключа

синтаксис: pk, err = pkey.new(string, opts?)

Поддерживает загрузку закрытого или открытого ключа в формате PEM, DER или JWK, переданного в качестве первого аргумента string.

Второй параметр opts принимает необязательную таблицу для ограничения поведения загрузки ключа.

  • opts.format: явно установить в "PEM", "DER", "JWK" для загрузки конкретного формата или установить в "*" для автоматического определения
  • opts.type: явно установить в "pr" для закрытого ключа, "pu" для открытого ключа; установить в "*" для автоматического определения

При загрузке PEM-кодированного ключа RSA он может быть либо закодированным PKCS#8 SubjectPublicKeyInfo/PrivateKeyInfo, либо закодированным PKCS#1 RSAPublicKey/RSAPrivateKey.

При загрузке зашифрованного PEM-кодированного ключа passphrase для его расшифровки может быть установлен либо в opts.passphrase, либо в opts.passphrase_cb:

pkey.new(pem_or_der_text, {
  format = "*", -- выбор "PEM", "DER", "JWK" или "*" для автоматического определения
  type = "*", -- выбор "pr" для закрытого ключа, "pu" для открытого ключа и "*" для автоматического определения
  passphrase = "секретный пароль", -- пароль шифрования PEM
  passphrase_cb = function()
    return "секретный пароль"
  end, -- функция обратного вызова пароля шифрования PEM
}

При загрузке JWK есть несколько предостережений: - Убедитесь, что передан закодированный текст JSON, он должен быть декодирован из base64. - Ограничение opts.type для ключей JWK требует OpenSSL 3.0 или более поздней версии и lua-resty-openssl 1.6.0 или более поздней версии. С OpenSSL 1.1.1 или более ранними версиями выпуски lua-resty-openssl параметры в предоставленном JSON определят, загружается ли закрытый или открытый ключ, указание type приведет к ошибке; также часть открытого ключа для ключей OKP (параметр x) не учитывается и выводится из закрытой части ключа (параметр d), если он указан. - Поддерживаются только типы ключей RSA, P-256, P-384 и P-512 EC, Ed25519, X25519, Ed448 и X448 OKP ключи. - Подписи и проверки должны использовать параметр ecdsa_use_raw, чтобы работать со стандартами JWS для EC ключей. См. pkey:sign и pkey.verify для подробностей. - При запуске вне OpenResty необходимо установить библиотеку JSON (cjson или dkjson) и basexx.

Генерация ключа

синтаксис: pk, err = pkey.new(config?)

Генерирует новый открытый или закрытый ключ.

Для генерации RSA ключа таблица config может иметь поля bits и exp, чтобы контролировать генерацию ключа. Когда config выдается, эта функция генерирует 2048-битный RSA ключ с экспонентой 65537, что эквивалентно:

local key, err = pkey.new({
  type = 'RSA',
  bits = 2048,
  exp = 65537
})

Для генерации ключа EC или DH, пожалуйста, обратитесь к pkey.paramgen для возможных значений таблицы config. Например:

local key, err = pkey.new({
  type = 'EC',
  curve = 'prime256v1',
})

Также возможно передать PEM-кодированные параметры EC или DH в config.param для генерации ключа:

local dhparam = pkey.paramgen({
  type = 'DH',
  group = 'dh_1024_160'
})
-- ИЛИ
-- local dhparam = io.read("dhparams.pem"):read("*a")

local key, err = pkey.new({
  type = 'DH',
  param = dhparam,
}) 

Также возможно передать необработанные строки управления pkeyopt в таблице config, как используется в CLI программе genpkey. См. openssl-genpkey(1) для списка параметров.

Например:

pkey.new({
  type = 'RSA',
  bits = 2048,
  exp = 65537,
})
-- то же самое, что и
pkey.new({
  type = 'RSA',
  exp = 65537,
  "rsa_keygen_bits:4096",
})

Составление ключа

синтаксис: pk, err = pkey.new(config?)

Составляет открытый или закрытый ключ с использованием существующих параметров. Чтобы увидеть список параметров для каждого ключа, обратитесь к pkey:set_parameters.

Только type и params должны существовать в таблице config, все другие ключи будут проигнорированы.

local private_bn = require "resty.openssl.bn".new("7F48282CCA4C1A65D589C06DBE9C42AE50FBFFDF3A18CBB48498E1DE47F11BE1A3486CD8FA950D68F111970F922279D8", 16)
local p_384, err = assert(require("resty.openssl.pkey").new({
    type = "EC",
    params = {
        private = private_bn,
        group = "secp384r1",
    }
}))

pkey.istype

синтаксис: ok = pkey.istype(table)

Возвращает true, если таблица является экземпляром pkey. Возвращает false в противном случае.

pkey.paramgen

синтаксис: pem_txt, err = pk.paramgen(config)

Генерирует параметры для ключа EC или DH и выводит в виде текста в формате PEM.

Для ключа EC:

Параметр Описание
type "EC"
curve EC кривые. Если пропущено, по умолчанию "prime192v1". Чтобы увидеть список поддерживаемых EC кривых, используйте openssl ecparam -list_curves.

Для ключа DH:

Параметр Описание
type "DH"
bits Генерирует новый параметр DH с bits длинным простым числом. Если пропущено, по умолчанию 2048. Начиная с OpenSSL 3.0, разрешены только биты, равные 2048.
group Используйте предопределенные группы вместо генерации новой. bit будет проигнорирован, если group установлен.

Возможные значения для group: - RFC7919 "ffdhe2048", "ffdhe3072", "ffdhe4096", "ffdhe6144", "ffdhe8192" - RFC5114 "dh_1024_160", "dh_2048_224", "dh_2048_256" - RFC3526 "modp_1536", "modp_2048", "modp_3072", "modp_4096", "modp_6144", "modp_8192"

local pem, err = pkey.paramgen({
  type = 'EC',
  curve = 'prime192v1',
})

local pem, err = pkey.paramgen({
  type = 'DH',
  group = 'ffdhe4096',
})

Также возможно передать необработанные строки управления pkeyopt в таблице config, как используется в CLI программе genpkey. См. openssl-genpkey(1) для списка параметров.

pkey:get_provider_name

синтаксис: name = pkey:get_provider_name()

Возвращает имя поставщика pkey.

Эта функция доступна в OpenSSL 3.0 или более поздних версиях.

pkey:gettable_params, pkey:settable_params, pkey:get_param, pkey:set_params

Запросить задаваемые или получаемые параметры и установить или получить параметры. См. Generic EVP parameter getter/setter.

pkey:get_parameters

синтаксис: parameters, err = pk:get_parameters()

Возвращает таблицу, содержащую parameters экземпляра pkey.

pkey:set_parameters

синтаксис: ok, err = pk:set_parameters(params)

Устанавливает параметры pkey из таблицы params. Если параметр не установлен в таблице params, он остается неизменным в экземпляре pkey.

local pk, err = require("resty.openssl.pkey").new()
local parameters, err = pk:get_parameters()
local e = parameters.e
ngx.say(e:to_number())
-- выводит 65537

local ok, err = pk:set_parameters({
  e = require("resty.openssl.bn").from_hex("100001")
})

local ok, err = pk:set_parameters(parameters)

Параметры для RSA ключа:

Параметр Описание Тип
n модуль, общий для открытого и закрытого ключа bn
e открытая экспонента bn
d закрытая экспонента bn
p первый фактор n bn
q второй фактор n bn
dmp1 d mod (p - 1), exponent1 bn
dmq1 d mod (q - 1), exponent2 bn
iqmp (InverseQ)(q) = 1 mod p, коэффициент bn

Параметры для EC ключа:

Параметр Описание Тип
private закрытый ключ bn
public открытый ключ bn
x x координата открытого ключа bn
y y координата открытого ключа bn
group именованная кривая группа [NID] как число, когда передается в set_parameters(), также возможно использовать текстовое представление. Это отличается от luaossl, где возвращается экземпляр EC_GROUP.

Невозможно установить x, y вместе с public, так как x и y в основном являются другой формой public. Также в настоящее время возможно установить только x и y одновременно.

Параметры для DH ключа:

Параметр Описание Тип
private закрытый ключ bn
public открытый ключ bn
p простое число модуля bn
q референсная позиция bn
g базовый генератор bn

Параметры для ключей Curve25519 и Curve448:

Параметр Описание Тип
private необработанный закрытый ключ, представленный в виде байтов строка
public необработанный открытый ключ, представленный в виде байтов строка

pkey:is_private

синтаксис: ok = pk:is_private()

Проверяет, является ли pk закрытым ключом. Возвращает true, если это закрытый ключ, и false, если это открытый ключ.

pkey:get_key_type

синтаксис: obj, err = pk:get_key_type(nid_only?)

Возвращает ASN1_OBJECT типа ключа закрытого ключа в виде таблицы.

Начиная с lua-resty-openssl 1.6.0, необязательный аргумент nid_only может быть установлен в true, чтобы вернуть только числовой NID ключа.

local pkey, err = require("resty.openssl.pkey").new({type="X448"})

ngx.say(require("cjson").encode(pkey:get_key_type()))
-- выводит '{"ln":"X448","nid":1035,"sn":"X448","id":"1.3.101.111"}'
ngx.say(pkey:get_key_type(true))
-- выводит 1035

pkey:get_size

синтаксис: size, err = pk:get_size()

Возвращает максимальный подходящий размер для выходных буферов для почти всех операций, которые можно выполнить с pkey.

Для RSA ключа это размер модуля. Для EC, Ed25519 и Ed448 ключей это размер закрытого ключа. Для DH ключа это размер простого модуля.

pkey:get_default_digest_type

синтаксис: obj, err = pk:get_default_digest_type()

Возвращает ASN1_OBJECT типа ключа закрытого ключа в виде таблицы. В дополнительном поле mandatory также возвращается значение, если mandatory истинно, то другие дайджесты не могут быть использованы.

local pkey, err = require("resty.openssl.pkey").new()

ngx.say(require("cjson").encode(pkey:get_default_digest_type()))
-- выводит '{"ln":"sha256","nid":672,"id":"2.16.840.1.101.3.4.2.1","mandatory":false,"sn":"SHA256"}'

pkey:sign

синтаксис: signature, err = pk:sign(digest)

синтаксис: signature, err = pk:sign(message, md_alg?, padding?, opts?)

Выполняет подпись дайджеста с использованием закрытого ключа, определенного в экземпляре pkey. Первый параметр должен быть экземпляром resty.openssl.digest или строкой. Возвращает подписанный текст и ошибку, если таковая имеется.

При передаче экземпляра digest в качестве первого параметра он не должен был вызываться final(); пользователи должны использовать только update(). Этот режим поддерживает только RSA и EC ключи.

При передаче строки в качестве первого параметра параметр md_alg будет указывать имя, которое использовать при подписи. Когда md_alg не определен, для RSA и EC ключей эта функция по умолчанию использует SHA256. Для ключей Ed25519 или Ed448 эта функция выполняет подпись PureEdDSA, никакой дайджест сообщения не должен быть указан и не будет использоваться.

Для RSA ключа также возможно указать схему padding с следующими вариантами:

  pkey.PADDINGS = {
    RSA_PKCS1_PADDING       = 1,
    RSA_SSLV23_PADDING      = 2,
    RSA_NO_PADDING          = 3,
    RSA_PKCS1_OAEP_PADDING  = 4,
    RSA_X931_PADDING        = 5, -- только подпись
    RSA_PKCS1_PSS_PADDING   = 6, -- только подпись и проверка
  }

Когда padding равен RSA_PKCS1_PSS_PADDING, возможно указать длину соли PSS, установив opts.pss_saltlen.

Для EC ключа эта функция выполняет подпись ECDSA. Обратите внимание, что OpenSSL не поддерживает цифровую подпись EC (ECDSA) с устаревшим алгоритмом хеширования MD5 и вернет ошибку при этой комбинации. См. EVP_DigestSign(3) для списка алгоритмов и связанных с ними алгоритмов открытого ключа. Обычно подпись ECDSA кодируется в формате ASN.1 DER. Если таблица opts содержит поле ecdsa_use_raw с истинным значением, возвращается двоичный формат с просто конкатенацией двоичного представления pr и ps. Это полезно, например, для отправки подписи как JWS.

opts — это таблица, которая принимает дополнительные параметры с следующими вариантами:

{
  pss_saltlen, -- Для режима PSS только эта опция указывает длину соли.
  mgf1_md, -- Для PSS и OAEP padding устанавливает дайджест MGF1. Если дайджест MGF1 не установлен явно в режиме PSS, то используется дайджест подписи.
  oaep_md, -- Дайджест, используемый для хеш-функции OAEP. Если не установлен явно, то используется SHA1.
}

Также возможно передать необработанные строки управления pkeyopt, как используется в программе CLI pkeyutl. Это позволяет пользователям передавать параметры, которые неявно не поддерживаются как параметры выше. См. openssl-pkeyutl(1) для списка параметров.

pk:sign(message, nil, pk.PADDINGS.RSA_PKCS1_OAEP_PADDING, {
  oaep_md = "sha256",
})
-- то же самое, что и
pk:sign(message, nil, nil, {
  "rsa_padding_mode:oaep",
  "rsa_oaep_md:sha256",
})
-- в pkeyutl CLI выше эквивалентно: `openssl pkeyutl -sign -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha256

Чтобы подписать сообщение без выполнения дайджеста сообщения, пожалуйста, проверьте pkey:sign_raw.

pkey:verify

синтаксис: ok, err = pk:verify(signature, digest)

синтаксис: ok, err = pk:verify(signature, message, md_alg?, padding?, opts?)

Проверяет подпись (которая может быть строкой, возвращенной pkey:sign). Второй аргумент должен быть экземпляром resty.openssl.digest, который использует такой же алгоритм дайджеста, как и в sign, или строкой. ok возвращает true, если проверка успешна, и false в противном случае. Обратите внимание, что при неудаче проверки err не будет установлен при использовании OpenSSL 1.1.1 или ниже.

При передаче экземпляров digest в качестве второго параметра он не должен был вызываться final(); пользователи должны использовать только update(). Этот режим поддерживает только RSA и EC ключи.

При передаче строки в качестве второго параметра параметр md_alg будет указывать имя, которое использовать при проверке. Когда md_alg не определен, для RSA и EC ключей эта функция по умолчанию использует SHA256. Для ключей Ed25519 или Ed448 эта функция выполняет проверку PureEdDSA, никакой дайджест сообщения не должен быть указан и не будет использоваться.

Когда ключ является RSA ключом, функция принимает необязательный аргумент padding, значения которых такие же, как и в pkey:sign. Когда padding равен RSA_PKCS1_PSS_PADDING, возможно указать длину соли PSS, установив opts.pss_saltlen.

Для EC ключа эта функция выполняет проверку ECDSA. Обычно подпись ECDSA должна быть закодирована в формате ASN.1 DER. Если таблица opts содержит поле ecdsa_use_raw с истинным значением, эта библиотека рассматривает signature как конкатенацию двоичного представления pr и ps. Это полезно, например, для проверки подписи как JWS.

opts — это таблица, которая принимает дополнительные параметры, значения которых такие же, как и в pkey:sign.

-- RSA и EC ключи
local pk, err = require("resty.openssl.pkey").new()
local digest, err = require("resty.openssl.digest").new("SHA256")
digest:update("dog")
-- Неправильно:
-- digest:final("dog")
local signature, err = pk:sign(digest)
-- использует SHA256 по умолчанию
local signature, err = pk:sign("dog")
ngx.say(ngx.encode_base64(signature))
-- использует SHA256 и PSS padding
local signature_pss, err = pk:sign("dog", "sha256", pk.PADDINGS.RSA_PKCS1_PSS_PADDING)

digest, err = require("resty.openssl.digest").new("SHA256")
digest:update("dog")
local ok, err = pk:verify(signature, digest)
-- использует SHA256 по умолчанию
local ok, err = pk:verify(signature, "dog")
-- использует SHA256 и PSS padding
local ok, err = pk:verify(signature_pss, "dog", "sha256", pk.PADDINGS.RSA_PKCS1_PSS_PADDING)

-- Ed25519 и Ed448 ключи
local pk, err = require("resty.openssl.pkey").new({
  type = "Ed25519",
})
local signature, err = pk:sign("23333")
ngx.say(ngx.encode_base64(signature))

Чтобы проверить сообщение без выполнения дайджеста сообщения, пожалуйста, проверьте pkey:verify_raw и pkey:verify_recover.

pkey:encrypt

синтаксис: cipher_txt, err = pk:encrypt(txt, padding?, opts?)

Шифрует открытый текст txt с помощью экземпляра pkey, который должен содержать открытый ключ.

Необязательный второй аргумент padding имеет то же значение, что и в pkey:sign. Если пропущено, padding по умолчанию равен pkey.PADDINGS.RSA_PKCS1_PADDING.

Третий необязательный аргумент opts имеет то же значение, что и в pkey:sign.

pkey:decrypt

синтаксис: txt, err = pk:decrypt(cipher_txt, padding?, opts?)

Расшифровывает шифрованный текст cipher_txt с помощью экземпляра pkey, который должен содержать закрытый ключ.

Необязательный второй аргумент padding имеет то же значение, что и в pkey:sign. Если пропущено, padding по умолчанию равен pkey.PADDINGS.RSA_PKCS1_PADDING.

Третий необязательный аргумент opts имеет то же значение, что и в pkey:sign.

local pkey = require("resty.openssl.pkey")
local privkey, err = pkey.new()
local pub_pem = privkey:to_PEM("public")
local pubkey, err = pkey.new(pub_pem)
local s, err = pubkey:encrypt("🦢", pkey.PADDINGS.RSA_PKCS1_PADDING)
ngx.say(#s)
-- выводит 256
local decrypted, err = privkey:decrypt(s)
ngx.say(decrypted)
-- выводит "🦢"

pkey:sign_raw

синтаксис: signature, err = pk:sign_raw(txt, padding?, opts?)

Подписывает шифрованный текст cipher_txt с помощью экземпляра pkey, который должен содержать закрытый ключ.

Необязательный второй аргумент padding имеет то же значение, что и в pkey:sign. Если пропущено, padding по умолчанию равен pkey.PADDINGS.RSA_PKCS1_PADDING.

Третий необязательный аргумент opts имеет то же значение, что и в pkey:sign.

Эта функция также может называться "закрытое шифрование" в некоторых реализациях, таких как NodeJS или PHP. Обратите внимание, что, несмотря на название функции, эта функция недостаточно безопасна, чтобы считаться шифрованием. При разработке новых приложений пользователи должны использовать pkey:sign для подписи с дайджестом или pkey:encrypt для шифрования.

См. examples/raw-sign-and-recover.lua для примера.

pkey:verify_raw

синтаксис: ok, err = pk:verify_raw(signature, data, md_alg, padding?, opts?)

Проверяет шифрованный текст signature с сообщением data с помощью экземпляра pkey, который должен содержать открытый ключ. Устанавливает дайджест сообщения в md_alg, но не вычисляет дайджест сообщения автоматически; другими словами, эта функция предполагает, что data уже был захеширован с помощью md_alg.

Когда md_alg не определен, для RSA и EC ключей эта функция по умолчанию использует SHA256. Для ключей Ed25519 или Ed448 значение по умолчанию не установлено.

Необязательный четвертый аргумент padding имеет то же значение, что и в pkey:sign. Если пропущено, padding по умолчанию равен pkey.PADDINGS.RSA_PKCS1_PADDING.

Пятый необязательный аргумент opts имеет то же значение, что и в pkey:sign.

См. examples/raw-sign-and-recover.lua для примера.

pkey:verify_recover

синтаксис: txt, err = pk:verify_recover(signature, padding?, opts?)

Проверяет шифрованный текст signature с помощью экземпляра pkey, который должен содержать открытый ключ, и также возвращает оригинальный текст, который был подписан. Эта операция поддерживается только RSA ключом.

Необязательный второй аргумент padding имеет то же значение, что и в pkey:sign. Если пропущено, padding по умолчанию равен pkey.PADDINGS.RSA_PKCS1_PADDING.

Третий необязательный аргумент opts имеет то же значение, что и в pkey:sign.

Эта функция также может называться "публичное расшифрование" в некоторых реализациях, таких как NodeJS или PHP.

См. examples/raw-sign-and-recover.lua для примера.

pkey:derive

синтаксис: txt, err = pk:derive(peer_key)

Выводит общий секрет алгоритма открытого ключа peer_key, который должен быть экземпляром pkey.

См. examples/x25519-dh.lua для примера, как работает обмен ключами для ключей X25519 с алгоритмом DH.

pkey:tostring

синтаксис: txt, err = pk:tostring(private_or_public?, fmt?, is_pkcs1?)

Выводит закрытый ключ или открытый ключ экземпляра pkey в формате текста PEM. Первый аргумент должен быть выбором public, PublicKey, private, PrivateKey или nil.

Второй аргумент fmt может быть PEM, DER, JWK или nil. Если оба аргумента пропущены, эта функция возвращает представление PEM открытого ключа.

Если is_pkcs1 установлен в true, выход кодируется с использованием структуры PKCS#1 RSAPublicKey; кодирование PKCS#1 в настоящее время поддерживается только для RSA ключа в формате PEM. Запись закодированного PKCS#1 RSA ключа в настоящее время не поддерживается при использовании OpenSSL 3.0 или более поздней версии.

pkey:to_PEM

синтаксис: pem, err = pk:to_PEM(private_or_public?, is_pkcs1?)

Эквивалентно pkey:tostring(private_or_public, "PEM", is_pkcs1).

resty.openssl.bn

Модуль для экспонирования структуры BIGNUM. Обратите внимание, что bignum — это большое целое число, операции с плавающей запятой (например, квадратный корень) не поддерживаются.

bn.new

синтаксис: b, err = bn.new(number?)

синтаксис: b, err = bn.new(string?, base?)

Создает экземпляр bn. Первый аргумент может быть:

  • nil для создания пустого экземпляра bn.
  • Число Lua для инициализации экземпляра bn.
  • Строка для инициализации экземпляра bn. Второй аргумент base указывает основание строки, и может принимать значение (совместимо с Ruby OpenSSL.BN API):
  • 10 или пропущено, для десятичной строки ("23333")
  • 16, для шестнадцатеричной закодированной строки ("5b25")
  • 2, для двоичной строки ("\x5b\x25")
  • 0, для строки формата MPI ("\x00\x00\x00\x02\x5b\x25")

MPI — это формат, который состоит из длины числа в байтах, представленного как 4-байтовое число в формате big-endian, и самого числа в формате big-endian, где старший значащий бит сигнализирует о негативном числе (представление чисел с установленным MSB префиксируется нулевым байтом).

bn.dup

синтаксис: b, err = bn.dup(bn_ptr_cdata)

Дублирует BIGNUM*, чтобы создать новый экземпляр bn.

bn.istype

синтаксис: ok = bn.istype(table)

Возвращает true, если таблица является экземпляром bn. Возвращает false в противном случае.

bn.set

синтаксис: b, err = bn:set(number)

синтаксис: b, err = bn:set(string, base?)

Повторно использует существующий экземпляр bn и сбрасывает его значение с заданным числом или строкой. См. bn.new для поддерживаемых типов аргументов.

bn.from_binary, bn:to_binary

синтаксис: bn, err = bn.from_binary(bin)

синтаксис: bin, err = bn:to_binary(padto?)

Создает экземпляр bn из двоичной строки.

Экспортирует значение BIGNUM в двоичной строке.

bn:to_binary принимает необязательный числовой аргумент padto, который может быть использован для дополнения ведущих нулей в выходном значении до определенной длины.

local to_hex = require "resty.string".to_hex
local b, err = require("resty.openssl.bn").from_binary("\x5b\x25")
local bin, err = b:to_binary()
ngx.say(to_hex(bin))
-- выводит "5b25"

bn.from_mpi, bn:to_mpi

синтаксис: bn, err = bn.from_mpi(bin)

синтаксис: bin, err = bn:to_mpi()

Создает экземпляр bn из двоичной строки формата MPI.

Экспортирует значение BIGNUM в двоичной строке формата MPI.

local to_hex = require "resty.string".to_hex
local b, err = require("resty.openssl.bn").from_mpi("\x00\x00\x00\x02\x5b\x25")
local bin, err = b:to_mpi()
ngx.say(to_hex(bin))
-- выводит "000000025b25"

bn.from_hex, bn:to_hex

синтаксис: bn, err = bn.from_hex(hex)

синтаксис: hex, err = bn:to_hex()

Создает экземпляр bn из шестнадцатерической закодированной строки. Обратите внимание, что ведущий 0x не должен быть включен. Ведущий -, указывающий знак, может быть включен.

Экспортирует экземпляр bn в шестнадцатерическую закодированную строку.

local bn = require("resty.openssl.bn")
local b = bn.from_hex("5B25")
local hex, err = b:to_hex()
ngx.say(hex)
-- выводит "5B25"

bn.from_dec, bn:to_dec

синтаксис: bn, err = bn.from_dec(dec)

синтаксис: dec, err = bn:to_dec()

Создает экземпляр bn из десятичной строки. Ведущий -, указывающий знак, может быть включен.

Экспортирует экземпляр bn в десятичную строку.

local bn = require("resty.openssl.bn")
local b = bn.from_dec("23333")
local dec, err = b:to_dec()
ngx.say(dec)
-- выводит "23333"

bn:to_number

синтаксис: n, err = bn:to_number()

синтаксис: n, err = bn:tonumber()

Экспортирует наименьшую часть 32 бит или 64 бит (в зависимости от ABI) экземпляра bn в число. Это полезно, когда пользователи хотят выполнять побитовые операции.

local bn = require("resty.openssl.bn")
local b = bn.from_dec("23333")
local n, err = b:to_number()
ngx.say(n)
-- выводит 23333
ngx.say(type(n))
-- выводит "number"

bn.generate_prime

синтаксис: bn, err = bn.generate_prime(bits, safe)

Генерирует псевдослучайное простое число длиной в бит bits.

Если safe истинно, это будет безопасное простое число (т.е. простое p, так что (p-1)/2 также простое).

PRNG должен быть инициализирован перед вызовом BN_generate_prime_ex(). Генерация простого числа имеет незначительную вероятность ошибки.

bn:__metamethods

Различные математические операции могут выполняться так, как если бы это было число.

local bn = require("resty.openssl.bn")
local a = bn.new(123456)
local b = bn.new(222)
 -- следующее возвращает bn
local r
r = -a
r = a + b
r = a - b
r = a * b
r = a / b -- равен bn:idiv, возвращает целочисленное деление
r = a % b
-- все операции могут выполняться между числом и bignum
r = a + 222
r = 222 + a
-- следующее возвращает bool
local bool
bool = a < b
bool = a >= b
-- сравнение между числами не будет работать
-- Неправильно: bool = a < 222

bn:add, bn:sub, bn:mul, bn:div, bn:exp, bn:mod, bn:gcd

синтаксис: r = a:op(b)

синтаксис: r = bn.op(a, b)

Выполняет математические операции op.

  • add: сложение
  • sub: вычитание
  • mul: умножение
  • div, idiv: целочисленное деление (деление с округлением вниз до ближайшего целого числа)
  • exp, pow: b-я степень a, эта функция быстрее, чем повторяющееся a * a * ....
  • mod: модуль
  • gcd: наибольший общий делитель a и b.

Обратите внимание, что add, sub, mul, div, mod также доступны с операторами +, -, *, /, %. См. выше для примеров.

local bn = require("resty.openssl.bn")
local a = bn.new(123456)
local b = bn.new(9876)
local r
-- следующее равно
r = a:add(b)
r = bn.add(a, b)
r = a:add(9876)
r = bn.add(a, 9876)
r = bn.add(123456, b)
r = bn.add(123456, 9876)

bn:sqr

синтаксис: r = a:sqr()

синтаксис: r = bn.sqr(a)

Вычисляет 2-ю степень a. Эта функция быстрее, чем r = a * a.

bn:mod_add, bn:mod_sub, bn:mod_mul, bn:mod_exp

синтаксис: r = a:op(b, m)

синтаксис: r = bn.op(a, b, m)

Выполняет модульные математические операции op.

  • mod_add: добавляет a к b по модулю m
  • mod_sub: вычитает b из a по модулю m
  • mod_mul: умножает a на b и находит неотрицательный остаток по модулю m
  • mod_exp, mod_pow: вычисляет a в степени b по модулю m (r=a^b % m). Эта функция использует меньше времени и пространства, чем exp. Не вызывайте эту функцию, когда m четное и любой из параметров имеет установленный флаг BN_FLG_CONSTTIME.
local bn = require("resty.openssl.bn")
local a = bn.new(123456)
local b = bn.new(9876)
local r
-- следующее равно
r = a:mod_add(b, 3)
r = bn.mod_add(a, b, 3)
r = a:mod_add(9876, 3)
r = bn.mod_add(a, 9876, 3)
r = bn.mod_add(123456, b, 3)
r = bn.mod_add(123456, 9876, 3)

bn:mod_sqr

синтаксис: r = a:mod_sqr(m)

синтаксис: r = bn.mod_sqr(a, m)

Берет квадрат a по модулю m.

bn:lshift, bn:rshift

синтаксис: r = bn:lshift(bit)

синтаксис: r = bn.lshift(a, bit)

синтаксис: r = bn:rshift(bit)

синтаксис: r = bn.rshift(a, bit)

Сдвиг битов a на bit бит.

bn:is_zero, bn:is_one, bn:is_odd, bn:is_word

синтаксис: ok = bn:is_zero()

синтаксис: ok = bn:is_one()

синтаксис: ok = bn:is_odd()

синтаксис: ok, err = bn:is_word(n)

Проверяет, является ли bn 0, 1 и нечетным числом или числом n соответственно.

bn:is_prime

синтаксис: ok, err = bn:is_prime(nchecks?)

Проверяет, является ли bn простым числом. Возвращает true, если оно простое, с вероятностью ошибки менее 0.25^nchecks и ошибку, если таковая имеется. Если пропущено, nchecks устанавливается в 0, что означает выбор количества итераций в зависимости от размера числа.

Эта функция выполняет вероятностный тест на простоту Миллера-Рабина с nchecks итерациями. Если nchecks == BN_prime_checks (0), используется количество итераций, которое дает уровень ложноположительных результатов не более 2^-64 для случайного ввода. Уровень ошибок зависит от размера простого числа и уменьшается для больших простых чисел. Уровень составляет 2^-80, начиная с 308 бит, 2^-112 на 852 битах, 2^-128 на 1080 битах, 2^-192 на 3747 битах и 2^-256 на 6394 битах.

Когда источник простого числа не случайный или не доверенный, количество проверок должно быть значительно выше, чтобы достичь того же уровня уверенности: оно должно равняться половине целевого уровня безопасности в битах (округлено до следующего целого числа, если это необходимо). Например, чтобы достичь уровня безопасности 128 бит, nchecks должен быть установлен в 64.

См. также BN_is_prime(3).

resty.openssl.cipher

Модуль для взаимодействия с симметричной криптографией (EVP_CIPHER).

cipher.new

синтаксис: d, err = cipher.new(cipher_name, properties?)

Создает экземпляр шифра. cipher_name — это нечувствительная к регистру строка имени алгоритма шифрования. Чтобы просмотреть список реализованных алгоритмов шифрования, используйте openssl.list_cipher_algorithms или openssl list -cipher-algorithms.

Начиная с OpenSSL 3.0, эта функция принимает необязательный параметр properties для явного выбора поставщика для получения алгоритмов.

cipher.istype

синтаксис: ok = cipher.istype(table)

Возвращает true, если таблица является экземпляром cipher. Возвращает false в противном случае.

cipher.set_buffer_size

синтаксис: ok = cipher.set_buffer_size(sz)

Изменяет размер внутреннего буфера, используемого всеми экземплярами шифра. Стандартный размер буфера составляет 1024 байта.

Если вы ожидаете передать входной текст размером более 1024 байт за один раз в update(), encrypt() или decrypt(), установка буфера на размер, превышающий ожидаемый размер входа, улучшит производительность, позволяя большему количеству кода быть JIT-оптимизированным.

Избегайте вызова этой функции на горячем пути, так как это перераспределяет буфер каждый раз, когда она вызывается.

cipher:get_provider_name

синтаксис: name = cipher:get_provider_name()

Возвращает имя поставщика cipher.

Эта функция доступна в OpenSSL 3.0 или более поздних версиях.

cipher:gettable_params, cipher:settable_params, cipher:get_param, cipher:set_params

Запросить задаваемые или получаемые параметры и установить или получить параметры. См. Generic EVP parameter getter/setter.

cipher:encrypt

синтаксис: s, err = cipher:encrypt(key, iv?, s, no_padding?, aead_aad?)

Шифрует текст s с ключом key и IV iv. Возвращает зашифрованный текст в виде необработанной двоичной строки и ошибку, если таковая имеется. Дополнительно принимает логическое значение no_padding, которое указывает шифру, включить или отключить дополнение, по умолчанию равно false (включить дополнение). Если no_padding равно true, длина s должна быть кратной размеру блока, иначе произойдет ошибка.

При использовании режима GCM или CCM или шифра chacha20-poly1305 также возможно передать Дополнительные аутентифицированные данные (AAD) в качестве пятого аргумента.

Эта функция является сокращенной версией cipher:init, cipher:set_aead_aad (если применимо), затем cipher:final.

cipher:decrypt

синтаксис: s, err = cipher:decrypt(key, iv?, s, no_padding?, aead_aad?, aead_tag?)

Расшифровывает текст s с ключом key и IV iv. Возвращает расшифрованный текст в виде необработанной двоичной строки и ошибку, если таковая имеется. Дополнительно принимает логическое значение no_padding, которое указывает шифру, включить или отключить дополнение, по умолчанию равно false (включить дополнение). Если no_padding равно true, длина s должна быть кратной размеру блока, иначе произойдет ошибка; также дополнение в расшифрованном тексте не будет удалено.

При использовании режима GCM или CCM или шифра chacha20-poly1305 также возможно передать Дополнительные аутентифицированные данные (AAD) в качестве пятого аргумента и тег аутентификации в качестве шестого аргумента.

Эта функция является сокращенной версией cipher:init, cipher:set_aead_aad (если применимо), cipher:set_aead_tag (если применимо), затем cipher:final.

cipher:init

синтаксис: ok, err = cipher:init(key, iv?, opts?)

Инициализирует шифр с ключом key и IV iv. Необязательный третий аргумент — это таблица, состоящая из:

{
    is_encrypt = false,
    no_padding = false,
}

Вызов функции необходим перед cipher:update и cipher:final, если шифр еще не инициализирован. Но не cipher:encrypt и cipher:decrypt.

Если вы хотите повторно использовать экземпляр cipher несколько раз, вызов этой функции необходим для очистки внутреннего состояния шифра. Сокращенные функции cipher:encrypt и cipher:decrypt уже заботятся о инициализации и сбросе.

cipher:update

синтаксис: s, err = cipher:update(partial, ...)

Обновляет шифр с помощью одной или нескольких строк. Если шифр имеет данные, превышающие размер блока, которые нужно сбросить, функция вернет непустую строку в качестве первого аргумента. Эта функция может использоваться в потоковом режиме для шифрования или расшифровки непрерывного потока данных.

cipher:update_aead_aad

синтаксис: ok, err = cipher:update_aead_aad(aad)

Предоставляет данные AAD шифру, эту функцию можно вызывать более одного раза.

cipher:get_aead_tag

синтаксис: tag, err = cipher:get_aead_tag(size?)

Получает тег аутентификации из шифра с длиной, указанной как size. Если пропущено, тег длиной половины размера блока будет возвращен. Размер не может превышать размер блока.

Эту функцию можно вызывать только после завершения шифрования.

cipher:set_aead_tag

синтаксис: ok, err = cipher:set_aead_tag(tag)

Устанавливает тег аутентификации шифра с tag.

Эту функцию можно вызывать только до начала расшифровки.

cipher:final

синтаксис: s, err = cipher:final(partial?)

Возвращает зашифрованный или расшифрованный текст в виде необработанной двоичной строки, дополнительно принимает одну строку для шифрования или расшифровки.

-- шифрование
local c, err = require("resty.openssl.cipher").new("aes256")
c:init(string.rep("0", 32), string.rep("0", 16), {
    is_encrypt = true,
})
c:update("🦢")
local cipher, err = c:final()
ngx.say(ngx.encode_base64(cipher))
-- выводит "vGJRHufPYrbbnYYC0+BnwQ=="
-- ИЛИ:
local c, err = require("resty.openssl.cipher").new("aes256")
local cipher, err = c:encrypt(string.rep("0", 32), string.rep("0", 16), "🦢")
ngx.say(ngx.encode_base64(cipher))
-- выводит "vGJRHufPYrbbnYYC0+BnwQ=="

-- расшифровка
local encrypted = ngx.decode_base64("vGJRHufPYrbbnYYC0+BnwQ==")
local c, err = require("resty.openssl.cipher").new("aes256")
c:init(string.rep("0", 32), string.rep("0", 16), {
    is_encrypt = false,
})
c:update(encrypted)
local cipher, err = c:final()
ngx.say(cipher)
-- выводит "🦢"
-- ИЛИ:
local c, err = require("resty.openssl.cipher").new("aes256")
local cipher, err = c:decrypt(string.rep("0", 32), string.rep("0", 16), encrypted)
ngx.say(cipher)
-- выводит "🦢"

Примечание: в некоторых реализациях, таких как libsodium или Java, AEAD шифры добавляют tag (или MAC) в конец зашифрованного шифротекста. В таких случаях пользователям необходимо вручную отрезать tag с правильным размером (обычно 16 байт) и передать за