两步验证支持库

kio 10月前 1017 v 1.0.1 2024-01-03

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

//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,下载次数:394)
最新回复 (8)
  • aika107 10月前
    0 2
    顶,感谢!
  • ccbwx 10月前
    0 3
  • cyzn_lfss 10月前
    0 4
    虽然不知道怎么用,但是要感谢您的分享!
  • 光庆 10月前
    0 5
    请楼主详细介绍一下呗,貌似不错的东西,不会用多可惜啊
  • 光庆 10月前
    0 6

    两步验证

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

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

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

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

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

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

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

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


  • 光庆 10月前
    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 10月前
    0 8
    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原生的

  • 光庆 10月前
    0 9
    bob Google2FA&nbsp;=&nbsp;class&nbsp;{ ctor(&nbsp;){ keyRegeneration&nbsp;=& ...

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

返回