Google Authenticator(谷歌身份验证器)

news/2024/11/29 11:43:53/

Google Authenticator(谷歌身份验证器)

什么是认证器?怎么对接?

Google Authenticator(谷歌身份验证器)是谷歌推出的一个动态密令工具,它有两种密令模式。分别是“TOTP 基于时间”、“HOTP 基于计数器”,通过手机上 简单的设置就可以设定自己独一的动态密令, 那么我们怎么将我们的程序和认证器进行对接呢?其实谷歌认证器并不是需要我们对接这个工具的API而是通过算法来决定,谷歌使用使用HMAC算法生成密令,通过基于次数或者基于时间两个模板进行计算,因此在程序中只需要使用相同的算法即可与之匹配。

TOTP 基于时间

  • HMAC算法使用固定为HmacSHA1
  • 更新时长固定为30秒
  • APP端输入数据维度只有两个:账户名称(自己随意填写方便自己查看)和base32格式的key

HOTP 基于计数器

基于计数器模式是根据一个共享秘钥K和一个C计数器进行算法计算

认证器安装

手机需要安装认证器:

  • Android版:安卓版下载
  • IOS版:苹果版下载

1、Base32.cs

using System;namespace GoogleAuthorization
{public static class Base32{public static byte[] ToBytes(string input){if (string.IsNullOrEmpty(input)){throw new ArgumentNullException("input");}input = input.TrimEnd('='); int byteCount = input.Length * 5 / 8; byte[] returnArray = new byte[byteCount];byte curByte = 0, bitsRemaining = 8;int mask = 0, arrayIndex = 0;foreach (char c in input){int cValue = CharToValue(c);if (bitsRemaining > 5){mask = cValue << (bitsRemaining - 5);curByte = (byte)(curByte | mask);bitsRemaining -= 5;}else{mask = cValue >> (5 - bitsRemaining);curByte = (byte)(curByte | mask);returnArray[arrayIndex++] = curByte;curByte = (byte)(cValue << (3 + bitsRemaining));bitsRemaining += 3;}}if (arrayIndex != byteCount){returnArray[arrayIndex] = curByte;}return returnArray;}public static string ToString(byte[] input){if (input == null || input.Length == 0){throw new ArgumentNullException("input");}int charCount = (int)Math.Ceiling(input.Length / 5d) * 8;char[] returnArray = new char[charCount];byte nextChar = 0, bitsRemaining = 5;int arrayIndex = 0;foreach (byte b in input){nextChar = (byte)(nextChar | (b >> (8 - bitsRemaining)));returnArray[arrayIndex++] = ValueToChar(nextChar);if (bitsRemaining < 4){nextChar = (byte)((b >> (3 - bitsRemaining)) & 31);returnArray[arrayIndex++] = ValueToChar(nextChar);bitsRemaining += 5;}bitsRemaining -= 3;nextChar = (byte)((b << bitsRemaining) & 31);}if (arrayIndex != charCount){returnArray[arrayIndex++] = ValueToChar(nextChar);while (arrayIndex != charCount) returnArray[arrayIndex++] = '='; }return new string(returnArray);}private static int CharToValue(char c){var value = (int)c;if (value < 91 && value > 64){return value - 65;}if (value < 56 && value > 49){return value - 24;}if (value < 123 && value > 96){return value - 97;}throw new ArgumentException("Character is not a Base32 character.", "c");}private static char ValueToChar(byte b){if (b < 26){return (char)(b + 65);}if (b < 32){return (char)(b + 24);}throw new ArgumentException("Byte is not a value Base32 value.", "b");}}
}

2、GoogleAuthenticator.cs

using GoogleAuthorization;
using System;
using System.Security.Cryptography;
using System.Text;namespace GoogleAuthenticator
{public class GoogleAuthenticator{/// <summary>/// 初始化验证码生成规则/// </summary>/// <param name="key">秘钥(手机使用Base32码)</param>/// <param name="duration">验证码间隔多久刷新一次(默认30秒和google同步)</param>public GoogleAuthenticator(string key){this.SERECT_KEY = key;this.SERECT_KEY_MOBILE = Base32.ToString(Encoding.UTF8.GetBytes(key));this.DURATION_TIME = 30;}/// <summary>/// 初始化验证码生成规则/// </summary>/// <param name="key">秘钥(手机使用Base32码)</param>/// <param name="duration">验证码间隔多久刷新一次(默认30秒和google同步)</param>public GoogleAuthenticator(long duration = 30, string key = "test"){this.SERECT_KEY = key;this.SERECT_KEY_MOBILE = Base32.ToString(Encoding.UTF8.GetBytes(key));this.DURATION_TIME = duration;}/// <summary>/// 间隔时间/// </summary>private long DURATION_TIME { get; set; }/// <summary>/// 迭代次数/// </summary>private long COUNTER{get{return (long)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds / DURATION_TIME;}}/// <summary>/// 秘钥/// </summary>private string SERECT_KEY { get; set; }/// <summary>/// 手机端输入的秘钥/// </summary>private string SERECT_KEY_MOBILE { get; set; }/// <summary>/// 到期秒数/// </summary>public long EXPIRE_SECONDS{get{return (DURATION_TIME - (long)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds % DURATION_TIME);}}/// <summary>/// 获取手机端秘钥/// </summary>/// <returns></returns>public string GetMobilePhoneKey(){if (SERECT_KEY_MOBILE == null)throw new ArgumentNullException("SERECT_KEY_MOBILE");return SERECT_KEY_MOBILE;}/// <summary>/// 生成认证码/// </summary>/// <returns>返回验证码</returns>public string GenerateCode(){return GenerateHashedCode(SERECT_KEY, COUNTER);}/// <summary>/// 按照次数生成哈希编码/// </summary>/// <param name="secret">秘钥</param>/// <param name="iterationNumber">迭代次数</param>/// <param name="digits">生成位数</param>/// <returns>返回验证码</returns>private string GenerateHashedCode(string secret, long iterationNumber, int digits = 6){byte[] counter = BitConverter.GetBytes(iterationNumber);if (BitConverter.IsLittleEndian)Array.Reverse(counter);byte[] key = Encoding.ASCII.GetBytes(secret);HMACSHA1 hmac = new HMACSHA1(key, true);byte[] hash = hmac.ComputeHash(counter);int offset = hash[hash.Length - 1] & 0xf;int binary =((hash[offset] & 0x7f) << 24)| ((hash[offset + 1] & 0xff) << 16)| ((hash[offset + 2] & 0xff) << 8)| (hash[offset + 3] & 0xff);int password = binary % (int)Math.Pow(10, digits); // 6 digitsreturn password.ToString(new string('0', digits));}}
}

 

3、使用方法

 string user_Code = Request["Google_Code"].ToString();string google_key = Common.PDDCommon.GetCode_GoogleAuthenticator(phone);if (string.IsNullOrEmpty(googleCode) || google_key.ToUpper() != googleCode.ToUpper()){json = SerializerJson.SuccessFlagToJson(0, "谷歌验证码不正确!");Response.Clear();Response.Write(json);Response.End();}

案例地址:

git:https://github.com/CN-Yi/GoogleAuthenticator

gitee:https://gitee.com/hsyi/GoogleAuthenticator


http://www.ppmy.cn/news/370424.html

相关文章

GoogleMap——谷歌地图Api的使用

最近公司想要在国外也使用地图功能&#xff0c;而我们国内使用的是高德地图&#xff0c;国外客户需要用谷歌地图&#xff0c;所以去了解了一下谷歌地图的使用&#xff0c;这里记录一下。 准备工作 首先你得有一个谷歌账号&#xff0c;然后得用一点小魔法&#xff0c;去谷歌地…

centos7安装谷歌Google浏览器

CentOS&#xff1a;1.配置yum下载源 cd /etc/yum.repos.d vim google-chrome.repo ## 配置下载源; [google-chrome] namegoogle-chrome baseurlhttp://dl.google.com/linux/rpm/stable/$basearch enable1 gpgcheck1 gpgkeyhttps://dl-ssl.google.com/linux/linux_signing_key.…

谷歌 Pixel 4 人像模式拍照算法揭秘

点击我爱计算机视觉标星&#xff0c;更快获取CVML新技术 文 / Neal Wadhwa&#xff0c;软件工程师和 Yinda Zhang&#xff0c;研究员&#xff0c; Google Research 人像模式是 Pixel 系列手机中相机的一个功能&#xff0c;任何人均能通过此功能拍摄出专业的浅景深图像。人像模式…

谷歌Pixel 4神奇在哪儿? AI黑科技带来四大改变!

图1&#xff1a;谷歌最新款旗舰智能手机Pixel 4 不久前在纽约硬件发布会上首次亮相后&#xff0c;谷歌2019年款旗舰智能手机Pixel 4和Pixel 4 XL本周开始销售。 与前三个版本类似&#xff0c;人工智能&#xff08;AI&#xff09;为Pixel许多独有的新功能和改进提供了动力。 这款…

编码生成矩阵与检错监督矩阵

本专栏包含信息论与编码的核心知识&#xff0c;按知识点组织&#xff0c;可作为教学或学习的参考。markdown版本已归档至【Github仓库&#xff1a;https://github.com/timerring/information-theory 】或者公众号【AIShareLab】回复 信息论 获取。 文章目录 线性分组码基本概念…

联想小新air14 2021款笔记本和小新pro14的区别哪个好

联想小新air14 2021款采用了1920*1080分辨率和16:9屏幕比例&#xff0c;联想小新Pro 14 2021采用全金属机身&#xff0c;轻至1.33Kg&#xff0c;薄至14.6mm。配备一块2.2K超高清雾面屏&#xff0c;22401400分辨率&#xff0c;100% sRGB&#xff08;典型值&#xff09;&#xff…

详解数据仓库和数据集市:ODS、DW、DWD、DWM、DWS、ADS

何为数仓DW Data warehouse&#xff08;可简写为DW或者DWH&#xff09;数据仓库&#xff0c;是在数据库已经大量存在的情况下&#xff0c;它是一整套包括了etl、调度、建模在内的完整的理论体系。 数据仓库的方案建设的目的&#xff0c;是为前端查询和分析作为基础&#xff0…

https://zhuanlan.zhihu.com/p/34897270

https://zhuanlan.zhihu.com/p/34897270