准备:

  一个谷歌二步验证APP,  我用的是ios 身份宝

资料:

  1.Google Authenticator 原理及Java实现   //主要参考

    https://blog.csdn.net/lizhengjava/article/details/76947962#

  2.谷歌验证 (Google Authenticator) 的实现原理是什么?

    https://www.zhihu.com/question/20462696

  3.谷歌验证,又称两步验证,

    https://www.360shouzhuan.com/android/news/youxi/1632.htm

这个是谷歌二步验证, 获取key, 与验证,

package com.rekoo;

//Google  Authenticator

// 只从google出了双重身份验证后,就方便了大家,等同于有了google一个级别的安全,但是我们该怎么使用google authenticator (双重身份验证),

//下面是java的算法,这样大家都可以得到根据key得到公共的秘钥了,直接复制,记得导入JAR包:
//
//commons-codec-1.8.jar
//
//junit-4.10.jar //测试方法:
//
//1、执行测试代码中的“genSecret”方法,将生成一个KEY(用户为testuser),URL打开是一张二维码图片。
//
//2、在手机中下载“GOOGLE身份验证器”。
//
//3、在身份验证器中配置账户,输入账户名(第一步中的用户testuser)、密钥(第一步生成的KEY),选择基于时间。
//
//4、运行authcode方法将key和要测试的验证码带进去(codes,key),就可以知道是不是正确的秘钥了!返回值布尔 //main我就不写了大家~~因为这个可以当做util工具直接调用就行了
// import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom; import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec; import org.apache.commons.codec.binary.Base32;
import org.apache.commons.codec.binary.Base64; public class GoogleAuthenticator { // taken from Google pam docs - we probably don't need to mess with these
public static final int SECRET_SIZE = 10; public static final String SEED = "g8GjEvTbW5oVSV7avLBdwIHqGlUYNzKFI7izOF8GwLDVKs2m0QN7vxRs2im5MDaNCWGmcD2rvcZx"; public static final String RANDOM_NUMBER_ALGORITHM = "SHA1PRNG"; int window_size = 3; // default 3 - max 17 (from google docs)最多可偏移的时间 public void setWindowSize(int s) {
if (s >= 1 && s <= 17)
window_size = s;
} public static Boolean authcode(String codes, String savedSecret) {
// enter the code shown on device. Edit this and run it fast before the
// code expires!
long code = Long.parseLong(codes);
long t = System.currentTimeMillis();
GoogleAuthenticator ga = new GoogleAuthenticator();
ga.setWindowSize(15); // should give 5 * 30 seconds of grace...
boolean r = ga.check_code(savedSecret, code, t);
return r;
} public static String genSecret(String name) {
String secret = GoogleAuthenticator.generateSecretKey();
//GoogleAuthenticator.getQRBarcodeURL("testuser","testhost", secret);
GoogleAuthenticator.getQRBarcodeURL(name,
"testhost", secret);
return secret;
} public static String generateSecretKey() {
SecureRandom sr = null;
try {
sr = SecureRandom.getInstance(RANDOM_NUMBER_ALGORITHM);
sr.setSeed(Base64.decodeBase64(SEED));
byte[] buffer = sr.generateSeed(SECRET_SIZE);
Base32 codec = new Base32();
byte[] bEncodedKey = codec.encode(buffer);
String encodedKey = new String(bEncodedKey);
return encodedKey;
}catch (NoSuchAlgorithmException e) {
// should never occur... configuration error
}
return null;
} public static String getQRBarcodeURL(String user, String host, String secret) {
String format = "https://www.google.com/chart?chs=200x200&chld=M%%7C0&cht=qr&chl=otpauth://totp/%s@%s%%3Fsecret%%3D%s";
return String.format(format, user, host, secret);
} public boolean check_code(String secret, long code, long timeMsec) {
Base32 codec = new Base32();
byte[] decodedKey = codec.decode(secret);
// convert unix msec time into a 30 second "window"
// this is per the TOTP spec (see the RFC for details)
long t = (timeMsec / 1000L) / 30L;
// Window is used to check codes generated in the near past.
// You can use this value to tune how far you're willing to go.
for (int i = -window_size; i <= window_size; ++i) {
long hash;
try {
hash = verify_code(decodedKey, t + i);
}catch (Exception e) {
// Yes, this is bad form - but
// the exceptions thrown would be rare and a static configuration problem
e.printStackTrace();
throw new RuntimeException(e.getMessage());
//return false;
}
if (hash == code) {
return true;
}
}
// The validation code is invalid.
return false;
} private static int verify_code(byte[] key, long t) throws NoSuchAlgorithmException, InvalidKeyException {
byte[] data = new byte[8];
long value = t;
for (int i = 8; i-- > 0; value >>>= 8) {
data[i] = (byte) value;
}
SecretKeySpec signKey = new SecretKeySpec(key, "HmacSHA1");
Mac mac = Mac.getInstance("HmacSHA1");
mac.init(signKey);
byte[] hash = mac.doFinal(data);
int offset = hash[20 - 1] & 0xF;
// We're using a long because Java hasn't got unsigned int.
long truncatedHash = 0;
for (int i = 0; i < 4; ++i) {
truncatedHash <<= 8;
// We are dealing with signed bytes:
// we just keep the first byte.
truncatedHash |= (hash[offset + i] & 0xFF);
}
truncatedHash &= 0x7FFFFFFF;
truncatedHash %= 1000000;
return (int) truncatedHash;
} public static void main(String[] args) {
String secret = genSecret("testuser");//获取key
System.out.println("secret : "+secret);
String key = "";
Boolean authcode = authcode(key, secret);//验证
if(authcode){
System.out.printf("真...........");
}else {
System.out.printf("假.........");
}
} }

最后: 亲爱的读者, 可以粉我一下吗?

java实现谷歌二步验证 (Google Authenticator)的更多相关文章

  1. PHP设置谷歌验证器(Google Authenticator)实现操作二步验证

    使用说明:开启Google的登陆二步验证(即Google Authenticator服务)后用户登陆时需要输入额外由手机客户端生成的一次性密码.实现Google Authenticator功能需要服务 ...

  2. 谷歌验证 (Google Authenticator) 的实现原理是什么?

    著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处.作者:徐小花链接:http://www.zhihu.com/question/20462696/answer/18731073来源: ...

  3. 黄聪:谷歌验证 (Google Authenticator) 的实现原理是什么?

    著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处.作者:徐小花链接:http://www.zhihu.com/question/20462696/answer/18731073来源: ...

  4. TOTP算法实现二步验证

    概念 TOTP算法(Time-based One-time Password algorithm)是一种从共享密钥和当前时间计算一次性密码的算法. 它已被采纳为Internet工程任务组标准RFC 6 ...

  5. Python使用otp实现二步验证

    https://www.cnblogs.com/lori/p/11077161.html https://blog.coding.net/blog/two-factor-authentication ...

  6. python根据密钥得到谷歌两步验证动态验证码

    # coding=utf-8 import time import base64 import sys import hashlib import hmac import struct def goo ...

  7. net core 接入 Google Authenticator

    一.什么谷歌身份验证器 1.英文名:Authenticator 许网站都需要绑定用以对相关账号进行“二步验证”保护,也叫“双重身份验证”的谷歌身份验证器,以加强安全级别. 2.作用: 这东西就相当于银 ...

  8. TeamViewer如何绑定谷歌二次验证码/谷歌身份验证?

    1.下载TeamViewer,找到谷歌二次验证界面 下载.注册TeamViewer后,点击右上角账户名-“编辑配置文件” [常规]-“双重验证”,点“启用”   进入[激活双重验证]界面,点“启动激活 ...

  9. 使用KeePass管理两步验证

    目录 使用KeePass管理两步验证 两步验证 KeePass中管理两步验证 KeeTrayTOTP插件使用 使用KeePass管理两步验证 文:铁乐与猫 2018-9-9 KeePass 是一款管理 ...

随机推荐

  1. Java中的方法重载与方法重写

    重载(overload) 重载是在一个类中,同名方法拥有不同的参数列表则视为重载.不同的参数列表包括:参数数量不同,参数类型不同,参数顺序不同.重载对于返回类型没有要求,所以不能通过返回类型去判断是否 ...

  2. Python 部分系统类的常用方法整理

    下面是常用的几个系统类的常用方法整理: list: 列表[1, 2,...] set: 集合,无重复元素{1, 2,...} str: 字符串 dict: 字典{a:'a', b:'b',...} T ...

  3. viewer.js 视图预览demo

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8&quo ...

  4. Laravel 系列入门教程(二)【最适合中国人的 Laravel 教程】

    本篇文章中,我将跟大家一起体验 Laravel 框架最重要的部分——路由系统. 如果你读过 2015 版的教程,你会发现那篇文章里大书特书的 Auth 系统构建已经被 Laravel 捎带手给解决了. ...

  5. 如何清除浮动(float)所带来的影响

    清除浮动(float) 1.定义和用法 在w3c中给了浮动这样的定义. "float 属性定义元素在哪个方向浮动.以往这个属性总应用于图像,使文本围绕在图像周围,不过在 CSS 中,任何元素 ...

  6. 2017-11-07 中文代码示例之Angular入门教程尝试

    "中文编程"知乎专栏原址 原文: 中文代码示例教程之Angular尝试 为了检验中文命名在Angular中的支持程度, 把Angular官方入门教程的示例代码中尽量使用了中文命名. ...

  7. spring学习总结——装配Bean学习一(自动装配)

    一.Spring配置的可选方案 Spring容器负责创建应用程序中的bean并通过DI来协调这些对象之间的关系.但是,作为开发人员,你需要告诉Spring要创建哪些bean并且如何将其装配在一起.当描 ...

  8. 【MM系列】SAP里批量设置采购信息记录删除标记

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[MM系列]SAP里批量设置采购信息记录删除标记 ...

  9. [Hive_add_7] Hive 实现最高气温统计

    0. 说明 Hive 通过 substr() 函数实现最高气温统计 1. Hive 实现最高气温统计 1.1 思路 将一行文本加载为 String 通过 substr() 函数截取年份和温度 1.2 ...

  10. Leancloud+Valine打造Hexo个人博客极简评论系统

    以下配置是基于Next主题6.1.0版本 效果见个人博客的最下方评论. Leancloud配置 首先访问Leancloud官网https://leancloud.cn/ 有Github账号的小伙伴可以 ...