Linux下RSA的lua实现

硬件里带的是MIPS的Linux,里面安装了Luajit, 需要实现RSA的功能。分2部分来尝试:

  • 在CentOS下使用lua实现
  • 在MIPS下使用lua实现

0. 下载openssl

我们这里实现的RSA基于openssl,所以先下载openssl.
在CentOS下下载openssl:

$git clone git://git.openssl.org/openssl.git

1. 编译openssl

CentOS是使用云服务,自带了openssl,执行查询版本命令

$openssl version
OpenSSL 1.0.2k-fips  26 Jan 2017

先考虑CentOS上交叉编译mips对应的so文件,先在下载的openssl根目录下执行config生成Makefile文件。

$./Configure linux-mips32 no-asm shared --prefix=/root/luatest/openssl

linux-mips32是因为我这边硬件的mips系统是32位,你需要选择自己正确的平台,支持的平台名称可以用./Configure LIST来查询.
另外prefix表示最后编译出来的so文件保存的目录

这个Makefile文件并不能直接用,需要修改:
找到 CROSS_COMPILE=改成CROSS_COMPILE= CROSS_COMPILE= /root/luatest/mips-gcc/bin/mips-linux-gnu-

其中 /root/luatest/mips-gcc/就是我这里安装交叉编译环境的根目录,开发者需要替换成自己的目录。

最后再执行make

$make
$make install

make成功后会在/root/luatest/openssl生成相应的不少文件,我们暂时只需要lib下的libcrypto.so,libcrypto.so.1.1,libssl.so,libssl.so.1.1

2. RSA加解密的C实现

在网上能找到很多种RSA的C实现,我这里用的是以下简单实现(通过 OpenSSL 调用)

/*******************************************************************************************
 *
 *  Copyright (C) Ravishanker Kusuma / ecofast.  All Rights Reserved.
 *
 *  File: rsautils.c 
 *  Date: 2017/12/01
 *  Desc: RSA Encryption & Decryption utils with OpenSSL in C
 *
 *  Thks: http://hayageek.com/rsa-encryption-decryption-openssl-c/
 *
 *  Compilation Command: gcc rsautils.c -fPIC -shared -lssl -lcrypto -o librsa.so
 *******************************************************************************************/

#include <openssl/pem.h>
#include <openssl/ssl.h>
#include <openssl/rsa.h>
#include <openssl/evp.h>
#include <openssl/bio.h>
 
const int padding = RSA_PKCS1_OAEP_PADDING;
 
int public_encrypt(unsigned char* data, int data_len, unsigned char* key, unsigned char* encrypted)
{
    int ret = -1;
    BIO* keybio = BIO_new_mem_buf(key, -1);
    if (keybio != NULL)
    {
        RSA* rsa = NULL;
        rsa = PEM_read_bio_RSA_PUBKEY(keybio, &rsa, NULL, NULL);
        if (rsa != NULL)
        {
            ret = RSA_public_encrypt(data_len, data, encrypted, rsa, padding);
            RSA_free(rsa);
        }
        BIO_free_all(keybio);
    }
    return ret;
}

int private_decrypt(unsigned char* enc_data, int data_len, unsigned char* key, unsigned char* decrypted)
{
    int ret = -1;
    BIO* keybio = BIO_new_mem_buf(key, -1);
    if (keybio != NULL)
    {
        RSA* rsa = NULL;
        rsa = PEM_read_bio_RSAPrivateKey(keybio, &rsa, NULL, NULL);
        if (rsa != NULL)
        {
            ret = RSA_private_decrypt(data_len, enc_data, decrypted, rsa, padding);
            RSA_free(rsa);
        }
        BIO_free_all(keybio);
    }
    return ret;
}

3. 编译RSAUtils.c

示例自带了编译命令gcc rsautils.c -fPIC -shared -lssl -lcrypto -o librsa.so,我们这里编译需要注意以下几个改动。

  • gcc 改成 /root/luatest/mips-gcc/bin/mips-linux-gnu-gcc,因为是交叉编译
  • 需要吧openssl的h文件加到INCLUDE的path里,其中XXXX是你的openssl相关h文件所在的目录
$export C_INCLUDE_PATH=XXXX:$C_INCLUDE_PATH
  • 需要把libcrypto.so,libcrypto.so.1.1,libssl.so,libssl.so.1.1 拷贝到/root/luatest/mips-gcc/lib/gcc/mips-linux-gnu/4.7.2 这样执行-l参数的时候才能找到libsssl.solibcrypto.so
    最后执行后会生成librsa.so是我们需要的文件。

4. 通过lua调用RASUtils.c定义的2个函数

上一步生成的librsa.so最终是需要发布到硬件的mips linux下才能验证,在这之前,我们先在CentOS下验证以下lua调用的过程。
所以还需要再生成一个so文件,这个是针对CentOS的。命令就是:

$gcc rsautils.c -fPIC -shared -lssl3 -lcrypto -o librsa_centos.so

其中-lssl3 -lcrypt 是根据CentOS现有安装的openssl在/user/lib64下的libssl3.solibcrypto.so来决定的

继续新建2个lua文件rsautils.lua和rsatest.lua,完全是拷贝过来的。

local ffi = require('ffi')
local rsa = ffi.load('./librsa.so')
local basexx = require('basexx')

local _M = {}

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 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-----]]

function _M.rsa_encrypt(plainText)
    local c_str = ffi.new("char[?]", 1024 / 8)
    ffi.copy(c_str, plainText)
    local pub = ffi.new("char[?]", #RSA_PUBLIC_KEY)
    ffi.copy(pub, RSA_PUBLIC_KEY)
    local cipherText = ffi.new("char[?]", 2048)
    local cipherLen = rsa.public_encrypt(c_str, #plainText, pub, cipherText)
    if cipherLen == -1 then
        return -1, nil
    end    
    return cipherLen, basexx.to_base64(ffi.string(cipherText, cipherLen))
end

function _M.rsa_decrypt(cipherLen, b64cipherText)
    local c_str = ffi.new("char[?]", cipherLen + 1)
    ffi.copy(c_str, basexx.from_base64(b64cipherText))
    local pri = ffi.new("char[?]", #RSA_PRIV_KEY)
    ffi.copy(pri, RSA_PRIV_KEY)
    local plainText = ffi.new("char[?]", 2048)
    local plainLen = rsa.private_decrypt(c_str, cipherLen, pri, plainText)
    if plainLen == -1 then
        return nil
    end    
    return ffi.string(plainText, plainLen)
end

return _M
local rsautils = require('rsautils')

local src_str = "my name is ecofast小0胡!!"
local cipherLen, cipher = rsautils.rsa_encrypt(src_str)
if cipherLen ~= -1 then
    local plain = rsautils.rsa_decrypt(cipherLen, cipher)    
    print("src text:", plain)
        
    print("=========================")
    local txt2 = rsautils.rsa_decrypt(128, "aeMIl3wyPP/DIJLudq49k1YeK9o6QhrScyjy2JHcJ7CmFOpQAmbwLxOe/rWigSYeWbAMUw2MB1KTIsool9zEuOSaoiZtgjfpDvf5g/MZUjPAmDofKVutG9xJNonVoK6usHKVcR7wozq/tJ8h/CUWyKGHnLgkxvU3ObbhLPm/wwI=")    
    print("src text2:", txt2)    
end

另外还有一个'basexx.lua'用于base64函数的。
最后在CentOS上运行可以成功:

$luajit rsatest.lua
src text:   my name is ecofast小0胡!!
=========================
src text2:  my name is ecofast小0胡!!

最后附上相关示例demo所有源码,以供参考!

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

推荐阅读更多精彩内容