hotp案例-Java

发布时间:2023年12月17日

hotp案例-Java

在这里插入图片描述

在这里插入图片描述

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.time.Instant;

public class OTPGenerator {

    public static void main(String[] args) {
        // 设置共享的密钥,此密钥应该与客户端共享
        String sharedSecret = "mySharedSecretKey";

        // 生成 TOTP 验证码
        String totp = generateTOTP(sharedSecret);
        System.out.println("生成的TOTP验证码: " + totp);

        // 模拟客户端验证过程
        boolean isVerified = verifyTOTP(sharedSecret, totp);
        if (isVerified) {
            System.out.println("TOTP验证通过");
        } else {
            System.out.println("TOTP验证失败");
        }
    }

    public static String generateTOTP(String sharedSecret) {
        long timeStep = 30; // 时间步长,通常为30秒
        long currentTime = Instant.now().getEpochSecond();
        long timeWindow = currentTime / timeStep;

        try {
            // 将密钥转换为字节数组
            byte[] keyBytes = sharedSecret.getBytes();

            // 创建一个HMAC算法的实例
            Mac hmac = Mac.getInstance("HmacSHA1");
            SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "RAW");
            hmac.init(keySpec);

            // 将时间窗口转换为字节数组
            byte[] timeWindowBytes = longToBytes(timeWindow);

            // 计算HMAC
            byte[] hmacResult = hmac.doFinal(timeWindowBytes);

            // 获取HMAC的后10位并计算验证码
            int offset = hmacResult[hmacResult.length - 1] & 0xF;
            int binary =
                    ((hmacResult[offset] & 0x7F) << 24) |
                            ((hmacResult[offset + 1] & 0xFF) << 16) |
                            ((hmacResult[offset + 2] & 0xFF) << 8) |
                            (hmacResult[offset + 3] & 0xFF);

            int otp = binary % 1000000; // 生成六位验证码
            return String.format("%06d", otp);
        } catch (NoSuchAlgorithmException | InvalidKeyException e) {
            e.printStackTrace();
            return null;
        }
    }

    public static boolean verifyTOTP(String sharedSecret, String userEnteredOTP) {
        // 获取当前时间戳
        long currentTime = Instant.now().getEpochSecond();
        long timeStep = 30; // 时间步长,与生成时保持一致

        for (int i = -1; i <= 1; i++) {
            long timeWindow = (currentTime / timeStep) + i;
            String otp = generateTOTP(sharedSecret, timeWindow);

            if (otp.equals(userEnteredOTP)) {
                return true;
            }
        }

        return false;
    }

    public static String generateTOTP(String sharedSecret, long timeWindow) {
        try {
            // 将密钥转换为字节数组
            byte[] keyBytes = sharedSecret.getBytes();

            // 创建一个HMAC算法的实例
            Mac hmac = Mac.getInstance("HmacSHA1");
            SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "RAW");
            hmac.init(keySpec);

            // 将时间窗口转换为字节数组
            byte[] timeWindowBytes = longToBytes(timeWindow);

            // 计算HMAC
            byte[] hmacResult = hmac.doFinal(timeWindowBytes);

            // 获取HMAC的后10位并计算验证码
            int offset = hmacResult[hmacResult.length - 1] & 0xF;
            int binary =
                    ((hmacResult[offset] & 0x7F) << 24) |
                            ((hmacResult[offset + 1] & 0xFF) << 16) |
                            ((hmacResult[offset + 2] & 0xFF) << 8) |
                            (hmacResult[offset + 3] & 0xFF);

            int otp = binary % 1000000; // 生成六位验证码
            return String.format("%06d", otp);
        } catch (NoSuchAlgorithmException | InvalidKeyException e) {
            e.printStackTrace();
            return null;
        }
    }

    public static byte[] longToBytes(long value) {
        byte[] result = new byte[8];
        for (int i = 7; i >= 0; i--) {
            result[i] = (byte) (value & 0xFF);
            value >>= 8;
        }
        return result;
    }
}
文章来源:https://blog.csdn.net/weixin_52236586/article/details/134988821
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。