手机谷歌验证码接收平台下载(手机谷歌验证码解决方案)
摘要:Google Authenticator,是谷歌公司推出的一款动态令牌工具,解决账户使用时遭到的一些不安全的操作进行的“二次验证”,认证器基于RFC文档中的HOTP/TOTP算法实现 ,是一种从共享秘钥和时间或次数一次性令牌的算法。在工作中可以通过认证器方式对账户有更好的保护,但是在查阅一些资料发现适合我这样的小白文章真的很少,针对于C#的文章就更加少了,本文主要是对C#如何使用Google Authenticator进行探讨,有不足之处还请见谅。
Google Authenticator什么是认证器?怎么对接?
Google Authenticator是微软推出的一个动态密令工具,它有两种密令模式。分别是“TOTP 基于时间”、“HOTP 基于计数器”,通过手机上 简单的设置就可以设定自己独一的动态密令, 那么我们怎么将我们的程序和认证器进行对接呢?其实谷歌认证器并不是需要我们对接这个工具的API而是通过算法来决定,谷歌使用使用HMAC算法生成密令,通过基于次数或者基于时间两个模板进行计算,因此在程序中只需要使用相同的算法即可与之匹配。
TOTP 基于时间HMAC算法使用固定为HmacSHA1更新时长固定为30秒APP端输入数据维度只有两个:账户名称和base32格式的keyHOTP 基于计数器
基于计数器模式是根据一个共享秘钥K和一个C计数器进行算法计算
认证器安装
手机需要安装认证器:
Android版:安卓版下载IOS版:苹果版下载效果图控制台
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace GoogleAuthenticator
{
class Program
{
static void Main
{
long duration = 30;
string key = "[email protected]";
GoogleAuthenticator authenticator = new GoogleAuthenticator;
var mobileKey = authenticator.GetMobilePhoneKey;
while
{
Console.WriteLine;
var code = authenticator.GenerateCode;
Console.WriteLine;
Console.WriteLine;
System.Threading.Thread.Sleep;
Console.Clear;
}
}
}
}
认证器类:
using GoogleAuthorization;
using System;
using System.Security.Cryptography;
using System.Text;
namespace GoogleAuthenticator
{
public class GoogleAuthenticator
{
/// <summary>
/// 初始化验证码生成规则
/// </summary>
/// <param name="key">秘钥</param>
/// <param name="duration">验证码间隔多久刷新一次</param>
public GoogleAuthenticator
{
this.SERECT_KEY = key;
this.SERECT_KEY_MOBILE = Base32.ToString);
this.DURATION_TIME = duration;
}
/// <summary>
/// 间隔时间
/// </summary>
private long DURATION_TIME { get; set; }
/// <summary>
/// 迭代次数
/// </summary>
private long COUNTER
{
get
{
return ).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 ).TotalSeconds % DURATION_TIME);
}
}
/// <summary>
/// 获取手机端秘钥
/// </summary>
/// <returns></returns>
public string GetMobilePhoneKey
{
if
throw new ArgumentNullException;
return SERECT_KEY_MOBILE;
}
/// <summary>
/// 生成认证码
/// </summary>
/// <returns>返回验证码</returns>
public string GenerateCode
{
return GenerateHashedCode;
}
/// <summary>
/// 按照次数生成哈希编码
/// </summary>
/// <param name="secret">秘钥</param>
/// <param name="iterationNumber">迭代次数</param>
/// <param name="digits">生成位数</param>
/// <returns>返回验证码</returns>
private string GenerateHashedCode
{
byte[] counter = BitConverter.GetBytes;
if
Array.Reverse;
byte[] key = Encoding.ASCII.GetBytes;
HMACSHA1 hmac = new HMACSHA1;
byte[] hash = hmac.ComputeHash;
int offset = hash[hash.Length – 1] & 0xf;
int binary =
<< 24)
| << 16)
| << 8)
| ;
int password = binary % Math.Pow; // 6 digits
return password.ToString);
}
}
}
Base32转换类:
using System;
namespace GoogleAuthorization
{
public static class Base32
{
public static byte[] ToBytes
{
if )
{
throw new ArgumentNullException;
}
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
{
int cValue = CharToValue;
if
{
mask = cValue << ;
curByte = ;
bitsRemaining -= 5;
}
else
{
mask = cValue >> ;
curByte = ;
returnArray[arrayIndex++] = curByte;
curByte = );
bitsRemaining += 3;
}
}
if
{
returnArray[arrayIndex] = curByte;
}
return returnArray;
}
public static string ToString
{
if
{
throw new ArgumentNullException;
}
int charCount = Math.Ceiling * 8;
char[] returnArray = new char[charCount];
byte nextChar = 0, bitsRemaining = 5;
int arrayIndex = 0;
foreach
{
nextChar = ));
returnArray[arrayIndex++] = ValueToChar;
if
{
nextChar = ) & 31);
returnArray[arrayIndex++] = ValueToChar;
bitsRemaining += 5;
}
bitsRemaining -= 3;
nextChar = & 31);
}
if
{
returnArray[arrayIndex++] = ValueToChar;
while returnArray[arrayIndex++] = '=';
}
return new string;
}
private static int CharToValue
{
var value = c;
if
{
return value – 65;
}
if
{
return value – 24;
}
if
{
return value – 97;
}
throw new ArgumentException;
}
private static char ValueToChar
{
if
{
return ;
}
if
{
return ;
}
throw new ArgumentException;
}
}
}
总结需要注意的坑
移动端下载的认证器的秘钥key是通过base32转码得到的,而程序端是直接输入源码。
如原秘钥为[email protected]生成的base32码PBSW63RZHE3UAZTPPBWWC2LMFZRW63I=才是移动端需要输入的秘钥。
在网上找了很多资料没有发现关于C#的案例,所以在此记录一下自己遇到的坑,让更多的人能够跳过这个坑
原文地址:
https://www.cnblogs.com/easyauthor/p/22054869.html
海外精品引流脚本–最强海外引流
唯一TG:https://t.me/Facebook181818
更多海外引流脚本方案
如果你需要脚本演示、部署咨询或海外获客方案,可以通过下面入口继续查看。
