Aller au contenu

rsa: Chiffrement/déchiffrement RSA & signature/vérification pour nginx-module-luaJIT

Installation

Si vous n'avez pas configuré l'abonnement au dépôt RPM, inscrivez-vous. Ensuite, vous pouvez procéder avec les étapes suivantes.

CentOS/RHEL 7 ou 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-rsa

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

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

Pour utiliser cette bibliothèque Lua avec NGINX, assurez-vous que nginx-module-lua est installé.

Ce document décrit lua-resty-rsa v1.1.1 publié le 09 novembre 2024.


Cette bibliothèque nécessite une version d'nginx avec OpenSSL, le module ngx_lua, et LuaJIT.

Synopsis

    # nginx.conf:

    server {
        location = /test {
            content_by_lua_file conf/test.lua;
        }
    }

    -- conf/test.lua:

    local resty_rsa = require "resty.rsa"
    local rsa_public_key, rsa_priv_key, err = resty_rsa:generate_rsa_keys(2048)
    if not rsa_public_key then
        ngx.say('generate rsa keys err: ', err)
    end

    ngx.say(rsa_public_key)
    --[[
    -----BEGIN RSA PUBLIC KEY-----
    MIIBCgKCAQEAuw4T755fepEyXTM66pzf6nv8NtnukQTMGnhmBFIFHp/P2vEpxjXU
    BBDUpzKkVFR3wuK9O1FNmRDAGNGYC0N/9cZNdhykA1NixJfKQzncN31VJTmNqJNZ
    W0x7H9ZGoh2aE0zCCZpRlC1Rf5rL0SVlBoQkn/n9LnYFwyLLIK5/d/y/NZVL6Z6L
    cyvga0zRajamLIjY0Dy/8YIwVV6kaSsHeRv2cOB03eam6gbhLGIz/l8wuJhIn1rO
    yJLQ36IOJymbbNmcC7+2hEQJP40qLvH7hZ1LaAkgQUHjfi8RvH2T1Jmce7XGPxCo
    Ed0yfeFz+pL1KeSWNey6cL3N5hJZE8EntQIDAQAB
    -----END RSA PUBLIC KEY-----
    ]]--

    ngx.say(rsa_priv_key)
    --[[
    -----BEGIN RSA PRIVATE KEY-----
    MIIEpAIBAAKCAQEAuw4T755fepEyXTM66pzf6nv8NtnukQTMGnhmBFIFHp/P2vEp
    xjXUBBDUpzKkVFR3wuK9O1FNmRDAGNGYC0N/9cZNdhykA1NixJfKQzncN31VJTmN
    qJNZW0x7H9ZGoh2aE0zCCZpRlC1Rf5rL0SVlBoQkn/n9LnYFwyLLIK5/d/y/NZVL
    6Z6Lcyvga0zRajamLIjY0Dy/8YIwVV6kaSsHeRv2cOB03eam6gbhLGIz/l8wuJhI
    n1rOyJLQ36IOJymbbNmcC7+2hEQJP40qLvH7hZ1LaAkgQUHjfi8RvH2T1Jmce7XG
    PxCoEd0yfeFz+pL1KeSWNey6cL3N5hJZE8EntQIDAQABAoIBAGim1ayIFK8EMQNH
    uDyui/Aqcc9WWky0PGTK23irUsXxb1708gQ89WNY70Cj6qBrqZ1VMb3QHPP4FSFN
    kh0rJJoi2g+ssm5R5r5KlhTKeFRrQInVC1Y3KhUUUwZa4aWtnhgSJ7Urq1yVhjU4
    K7PVkhH1OHBwcp/d1Bd6jd65AgPkY63P+WpcARJkClmQ1RhgoRwThyJdpKrV4/gO
    ha0AUGlJNRNvRwiZxP0zaI5C8RdrG96SnVpeYOcD0z/M1HVlkoYMXsXLKttwLfpK
    88Igtm6ZJwRpfuMF5VA+9hHaYGCBdGz0B/rMp2fc+EtrOavYQGrWIWi2RL1Qk6Rt
    BUyeTgECgYEA9anj4n/cak1MT+hbNFsL31mJXryl1eVNjEZj/iPMztpdS15CmFgj
    Kjr9UuintjSiK7Is43nZUWWyP1XQjRhVi2uP7PRIv92QNl/YteWD6tYCInJHKe2J
    QqYyZrElezsdayXb5DK6bi1UIYYji90g79N7x6pOR0UnQNQUXTv+Y8ECgYEAwuzl
    6Ez4BSXIIL9NK41jfNMa73Utfl5oO1f6mHM2KbILqaFE76PSgEeXDbOKdcjCbbqC
    KCGjwyPd+Clehg4vkYXTq1y2SQGHwfz7DilPSOxhPY9ND7lGbeNzDUK4x8xe52hd
    MWKdgqeqCK83e5D0ihzRiMah8dbxmlfLAOZ3sPUCgYEA0dT9Czg/YqUHq7FCReQG
    rg3iYgMsexjTNh/hxO97PqwRyBCJPWr7DlU4j5qdteobIsubv+kSEI6Ww7Ze3kWM
    u/tyAeleQlPTnD4d8rBKD0ogpJ+L3WpBNaaToldpNmr149GAktgpmXYqSEA1GIAW
    ZAL11UPIfOO6dYswobpevYECgYEApSosSODnCx2PbMgL8IpWMU+DNEF6sef2s8oB
    aam9zCi0HyCqE9AhLlb61D48ZT8eF/IAFVcjttauX3dWQ4rDna/iwgHF5yhnyuS8
    KayxJJ4+avYAmwEnfzdJpoPRpGI0TCovRQhFZI8C0Wb+QTJ7Mofmt9lvIUc64sff
    GD0wT/0CgYASMf708dmc5Bpzcis++EgMJVb0q+ORmWzSai1NB4bf3LsNS6suWNNU
    zj/JGtMaGvQo5vzGU4exNkhpQo8yUU5YbHlA8RCj7SYkmP78kCewEqxlx7dbcuj2
    LAPWpiDca8StTfEphoKEVfCPHaUk0MlBHR4lCrnAkEtz23vhZKWhFw==
    -----END RSA PRIVATE KEY-----
    ]]--

    local pub, err = resty_rsa:new({ public_key = rsa_public_key })
    if not pub then
        ngx.say("new rsa err: ", err)
        return
    end
    local encrypted, err = pub:encrypt("hello")
    if not encrypted then
        ngx.say("failed to encrypt: ", err)
        return
    end
    ngx.say("encrypted length: ", #encrypted)

    local priv, err = resty_rsa:new({ private_key = rsa_priv_key })
    if not priv then
        ngx.say("new rsa err: ", err)
        return
    end
    local decrypted = priv:decrypt(encrypted)
    ngx.say(decrypted == "hello")

    local algorithm = "SHA256"
    local priv, err = resty_rsa:new({ private_key = rsa_priv_key, algorithm = algorithm })
    if not priv then
        ngx.say("new rsa err: ", err)
        return
    end

    local str = "hello"
    local sig, err = priv:sign(str)
    if not sig then
        ngx.say("failed to sign:", err)
        return
    end
    ngx.say("sig length: ", #sig)

    local pub, err = resty_rsa:new({ public_key = rsa_public_key, algorithm = algorithm })
    if not pub then
        ngx.say("new rsa err: ", err)
        return
    end
    local verify, err = pub:verify(str, sig)
    if not verify then
        ngx.say("verify err: ", err)
        return
    end
    ngx.say(verify)

Méthodes

Pour charger cette bibliothèque,

  1. vous devez spécifier le chemin de cette bibliothèque dans la directive lua_package_path de ngx_lua. Par exemple, lua_package_path "/path/to/lua-resty-rsa/lib/?.lua;;";.
  2. vous utilisez require pour charger la bibliothèque dans une variable locale Lua :
    local rsa = require "resty.rsa"

generate_rsa_keys

syntax: public_key, private_key, err = rsa:generate_rsa_keys(bits, in_pkcs8_fmt)

Génère une clé publique rsa et une clé privée en spécifiant le nombre de bits. Le in_pkcs8_fmt est optionnel. Si in_pkcs8_fmt est vrai, la clé privée générée est au format PKCS#8 et la clé publique est au format PKIX, qui commence par -----BEGIN PUBLIC ou -----BEGIN PRIVATE. Sinon, les clés générées sont au format PKCS#1, qui commence par -----BEGIN RSA.

new

syntax: obj, err = rsa:new(opts)

Crée une nouvelle instance d'objet rsa en spécifiant une table d'options opts.

La table d'options accepte les options suivantes :

  • public_key Spécifie la clé publique rsa.
  • private_key Spécifie la clé privée rsa.
  • password Spécifie le mot de passe pour lire la clé rsa.
  • key_type Spécifie le type de clé donnée. Par défaut, le type sera détecté à partir de la valeur de la clé.
valeur de key_type signification
rsa.KEY_TYPE.PKCS1 La clé d'entrée est au format PKCS#1 (commence généralement par -----BEGIN RSA PUBLIC).
rsa.KEY_TYPE.PKIX La clé d'entrée est au format PKIX (commence généralement par -----BEGIN PUBLIC).
-- crée un objet rsa avec une clé publique au format PKIX
local resty_rsa = require "resty.rsa"
local pub, err = resty_rsa:new({
    public_key = RSA_PKCS8_PUB_KEY,
    key_type = resty_rsa.KEY_TYPE.PKIX,
})

-- crée un objet rsa avec une clé privée au format pkcs#8
local priv, err = resty_rsa:new({
    private_key = RSA_PKCS8_PASS_PRIV_KEY,
    key_type = resty_rsa.KEY_TYPE.PKCS8,
    -- vous devez spécifier le mot de passe si la clé est chiffrée
    -- password = "foobar",
})
  • padding Spécifie le mode de remplissage lorsque vous souhaitez chiffrer/déchiffrer.
  • algorithm Spécifie l'algorithme de hachage lorsque vous souhaitez signer/vérifier.
valeur de algorithm signification
md4/MD4/RSA-MD4/md4WithRSAEncryption hachage avec md4
md5/MD5/RSA-MD5/md5WithRSAEncryption/ssl3-md5 hachage avec md5
ripemd160/RIPEMD160/RSA-RIPEM160/ripemd160WithRSA/rmd160 hachage avec ripemd160
sha1/SHA1/RSA-SHA1/sha1WithRSAEncryption/ssl3-sha1 hachage avec sha1
sha224/SHA224/RSA-SHA224/sha224WithRSAEncryption hachage avec sha224
sha256/SHA256/RSA-SHA256/sha256WithRSAEncryption hachage avec sha256
sha384/SHA384/RSA-SHA384/sha384WithRSAEncryption hachage avec sha384
sha512/SHA512/RSA-SHA512/sha512WithRSAEncryption hachage avec sha512

encrypt

syntax: encrypted, err = obj:encrypt(str)

decrypt

syntax: decrypted, err = obj:decrypt(encrypted)

sign

syntax: signature, err = obj:sign(str)

verify

syntax: ok, err = obj:verify(str, signature)

Performance

J'ai obtenu le résultat :

encrypt for 50000 times cost : 2.4110000133514s
decrypt for 50000 times cost : 57.196000099182s
sign for 50000 times cost : 59.169999837875s
verify for 50000 times cost : 1.8230001926422s

lorsque j'ai exécuté ce script.

local resty_rsa = require "resty.rsa"
local algorithm = "SHA256"

local rsa_public_key, rsa_priv_key, err = resty_rsa:generate_rsa_keys(2048)
if not rsa_public_key then
    ngx.say("generate rsa keys err: ", err)
    return
end

local pub, err = resty_rsa:new({
    public_key = rsa_public_key,
    padding = resty_rsa.PADDING.RSA_PKCS1_PADDING,
    algorithm = algorithm,
})
if not pub then
    ngx.say("new rsa err: ", err)
    return
end

local priv, err = resty_rsa:new({
    private_key = rsa_priv_key,
    padding = resty_rsa.PADDING.RSA_PKCS1_PADDING,
    algorithm = algorithm,
})
if not priv then
    ngx.say("new rsa err: ", err)
    return
end

local num = 5 * 10000

local str = "hello test"

local encrypted, decrypted, err, sig, verify

ngx.update_time()
local now = ngx.now()

local function timer(operation)
    ngx.update_time()
    local t = ngx.now()

    ngx.say(operation, " for ", num, " times cost : ", t - now, "s")
    now = t
end

for _ = 1, num do
    encrypted, err = pub:encrypt(str)
    if not encrypted then
        ngx.say("failed to encrypt: ", err)
        return
    end
end

timer("encrypt")

for _ = 1, num do
    decrypted = priv:decrypt(encrypted)
    if decrypted ~= str then
        ngx.say("decrypted not match")
        return
    end
end

timer("decrypt")

for _ = 1, num do
    sig, err = priv:sign(str)
    if not sig then
        ngx.say("failed to sign:", err)
        return
    end
end

timer("sign")

for _ = 1, num do
    verify, err = pub:verify(str, sig)
    if not verify then
        ngx.say("verify err: ", err)
        return
    end
end

timer("verify")

Étapes de publication

  1. mettez à jour le _VERSION dans lib/resty/rsa.lua
  2. mettez à jour le version dans dist.ini
  3. renommez le rockspec actuel à la nouvelle version et mettez à jour la référence dans celui-ci.
  4. taguez la nouvelle version
  5. opm upload

Voir aussi

GitHub

Vous pouvez trouver des conseils de configuration supplémentaires et de la documentation pour ce module dans le dépôt GitHub pour nginx-module-rsa.