TOTP算法 基于时间的一次性密码
/**
Copyright (c) 2011 IETF Trust and the persons identified as
authors of the code. All rights reserved. Redistribution and use in source and binary forms, with or without
modification, is permitted pursuant to, and subject to the license
terms contained in, the Simplified BSD License set forth in Section
4.c of the IETF Trust's Legal Provisions Relating to IETF Documents
(http://trustee.ietf.org/license-info).
*/ import java.lang.reflect.UndeclaredThrowableException;
import java.security.GeneralSecurityException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.math.BigInteger;
import java.util.TimeZone; /**
* This is an example implementation of the OATH TOTP algorithm. Visit
* www.openauthentication.org for more information.
*
* @author Johan Rydell, PortWise, Inc.
*/ public class TOTP { private TOTP() {
} /**
* This method uses the JCE to provide the crypto algorithm. HMAC computes a
* Hashed Message Authentication Code with the crypto hash algorithm as a
* parameter.
*
* @param crypto
* : the crypto algorithm (HmacSHA1, HmacSHA256, HmacSHA512)
* @param keyBytes
* : the bytes to use for the HMAC key
* @param text
* : the message or text to be authenticated
*/
private static byte[] hmac_sha(String crypto, byte[] keyBytes, byte[] text) {
try {
Mac hmac;
hmac = Mac.getInstance(crypto);
SecretKeySpec macKey = new SecretKeySpec(keyBytes, "RAW");
hmac.init(macKey);
return hmac.doFinal(text);
} catch (GeneralSecurityException gse) {
throw new UndeclaredThrowableException(gse);
}
} /**
* This method converts a HEX string to Byte[]
*
* @param hex
* : the HEX string
*
* @return: a byte array
*/ private static byte[] hexStr2Bytes(String hex) {
// Adding one byte to get the right conversion
// Values starting with "0" can be converted
byte[] bArray = new BigInteger("10" + hex, 16).toByteArray(); // Copy all the REAL bytes, not the "first"
byte[] ret = new byte[bArray.length - 1];
for (int i = 0; i < ret.length; i++)
ret[i] = bArray[i + 1];
return ret;
} private static final int[] DIGITS_POWER
// 0 1 2 3 4 5 6 7 8
= { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000 }; /**
* This method generates a TOTP value for the given set of parameters.
*
* @param key
* : the shared secret, HEX encoded
* @param time
* : a value that reflects a time
* @param returnDigits
* : number of digits to return
*
* @return: a numeric String in base 10 that includes
* {@link truncationDigits} digits
*/ public static String generateTOTP(String key, String time,
String returnDigits) {
return generateTOTP(key, time, returnDigits, "HmacSHA1");
} /**
* This method generates a TOTP value for the given set of parameters.
*
* @param key
* : the shared secret, HEX encoded
* @param time
* : a value that reflects a time
* @param returnDigits
* : number of digits to return
*
* @return: a numeric String in base 10 that includes
* {@link truncationDigits} digits
*/ public static String generateTOTP256(String key, String time,
String returnDigits) {
return generateTOTP(key, time, returnDigits, "HmacSHA256");
} /**
* This method generates a TOTP value for the given set of parameters.
*
* @param key
* : the shared secret, HEX encoded
* @param time
* : a value that reflects a time
* @param returnDigits
* : number of digits to return
*
* @return: a numeric String in base 10 that includes
* {@link truncationDigits} digits
*/ public static String generateTOTP512(String key, String time,
String returnDigits) {
return generateTOTP(key, time, returnDigits, "HmacSHA512");
} /**
* This method generates a TOTP value for the given set of parameters.
*
* @param key
* : the shared secret, HEX encoded
* @param time
* : a value that reflects a time
* @param returnDigits
* : number of digits to return 返回长度 --6
* @param crypto
* : the crypto function to use
*
* @return: a numeric String in base 10 that includes
* {@link truncationDigits} digits
*/ public static String generateTOTP(String key, String time,
String returnDigits, String crypto) {
int codeDigits = Integer.decode(returnDigits).intValue();
String result = null; // Using the counter
// First 8 bytes are for the movingFactor
// Compliant with base RFC 4226 (HOTP)
while (time.length() < 16)
time = "0" + time; // Get the HEX in a Byte[]
byte[] msg = hexStr2Bytes(time);
byte[] k = hexStr2Bytes(key);
byte[] hash = hmac_sha(crypto, k, msg); // put selected bytes into result int
int offset = hash[hash.length - 1] & 0xf; int binary = ((hash[offset] & 0x7f) << 24)
| ((hash[offset + 1] & 0xff) << 16)
| ((hash[offset + 2] & 0xff) << 8) | (hash[offset + 3] & 0xff); int otp = binary % DIGITS_POWER[codeDigits]; result = Integer.toString(otp);
while (result.length() < codeDigits) {
result = "0" + result;
}
return result;
} public static void main(String[] args) {
// Seed for HMAC-SHA1 - 20 bytes
String seed = "3132333435363738393031323334353637383930";
// Seed for HMAC-SHA256 - 32 bytes
String seed32 = "3132333435363738393031323334353637383930"
+ "313233343536373839303132";
// Seed for HMAC-SHA512 - 64 bytes
String seed64 = "3132333435363738393031323334353637383930"
+ "3132333435363738393031323334353637383930"
+ "3132333435363738393031323334353637383930" + "31323334";
long T0 = 0;
long X = 30;
long testTime[] = { 59L, 1111111109L, 1111111111L, 1234567890L,
2000000000L, 20000000000L }; String steps = "0";
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
df.setTimeZone(TimeZone.getTimeZone("UTC"));
try {
System.out.println("+---------------+-----------------------+"
+ "------------------+--------+--------+");
System.out.println("| Time(sec) | Time (UTC format) "
+ "| Value of T(Hex) | TOTP | Mode |");
System.out.println("+---------------+-----------------------+"
+ "------------------+--------+--------+"); for (int i = 0; i < testTime.length; i++) {
long T = (testTime[i] - T0) / X;
steps = Long.toHexString(T).toUpperCase();
while (steps.length() < 16)
steps = "0" + steps;
String fmtTime = String.format("%1$-11s", testTime[i]);
String utcTime = df.format(new Date(testTime[i] * 1000));
// seed
System.out.print("| " + fmtTime + " | " + utcTime + " | "
+ steps + " |");
System.out.println(generateTOTP(seed, steps, "8", "HmacSHA1")
+ "| SHA1 |"); // seed32
System.out.print("| " + fmtTime + " | " + utcTime + " | "
+ steps + " |");
System.out.println(generateTOTP(seed32, steps, "8",
"HmacSHA256") + "| SHA256 |"); // seed64
System.out.print("| " + fmtTime + " | " + utcTime + " | "
+ steps + " |");
System.out.println(generateTOTP(seed64, steps, "6",
"HmacSHA512") + "| SHA512 |"); System.out.println("+---------------+-----------------------+"
+ "------------------+--------+--------+");
}
} catch (final Exception e) {
System.out.println("Error : " + e);
}
}
}
TOTP算法 基于时间的一次性密码的更多相关文章
- TOTP:Time-based One-time Password Algorithm(基于时间的一次性密码算法)
TOTP:Time-based One-time Password Algorithm(基于时间的一次性密码算法) TOTP - Time-based One-time Password Algori ...
- 动态密码卡TOTP算法
TOTP NET实现:http://googleauthcsharp.codeplex.com/ 引用:http://www.cnblogs.com/wangxin201492/p/5030943.h ...
- [信息安全] 4.一次性密码 && 身份认证三要素
[信息安全]系列博客:http://www.cnblogs.com/linianhui/category/985957.html 在信息安全领域,一般把Cryptography称为密码,而把Passw ...
- TOTP算法实现二步验证
概念 TOTP算法(Time-based One-time Password algorithm)是一种从共享密钥和当前时间计算一次性密码的算法. 它已被采纳为Internet工程任务组标准RFC 6 ...
- JavaScript基于时间的动画算法
转自:https://segmentfault.com/a/1190000002416071 前言 前段时间无聊或有聊地做了几个移动端的HTML5游戏.放在不同的移动端平台上进行测试后有了诡异的发现, ...
- Google Cardboard的九轴融合算法——基于李群的扩展卡尔曼滤波
Google Cardboard的九轴融合算法 --基于李群的扩展卡尔曼滤波 极品巧克力 前言 九轴融合算法是指通过融合IMU中的加速度计(三轴).陀螺仪(三轴).磁场计(三轴),来获取物体姿态的方法 ...
- 基于时间的 SQL注入研究
SQL注入攻击是业界一种非常流行的攻击方式,是由rfp在1998年<Phrack>杂志第54期上的“NT Web Technology Vulnerabilities”文章中首次提出的.时 ...
- 如何用一次性密码通过 SSH 安全登录 Linux
有人说,安全不是一个产品,而是一个过程.虽然 SSH 协议被设计成使用加密技术来确保安全,但如果使用不当,别人还是能够破坏你的系统:比如弱密码.密钥泄露.使用过时的 SSH 客户端等,都能引发安全问题 ...
- 2019-9-9:渗透测试,基础学习,phpmyadmin getshell方法,基于时间的盲注,基于报错的注入,笔记
phpmyadmin getshell方法1,查看是否有导入导出设置 show global variables like '%secure-file-priv%';2,如果secure-file-p ...
随机推荐
- 使用Spring-hadoop小结
SpringHadoop是通过Spring框架来调用hdfs,跟直接调用hdfs的最大的不同区别是Spring通过依赖注入的方式生成操作hdfs所需要的configuration和filesystem ...
- Bzoj4872: [Shoi2017]分手是祝愿
题面 Bzoj Sol 首先从大向小,能关就关显然是最优 然后 设\(f[i]\)表示剩下最优要按i个开关的期望步数,倒推过来就是 \[ f[i]=f[i-1]*i*inv[n]+f[i+1]*(n- ...
- ZJOI2007仓库建设
斜率优化 # include <stdio.h> # include <stdlib.h> # include <iostream> # include <s ...
- linux开机启动流程及需要开机启动服务讲解和修改及防火墙
linux系统从开机到登陆的启动流程. 1.开机BIOS自检 2.MBR引导 3.grub引导菜单 4.加载内核kernel 5.启动init进程 6.读取inittab文件,执行rc.sysinit ...
- 关于如何使用SVN的一些建议
SVN是管理源码的主流方式之一,当多人同时编辑同一项目时经常会出现冲突,本文主要针对Asp.net 项目开发中使用SVN提出一点建议. 1.忽略asp.net 项目中的非源代码文件 .VS目录是vis ...
- java--抽象类实例(包含静态内部抽象类)
静态内部抽象类可以被继承. public class testfather { public static void main(String[] args) { person.talk2 a = ne ...
- 设计模式——职责链模式(C++实现)
#include <iostream> #include <string> using namespace std; class Handler { public: Handl ...
- zabbix添加自定义监控项
zabbix添加自定义监控项 author:headsen chen 2017-10-16 17:23:17 个人原创,转载请注明作者,出处,否则依法追究法律责任 主机端配置: 首先安装好za ...
- webpack打包不识别es6语法的坑
今天Vue项目npm run build 后webpack,报错uglifyjs,自己研究了一下,翻译过来,意思是不识别项目中写的高级语法,这里要把项目里es6语法转es5让浏览器识别, 也就是web ...
- mybatis学习日记-day01
Mybatis说明: MyBatis 使用简单的 XML或注解用于配置和原始映射,将接口和 Java 的POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的 ...