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 
#include 
#include 
#include 
#include 
 
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所有源码,以供参考!

你可能感兴趣的:(Linux下RSA的lua实现)