Sfoglia il codice sorgente

add: TOTP接口、BASE32接口

chenxuuu 4 anni fa
parent
commit
569507fdd0
5 ha cambiato i file con 182 aggiunte e 0 eliminazioni
  1. 12 0
      demo/crypto/main.lua
  2. 4 0
      lua/src/lstrlib.c
  3. 124 0
      lua/src/lstrlib_exts.c
  4. 3 0
      luat/include/luat_str.h
  5. 39 0
      luat/modules/luat_lib_crypto.c

+ 12 - 0
demo/crypto/main.lua

@@ -45,6 +45,18 @@ sys.timerLoopStart(function()
     log.info("AES", "aes-128-cbc", data2_decrypt)
     log.info("mem", rtos.meminfo("sys"))
 
+
+    --totp的密钥
+    local secret = "VK54ZXPO74ISEM2E"
+    --写死时间戳用来测试
+    local ts = 1646796576
+    --生成十分钟的动态码验证下
+    for i=1,600,30 do
+        local r = crypto.totp(secret,ts+i)
+        local time = os.date("*t",ts+i + 8*3600)--东八区
+        log.info("totp",r,time.hour,time.min,time.sec)
+    end
+
 end, 2000)
 
 sys.taskInit(function()

+ 4 - 0
lua/src/lstrlib.c

@@ -1543,6 +1543,8 @@ int l_str_toValue (lua_State *L);
 int l_str_urlEncode (lua_State *L);
 int l_str_toBase64(lua_State *L);
 int l_str_fromBase64(lua_State *L);
+int l_str_toBase32(lua_State *L);
+int l_str_fromBase32(lua_State *L);
 int l_str_startsWith(lua_State *L);
 int l_str_endsWith(lua_State *L);
 int l_str_strs(lua_State *L);
@@ -1579,6 +1581,8 @@ static const rotable_Reg strlib[] = {
   {"urlEncode", l_str_urlEncode, 0},
   {"fromBase64", l_str_fromBase64, 0},
   {"toBase64", l_str_toBase64, 0},
+  {"fromBase32", l_str_fromBase32, 0},
+  {"toBase32", l_str_toBase32, 0},
 
   {"startsWith", l_str_startsWith, 0},
   {"endsWith", l_str_endsWith, 0},

+ 124 - 0
lua/src/lstrlib_exts.c

@@ -503,6 +503,130 @@ int l_str_fromBase64(lua_State *L) {
   return 1;
 }
 
+////////////////////////////////////////////
+////                 BASE32            /////
+////////////////////////////////////////////
+// Copyright 2010 Google Inc.
+// Author: Markus Gutschke
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+int luat_str_base32_decode(const uint8_t *encoded, uint8_t *result, int bufSize) {
+  int buffer = 0;
+  int bitsLeft = 0;
+  int count = 0;
+  for (const uint8_t *ptr = encoded; count < bufSize && *ptr; ++ptr) {
+    uint8_t ch = *ptr;
+    if (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n' || ch == '-') {
+      continue;
+    }
+    buffer <<= 5;
+
+    // Deal with commonly mistyped characters
+    if (ch == '0') {
+      ch = 'O';
+    } else if (ch == '1') {
+      ch = 'L';
+    } else if (ch == '8') {
+      ch = 'B';
+    }
+
+    // Look up one base32 digit
+    if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z')) {
+      ch = (ch & 0x1F) - 1;
+    } else if (ch >= '2' && ch <= '7') {
+      ch -= '2' - 26;
+    } else {
+      return -1;
+    }
+
+    buffer |= ch;
+    bitsLeft += 5;
+    if (bitsLeft >= 8) {
+      result[count++] = buffer >> (bitsLeft - 8);
+      bitsLeft -= 8;
+    }
+  }
+  if (count < bufSize) {
+    result[count] = '\000';
+  }
+  return count;
+}
+
+int luat_str_base32_encode(const uint8_t *data, int length, uint8_t *result,
+                  int bufSize) {
+  if (length < 0 || length > (1 << 28)) {
+    return -1;
+  }
+  int count = 0;
+  if (length > 0) {
+    int buffer = data[0];
+    int next = 1;
+    int bitsLeft = 8;
+    while (count < bufSize && (bitsLeft > 0 || next < length)) {
+      if (bitsLeft < 5) {
+        if (next < length) {
+          buffer <<= 8;
+          buffer |= data[next++] & 0xFF;
+          bitsLeft += 8;
+        } else {
+          int pad = 5 - bitsLeft;
+          buffer <<= pad;
+          bitsLeft += pad;
+        }
+      }
+      int index = 0x1F & (buffer >> (bitsLeft - 5));
+      bitsLeft -= 5;
+      result[count++] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"[index];
+    }
+  }
+  if (count < bufSize) {
+    result[count] = '\000';
+  }
+  return count;
+}
+
+/*
+将字符串进行base32编码
+@api string.toBase32(str)
+@string 需要转换的字符串
+@return string 解码后的字符串,如果解码失败会返回0长度字符串
+*/
+int l_str_toBase32(lua_State *L) {
+  size_t len = 0;
+  const char* str = luaL_checklstring(L, 1, &len);
+  if (len == 0) {
+    lua_pushstring(L, "");
+    return 1;
+  }
+  luaL_Buffer buff = {0};
+  luaL_buffinitsize(L, &buff, len * 2);
+  int rl = luat_str_base32_encode((const uint8_t * )str,len,buff.b,buff.size);
+  luaL_pushresultsize(&buff, rl);
+  return 1;
+}
+
+/*
+将字符串进行base32解码
+@api string.fromBase32(str)
+@string 需要转换的字符串
+@return string 解码后的字符串,如果解码失败会返回0长度字符串
+*/
+int l_str_fromBase32(lua_State *L) {
+  size_t len = 0;
+  const char* str = luaL_checklstring(L, 1, &len);
+  if (len == 0) {
+    lua_pushstring(L, "");
+    return 1;
+  }
+  luaL_Buffer buff = {0};
+  luaL_buffinitsize(L, &buff, len + 1);
+  int rl = luat_str_base32_decode((const uint8_t * )str,buff.b,buff.size);
+  luaL_pushresultsize(&buff, rl);
+  return 1;
+}
+
 /*
 判断字符串前缀
 @api string.startsWith(str, prefix)

+ 3 - 0
luat/include/luat_str.h

@@ -11,4 +11,7 @@ int luat_str_base64_encode( unsigned char *dst, size_t dlen, size_t *olen,
 int luat_str_base64_decode( unsigned char *dst, size_t dlen, size_t *olen,
                    const unsigned char *src, size_t slen );
 
+int luat_str_base32_decode(const uint8_t *encoded, uint8_t *result, int bufSize);
+int luat_str_base32_encode(const uint8_t *data, int length, uint8_t *result,int bufSize);
+
 #endif

+ 39 - 0
luat/modules/luat_lib_crypto.c

@@ -7,6 +7,7 @@
 */
 #include "luat_base.h"
 #include "luat_crypto.h"
+#include "luat_malloc.h"
 
 #define LUAT_LOG_TAG "crypto"
 #include "luat_log.h"
@@ -364,6 +365,43 @@ static int l_crypto_trng(lua_State *L) {
     return 0;
 }
 
+/**
+计算TOTP动态密码的结果
+@api crypto.totp(secret,time)
+@string 网站提供的密钥(就是BASE32编码后的结果)
+@int 可选,时间戳,默认当前时间
+@return int 计算得出的六位数结果 计算失败返回nil
+@usage
+--使用当前系统时间计算
+local otp = crypto.totp("asdfassdfasdfass")
+ */
+static int l_crypto_totp(lua_State *L) {
+    size_t len = 0;
+    char* secret_base32 = luaL_checklstring(L,1,&len);
+
+    char * secret = (char *)luat_heap_malloc(len+1);
+    len = luat_str_base32_decode((const uint8_t * )secret_base32,(uint8_t*)secret,len+1);
+
+    uint64_t t = luaL_optinteger(L,2,time(NULL))/30;
+    uint8_t data[sizeof(t)] = {0};
+    for(int i=0;i<sizeof(t);i++)
+        data[sizeof(t)-1-i] = *(((uint8_t*)&t)+i);
+    uint8_t hmac[20] = {0};
+    if(luat_crypto_hmac_sha1_simple((const char *)data, sizeof(data), (const char *)secret, len, hmac) == 0)
+    {
+        uint8_t offset = hmac[19] & 0x0f;
+        uint32_t r = (
+                        ((uint32_t)((hmac[offset + 0] & 0x7f)) << 24) |
+                        ((uint32_t)((hmac[offset + 1] & 0xff)) << 16) |
+                        ((uint32_t)((hmac[offset + 2] & 0xff)) << 8) |
+                        ((uint32_t)(hmac[offset + 3] & 0xff))
+                    ) % 1000000;
+        lua_pushinteger(L,r);
+        return 1;
+    }
+    return 0;
+}
+
 #include "rotable.h"
 static const rotable_Reg reg_crypto[] =
 {
@@ -383,6 +421,7 @@ static const rotable_Reg reg_crypto[] =
     { "crc32",          l_crypto_crc32          ,0},
     { "crc8",           l_crypto_crc8           ,0},
     { "trng",           l_crypto_trng           ,0},
+    { "totp",           l_crypto_totp           ,0},
 	{ NULL,             NULL                    ,0}
 };