• Stars
    star
    265
  • Rank 153,433 (Top 4 %)
  • Language
    Lua
  • License
    MIT License
  • Created over 9 years ago
  • Updated over 2 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

RSA encrypt/decrypt & sign/verify for OpenResty/LuaJIT

Name

lua-resty-rsa - RSA functions for LuaJIT

Status

This library is considered production ready.

Build status: pass

Description

This library requires an nginx build with OpenSSL, the ngx_lua module, and LuaJIT.

Synopsis

    # nginx.conf:

    lua_package_path "/path/to/lua-resty-rsa/lib/?.lua;;";

    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)

Methods

To load this library,

  1. you need to specify this library's path in ngx_lua's lua_package_path directive. For example, lua_package_path "/path/to/lua-resty-rsa/lib/?.lua;;";.
  2. you use require to load the library into a local Lua variable:
    local rsa = require "resty.rsa"

generate_rsa_keys

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

Generate rsa public key and private key by specifying the number of bits. The in_pkcs8_fmt is optional. If in_pkcs8_fmt is true, the generated priviate key is in PKCS#8 format and the public key is in PKIX format, which start with -----BEGIN PUBLIC or -----BEGIN PRIVATE. Otherwise the generated keys are in PKCS#1 format, which start with -----BEGIN RSA.

new

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

Creates a new rsa object instance by specifying an options table opts.

The options table accepts the following options:

  • public_key Specifies the public rsa key.
  • private_key Specifies the private rsa key.
  • password Specifies the password to read rsa key.
  • key_type Specifies the type of given key. By default the type will be detected from the value of the key.
key_type value meaning
rsa.KEY_TYPE.PKCS1 The input key is in PKCS#1 format(usually starts with -----BEGIN RSA PUBLIC).
rsa.KEY_TYPE.PKIX The input key is in PKIX format(usually starts with -----BEGIN PUBLIC).
-- creates a rsa object with PKIX format of public key
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,
})

-- creates a rsa object with pkcs#8 format of private key
local priv, err = resty_rsa:new({
    private_key = RSA_PKCS8_PASS_PRIV_KEY,
    key_type = resty_rsa.KEY_TYPE.PKCS8,
    -- you need to specify the password if the pkey is encrypted
    -- password = "foobar",
})
  • padding Specifies the padding mode when you want to encrypt/decrypt.
  • algorithm Specifies the digest algorithm when you want to sign/verify.
algorithm value meaning
md4/MD4/RSA-MD4/md4WithRSAEncryption digest with md4
md5/MD5/RSA-MD5/md5WithRSAEncryption/ssl3-md5 digest with md5
ripemd160/RIPEMD160/RSA-RIPEM160/ripemd160WithRSA/rmd160 digest with ripemd160
sha1/SHA1/RSA-SHA1/sha1WithRSAEncryption/ssl3-sha1 digest with sha1
sha224/SHA224/RSA-SHA224/sha224WithRSAEncryption digest with sha224
sha256/SHA256/RSA-SHA256/sha256WithRSAEncryption digest with sha256
sha384/SHA384/RSA-SHA384/sha384WithRSAEncryption digest with sha384
sha512/SHA512/RSA-SHA512/sha512WithRSAEncryption digest with 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

I got the result:

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

when I run this 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")

Author

Dejiang Zhu (doujiang24) [email protected]

Zexuan Luo (spacewander)

Release Steps

  1. update the _VERSION in lib/resty/rsa.lua
  2. update the version in dist.ini
  3. rename current rockspec to the new version and update the reference in it.
  4. tag the new version
  5. opm upload

Copyright and License

This module is licensed under the MIT license.

Copyright (C) 2014-2018, by Dejiang Zhu (doujiang24) [email protected] Copyright (C) 2018-, by Zexuan Luo (spacewander)

All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

  • Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

  • Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

See Also

More Repositories

1

explore-flask-zh

Explore Flask中文翻译。关于flask的一些最佳实践。
HTML
399
star
2

debugger-utils

Utils collection for extending gdb with python
Python
57
star
3

luafilesystem

Reimplement luafilesystem via LuaJIT FFI
Lua
57
star
4

SystemTapBeginnersGuide_zh

SystemTap新手指南中文翻译。翻译自https://sourceware.org/systemtap/SystemTap_Beginners_Guide
32
star
5

blogWithMarkdown

write blogs in Markdown
25
star
6

boltcli

boltcli is the redis-cli for boltdb with Lua script support
Go
25
star
7

openresty-vim

A vim plugin offers nginx/openresty syntax highlight and directives completion
Vim Script
24
star
8

quick

Like curl, but for HTTP over QUIC
Go
20
star
9

lua-resty-base-encoding

A faster alternative to base64 encoding and provides missing base encoding for OpenResty application
C
15
star
10

GSoC

[Abandoned] a commandline tool which helps you search/filter projects in Google Summer of Code
JavaScript
15
star
11

luacov-console

Combine luacov with your development cycle and CI
Lua
14
star
12

find

Wrap find(1) with terminal UI.
Python
14
star
13

pretty-openresty-docs

This project is archived because I don't use dash/zeal anymore
Python
13
star
14

lua-resty-murmurhash3

The Lua binding of murmurhash3 via LuaJIT FFI
C++
13
star
15

ngx_http_example_or_module

C
11
star
16

luabenchmark

A tiny library for benchmark.
Lua
9
star
17

lua-resty-mime-sniff

Sniff the real MIME type of given data in your OpenResty app
Lua
9
star
18

go-suffix-tree

A suffix-tree index implemented in go
Go
7
star
19

posixpsutil

A ruby port of psutil, available on Linux yet. Documents:
Ruby
6
star
20

awesome-systemtap

A growing list of high-quality systemtap resources and fantastic systemtap collections.
5
star
21

EasyTable

EasyTable 是我的C++大作业。用QT做的简单的制表程序。外表简陋,功能有限。第一次在github上展示自己的程序,请多指教!
C++
4
star
22

vim-textobj-lua

Python
3
star
23

lmdbcli

lmdbcli is the redis-cli for lmdb with Lua script support
Go
3
star
24

P2PMoney

软件架构大作业 - P2P贷款平台系统
Ruby
2
star
25

AlgorithmAndDataStructure

Implement algorithms and data structures in different languages
JavaScript
2
star
26

scandisk

A simple tool to generate html report for disk usage.
Go
1
star
27

little-lua-glob

A little implementation of glob in Lua
Lua
1
star
28

rails-bootstrap-progressbar

build Bootstrap 3 progress bar quickly in rails
Ruby
1
star
29

git-replay

Go
1
star
30

Intel_MKL_sample_collection

The collection of sample used Intel Math Kernel Library
C
1
star
31

kafka-cli

Fork from github.com/shafreeck/kafka-cli. The origin one doesn't continue so I fork it. Have no plan to submit back so I don't use the Fork button to fork it.
Go
1
star