验证码生成工具google authenticator

本文详细介绍了如何使用Google Authenticator进行两步验证的实现步骤,包括定义种子秘钥、生成私钥、在APP中获取验证码以及校验验证码的过程。主要代码示例展示了如何在Java中生成和校验密钥,对于iOS和Android应用,可以搜索相关教程获取更多信息。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

1.定义种子秘钥

2.生成私钥

3.根据私钥到app应用上获取验证

4.校验验证码


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

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

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

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

1.定义种子秘钥

种子秘钥根据项目自己定义一个高复杂度的秘钥

代码中这段

public static final String SEED = "F583513762484929976ED25B18FDE6B4";

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

@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);
    }

}

2.生成私钥

String secretKey = generateSecretKey(); 生成私钥 ,生成的私钥配置到app中,名称随便,秘钥填生成的,实际使用中你有可能使用接口api或者扫描方式来调用接口获取

3.根据私钥到app应用上获取验证

     生成的私钥配置到app中,名称随便,秘钥填生成的,即可立即获取

4.校验验证码

登录校验则是这段核心,取用户配置的私钥+传递过来的6位验证码

check_code("KISNJ4O2OMHKB73F", Long.valueOf("943952"), System.currentTimeMillis());

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

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

### 解析多设备登录时 Authenticator 验证码无效的原因 当遇到 Google Authenticator 在不同设备上生成验证码无效的情况,通常是因为时间同步问题或者密钥配置不一致所引起的[^3]。 #### 时间同步问题 Google Authenticator 使用的是基于时间的一次性密码 (TOTP),这意味着客户端的时间戳必须与服务器端保持高度同步。如果多个设备之间存在显著的时间差异,则可能导致生成验证码无法通过验证。 #### 密钥一致性校验 确保用于初始化各个设备上的 Google Authenticator 应用程序的共享秘密(secret key)完全相同非常重要。任何细微差别都会影响到最终计算出来的 TOTP 值。因此,在分发 secret key 给用户之前,请仔细核对其准确性并指导用户正确输入。 ```java // 示例代码展示如何处理登录请求中的验证码验证逻辑 @PostMapping("/login") public ResponseEntity login(@RequestBody Map<String, Object> requestBody) { String phone = (String)requestBody.get("phone"); String code = (String)requestBody.get("code"); // 进行验证码有效性检查前先确认服务端时间和客户端时间偏差范围内的容忍度设置合理 boolean isValidCode = userService.validateTotpCode(phone, code); if (!isValidCode){ throw new RuntimeException("Invalid verification code."); } return ResponseEntity.ok(null); } ``` 对于 iOS 设备特别需要注意的是,部分情况下由于操作系统特性可能会导致某些字符编码转换错误从而使得导入 Secret Key 出现问题。建议采用 QR Code 方式来传递 Secret Key 而不是手动输入字符串形式的 Base32 编码数据。 ### 提供统一且可靠的登录体验 考虑到用户体验以及安全性需求,可以考虑实现更加灵活的身份验证机制支持多种登录方式,如短信验证码、电子邮件链接等作为备用选项之一[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值