openresty-rsa加解密庫(kù)

最近在項(xiàng)目中用到OpenResty做服務(wù)端的接口糖荒,其中接口認(rèn)證方面又用到了RSA算法進(jìn)行加解密。但是目前OpenResty并沒有官方的rsa模塊寂嘉,只有doujiang24前輩提供的lua-resty-rsa庫(kù)泉孩,但是該庫(kù)只支持公鑰加密私鑰解密寓搬,對(duì)私鑰加密公鑰解密卻不支持,為了完善這一方面的缺陷句喷,開發(fā)了自己的rsa加解密庫(kù)唾琼。
因?yàn)閘ua相關(guān)的RSA加解密庫(kù)比較少锡溯,而C和C++相關(guān)的RSA加解密庫(kù)卻比較多哑姚,因此萌生了通過LuaJit的FFI 拓展庫(kù)來調(diào)用C或C++實(shí)現(xiàn)來封裝成Lua 的RSA庫(kù)。經(jīng)過谷歌終于找到了一個(gè)很符合要求的實(shí)現(xiàn)方法:
http://hayageek.com/rsa-encryption-decryption-openssl-c/

下面就來說說整個(gè)開發(fā)詳細(xì)流程

安裝OpenSSL

RSA加密和解密的公鑰私鑰由OpenSSL生成倡蝙。在Ubuntu下寺鸥,安裝OpenSSL通過以下兩條命令可以完成:

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

生成公鑰和私鑰

-- 生成 RSA 私鑰(傳統(tǒng)格式的,PKCS#1標(biāo)準(zhǔn))
openssl genrsa -out rsa_private_key.pem 1024
-- 將傳統(tǒng)格式的私鑰轉(zhuǎn)換成 PKCS#8 格式的(JAVA需要使用的私鑰需要經(jīng)過PKCS#8編碼,而本次在項(xiàng)目作為接口使用Lua編寫,如不需要這一步其實(shí)可以略過)
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

編譯動(dòng)態(tài)鏈接庫(kù)

參考上面給的鏈接躬贡,要封裝的RSA加解密C語(yǔ)言實(shí)現(xiàn)版如下:
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庫(kù)

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

使用rsa.so庫(kù)

生成的動(dòng)態(tài)鏈接庫(kù)放到usr/lib目錄下就能使用了,以下使用rsa.so封裝了一個(gè)lua版的rsa加解密庫(kù)

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)
    --存放加密結(jié)果
    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)
    --存放解密結(jié)果
    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)
    --存放加密結(jié)果
    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)
    --存放解密結(jié)果
    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加解密第三方庫(kù)就制作完成了闯第,支持公鑰加密私鑰解密缀拭,也支持私鑰加密公鑰解密。下面貼出本人的測(cè)試代碼:

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------')

項(xiàng)目已托管到Github,歡迎star或fork褐荷,也歡迎提出改進(jìn)意見叛甫。
傳送門:lua-rsa

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末其监,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子抖苦,更是在濱河造成了極大的恐慌,老刑警劉巖鼎俘,帶你破解...
    沈念sama閱讀 211,561評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件辩涝,死亡現(xiàn)場(chǎng)離奇詭異怔揩,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)伏伐,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,218評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門藐翎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來实幕,“玉大人昆庇,你說我怎么就攤上這事≌海” “怎么了表蝙?”我有些...
    開封第一講書人閱讀 157,162評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵昼扛,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我抄谐,道長(zhǎng)蛹含,這世上最難降的妖魔是什么塞颁? 我笑而不...
    開封第一講書人閱讀 56,470評(píng)論 1 283
  • 正文 為了忘掉前任酷窥,我火速辦了婚禮,結(jié)果婚禮上蓬推,老公的妹妹穿的比我還像新娘沸伏。我一直安慰自己,他們只是感情好毅糟,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,550評(píng)論 6 385
  • 文/花漫 我一把揭開白布喇肋。 她就那樣靜靜地躺著,像睡著了一般迹辐。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上右核,一...
    開封第一講書人閱讀 49,806評(píng)論 1 290
  • 那天贺喝,我揣著相機(jī)與錄音,去河邊找鬼躏鱼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛染苛,可吹牛的內(nèi)容都是我干的鹊漠。 我是一名探鬼主播,決...
    沈念sama閱讀 38,951評(píng)論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼茶行,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼躯概!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起畔师,我...
    開封第一講書人閱讀 37,712評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤娶靡,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后看锉,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體姿锭,經(jīng)...
    沈念sama閱讀 44,166評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,510評(píng)論 2 327
  • 正文 我和宋清朗相戀三年伯铣,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了呻此。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,643評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖郑兴,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情览效,我是刑警寧澤锤灿,帶...
    沈念sama閱讀 34,306評(píng)論 4 330
  • 正文 年R本政府宣布状囱,位于F島的核電站,受9級(jí)特大地震影響叨粘,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜冻晤,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,930評(píng)論 3 313
  • 文/蒙蒙 一攘轩、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧笨篷,春花似錦、人聲如沸腺晾。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,745評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春哈误,著一層夾襖步出監(jiān)牢的瞬間蜜自,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,983評(píng)論 1 266
  • 我被黑心中介騙來泰國(guó)打工婆殿, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留怕磨,地道東北人肠鲫。 一個(gè)月前我還...
    沈念sama閱讀 46,351評(píng)論 2 360
  • 正文 我出身青樓帜消,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子生闲,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,509評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容