Browse Source

add: 添加rsa库 https://gitee.com/openLuat/LuatOS/issues/I5EQW4

Wendal Chen 3 years ago
parent
commit
47cf5004a3
5 changed files with 243 additions and 0 deletions
  1. 151 0
      components/rsa/binding/luat_lib_rsa.c
  2. 55 0
      demo/rsa/main.lua
  3. 27 0
      demo/rsa/privkey.pem
  4. 9 0
      demo/rsa/public.pem
  5. 1 0
      luat/include/luat_libs.h

+ 151 - 0
components/rsa/binding/luat_lib_rsa.c

@@ -0,0 +1,151 @@
+/*
+@module  rsa
+@summary RSA加密解密
+@version 1.0
+@date    2022.11.03
+@demo    rsa
+@usage
+-- 在电脑上生成私钥和公钥, 当前最高支持4096bit, 一般来说2048bit就够用了
+-- openssl genrsa -out privkey.pem 2048
+-- openssl rsa -in privkey.pem -pubout -out public.pem
+-- privkey.pem 是解码用的, public.pem 是加密用的
+-- public.pem 一般放在设备端,上传时加密用, 服务器端使用privkey.pem解密,当然这取决于你的业务需要.
+
+local res = rsa.encrypt((io.readFile("/luadb/public.pem")), "abc")
+-- 打印结果
+log.info("rsa", "encrypt", res and #res or 0, res and res:toHex() or "")
+
+-- 下面是解密, 通常不会在设备端进行, 这里主要是演示用法, 会很慢
+if res then
+    -- 读取私钥, 然后解码数据
+    local dst = rsa.decrypt((io.readFile("/luadb/privkey.pem")), res, "")
+    log.info("rsa", "decrypt", dst and #dst or 0, dst and dst:toHex() or "")
+end
+*/
+
+#include "luat_base.h"
+#include "luat_malloc.h"
+#include "luat_crypto.h"
+
+#define LUAT_LOG_TAG "rs"
+#include "luat_log.h"
+
+#include "mbedtls/rsa.h"
+#include "mbedtls/pk.h"
+#include "mbedtls/entropy.h"
+#include "mbedtls/ctr_drbg.h"
+
+static int myrand( void *rng_state, unsigned char *output, size_t len ) {
+    luat_crypto_trng((char*)output, len);
+    return 0;
+}
+
+/*
+RSA加密
+@api rsa.encrypt(key, data)
+@string 公钥数据,仅支持PEM格式
+@string 待加密数据, 不能超过公钥位数的一半, 例如 2048bit的公钥, 只能加密128字节的数据
+@return string 加密成功后的数据,若失败会返回nil
+@usage
+-- 下面代码中的 "abc" 是待加密数据
+local res = rsa.encrypt((io.readFile("/luadb/public.pem")), "abc")
+-- 打印结果
+log.info("rsa", "encrypt", res and #res or 0, res and res:toHex() or "")
+*/
+static int l_rsa_encrypt(lua_State* L) {
+    int ret = 0;
+    size_t datalen = 0;
+    size_t keylen = 0;
+    size_t rsa_len = 0;
+    char buff[1024];
+    const char* key = luaL_checklstring(L, 1, &keylen);
+    const char* data = luaL_checklstring(L, 2, &datalen);
+
+    mbedtls_pk_context ctx_pk;
+    mbedtls_rsa_context *rsa;
+    mbedtls_pk_init(&ctx_pk);
+    ret = mbedtls_pk_parse_public_key(&ctx_pk, (const unsigned char*)key, keylen + 1);
+    if (ret) {
+        mbedtls_pk_free(&ctx_pk);
+        LLOGW("bad public key %04X", -ret);
+        return 0;
+    }
+    rsa = (mbedtls_rsa_context *)ctx_pk.pk_ctx;
+    rsa_len = rsa->len;
+    //LLOGD("output len %d", rsa->len);
+
+    ret = mbedtls_rsa_pkcs1_encrypt( ctx_pk.pk_ctx, myrand, NULL, MBEDTLS_RSA_PUBLIC, datalen, (const unsigned char*)data, (unsigned char*)buff );
+    mbedtls_pk_free(&ctx_pk);
+
+    if (ret) {
+        LLOGW("mbedtls_rsa_pkcs1_encrypt %04X", -ret);
+        return 0;
+    }
+    lua_pushlstring(L, buff, rsa_len);
+    return 1;
+}
+
+/*
+RSA解密
+@api rsa.encrypt(key, data, pwd)
+@string 私钥数据,仅支持PEM格式
+@string 待解密数据
+@return string 解密成功后的数据,若失败会返回nil
+@usage
+-- 注意, 解密通常很慢, 建议在服务器端进行
+-- res 是待解密的数据
+local dst = rsa.decrypt((io.readFile("/luadb/privkey.pem")), res, "")
+log.info("rsa", "decrypt", dst and #dst or 0, dst and dst:toHex() or "")
+*/
+static int l_rsa_decrypt(lua_State* L) {
+    int ret = 0;
+    size_t ilen = 0;
+    size_t keylen = 0;
+    size_t rsa_len = 0;
+    size_t olen = 0;
+    size_t pwdlen = 0;
+    char buff[1024];
+    const char* key = luaL_checklstring(L, 1, &keylen);
+    const char* data = luaL_checklstring(L, 2, &ilen);
+    const char* pwd = luaL_optlstring(L, 3, "", &pwdlen);
+
+    mbedtls_pk_context ctx_pk;
+    mbedtls_rsa_context *rsa;
+    mbedtls_pk_init(&ctx_pk);
+    ret = mbedtls_pk_parse_key(&ctx_pk, (const unsigned char*)key, keylen + 1, (const unsigned char*)pwd, pwdlen);
+    if (ret) {
+        mbedtls_pk_free(&ctx_pk);
+        LLOGW("bad private key %04X", -ret);
+        return 0;
+    }
+    rsa = (mbedtls_rsa_context *)ctx_pk.pk_ctx;
+    rsa_len = rsa->len;
+    if (rsa_len != ilen) {
+        mbedtls_pk_free(&ctx_pk);
+        LLOGW("data len NOT match expect %d but %d", rsa_len, ilen);
+        return 0;
+    }
+    //LLOGD("output len %d", rsa->len);
+
+    ret = mbedtls_rsa_pkcs1_decrypt( ctx_pk.pk_ctx, myrand, NULL, MBEDTLS_RSA_PRIVATE, &olen, (const unsigned char*)data, (unsigned char*)buff, 1024);
+    mbedtls_pk_free(&ctx_pk);
+
+    if (ret) {
+        LLOGW("mbedtls_rsa_pkcs1_decrypt %04X", -ret);
+    }
+    lua_pushlstring(L, buff, olen);
+    return 1;
+}
+
+#include "rotable2.h"
+static const rotable_Reg_t reg_rsa[] =
+{
+    { "encrypt" ,        ROREG_FUNC(l_rsa_encrypt)},
+    { "decrypt" ,        ROREG_FUNC(l_rsa_decrypt)},
+	{ NULL,              ROREG_INT(0) }
+};
+
+LUAMOD_API int luaopen_rsa( lua_State *L ) {
+    luat_newlib2(L, reg_rsa);
+    return 1;
+}

+ 55 - 0
demo/rsa/main.lua

@@ -0,0 +1,55 @@
+
+--- 模块功能:rsa示例
+-- @module rsa
+-- @author wendal
+-- @release 2022.11.03
+
+--[[
+提醒: 本demo需要用到公钥和私钥, demo目录中的公钥私钥文件是演示用的, 实际使用请自行生成
+
+生成公钥私钥, 可使用openssl命令, 或者找个网页生成. 2048 是RSA位数, 最高支持4096,但不推荐,因为很慢.
+
+openssl genrsa -out privkey.pem 2048
+openssl rsa -in privkey.pem -pubout -out public.pem
+
+
+-- 下载脚本和资源到设备时, 务必加上本目录下的两个 pem 文件, 否则本demo无法运行.
+]]
+
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "rsademo"
+VERSION = "1.0.1"
+
+log.info("main", PROJECT, VERSION)
+
+-- sys库是标配
+_G.sys = require("sys")
+
+
+sys.taskInit(function()
+    -- 为了日志能正常显示出来, 这里特意延时2秒, 实际使用中不需要
+    sys.wait(2000)
+
+    -- 检查是否带rsa库, 没有就提醒一下吧
+    if not rsa then
+        log.warn("main", "this demo need rsa lib!!!")
+        return
+    end
+
+    -- 读取公钥并马上加密数据
+    local res = rsa.encrypt((io.readFile("/luadb/public.pem")), "abc")
+    -- 打印结果
+    log.info("rsa", "encrypt", res and #res or 0, res and res:toHex() or "")
+
+    -- 下面是解密, 通常不会在设备端进行, 这里主要是演示用法, 会很慢
+    if res then
+        -- 读取私钥, 然后解码数据
+        local dst = rsa.decrypt((io.readFile("/luadb/privkey.pem")), res, "")
+        log.info("rsa", "decrypt", dst and #dst or 0, dst and dst:toHex() or "")
+    end
+end)
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 27 - 0
demo/rsa/privkey.pem

@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEAp0WakShvpE1/28hyZzz0TFiBpN/d6EU2Wkl5lrazTxK/LDdZ
+kAQuz6eA+kdPUqSueIpN0X8DT4Or5/0yD/ABvgW2t7A6g2/zQpzv9IoAl2f1Vhnx
+dd7iSnhWTeF80lywp4VlHHEVVp7ZCqod59qa9nyp45ycWPwV0VCdX6NwS7chPodC
+/Nf4UVbC1/JJ26WPVKqgOuSz0hIX58pnEaU/ntSDuJiLcKdCNUyIHJEzNYGaQVwx
+mqBoyolktkTOL04AW/OXlOTP8eZrEZpckrODDaWlLUOt5SARS6qUYJSvuyYry8a0
+rGOLbCnoIYVBvu8NX8I5hfeMGnYkEdpx6x/xYwIDAQABAoIBADfwehGDYVqkJFc/
+AKtv4g9KJgkaaN7NjrDBE62IagzOqypBVG1qSLFfRi3s/SUZN9POBNpDzLqhwTKz
+JTPZQuvmg0WI5Pihzst/KmwwXqRDuvNRd8PAhxL6jXo8J38+SkGrxbWuR8GRG+qK
+G7g3Dk3SQQqCjHLh0vYOLKMYSGy5RgfIQyve6yBK1LHeanzgGgcSbawsvCiiDOkb
+Y3I8CHasnK/Hxpmx/NzfNfY+r32AVXx4b+sN2YxB7A9OCxgdwYQHxYvKZ1JIiCh+
+Mv85wDHT25SJ5NLdP/jHILgGrgpyDN5+9c4fk3rjkoTrTs01wJ4rQfItkQ1Zlr0/
+9tub6mECgYEA2e7gerNRv53L0HkY9GS0B7Esi2FiUc/oh4xKRKPm+/ydXcroVbAK
+Mz3mCVlRNvkA+68P670s3AKVpeB671R70dCY+MQXTeNaxc0NlhGOKYoerPd9D/GN
+CF460AT2SQEWYTdIbin2dxeROEuC79zn1yczxnSwjAvqDwpvpHceP3ECgYEAxH1a
+hXk84U5PGKyUuAVMNMaQQll8rcxoFThxrei7iNT6SfVAeHQufCgeW9g1cOL5Vjmk
+9Te1caJt2VXaAhq883qZ1ABypQgcfUwLaK6q4BzAIPtYRIpkJstFKaYWqYaVwCGh
+QTqcP+ebEJ1BgKgxH4nXjlMUMwf8qzTGmQlO/BMCgYEAzZblG7uIlgyFVnC3Eu7h
+SxRgIkjHWMia4yx8b45zfCpORkoBrbw5kyeEmDMzQ3nZ7JS0nz5CUHb7t5UyRA7e
+FAwGEz/hgC/H1Svg8j4zb4qF78Q1rdHAqzFBqDXWJP6qnyFo6cwaXzTTYVkS97bc
+24J2/HPejO88ad39fhiFZ3ECgYEAvDJgaGU2BYrOwZBTJWqVkhr5g0NY4tJcgq68
+W1kFfkqXrAzGglitSWfXpBqTHRuYu5icwe5o0H1F/5t2IvvfLMmp2t/O7vi06OHU
+L6DUs7F16GE1KvjuciXRidG19QueFRdg7ywnCiJYaHJmkccGvfF1z7ENMM+el5EG
+AwBicZcCgYBdcmz3nmTyGb+BY6yHDNrJh97eSJaP5KOpfs1ZGM4Jx/Pa391q1X9Y
+WigaNEpW5eJKzTnyX0GlbEPPhTkBJS4ZwuKRZBvwzmLdoICA+i7gpjwfqDcrdJND
+IhEjjWogNyIvepre3eL1HMaJr6TS4j7wZTl7Ha4httCNBkQb0qJeWw==
+-----END RSA PRIVATE KEY-----

+ 9 - 0
demo/rsa/public.pem

@@ -0,0 +1,9 @@
+-----BEGIN PUBLIC KEY-----
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp0WakShvpE1/28hyZzz0
+TFiBpN/d6EU2Wkl5lrazTxK/LDdZkAQuz6eA+kdPUqSueIpN0X8DT4Or5/0yD/AB
+vgW2t7A6g2/zQpzv9IoAl2f1Vhnxdd7iSnhWTeF80lywp4VlHHEVVp7ZCqod59qa
+9nyp45ycWPwV0VCdX6NwS7chPodC/Nf4UVbC1/JJ26WPVKqgOuSz0hIX58pnEaU/
+ntSDuJiLcKdCNUyIHJEzNYGaQVwxmqBoyolktkTOL04AW/OXlOTP8eZrEZpckrOD
+DaWlLUOt5SARS6qUYJSvuyYry8a0rGOLbCnoIYVBvu8NX8I5hfeMGnYkEdpx6x/x
+YwIDAQAB
+-----END PUBLIC KEY-----

+ 1 - 0
luat/include/luat_libs.h

@@ -132,5 +132,6 @@ LUAMOD_API int luaopen_mobile( lua_State *L );
 LUAMOD_API int luaopen_protobuf( lua_State *L );
 
 LUAMOD_API int luaopen_httpsrv( lua_State *L );
+LUAMOD_API int luaopen_rsa( lua_State *L );
 
 #endif