Преглед изворни кода

add: gmssl.sm2加解密添加网站兼容模式

https://gitee.com/openLuat/LuatOS/issues/I8844M
Wendal Chen пре 2 година
родитељ
комит
da5a2e707f
3 измењених фајлова са 99 додато и 32 уклоњено
  1. 75 20
      components/gmssl/bind/luat_lib_gmssl.c
  2. 2 2
      components/gmssl/include/gmssl/api.h
  3. 22 10
      demo/gmssl/main.lua

+ 75 - 20
components/gmssl/bind/luat_lib_gmssl.c

@@ -74,12 +74,14 @@ static void DeletePaddingBuf(luaL_Buffer *B, const char *pPadding, size_t nBufLe
 
 /*
 sm2算法加密
-@api sm.sm2encrypt(pkx,pky,data)
-@string 公钥x,必选
-@string 公钥y,必选
-@string 待计算的数据,必选,最长255字节
-@return string 加密后的字符串, 原样输出,未经HEX转换
+@api sm.sm2encrypt(pkx,pky,data, mode)
+@string 公钥x,必选. HEX字符串
+@string 公钥y,必选. HEX字符串
+@string 待计算的数据,必选,最长32字节, 非HEX字符串
+@boolean 输出模式,默认false. false-GMSSL默认格式, true-网站兼容模式
+@return string 加密后的字符串, 原样输出,未经HEX转换. 若加密失败会返回nil或空字符串
 @usage
+-- 提示 mode 参数是 2023.10.17 新增
 local originStr = "encryption standard"
 local pkx = "435B39CCA8F3B508C1488AFC67BE491A0F7BA07E581A0E4849A5CF70628A7E0A"
 local pky = "75DDBA78F15FEECB4C7895E2C1CDF5FE01DEBB2CDBADF45399CCF77BBA076A42"
@@ -102,40 +104,67 @@ static int l_sm2_encrypt(lua_State *L)
     //检查参数合法性
     if((pkxLen!=64))
     {
-        return luaL_error(L, "invalid pkx password length=%d", pkxLen);
+        LLOGE("invalid pkx password length=%d", pkxLen);
+        return 0;
     }
     if((pkyLen!=64))
     {
-        return luaL_error(L, "invalid pky password length=%d", pkyLen);
+        LLOGE("invalid pky password length=%d", pkyLen);
+        return 0;
     }
     if (pBufLen > SM2_MAX_PLAINTEXT_SIZE) {
         LLOGD("data too large max %d but %d", SM2_MAX_PLAINTEXT_SIZE, pBufLen);
         return 0;
     }
 
+    int mode = 0;
+    if (lua_isboolean(L, 4)) {
+        mode = lua_toboolean(L, 4);
+    }
+
     SM2_KEY sm2 = {0};
-    SM2_POINT point;
+    SM2_POINT point = {0};
     luat_str_fromhex(pkx, 64, (char*)point.x);
     luat_str_fromhex(pky, 64, (char*)point.y);
     ret = sm2_key_set_public_key(&sm2, (const SM2_POINT*)&point);
-    LLOGD("sm2_key_set_public_key %d", ret);
+    if (ret != 1) {
+        LLOGD("sm2_key_set_public_key %d", ret);
+        return 0;
+    }
 
-    unsigned char out[SM2_MAX_CIPHERTEXT_SIZE] = {0};
+    uint8_t out[SM2_MAX_CIPHERTEXT_SIZE] = {0};
     size_t olen = 0;
-
-    ret = sm2_encrypt(&sm2, (const unsigned char *)pBuf, pBufLen, out, &olen);
-    LLOGD("sm2_encrypt ret %d", ret);
+    if (mode) {
+        SM2_CIPHERTEXT C = {0};
+        ret = sm2_do_encrypt(&sm2, (const uint8_t *)pBuf, pBufLen, &C);
+        // LLOGD("sm2_do_encrypt ret %d", ret);
+        // LLOGD("C->ciphertext_size %04X", C.ciphertext_size);
+        memcpy(out, &C.point.x, 32);
+        memcpy(out + 32, &C.point.y, 32);
+        memcpy(out + 64, C.hash, 32);
+        memcpy(out + 96, C.ciphertext, C.ciphertext_size);
+        olen = 96 + C.ciphertext_size;
+    }
+    else {
+        ret = sm2_encrypt(&sm2, (const uint8_t *)pBuf, pBufLen, out, &olen);
+    }
+    if (ret != 1) {
+        LLOGD("sm2_encrypt ret %d", ret);
+        return 0;
+    }
     lua_pushlstring(L, (char*)out, olen);
     return 1;
 }
 
 /*
 sm2算法解密
-@api sm.sm2decrypt(private,data)
-@string 私钥,必选
-@string 待计算的数据,必选
-@return string 解密后的字符串,未经HEX转换
+@api sm.sm2decrypt(private,data,mode)
+@string 私钥,必选,HEX字符串
+@string 待计算的数据,必选,原始数据,非HEX字符串
+@boolean 输出模式,默认false. false-GMSSL默认格式, true-网站兼容模式
+@return string 解密后的字符串,未经HEX转换.若解密失败会返回nil或空字符串
 @usage
+-- 提示 mode 参数是 2023.10.17 新增
 local originStr = "encryption standard"
 local pkx = "435B39CCA8F3B508C1488AFC67BE491A0F7BA07E581A0E4849A5CF70628A7E0A"
 local pky = "75DDBA78F15FEECB4C7895E2C1CDF5FE01DEBB2CDBADF45399CCF77BBA076A42"
@@ -153,10 +182,20 @@ static int l_sm2_decrypt(lua_State *L)
     const char *pBuf = lua_tolstring(L, 2,&pBufLen);
     int ret = 0;
 
+    int mode = 0;
+    if (lua_isboolean(L, 3)) {
+        mode = lua_toboolean(L, 3);
+    }
+
     //检查参数合法性
     if((privateLen!=64))
     {
-        return luaL_error(L, "invalid private password length=%d", privateLen);
+        LLOGE("invalid private password length=%d", privateLen);
+        return 0;
+    }
+    if (pBufLen < 97) {
+        LLOGE("待数据太短,应该要97字节以上");
+        return 0;
     }
     
     SM2_KEY sm2 = {0};
@@ -164,8 +203,24 @@ static int l_sm2_decrypt(lua_State *L)
     size_t olen = 0;
     luat_str_fromhex(private, 64, (char*)sm2.private_key);
 
-    ret = sm2_decrypt(&sm2, (uint8_t*)pBuf, pBufLen, (uint8_t*)out, &olen);
-    LLOGD("sm2_decrypt ret %d", ret);
+    if (mode) {
+        // LLOGD("网站兼容模式");
+        SM2_CIPHERTEXT C = {0};
+        C.ciphertext_size = (uint8_t)(pBufLen - 96);
+        memcpy(&C.point.x, pBuf, 32);
+        memcpy(&C.point.y, pBuf + 32, 32);
+        memcpy(C.hash, pBuf + 64, 32);
+        memcpy(C.ciphertext, pBuf + 96, C.ciphertext_size);
+        ret = sm2_do_decrypt(&sm2, &C, (uint8_t *)out, &olen);
+    }
+    else {
+        // LLOGD("GMSSL默认模式");
+        ret = sm2_decrypt(&sm2, (uint8_t*)pBuf, pBufLen, (uint8_t*)out, &olen);
+    }
+    if (ret != 1) {
+        LLOGD("sm2_decrypt ret %d", ret);
+        return 0;
+    }
     lua_pushlstring(L, (char*)out, olen);
     return 1;
 }

+ 2 - 2
components/gmssl/include/gmssl/api.h

@@ -12,10 +12,10 @@
 
 
 #ifdef WIN32
-#define _gmssl_export  __declspec(dllexport)
+#define _gmssl_export
 #else
 // use -fvisibility=hidden to change the "default" behavior
-#define _gmssl_export  __attribute__((visibility("default")))
+#define _gmssl_export
 #endif
 
 

+ 22 - 10
demo/gmssl/main.lua

@@ -27,22 +27,34 @@ sys.taskInit(function()
     -- SM2 , 非对称加密, 类似于RSA,但属于椭圆算法
     -- 就当前实现还是比较慢的
     if gmssl.sm2encrypt then -- 部分BSP不支持
-        local originStr = "encryption standard"
-        local pkx = "191BFF8148006EEA72D857CB974DB9F4903B3CA3655D8D597AD4663F5044DCB1"
-        local pky = "E2F7888AF1FCD8C653A8059CD2F379855389F71A7709E2C1EE1E914C855EF119"
-        local private = "1649AB77A00637BD5E2EFE283FBF353534AA7F7CB89463F208DDBC2920BB0DA0"
+        local originStr = "!!from LuatOS!!"
+        local pkx = "ABE87C924B7ECFDEA1748A06E89003C9F7F4DC5C3563873CE2CAE46F66DE8141"
+        local pky = "9514733D38CC026F2452A6A3A3A4DA0C28F864AFA5FE2C45E0EB6B761FBB5286"
+        local private = "129EDC282CD2E9C1144C2E7315F926D772BC96600D2771E8BE02060313FE00D5"
+
+        -- GMSSL默认格式
+        log.info("==== SM2 默认GMSSL模式")
         local encodeStr = gmssl.sm2encrypt(pkx,pky,originStr)
+        log.info("对比", originStr,"encrypt",string.toHex(encodeStr))
+        log.info("gmssl.sm2decrypt",gmssl.sm2decrypt(private,encodeStr))
+
+        -- 网站兼容模式 https://i.goto327.top/CryptTools/SM2.aspx
+        -- 密钥格式 C1C3C2
+        log.info("==== SM2 网站兼容模式")
+        local encodeStr = gmssl.sm2encrypt(pkx,pky,originStr, true)
         print(originStr,"encrypt",string.toHex(encodeStr))
-        log.info("testsm.sm2decrypt",gmssl.sm2decrypt(private,encodeStr,pkx,pky))
+        log.info("gmssl.sm2decrypt",gmssl.sm2decrypt(private,encodeStr,true))
     end
 
     -- SM3 算法, hash类
     if gmssl.sm3update then
+        log.info("=== SM3测试")
         encodeStr = gmssl.sm3update("lqlq666lqlq946")
-        log.info("testsm.sm3update",string.toHex(encodeStr))
+        log.info("gmssl.sm3update",string.toHex(encodeStr))
     end
 
     if gmssl.sm4encrypt then
+        log.info("=== SM4测试")
         local passwd = "1234567890123456"
         local iv = "1234567890666666"
         -- SM4 算法, 对称加密
@@ -50,22 +62,22 @@ sys.taskInit(function()
         --加密模式:ECB;填充方式:ZeroPadding;密钥:1234567890123456;密钥长度:128 bit
         encodeStr = gmssl.sm4encrypt("ECB","ZERO",originStr,passwd)
         print(originStr,"encrypt",string.toHex(encodeStr))
-        log.info("testsm.sm4decrypt",gmssl.sm4decrypt("ECB","ZERO",encodeStr,passwd))
+        log.info("gmssl.sm4decrypt",gmssl.sm4decrypt("ECB","ZERO",encodeStr,passwd))
 
         originStr = ">>SM4 ECB Pkcs5Padding test<<"
         --加密模式:ECB;填充方式:Pkcs5Padding;密钥:1234567890123456;密钥长度:128 bit
         encodeStr = gmssl.sm4encrypt("ECB","PKCS5",originStr,passwd)
         print(originStr,"encrypt",string.toHex(encodeStr))
-        log.info("testsm.sm4decrypt",gmssl.sm4decrypt("ECB","PKCS5",encodeStr,passwd))
+        log.info("gmssl.sm4decrypt",gmssl.sm4decrypt("ECB","PKCS5",encodeStr,passwd))
 
         originStr = ">>SM4 CBC Pkcs5Padding test<<"
         --加密模式:CBC;填充方式:Pkcs5Padding;密钥:1234567890123456;密钥长度:128 bit;偏移量:1234567890666666
         encodeStr = gmssl.sm4encrypt("CBC","PKCS5",originStr,passwd,iv)
         print(originStr,"encrypt",string.toHex(encodeStr))
-        log.info("testsm.sm4decrypt",gmssl.sm4decrypt("CBC","PKCS5",encodeStr,passwd, iv))
+        log.info("gmssl.sm4decrypt",gmssl.sm4decrypt("CBC","PKCS5",encodeStr,passwd, iv))
     end
 
-    log.info("sm", "ALL Done")
+    log.info("gmssl", "ALL Done")
 end)
 
 -- 用户代码已结束---------------------------------------------