TOTP:Time-based One-time Password Algorithm(基于时间的一次性密码算法)
TOTP:Time-based One-time Password Algorithm(基于时间的一次性密码算法)
TOTP - Time-based One-time Password Algorithm is an extension of the HMAC-based One Time Password algorithm HOTP to support a time based moving factor.
TOTP(基于时间的一次性密码算法)是支持时间作为动态因素基于HMAC一次性密码算法的扩展。
维基百科:http://en.wikipedia.org/wiki/Time-based_One-time_Password_Algorithm
RFC 6238:http://tools.ietf.org/html/rfc6238
项目:
Google Authenticator
项目地址:http://code.google.com/p/google-authenticator/
运行截图:
实现:
1)Prover与Verifier之间必须时钟同步;
2)Prover与Verifier之间必须共享密钥;
3)Prover与Verifier之间必须使用相同的时间步长
算法:
K 共享密钥
T 时间
T0 开始计数的时间步长
X 时间步长
TOTP = Truncate(HMAC-SHA-1(K, (T - T0) / X))
代码示例:

/**
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
* @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));
System.out.print("| " + fmtTime + " | " + utcTime + " | "
+ steps + " |");
System.out.println(generateTOTP(seed, steps, "8", "HmacSHA1")
+ "| SHA1 |");
System.out.print("| " + fmtTime + " | " + utcTime + " | "
+ steps + " |");
System.out.println(generateTOTP(seed32, steps, "8",
"HmacSHA256") + "| SHA256 |");
System.out.print("| " + fmtTime + " | " + utcTime + " | "
+ steps + " |");
System.out.println(generateTOTP(seed64, steps, "8",
"HmacSHA512") + "| SHA512 |"); System.out.println("+---------------+-----------------------+"
+ "------------------+--------+--------+");
}
} catch (final Exception e) {
System.out.println("Error : " + e);
}
}
}

运行结果:
iOS 开发讨论群:82873648
本作品采用知识共享署名-非商业性使用 3.0 许可协议进行许可。
转载请署名李震(博客地址:http://www.cnblogs.com/dyingbleed/),且不得用于商业目的。
TOTP:Time-based One-time Password Algorithm(基于时间的一次性密码算法)的更多相关文章
- TOTP算法 基于时间的一次性密码
/** Copyright (c) 2011 IETF Trust and the persons identified as authors of the code. All rights rese ...
- 翻译[RFC6238] TOTP: Time-Based One-Time Password Algorithm
在闲暇时间做了一个TOTP相关的开源项目,在项目初步完成之余,我尝试对[RFC6238]文档进行了翻译,供大家参考与查阅,若有不妥之处,还望各位前辈海涵斧正. [RFC6238] : Time-Bas ...
- [Swift]LeetCode981. 基于时间的键值存储 | Time Based Key-Value Store
Create a timebased key-value store class TimeMap, that supports two operations. 1. set(string key, s ...
- mahout demo——本质上是基于Hadoop的分步式算法实现,比如多节点的数据合并,数据排序,网路通信的效率,节点宕机重算,数据分步式存储
摘自:http://blog.fens.me/mahout-recommendation-api/ 测试程序:RecommenderTest.java 测试数据集:item.csv 1,101,5.0 ...
- 普林斯顿大学算法课 Algorithm Part I Week 3 排序算法复杂度 Sorting Complexity
计算复杂度(Computational complexity):用于研究解决特定问题X的算法效率的框架 计算模型(Model of computation):可允许的操作(Allowable oper ...
- 基于视觉信息的网页分块算法(VIPS) - yysdsyl的专栏 - 博客频道 - CSDN.NET
基于视觉信息的网页分块算法(VIPS) - yysdsyl的专栏 - 博客频道 - CSDN.NET 于视觉信息的网页分块算法(VIPS) 2012-07-29 15:22 1233人阅读 评论(1) ...
- mysql 开发进阶篇系列 43 逻辑备份与恢复(mysqldump 的基于时间和位置的不完全恢复)
一. 概述 在上篇讲到了逻辑备份,使用mysqldump工具来备份一个库,并使用完全恢复还原了数据库.在结尾也讲到了误操作是不能用完全恢复的.解决办法是:我们需要恢复到误操作之前的状态,然后跳过误操作 ...
- 基于时间的 SQL注入研究
SQL注入攻击是业界一种非常流行的攻击方式,是由rfp在1998年<Phrack>杂志第54期上的“NT Web Technology Vulnerabilities”文章中首次提出的.时 ...
- SQL基于时间的盲注过程
0x00 前言 由于要使用到基于时间的盲注,但是我觉得基于时间的盲注其实就是基于布尔的盲注的升级版,所以我想顺便把基于布尔的盲注分析总结了: 首先我觉得基于时间的盲注和基于布尔的盲注的最直观的差别就是 ...
随机推荐
- JS 与Flex交互:html中的js 与flex中的actionScript通信
Flex与JavaScript交互的问题,这里和大家分享一下,主要包括Flex调用JavaScript中的函数和JavaScript调用Flex中的函数两大部分内容. Flex 与JavaScript ...
- Android -- Sqlite事务
这也是通过Android Juint来实现的. 基于上一次的工程继续,上一次工程传送门:<Android–Android Juint 与 Sqlite> http://www.cnblog ...
- 推荐9款使用CSS3实现的超酷动画效果
大家都知道,在网页制作时使用CSS技术,可以有效地对页面的布局.字体.颜色.背景和其它效果实现更加精确的控制.只要对相应的代码做一些简单的修改,就可以改变同一页面的不同部分,或者页数不同的网页的外观和 ...
- leetCode 86.Partition List(分区链表) 解题思路和方法
Given a linked list and a value x, partition it such that all nodes less than x come before nodes gr ...
- discuz,ecshop的伪静态规则(apache+nginx)
discuz(nginx): (备注:该规则也适用于二级目录) rewrite ^([^\.]*)/topic-(.+)\.html$ $/portal.php?mod=topic&topic ...
- 利用反射实现JavaBean的自动赋值
最近开发公司的一个项目,因项目不是很大的项目,所以仅仅采用了spring MVC框架,但是数据库很多表中的字段至少15个,这样当每次将数据库表中的数据取出来放入javabean中时,写setXXX方法 ...
- angularjs中的$eval方法
在controller中定义了一个变量 $scope.a_1 = "abc"; 想在view里面动态输出,因为这个数字是动态的,这么输出肯定是不行的{{'a_' + '1'}},因 ...
- Python break
break退出循环 用 for 循环或者 while 循环时,如果要在循环体内直接退出循环,可以使用 break 语句. 比如计算1至100的整数和,我们用while来实现: sum = 0 x = ...
- MySQL 清理slowlog方法
MySQL 清理slowlog方法 SET GLOBAL slow_query_log = 'OFF'; ALTER TABLE mysql.slow_log RENAME mysql.slow_lo ...
- 关于SQLite在Android开发中的知识点总结
一.存放位置 1.内部存储-放在 data/data 底下, 也就是内部存储, 里面的文件以及文件夹是私有的, 其他 app 不能访问, 也随着 app 卸载而删除; 2.放在 sd 卡里面, 如果设 ...