当前位置: 首页 > news >正文

验证码生成工具google authenticator

应用场景:通过google authenticator 生成验证码进行登录

原理:本文不再陈述,参考网上搜索结果

过程:定义种子秘钥-->生成私钥-->根据私钥到app应用上获取验证--->校验验证码

app: ios 和andriod的app会有一定差异,网上可以找到,ios可以到app store搜索获取

 

以下工具完成:定义种子秘钥-->生成私钥

@Slf4j
public class GoogleAuthenticatorUtils {


    public static final int SECRET_SIZE = 10;// 来自谷歌文档,不用修改
    public static final String SEED = "F583513762484929976ED25B18FDE6B4";// 产生密钥的种子  种子秘钥一个 私钥可以生成多个,main方法中
    public static final String RANDOM_NUMBER_ALGORITHM = "SHA1PRNG";// 安全哈希算法(Secure Hash Algorithm)
    private static Integer window_size = 3;//可偏移的时间 -- 3*30秒的验证时间(客户端30秒生成一次验证码)

    /**
     * 生成密钥
     *
     * @return
     */
    public static String generateSecretKey() {
        SecureRandom sr;
        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);
            return new String(bEncodedKey);
        } catch (Exception e) {
            log.error("generateSecretKey:" + e.getMessage(), e);
        }
        return null;
    }

    /**
     * 校验验证码
     *
     * @param secret
     * @param code
     * @param timeMsec
     * @return
     */
    public static Boolean check_code(String secret, long code, long timeMsec) {
        Base32 codec = new Base32();
        byte[] decodedKey = codec.decode(secret);
        long t = (timeMsec / 1000L) / 30L;
        for (int i = -window_size; i <= window_size; ++i) {
            long hash;
            try {
                hash = verify_code(decodedKey, t + i);
            } catch (Exception e) {
                log.error(e.getMessage(), e);
                throw new RuntimeException("校验异常");
            }
            if (hash == code) {
                return true;
            }
        }
        return false;
    }

    /**
     * 生成验证码
     *
     * @param key
     * @param t
     * @return
     * @throws NoSuchAlgorithmException
     * @throws InvalidKeyException
     */
    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;
        long truncatedHash = 0;
        for (int i = 0; i < 4; ++i) {
            truncatedHash <<= 8;
            truncatedHash |= (hash[offset + i] & 0xFF);
        }
        truncatedHash &= 0x7FFFFFFF;
        truncatedHash %= 1000000;
        return (int) truncatedHash;
    }

    public static void main(String[] args) {
        String secretKey = generateSecretKey();
        System.out.println(secretKey);
        Boolean aBoolean = check_code("KISNJ4O2OMHKB73F", Long.valueOf("943952"), System.currentTimeMillis());
        System.out.println(aBoolean);
    }

}

 

关于私钥,可以通过扫描获取,二维码生成可通过在线二维码生成工具获取,私钥配置到数据库中用于后续登录校验使用(即main方法中实际校验结果)

网上搜索一堆:在线二维码生成工具   生成下载即可;代码方面的可参考搜其他相关二维码生成工具代码

 

相关文章:

  • Mysql日期格式及内置日期函数
  • spring boot 开发单体应用
  • Linux入门之配置网桥
  • 【图像分割-阈值分割】基于灰狼算法二维最大熵多阈值图像分割附matlab代码
  • 【智能优化算法-烟花算法】基于烟花算法求解单目标优化问题含Matlab源码
  • 从零玩转jQuery(基础篇)
  • 微信|QQ扫码登录网页版二维码失效问题解决方案|网站无法访问PC网页版如何解决|安卓软件历史版本下载|FV|fooview悬浮球帮助教程
  • Java项目:JSP唱片销售积分商城管理系统
  • Rust(5): 函数类型
  • 【软件测试】软件测试基础概念总结
  • 【Vue五分钟】 Vue Router的使用场景
  • sftpgo集成minio 测试
  • SPI总线协议详解
  • 【产品设计】产品外观设计的特点与优势
  • SpingBoot自动装配原理
  • Android组件 - 收藏集 - 掘金
  • Apache的80端口被占用以及访问时报错403
  • Bytom交易说明(账户管理模式)
  • js学习笔记
  • Node 版本管理
  • Python3爬取英雄联盟英雄皮肤大图
  • SwizzleMethod 黑魔法
  • Transformer-XL: Unleashing the Potential of Attention Models
  • 跳前端坑前,先看看这个!!
  • 延迟脚本的方式
  • 一些基于React、Vue、Node.js、MongoDB技术栈的实践项目
  • 鱼骨图 - 如何绘制?
  • “十年磨一剑”--有赞的HBase平台实践和应用之路 ...
  • Java总结 - String - 这篇请使劲喷我
  • 基于django的视频点播网站开发-step3-注册登录功能 ...
  • 通过调用文摘列表API获取文摘
  • 资深实践篇 | 基于Kubernetes 1.61的Kubernetes Scheduler 调度详解 ...
  • ​二进制运算符:(与运算)、|(或运算)、~(取反运算)、^(异或运算)、位移运算符​
  • # Panda3d 碰撞检测系统介绍
  • #1014 : Trie树
  • (Git) gitignore基础使用
  • (zhuan) 一些RL的文献(及笔记)
  • (笔记)Kotlin——Android封装ViewBinding之二 优化
  • (编译到47%失败)to be deleted
  • (二)基于wpr_simulation 的Ros机器人运动控制,gazebo仿真
  • (附源码)计算机毕业设计ssm基于B_S的汽车售后服务管理系统
  • (转)mysql使用Navicat 导出和导入数据库
  • ******之网络***——物理***
  • . Flume面试题
  • .“空心村”成因分析及解决对策122344
  • .Net Web项目创建比较不错的参考文章
  • .net 怎么循环得到数组里的值_关于js数组
  • .net连接MySQL的方法
  • .NET企业级应用架构设计系列之技术选型
  • .NET使用HttpClient以multipart/form-data形式post上传文件及其相关参数
  • .Net下使用 Geb.Video.FFMPEG 操作视频文件
  • .net中应用SQL缓存(实例使用)
  • :如何用SQL脚本保存存储过程返回的结果集
  • [ C++ ] STL---string类的使用指南
  • [ 云计算 | AWS ] AI 编程助手新势力 Amazon CodeWhisperer:优势功能及实用技巧