luat_lib_rsa.c 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. /*
  2. @module rsa
  3. @summary RSA加密解密
  4. @version 1.0
  5. @date 2022.11.03
  6. @demo rsa
  7. @tag LUAT_USE_RSA
  8. @usage
  9. -- 请在电脑上生成私钥和公钥, 当前最高支持4096bit, 一般来说2048bit就够用了
  10. -- openssl genrsa -out privkey.pem 2048
  11. -- openssl rsa -in privkey.pem -pubout -out public.pem
  12. -- privkey.pem 是私钥, public.pem 是公钥
  13. -- 私钥用于 加密 和 签名, 通常保密, 放在服务器端
  14. -- 公钥用于 解密 和 验签, 一般可公开,放在设备端
  15. -- 为了演示API使用, 这里把私钥也放在设备上
  16. local res = rsa.encrypt((io.readFile("/luadb/public.pem")), "abc")
  17. -- 打印结果
  18. log.info("rsa", "encrypt", res and #res or 0, res and res:toHex() or "")
  19. -- 下面是解密, 通常不会在设备端进行, 这里主要是演示用法, 会很慢
  20. if res then
  21. -- 读取私钥, 然后解码数据
  22. local dst = rsa.decrypt((io.readFile("/luadb/privkey.pem")), res, "")
  23. log.info("rsa", "decrypt", dst and #dst or 0, dst and dst:toHex() or "")
  24. end
  25. -- 演示签名和验签
  26. local hash = crypto.sha1("1234567890"):fromHex()
  27. -- 签名通常很慢, 通常是服务器做
  28. local sig = rsa.sign((io.readFile("/luadb/privkey.pem")), rsa.MD_SHA1, hash, "")
  29. log.info("rsa", "sign", sig and #sig or 0, sig and sig:toHex() or "")
  30. if sig then
  31. -- 验签是很快的
  32. local ret = rsa.verify((io.readFile("/luadb/public.pem")), rsa.MD_SHA1, hash, sig)
  33. log.info("rsa", "verify", ret)
  34. end
  35. */
  36. #include "luat_base.h"
  37. #include "luat_mem.h"
  38. #include "luat_crypto.h"
  39. #include "luat_fs.h"
  40. #define LUAT_LOG_TAG "rsa"
  41. #include "luat_log.h"
  42. #include "mbedtls/rsa.h"
  43. #include "mbedtls/pk.h"
  44. #include "mbedtls/entropy.h"
  45. #include "mbedtls/ctr_drbg.h"
  46. #include "mbedtls/md.h"
  47. static int myrand( void *rng_state, unsigned char *output, size_t len ) {
  48. (void)rng_state;
  49. luat_crypto_trng((char*)output, len);
  50. return 0;
  51. }
  52. /*
  53. RSA加密
  54. @api rsa.encrypt(key, data)
  55. @string 公钥数据,仅支持PEM格式
  56. @string 待加密数据, 不能超过公钥位数的一半, 例如 2048bit的公钥, 只能加密128字节的数据
  57. @return string 加密成功后的数据,若失败会返回nil
  58. @usage
  59. -- 下面代码中的 "abc" 是待加密数据
  60. local res = rsa.encrypt((io.readFile("/luadb/public.pem")), "abc")
  61. -- 打印结果
  62. log.info("rsa", "encrypt", res and #res or 0, res and res:toHex() or "")
  63. */
  64. static int l_rsa_encrypt(lua_State* L) {
  65. int ret = 0;
  66. size_t ilen = 0;
  67. size_t keylen = 0;
  68. size_t olen = 0;
  69. char buff[1024];
  70. const char* key = luaL_checklstring(L, 1, &keylen);
  71. const char* data = luaL_checklstring(L, 2, &ilen);
  72. mbedtls_pk_context ctx_pk;
  73. mbedtls_pk_init(&ctx_pk);
  74. ret = mbedtls_pk_parse_public_key(&ctx_pk, (const unsigned char*)key, keylen + 1);
  75. if (ret) {
  76. mbedtls_pk_free(&ctx_pk);
  77. LLOGW("bad public key %04X", -ret);
  78. return 0;
  79. }
  80. ret = mbedtls_pk_encrypt(&ctx_pk, (const unsigned char*)data, ilen, (unsigned char*)buff, &olen, 1024, myrand, NULL);
  81. mbedtls_pk_free(&ctx_pk);
  82. if (ret) {
  83. LLOGW("mbedtls_rsa_pkcs1_encrypt %04X", -ret);
  84. return 0;
  85. }
  86. lua_pushlstring(L, buff, olen);
  87. return 1;
  88. }
  89. /*
  90. RSA解密
  91. @api rsa.decrypt(key, data, pwd)
  92. @string 私钥数据,仅支持PEM格式
  93. @string 待解密数据
  94. @string 私钥的密码,可选
  95. @return string 解密成功后的数据,若失败会返回nil
  96. @usage
  97. -- 注意, 解密通常很慢, 建议在服务器端进行
  98. -- res 是待解密的数据
  99. local dst = rsa.decrypt((io.readFile("/luadb/privkey.pem")), res, "")
  100. log.info("rsa", "decrypt", dst and #dst or 0, dst and dst:toHex() or "")
  101. */
  102. static int l_rsa_decrypt(lua_State* L) {
  103. int ret = 0;
  104. size_t ilen = 0;
  105. size_t keylen = 0;
  106. size_t rsa_len = 0;
  107. size_t olen = 0;
  108. size_t pwdlen = 0;
  109. char buff[1024];
  110. const char* key = luaL_checklstring(L, 1, &keylen);
  111. const char* data = luaL_checklstring(L, 2, &ilen);
  112. const char* pwd = luaL_optlstring(L, 3, "", &pwdlen);
  113. mbedtls_pk_context ctx_pk;
  114. mbedtls_pk_init(&ctx_pk);
  115. ret = mbedtls_pk_parse_key(&ctx_pk, (const unsigned char*)key, keylen + 1, (const unsigned char*)pwd, pwdlen
  116. #if MBEDTLS_VERSION_NUMBER >= 0x03000000
  117. , myrand, NULL
  118. #endif
  119. );
  120. if (ret) {
  121. mbedtls_pk_free(&ctx_pk);
  122. LLOGW("bad private key %04X", -ret);
  123. return 0;
  124. }
  125. rsa_len = (mbedtls_pk_get_bitlen(&ctx_pk) + 7 ) / 8;
  126. if (rsa_len != ilen) {
  127. mbedtls_pk_free(&ctx_pk);
  128. LLOGW("data len NOT match expect %d but %d", rsa_len, ilen);
  129. return 0;
  130. }
  131. ret = mbedtls_pk_decrypt(&ctx_pk, (const unsigned char*)data, ilen, (unsigned char*)buff, &olen, 1024, myrand, NULL);
  132. mbedtls_pk_free(&ctx_pk);
  133. if (ret) {
  134. LLOGW("mbedtls_rsa_pkcs1_decrypt %04X", -ret);
  135. return 0;
  136. }
  137. lua_pushlstring(L, buff, olen);
  138. return 1;
  139. }
  140. /*
  141. RSA验签
  142. @api rsa.verify(key, md, hash, sig)
  143. @string 公钥数据,仅支持PEM格式
  144. @int 签名模式, 例如 rsa.MD_SHA1 , rsa.MD_SHA256
  145. @string hash数据, 如果是HEX字符串,记得fromHex转二进制数据
  146. @string sig数据, 如果是HEX字符串,记得fromHex转二进制数据
  147. @return bool 有效返回true,否则为false,出错返回nil
  148. @usage
  149. local ret = rsa.verify((io.readFile("/luadb/public.pem")), rsa.MD_SHA1, hash, sig)
  150. log.info("rsa", "verify", ret)
  151. */
  152. static int l_rsa_verify(lua_State* L) {
  153. int ret = 0;
  154. size_t hash_len = 0;
  155. size_t sig_len = 0;
  156. size_t keylen = 0;
  157. const char* key = luaL_checklstring(L, 1, &keylen);
  158. mbedtls_md_type_t md = luaL_checkinteger(L, 2);
  159. const char* hash = luaL_checklstring(L, 3, &hash_len);
  160. const char* sig = luaL_checklstring(L, 4, &sig_len);
  161. mbedtls_pk_context ctx_pk;
  162. mbedtls_pk_init(&ctx_pk);
  163. ret = mbedtls_pk_parse_public_key(&ctx_pk, (const unsigned char*)key, keylen + 1);
  164. if (ret) {
  165. mbedtls_pk_free(&ctx_pk);
  166. LLOGW("bad public key %04X", -ret);
  167. return 0;
  168. }
  169. ret = mbedtls_pk_verify(&ctx_pk, md, (const unsigned char*)hash, hash_len, (const unsigned char*)sig, sig_len);
  170. lua_pushboolean(L, ret == 0 ? 1 : 0);
  171. return 1;
  172. }
  173. /*
  174. RSA签名
  175. @api rsa.sign(key, md, hash, pwd)
  176. @string 私钥数据,仅支持PEM格式
  177. @int 签名模式, 例如 rsa.MD_SHA1 , rsa.MD_SHA256
  178. @string hash数据, 如果是HEX字符串,记得fromHex转二进制数据
  179. @string 私钥密码, 可选
  180. @return string 成功返回sig数据, 否则返回nil
  181. @usage
  182. local sig = rsa.sign((io.readFile("/luadb/privkey.pem")), rsa.MD_SHA1, hash, "")
  183. log.info("rsa", "sign", sig and #sig or 0, sig and sig:toHex() or "")
  184. */
  185. static int l_rsa_sign(lua_State* L) {
  186. int ret = 0;
  187. size_t pwdlen = 0;
  188. size_t hash_len = 0;
  189. size_t sig_len = 0;
  190. size_t keylen = 0;
  191. char sig[MBEDTLS_PK_SIGNATURE_MAX_SIZE] = {0};
  192. const char* key = luaL_checklstring(L, 1, &keylen);
  193. mbedtls_md_type_t md = luaL_checkinteger(L, 2);
  194. const char* hash = luaL_checklstring(L, 3, &hash_len);
  195. const char* pwd = luaL_optlstring(L, 4, "", &pwdlen);
  196. mbedtls_pk_context ctx_pk;
  197. mbedtls_pk_init(&ctx_pk);
  198. ret = mbedtls_pk_parse_key(&ctx_pk, (const unsigned char*)key, keylen + 1, (const unsigned char*)pwd, pwdlen
  199. #if MBEDTLS_VERSION_NUMBER >= 0x03000000
  200. , myrand, NULL
  201. #endif
  202. );
  203. if (ret) {
  204. mbedtls_pk_free(&ctx_pk);
  205. LLOGW("bad private key %04X", -ret);
  206. return 0;
  207. }
  208. ret = mbedtls_pk_sign(&ctx_pk, md, (const unsigned char*)hash, hash_len, (unsigned char*)sig,
  209. #if MBEDTLS_VERSION_NUMBER >= 0x03000000
  210. MBEDTLS_PK_SIGNATURE_MAX_SIZE,
  211. #endif
  212. &sig_len, myrand, NULL);
  213. mbedtls_pk_free(&ctx_pk);
  214. if (ret) {
  215. LLOGW("mbedtls_pk_sign %04X", -ret);
  216. return 0;
  217. }
  218. lua_pushlstring(L, sig, sig_len);
  219. return 1;
  220. }
  221. #include "rotable2.h"
  222. static const rotable_Reg_t reg_rsa[] =
  223. {
  224. { "encrypt" , ROREG_FUNC(l_rsa_encrypt)},
  225. { "decrypt" , ROREG_FUNC(l_rsa_decrypt)},
  226. { "verify", ROREG_FUNC(l_rsa_verify)},
  227. { "sign", ROREG_FUNC(l_rsa_sign)},
  228. //@const MD_MD5 MD5模式,用于签名和验签
  229. { "MD_MD5", ROREG_INT(MBEDTLS_MD_MD5)},
  230. //@const MD_SHA1 SHA1模式,用于签名和验签
  231. { "MD_SHA1", ROREG_INT(MBEDTLS_MD_SHA1)},
  232. //@const MD_SHA224 SHA224模式,用于签名和验签
  233. { "MD_SHA224", ROREG_INT(MBEDTLS_MD_SHA224)},
  234. //@const MD_SHA256 SHA256模式,用于签名和验签
  235. { "MD_SHA256", ROREG_INT(MBEDTLS_MD_SHA256)},
  236. { NULL, ROREG_INT(0) }
  237. };
  238. LUAMOD_API int luaopen_rsa( lua_State *L ) {
  239. luat_newlib2(L, reg_rsa);
  240. return 1;
  241. }