java 双因素认证(2FA)TOTP demo

TOTP 的全称是"基于时间的一次性密码"(Time-based One-time Password)。它是公认的可靠解决方案,已经写入国际标准 RFC6238。
很早就知道有这个东西了,一直不知道是怎么实现的.
比如 QQ 安全中心的密钥,U盾,就是动态密码之类的.
今天看到阮一峰老师的博客才知道实现原理.
概念性的东西参考
http://www.ruanyifeng.com/blog/2017/11/2fa-tutorial.html
实现代码:

package totp;

import java.security.MessageDigest;
import java.util.Date;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class TOTP {

    // TC = floor((unixtime(now) − unixtime(T0)) / TS)
    // TC = floor(unixtime(now) / 30)
    // TOTP = HASH(SecretKey, TC)
    private static final char[] HEX_DIGITS = "0123456789abcdef".toCharArray();

    public static void main(String[] args) {

        Pattern pattern = Pattern.compile("\\d");
        String key = UUID.randomUUID().toString().replace("-", "");

        for (int i = 0; i < 70; i++) {

            String TC = String.valueOf((int) Math.floor(new Date().getTime() / 1000 / 30));
            String TOTP = sha1(TC + key);

            Matcher matcher = pattern.matcher(TOTP);
            String result = "";
            while (matcher.find()) {
                result += matcher.group();
            }
            result = result.substring(result.length() - 6);
            System.out.println(i + "  --  " + result);

            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    public static String sha1(String srcStr) {
        return hash("SHA-1", srcStr);
    }

    public static String hash(String algorithm, String srcStr) {
        try {
            MessageDigest md = MessageDigest.getInstance(algorithm);
            byte[] bytes = md.digest(srcStr.getBytes("utf-8"));
            return toHex(bytes);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static String toHex(byte[] bytes) {
        StringBuilder ret = new StringBuilder(bytes.length * 2);
        for (int i = 0; i < bytes.length; i++) {
            ret.append(HEX_DIGITS[(bytes[i] >> 4) & 0x0f]);
            ret.append(HEX_DIGITS[bytes[i] & 0x0f]);
        }
        return ret.toString();
    }
}

转载于:https://www.cnblogs.com/mysgk/p/9427246.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值