硬件里带的是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.so
和libcrypto.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.so
和libcrypto.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所有源码,以供参考!