两步验证支持库

kio 2024-1-3 1499 v 1.0.1 2024-01-03

把开源的一个两步验证写成aardio格式了,抛砖引玉,希望aardio生态越来越好。

Code AardioLine:82复制
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
    • //otp 动态令牌两步验证支持库
    • namespace kio;
    • import com;
    • import dotNet;
    • import System;
    • //参考:https://githubfast.com/kspearrin/Otp.NET
    • namespace otp {
    • dll = ..dotNet.loadFile($ "~\lib\kio\otp\Otp.NET.dll");
    • base = dll.import("OtpNet");
    • Base32 = function() {
    • return base.Base32Encoding();
    • }
    • Hotp = function(secretKey, mode = 0, totpSize = 6) {
    • return base.Hotp(Base32().ToBytes(secretKey), mode, totpSize);
    • }
    • Totp = function(secretKey, step = 30, mode = 0, totpSize = 6) {
    • return base.Totp(Base32().ToBytes(secretKey), step, mode, totpSize);
    • }
    • VerificationWindow = function(previous = 0, future = 0) {
    • return base.VerificationWindow(previous, future);
    • }
    • OtpUri=function(secrt,user,issuer,otptype=0,mode=0,digits=6,period=30,couner=0){
    • return base.OtpUri(otptype,secrt,user,issuer,mode,digits,period,couner);
    • }
    • GenerateRandomKey=function(mode = 0){
    • select(mode) {
    • case 2 {
    • mode=64;
    • }
    • case 1 {
    • mode=32;
    • }
    • else {
    • mode=20;
    • }
    • }
    • return base.Base32Encoding().ToString(base.KeyGeneration.GenerateRandomKey(mode));
    • }
    • }
    • /**intellisense(kio)
    • otp = otp动态令牌操作库(两步验证)
    • end intellisense**/
    • /**intellisense(kio.otp)
    • Base32()=创建Base32\n!Base32.
    • GenerateRandomKey(__)=创建随机密钥,默认Sha1模式\n参数: 0 Sha1 \n 1 Sha256 \n 2 Sha512
    • Hotp("__")=创建Hotp,事件同步一次性密码\n!Hotp.
    • Hotp("__",mode,totpSize)=创建Hotp,事件同步一次性密码\n参数1:字符串,Base32格式secret\n参数2:模式,Sha1 0 Sha256 1 Sha512 2\n参数3:验证码长度,常见6或8\n!Hotp.
    • Totp("__")=创建Totp,时间同步一次性密码\n参数:字符串,Base32格式secret,默认30s刷新6位长度Sha1\n!Totp.
    • Totp("__",step,mode,totpSize)=创建Totp,时间同步一次性密码\n参数1:字符串,Base32格式secret\n参数2:刷新时间,15或30或60\n参数3:模式,Sha1 0 Sha256 1 Sha512\n参数4:验证码长度,常见6或8\n!Totp.
    • VerificationWindow()=创建VerificationWindow\n参数1:整数,Base32格式secret\n参数2:整数\n!VerificationWindow.
    • OtpUri("__","user","isuser",0/*Totp*/,0/*sha1*/,6,30,0/*counter*/)=创建OtpUri\n!OtpUri.
    • OtpUri("__","user")=创建OtpUri,默认totp,sha1,6,30\n!OtpUri.
    • Totp()=!Totp.
    • Hotp()=!Hotp.
    • OtpUri()=!OtpUri.
    • end intellisense**/
    • /**intellisense(!OtpUri)
    • ToString()=返回字符串
    • end intellisense**/
    • /**intellisense(!Totp)
    • ComputeTotp()=验证码
    • RemainingSeconds()=剩余秒数
    • VerifyTotp=@//基于RFC建议验证,通过返回true\n//参数1:字符串验证码\n//参数2:C# out timeWindowUsed的长输出\n//参数3:RFC建议允许延迟一个步长,如创建时步长15则验证时间为30,以此类推\n\nvar rfc=kio.otp.VerificationWindow(1,1)\nvar timeWindowUsed=com.long(0)\nvar t=__.VerifyTotp("000000",timeWindowUsed,rfc.RfcSpecifiedNetworkDelay)\nconsole.log(t)\n
    • end intellisense**/
    • /**intellisense(!Hotp)
    • ComputeHOTP(0/*计数器*/)=验证码\n参数1:整数,计数器
    • VerifyHotp("__",0)=验证,通过返回true\n参数1:字符串,待验证的码\n参数2:整数,计数器
    • end intellisense**/
    • /**intellisense(!Base32)
    • ToBytes("__")=Base32到字节数组\n参数:字符串,Base32编码
    • ToString(__)=字节数组到Base32\n参数:字节数组,raw.buffer()
    • end intellisense**/
    • /**intellisense(!VerificationWindow)
    • RfcSpecifiedNetworkDelay=只读属性
    • end intellisense**/

    附件含有demo演示,可以下载查看

    用法:kio整个文件夹解压到lib

    上传的附件:
    • kio.7z (大小:8.77K,下载次数:667)
    最新回复 (8)
    • aika107 2024-1-3
      0 2
      顶,感谢!
    • ccbwx 2024-1-3
      0 3
    • cyzn_lfss 2024-1-5
      0 4
      虽然不知道怎么用,但是要感谢您的分享!
    • 光庆 2024-1-5
      0 5
      请楼主详细介绍一下呗,貌似不错的东西,不会用多可惜啊
    • 光庆 2024-1-5
      0 6

      两步验证

      两步验证(双因素身份验证)是一种用于验证用户身份的安全技术,它会配合用户账户的密码,用另一种验证方法(如短信验证、手机应用程序验证等)来确认用户的登录身份。这样即使黑客能够获得用户的密码,也无法验证其身份,除非使用另一种可用于验证的方法。两步验证在今天,成了一种最佳安全标准,被广泛应用在多种重要场景中,如支付、网络账户登录等。

      两步验证的原理与对密码的安全保护概念同构,就是通过同时使用多种验证方法,来验证用户的账户与其所使用的设备,以此来阻止恶意黑客的访问。

      两步验证可以有效地防止恶意黑客攻击,一般常用的双因素身份验证方法包括:

      1、基于短信的身份验证:必须输入短信验证码才能登录或访问该系统,短信验证码发送到注册时填写的手机号上。

      2、基于应用程序的身份验证:使用应用程序,比如Google身份验证器和微软身份验证器,可以发送随机生成的验证码到用户手机上,来确认用户是否真实存在。

      3、基于动态令牌的身份验证:用户需要插入一个动态令牌,只有这个动态令牌上的数字才能被用来登录。

      4、生物识别的身份验证:这种方式主要是使用指纹或脸部特征来验证身份;而面部识别则是捕捉用户面部特征,将其比较与注册时的数据,来实时验证访问者的身份。

      两步验证使用得越多,可以让系统与设备得到更加全面的保护,减少被恶意攻击的风险。因此值得强调的是,尽量使用两步验证来保护自己的账户信息,安全起见,最好不要在公共场所使用未经验证的账户与设备;另外,应定期更新账户的安全存储位置,如果需要安装新的安全软件,也应及时安装更新。


    • 光庆 2024-1-5
      0 7

      在互联网时代中大家的账号越来越多,因此管理起来很麻烦,利用密码管理器可以很大程度上减轻负担,但如今只使用一个强密码或许已经不足以保护账户。

      两步验证应运而生

      顾名思义,两步验证2FA是指登陆账户时需要两次验证,第一次验证就是传统的账号+密码,第二次验证,目前有多种方案,常见的是短信验证码,但随着黑客技术发展,窃取拦截手机短信已成为可能,因此虚拟验证器Authenticator,逐渐成为主流两步验证方案。

      它们大多使用TOTP算法,因此虚拟验证器大多是通用的

      TOTP算法(Time-based One-time Password algorithm)是一种从共享密钥和当前时间计算一次性密码的算法。 它已被采纳为Internet工程任务组标准RFC 6238,是Initiative for Open Authentication(OATH)的基石,并被用于许多双因素身份验证系统。

      对于,银行账户、网盘等重要账户强烈建议大家开启两步验证

      目前常用的虚拟验证器有Google Authenticator、Microsoft Authenticator 、Authy 、QQ安全中心(仅用于QQ服务)等,其中以Google Authenticator最为常见(出现时间早)


    • bob 2024-1-9
      0 8
      Code AardioLine:111复制
    • 1.
    • 2.
    • 3.
    • 4.
    • 5.
    • 6.
    • 7.
    • 8.
    • 9.
    • 10.
    • 11.
    • 12.
    • 13.
    • 14.
    • 15.
    • 16.
    • 17.
    • 18.
    • 19.
    • 20.
    • 21.
    • 22.
    • 23.
    • 24.
    • 25.
    • 26.
    • 27.
    • 28.
    • 29.
    • 30.
    • 31.
    • 32.
    • 33.
    • 34.
    • 35.
    • 36.
    • 37.
    • 38.
    • 39.
    • 40.
    • 41.
    • 42.
    • 43.
    • 44.
    • 45.
    • 46.
    • 47.
    • 48.
    • 49.
    • 50.
    • 51.
    • 52.
    • 53.
    • 54.
    • 55.
    • 56.
    • 57.
    • 58.
    • 59.
    • 60.
    • 61.
    • 62.
    • 63.
    • 64.
    • 65.
    • 66.
    • 67.
    • 68.
    • 69.
    • 70.
    • 71.
    • 72.
    • 73.
    • 74.
    • 75.
    • 76.
    • 77.
    • 78.
    • 79.
    • 80.
    • 81.
    • 82.
    • 83.
    • 84.
    • 85.
    • 86.
    • 87.
    • 88.
    • 89.
    • 90.
    • 91.
    • 92.
    • 93.
    • 94.
    • 95.
    • 96.
    • 97.
    • 98.
    • 99.
    • 100.
    • 101.
    • 102.
    • 103.
    • 104.
    • 105.
    • 106.
    • 107.
    • 108.
    • 109.
    • 110.
    • 111.
      • Google2FA = class {
      • ctor( ){
      • keyRegeneration = 30; // 密钥生成间隔周期时间(单位/秒)
      • otpLength = 6; // 生成令牌长度
      • lut = { A = 0; B = 1; C = 2; D = 3; E = 4; F = 5; G = 6; H = 7;
      • I = 8; J = 9; K = 10; L = 11; M = 12; N = 13; O = 14; P = 15;
      • Q = 16; R = 17; S = 18; T = 19; U = 20; V = 21; W = 22; X = 23;
      • Y = 24; Z = 25; ['2'] = 26; ['3'] = 27; ['4'] = 28; ['5'] = 29;['6'] = 30;['7']= 31
      • }
      • };
      • math.randomize();
      • generate_secret_key = function() {
      • var key = {"2";"3";"4";"5";"6";"7";"Q";"W";"E";"R";"T";"Y";"U";"I";"O";"P";"A";"S";"D";"F";"G";"H";"J";"K";"L";"Z";"X";"C";"V";"B";"N";"M"};
      • var s = "";
      • for(i=1;16){
      • s ++= key[math.random(1,32)];
      • }
      • return s;
      • }
      • get_timestamp = function() {
      • return math.floor(tonumber(time.now())/keyRegeneration);
      • }
      • base32_decode = function(key){
      • var key = string.upper(key);
      • var tab_key = string.split(key);
      • var n = 0
      • var j = 0
      • var sec_key = "";
      • for(i=1;16){
      • n = n<<5;
      • n = n + lut[tab_key[i]]
      • j = j + 5;
      • if(j>=8){
      • j = j-8
      • sec_key ++= string.pack(( n & (0xFF << j)) >> j);
      • }
      • }
      • return sec_key;
      • }
      • pack = function(num){
      • var tab = {};
      • var val = num % 256;
      • table.insert(tab,val);
      • for(i=1;3){
      • num = math.floor(num / 256);
      • val = num % 256;
      • table.insert(tab,val);
      • }
      • return string.pack(tab);
      • }
      • oath_truncate = function(hash){
      • var tab_hash ={}
      • for m in string.gmatch(hash,".") {
      • table.push(tab_hash,m)
      • }
      • var offset = string.unpack(tab_hash[20]) & 0xf;
      • return (((string.unpack(tab_hash[offset+1]) & 0x7f) << 24 ) |
      • ((string.unpack(tab_hash[offset+2]) & 0xff) << 16 ) |
      • ((string.unpack(tab_hash[offset+3]) & 0xff) << 8 ) |
      • (string.unpack(tab_hash[offset+4]) & 0xff)) % 10**otpLength;
      • }
      • oath_hotp = function(key,timestamp){
      • bin_counter = this.pack(0) ++ this.pack(timestamp);
      • hash = crypt.hmac(this.base32_decode(key),bin_counter).getValue();
      • return this.oath_truncate(hash);
      • }
      • verify_key = function(keyseed,otpkey){
      • var result = false;
      • var timeStamp = this.get_timestamp();
      • for(i=timeStamp-4;timeStamp+4;1){
      • if (this.oath_hotp(keyseed,i) == otpkey) return true;
      • }
      • return result;
      • }
      • qrcode = function(accout,key){
      • return "otpauth://totp/"++string.trim(accout)++"?secret="++key;
      • }
      • }
      • namespace Google2FA{
      • import crypt.hmac;
      • import math;
      • table = ..table;
      • string = ..string;
      • time = ..time;
      • }
      • /*intellisense()
      • Google2FA() = 初始化常量;
      • Google2FA() = !Google2FA.
      • !Google2FA.generate_secret_key() = 生成随机密钥
      • !Google2FA.get_timestamp() = 指定时间戳
      • !Google2FA.oath_hotp(随机密钥,指定时间戳) = 生成一次性密码
      • !Google2FA.verify_key(随机密码,一次性密码) = 验证一次性密码
      • !Google2FA.qrcode(帐号,随机密码) = 生成可用于二维码显示的URI地址
      • end intellisense*/

      给来个aardio原生的

    • 光庆 2024-1-9
      0 9
      bob Google2FA&nbsp;=&nbsp;class&nbsp;{ ctor(&nbsp;){ keyRegeneration&nbsp;=& ...

      你重开一贴,顺便弄个例程上来,我给你收藏一下呗

    返回