openresty-rsa加解密库

最近在项目中用到OpenResty做服务端的接口,其中接口认证方面又用到了RSA算法进行加解密。但是目前OpenResty并没有官方的rsa模块,只有doujiang24前辈提供的lua-resty-rsa库,但是该库只支持公钥加密私钥解密,对私钥加密公钥解密却不支持,为了完善这一方面的缺陷,开发了自己的rsa加解密库。
因为lua相关的RSA加解密库比较少,而C和C++相关的RSA加解密库却比较多,因此萌生了通过LuaJit的FFI 拓展库来调用C或C++实现来封装成Lua 的RSA库。经过谷歌终于找到了一个很符合要求的实现方法:
http://hayageek.com/rsa-encryption-decryption-openssl-c/

下面就来说说整个开发详细流程

安装OpenSSL

RSA加密和解密的公钥私钥由OpenSSL生成。在Ubuntu下,安装OpenSSL通过以下两条命令可以完成:

sudo apt-get install openssl
sudo apt-get install libssl-dev

生成公钥和私钥

-- 生成 RSA 私钥(传统格式的,PKCS#1标准)
openssl genrsa -out rsa_private_key.pem 1024
-- 将传统格式的私钥转换成 PKCS#8 格式的(JAVA需要使用的私钥需要经过PKCS#8编码,而本次在项目作为接口使用Lua编写,如不需要这一步其实可以略过)
openssl pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt
-- 生成 RSA 公钥
openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem

编译动态链接库

参考上面给的链接,要封装的RSA加解密C语言实现版如下:
rsa.c文件

#include <openssl/pem.h>
#include <openssl/ssl.h>
#include <openssl/rsa.h>
#include <openssl/evp.h>
#include <openssl/bio.h>
#include <openssl/err.h>
#include <stdio.h>
 
int padding = RSA_PKCS1_PADDING;
 
RSA * createRSA(unsigned char * key,int public)
{
    RSA *rsa= NULL;
    BIO *keybio ;
    keybio = BIO_new_mem_buf(key, -1);
    if (keybio==NULL)
    {
        printf( "Failed to create key BIO");
        return 0;
    }
    if(public)
    {
        rsa = PEM_read_bio_RSA_PUBKEY(keybio, &rsa,NULL, NULL);
    }
    else
    {
        rsa = PEM_read_bio_RSAPrivateKey(keybio, &rsa,NULL, NULL);
    }
    if(rsa == NULL)
    {
        printf( "Failed to create RSA");
    }
 
    return rsa;
}
 
int public_encrypt(unsigned char * data,int data_len,unsigned char * key, unsigned char *encrypted)
{
    RSA * rsa = createRSA(key,1);
    int result = RSA_public_encrypt(data_len,data,encrypted,rsa,padding);
    return result;
}
int private_decrypt(unsigned char * enc_data,int data_len,unsigned char * key, unsigned char *decrypted)
{
    RSA * rsa = createRSA(key,0);
    int  result = RSA_private_decrypt(data_len,enc_data,decrypted,rsa,padding);
    return result;
}
 
 
int private_encrypt(unsigned char * data,int data_len,unsigned char * key, unsigned char *encrypted)
{
    RSA * rsa = createRSA(key,0);
    int result = RSA_private_encrypt(data_len,data,encrypted,rsa,padding);
    return result;
}
int public_decrypt(unsigned char * enc_data,int data_len,unsigned char * key, unsigned char *decrypted)
{
    RSA * rsa = createRSA(key,1);
    int  result = RSA_public_decrypt(data_len,enc_data,decrypted,rsa,padding);
    return result;
}
 
void printLastError(char *msg)
{
    char * err = malloc(130);;
    ERR_load_crypto_strings();
    ERR_error_string(ERR_get_error(), err);
    printf("%s ERROR: %s\n",msg, err);
    free(err);
}

在ubuntu下通过以下命令来生成.so库

# gcc rsa.c -fPIC -shared -o librsa.so

使用rsa.so库

生成的动态链接库放到usr/lib目录下就能使用了,以下使用rsa.so封装了一个lua版的rsa加解密库

module("rsa", package.seeall)
local ffi = require('ffi')
 
local rsa = ffi.load('rsa')
 
ffi.cdef [[
int public_encrypt(unsigned char * data,int data_len,unsigned char * key, unsigned char *encrypted);
int private_decrypt(unsigned char * enc_data,int data_len,unsigned char * key, unsigned char *decrypted);
 
int private_encrypt(unsigned char * data,int data_len,unsigned char * key, unsigned char *encrypted);
int public_decrypt(unsigned char * enc_data,int data_len,unsigned char * key, unsigned char *decrypted);
]]
 
local _M = { _VERSION = '1.0' }
 
--公钥加密
function _M.public_encrypt(msg, publicKey)
    local c_str = ffi.new("char[?]", 1024 / 8)
    ffi.copy(c_str, msg)
    local pub = ffi.new("char[?]", #publicKey)
    ffi.copy(pub, publicKey)
    --存放加密结果
    local encrypt = ffi.new("char[?]", 2048)
    local ret = rsa.public_encrypt(c_str, #msg, pub, encrypt)
    if ret == -1 then
        return nil
    end
    return ffi.string(encrypt,ret)
end
 
--私钥解密
function _M.private_decrypt(msg, privateKey)
    local c_str = ffi.new("char[?]", 1024 / 8)
    ffi.copy(c_str, msg)
    local pri = ffi.new("char[?]", #privateKey)
    ffi.copy(pri, privateKey)
    --存放解密结果
    local decrypt = ffi.new("char[?]", 2048)
    local ret = rsa.private_decrypt(c_str, #msg, pri, decrypt)
    if ret == -1 then
        return nil
    end
    return ffi.string(decrypt,ret)
end
 
--私钥加密
function _M.private_encrypt(msg, privateKey)
    local c_str = ffi.new("char[?]", 1024 / 8)
    ffi.copy(c_str, msg)
    local pri = ffi.new("char[?]", #privateKey)
    ffi.copy(pri, privateKey)
    --存放加密结果
    local encrypt = ffi.new("char[?]", 2048)
    local ret = rsa.private_encrypt(c_str, #msg, pri, encrypt)
    if ret == -1 then
        return nil
    end
    return ffi.string(encrypt,ret)
end
 
--公钥解密
function _M.public_decrypt(msg, publicKey)
    local c_str = ffi.new("char[?]", 1024 / 8)
    ffi.copy(c_str, msg)
    local pub = ffi.new("char[?]", #publicKey)
    ffi.copy(pub, publicKey)
    --存放解密结果
    local decrypt = ffi.new("char[?]", 2048)
    local ret = rsa.public_decrypt(c_str, #msg, pub, decrypt)
    if ret == -1 then
        return nil
    end
    return ffi.string(decrypt,ret)
end
 
return _M

就这样,本人的openresty rsa加解密第三方库就制作完成了,支持公钥加密私钥解密,也支持私钥加密公钥解密。下面贴出本人的测试代码:

local rsa = require "resty.rsa"
local RSA_PUBLIC_KEY = [[-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC3bTBJNQJjY6u7Y5b2eOWws0yW
CGuWPm6MGOSVan65wCrJa5p3q3sodQUDVPotjsknjLlje9E1F7Bx94ZuqTwkvAr6
ieLkgbbeqTCzeJ0AryUXiF3auxFSPdpBoD6nxtEeN8bZwfa/IYzdKyKlbhiQbUMN
qWgmxiPVwupwAML7RQIDAQAB
-----END PUBLIC KEY-----]]
local RSA_PRIV_KEY = [[-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQC3bTBJNQJjY6u7Y5b2eOWws0yWCGuWPm6MGOSVan65wCrJa5p3
q3sodQUDVPotjsknjLlje9E1F7Bx94ZuqTwkvAr6ieLkgbbeqTCzeJ0AryUXiF3a
uxFSPdpBoD6nxtEeN8bZwfa/IYzdKyKlbhiQbUMNqWgmxiPVwupwAML7RQIDAQAB
AoGAc4NXvUKc1mqWY9Q75cwNGlJQEMwMtPlsNN4YVeBTHjdeuqoBBQwA62GGXqrN
QpOBKl79ASGghob8n0j6aAY70PQqHSU4c06c7UlkeEvxJKlyUTO2UgnjjIHb2flR
uW8y3xmjpXAfwe50eAVMNhCon7DBc+XMF/paSVwiG8V+GAECQQDvosVLImUkIXGf
I2AJ2iSOUF8W1UZ5Ru68E8hJoVkNehk14RUFzTkwhoPHYDseZyEhSunFQbXCotlL
Ar5+O+lBAkEAw/PJXvi3S557ihDjYjKnj/2XtIa1GwBJxOliVM4eVjfRX15OXPR2
6shID4ZNWfkWN3fjVm4CnUS41+bzHNctBQJAGCeiF3a6FzA/0bixH40bjjTPwO9y
kRrzSYX89F8NKOybyfCMO+95ykhk1B4BF4lxr3drpPSAq8Paf1MhfHvxgQJBAJUB
0WNy5o+OWItJBGAr/Ne2E6KnvRhnQ7GFd8zdYJxXndNTt2tgSv2Gh6WmjzOYApjz
heC3jy1gkN89NCn+RrECQBTvoqFHfyAlwOGC9ulcAcQDqj/EgCRVkVe1IsQZenAe
rKCWlUaeIKeVkRz/wzb1zy9AVsPC7Zbnf4nrOxJ23mI=
-----END RSA PRIVATE KEY-----]]
 
ngx.say('-----公钥加密私钥解密 start------')
local str='i love lwl'
 
local encryptPubStr = rsa.public_encrypt(str, RSA_PUBLIC_KEY)
if not encryptPubStr then
ngx.say('pub encrypt failed')
end
local decryptPriStr=rsa.private_decrypt(encryptPubStr,RSA_PRIV_KEY)
if not decryptPriStr then
ngx.say('pri decrypt failed')
end
ngx.say('公钥加密私钥解密成功\n'..decryptPriStr)
ngx.say('-----公钥加密私钥解密 end------')
 
ngx.say('================================')
 
ngx.say('-----私钥加密公钥解密 start------')
local str='i like lwl'
 
local encryptPriStr = rsa.private_encrypt(str, RSA_PRIV_KEY)
if not encryptPriStr then
ngx.say('pri encrypt failed')
end
local decryptPubStr=rsa.public_decrypt(encryptPriStr,RSA_PUBLIC_KEY)
if not decryptPubStr then
ngx.say('pub decrypt failed')
end
ngx.say('公钥加密私钥解密成功\n'..decryptPubStr)
ngx.say('-----私钥加密公钥解密 end------')

项目已托管到Github,欢迎star或fork,也欢迎提出改进意见。
传送门:lua-rsa

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,539评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,594评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,871评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,963评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,984评论 6 393
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,763评论 1 307
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,468评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,357评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,850评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,002评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,144评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,823评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,483评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,026评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,150评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,415评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,092评论 2 355

推荐阅读更多精彩内容