zoukankan      html  css  js  c++  java
  • 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();
    	}
    }
    
    
    有问题请联系hudcan@sina.com 个人网站:http://ext.123456cc.cc
  • 相关阅读:
    Python网络爬虫第三弹《爬取get请求的页面数据》
    18.增量式爬虫
    17.基于scrapy-redis两种形式的分布式爬虫
    关于进程内存磁盘的一些命令
    linux其他命令
    ls -用于显示指定工作目录下之内容(列出目前工作目录所含之文件及子目录)
    mkdir和touch
    ls -列出当前目录下所有的文件或者目录
    cat -用于连接文件并打印到标准输出设备上
    rm -移动文件
  • 原文地址:https://www.cnblogs.com/mysgk/p/9427246.html
Copyright © 2011-2022 走看看