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

Google Authenticator(谷歌身份验证器)C#版相关推荐

  1. 使用google authenticator(谷歌身份验证器)打造用户登录动态口令

    google authenticator php 服务端 使用php类 直接下载 https://github.com/PHPGangsta/GoogleAuthenticator/raw/maste ...

  2. Google authenticator 谷歌身份验证,实现动态口令

    Google authenticator 谷歌身份验证,实现动态口令 google authenticator php 服务端 使用PHP类 require_once '../PHPGangsta/G ...

  3. 使用C++实现谷歌身份验证器(Google Authenticator)

    使用C++实现谷歌身份验证器(Google Authenticator) 本机环境: windows10 x64位运行环境 1.进入网站:http://slproweb.com/products/Wi ...

  4. 【SpringBoot】61、SpringBoot中使用谷歌身份验证器(Google Authenticator)实现二步身份验证

    Google 身份验证器 Google Authenticator 是谷歌推出的基于时间的一次性密码 (Time-based One-time Password,简称 TOTP),只需要在手机上安装该 ...

  5. 使用谷歌身份验证器(Google Authenticator)保护你的后台

    为何要使用谷歌身份验证器 普通的网站只使用账号.密码.图形验证码进行后台登录.根据我(作为站长)多年的经验来看,这种方式安全性很低,尤其是使用 http 协议,明文的帐号和密码相当于在网络上裸奔.如果 ...

  6. Google Authenticator windows client 谷歌身份验证器 windows 电脑端

    谷歌身份验证器现在有安卓客户端和ios客户端,本人开发了一个windows客户端,基于 .NETFramework v4.7 开发,已在 github 上开源,可以在 github 上直接下载. gi ...

  7. 使用谷歌身份验证器增强SSH安全

    一般大家都是使用账号和密码远程SSH登录管理服务器.但SSH账号和密码很容易泄露,或者经常遭遇暴力破解.咨询过前同事赛赛,他们目前使用了谷歌身份验证器.查看了谷歌身份验证器的github和其它网上文档 ...

  8. 如何为SSH登录建立双因子验证机制(谷歌身份验证器)?

    前言 默认情况下,SSH已经在远程机器之间使用安全的数据通信;但是如果你想为自己的SSH连接添加另外某种安全层,可以添加谷歌身份验证器(Google Authenticator)双因子验证模块,该模块 ...

  9. 二次验证码小程序与谷歌身份验证器不同点是?

    名称1[二次验证码]小程序 名称2 谷歌身份验证器(Google Authenticator) 粗略对比两个产品异同 [二次验证码]小程序 搜索:微信搜索.微信目前65个小程序入口,倒是容易找到它 使 ...

  10. 谷歌身份验证器代码实现

    手机下载谷歌身份验证器,无需联网也可以用. 工具类 public class GoogleAuthenticator{// 生成的key长度( Generate secret key length)p ...

最新文章

  1. oracle加undo+resize,How To resize undo tablespace in Oracle
  2. ubuntu 杀死进程命令
  3. Java的应用领域有哪些呢?分享这几个
  4. VTK:可视化之PointSize
  5. 「CameraCalibration」传感器(相机、激光雷达、其他传感器)标定笔记
  6. redis源码剖析(十六)——服务端思维导图整理
  7. 各种数据库对应的jar包、驱动类名和URL格式
  8. ALM 中查看某个 test 的更改 history 历史
  9. Diango博客--24.单元测试:测试评论应用
  10. Java实现微信扫一扫
  11. sourcetree拉取项目时报错,解决两个冲突
  12. [深入理解Android卷一全文-第六章]深入理解Binder
  13. Qt5/6使用FFmpeg进行视频格式转换的两种方式
  14. java青蛙跳台阶问题
  15. php12生肖是哪个,生肖查询-十二属相年份查询-生肖五行查询-12生肖顺序查询
  16. 微信会员卡-创建会员卡接口post参数字段说明
  17. Java Swing制作超简单版打地鼠小游戏
  18. 突破技术发展瓶颈、成功转型的重要因素
  19. free pascal
  20. 许石林:《赤壁》是《无极》的另一极

热门文章

  1. nextdate函数 c语言,NextDate函数包含3个变量month,day和year,函数的输出为输入日期后一天日期.要求month,day和year满足下列...
  2. 复合梯形公式C语言程序,求运用c++来实现复合梯形公式的代码
  3. Altium Designer 入门及环境配置
  4. Acwing-45. 之字形打印二叉树
  5. Acwing 1227. 分巧克力
  6. 多线程总结--小码哥java
  7. Java利用递归算法实现24点游戏
  8. 阿里云 vps 关机 重启 无法连接
  9. 史上首次!个人所得税退税来了!如何退?怎么操作?
  10. 代码传奇 | 搞罢餐的热血青年到 PHP大神的蜕变——“鸟哥”惠新宸