日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > java >内容正文

java

java 手机动态口令_动态密码TOTP的Java实现

發(fā)布時(shí)間:2024/1/8 java 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java 手机动态口令_动态密码TOTP的Java实现 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一、HOTP

HOTP 算法,全稱是“An HMAC-Based One-Time Password Algorithm”,是一種基于事件計(jì)數(shù)的一次性密碼生成算法,詳細(xì)的算法介紹可以查看 RFC 4226。其實(shí)算法本身非常簡(jiǎn)單,算法本身可以用兩條簡(jiǎn)短的表達(dá)式描述:

HOTP(K,C) = Truncate(HMAC-SHA-1(K,C))

PWD(K,C,digit) = HOTP(K,C) mod 10^Digit

二、TOTP

TOTP 算法,全稱是 TOTP: Time-Based One-Time Password Algorithm,其基于 HOTP 算法實(shí)現(xiàn),核心是將移動(dòng)因子從 HOTP 中的事件計(jì)數(shù)改為時(shí)間差。完整的 TOTP 算法的說(shuō)明可以查看 RFC 6238,其公式描述也非常簡(jiǎn)單:

TOTP = HOTP(K, T) // T is an integer

and represents the number of time steps between the initial counter

time T0 and the current Unix time

More specifically, T = (Current Unix time - T0) / X, where the

default floor function is used in the computation.

參考《https://segmentfault.com/a/1190000008394200》

這篇文章已經(jīng)介紹清楚動(dòng)態(tài)密碼的原理,本文僅在理論的基礎(chǔ)上使用Java實(shí)現(xiàn)。

三、TOTP具體Java實(shí)現(xiàn)

子服務(wù)端:啟用不含verifyTOTP*()驗(yàn)證方法的TOTP,使用子服務(wù)端的賬戶和密碼加密,向驗(yàn)證服務(wù)端發(fā)送動(dòng)態(tài)口令。

驗(yàn)證服務(wù)端:驗(yàn)證子服務(wù)端的口令,根據(jù)子服務(wù)端標(biāo)識(shí)信息,使用其賬戶和密碼加密得到口令,比對(duì)口令是否一致即可。

前提:因?yàn)槭褂脮r(shí)間作為動(dòng)態(tài)因子加密口令,子服務(wù)端的時(shí)間應(yīng)和驗(yàn)證服務(wù)端的時(shí)間一致,比如使用同一個(gè)授時(shí)服務(wù)器授時(shí)。

推薦使用柔性口令驗(yàn)證,使用柔性驗(yàn)證時(shí)請(qǐng)?jiān)O(shè)置時(shí)間回溯參數(shù),避免因口令在網(wǎng)絡(luò)中傳輸消耗時(shí)間,或者服務(wù)端時(shí)間誤差導(dǎo)致口令失效。

/**

*

ClassName: TOTP

*

Description: TOTP = HOTP(K, T) // T is an integer

* and represents the number of time steps between the initial counter

* time T0 and the current Unix time

*

* More specifically, T = (Current Unix time - T0) / X, where the

* default floor function is used in the computation.

*

* @author wangqian

* @date 2018-04-03 11:44

*/

public class TOTP {

public static void main(String[] args) {

try {

for (int j = 0; j < 10; j++) {

String totp = generateMyTOTP("account01", "12345");

System.out.println(String.format("加密后: %s", totp));

Thread.sleep(1000);

}

} catch (final Exception e) {

e.printStackTrace();

}

}

/**

* 共享密鑰

*/

private static final String SECRET_KEY = "ga35sdia43dhqj6k3f0la";

/**

* 時(shí)間步長(zhǎng) 單位:毫秒 作為口令變化的時(shí)間周期

*/

private static final long STEP = 30000;

/**

* 轉(zhuǎn)碼位數(shù) [1-8]

*/

private static final int CODE_DIGITS = 8;

/**

* 初始化時(shí)間

*/

private static final long INITIAL_TIME = 0;

/**

* 柔性時(shí)間回溯

*/

private static final long FLEXIBILIT_TIME = 5000;

/**

* 數(shù)子量級(jí)

*/

private static final int[] DIGITS_POWER = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000};

private TOTP() {

}

/**

* 生成一次性密碼

*

* @param code 賬戶

* @param pass 密碼

* @return String

*/

public static String generateMyTOTP(String code, String pass) {

if (EmptyUtil.isEmpty(code) || EmptyUtil.isEmpty(pass)) {

throw new RuntimeException("賬戶密碼不許為空");

}

long now = new Date().getTime();

String time = Long.toHexString(timeFactor(now)).toUpperCase();

return generateTOTP(code + pass + SECRET_KEY, time);

}

/**

* 剛性口令驗(yàn)證

*

* @param code 賬戶

* @param pass 密碼

* @param totp 待驗(yàn)證的口令

* @return boolean

*/

public static boolean verifyTOTPRigidity(String code, String pass, String totp) {

return generateMyTOTP(code, pass).equals(totp);

}

/**

* 柔性口令驗(yàn)證

*

* @param code 賬戶

* @param pass 密碼

* @param totp 待驗(yàn)證的口令

* @return boolean

*/

public static boolean verifyTOTPFlexibility(String code, String pass, String totp) {

long now = new Date().getTime();

String time = Long.toHexString(timeFactor(now)).toUpperCase();

String tempTotp = generateTOTP(code + pass + SECRET_KEY, time);

if (tempTotp.equals(totp)) {

return true;

}

String time2 = Long.toHexString(timeFactor(now - FLEXIBILIT_TIME)).toUpperCase();

String tempTotp2 = generateTOTP(code + pass + SECRET_KEY, time2);

return tempTotp2.equals(totp);

}

/**

* 獲取動(dòng)態(tài)因子

*

* @param targetTime 指定時(shí)間

* @return long

*/

private static long timeFactor(long targetTime) {

return (targetTime - INITIAL_TIME) / STEP;

}

/**

* 哈希加密

*

* @param crypto 加密算法

* @param keyBytes 密鑰數(shù)組

* @param text 加密內(nèi)容

* @return byte[]

*/

private static byte[] hmac_sha(String crypto, byte[] keyBytes, byte[] text) {

try {

Mac hmac;

hmac = Mac.getInstance(crypto);

SecretKeySpec macKey = new SecretKeySpec(keyBytes, "AES");

hmac.init(macKey);

return hmac.doFinal(text);

} catch (GeneralSecurityException gse) {

throw new UndeclaredThrowableException(gse);

}

}

private static byte[] hexStr2Bytes(String hex) {

byte[] bArray = new BigInteger("10" + hex, 16).toByteArray();

byte[] ret = new byte[bArray.length - 1];

System.arraycopy(bArray, 1, ret, 0, ret.length);

return ret;

}

private static String generateTOTP(String key, String time) {

return generateTOTP(key, time, "HmacSHA1");

}

private static String generateTOTP256(String key, String time) {

return generateTOTP(key, time, "HmacSHA256");

}

private static String generateTOTP512(String key, String time) {

return generateTOTP(key, time, "HmacSHA512");

}

private static String generateTOTP(String key, String time, String crypto) {

StringBuilder timeBuilder = new StringBuilder(time);

while (timeBuilder.length() < 16)

timeBuilder.insert(0, "0");

time = timeBuilder.toString();

byte[] msg = hexStr2Bytes(time);

byte[] k = key.getBytes();

byte[] hash = hmac_sha(crypto, k, msg);

return truncate(hash);

}

/**

* 截?cái)嗪瘮?shù)

*

* @param target 20字節(jié)的字符串

* @return String

*/

private static String truncate(byte[] target) {

StringBuilder result;

int offset = target[target.length - 1] & 0xf;

int binary = ((target[offset] & 0x7f) << 24)

| ((target[offset + 1] & 0xff) << 16)

| ((target[offset + 2] & 0xff) << 8) | (target[offset + 3] & 0xff);

int otp = binary % DIGITS_POWER[CODE_DIGITS];

result = new StringBuilder(Integer.toString(otp));

while (result.length() < CODE_DIGITS) {

result.insert(0, "0");

}

return result.toString();

}

}

總結(jié)

以上是生活随笔為你收集整理的java 手机动态口令_动态密码TOTP的Java实现的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 国产区第一页 | av影片在线播放 | 青青草97| 久久一二区 | 性做爰裸体按摩视频 | 四季av中文字幕一区 | 黄色高清视频在线观看 | 含羞草一区二区 | 超碰夜夜| 国产精品无码粉嫩小泬 | 久久国产一 | 成人av网站在线观看 | 日本成人在线播放 | 奶水旺盛的女人伦理 | 成 人 黄 色 片 在线播放 | a级小视频| 国产伦人伦偷精品视频 | 国产最新av| 激情网站在线观看 | 99精品国产一区 | 精品免费在线观看 | 日韩精品高清视频 | 欧美日韩国产一级片 | 朝鲜黄色片 | 91传媒理伦片在线观看 | 九九精品免费视频 | 2019中文在线观看 | 在线不卡日本 | 久久刺激 | 中文字幕日韩专区 | 亚洲人成小说 | 九九热这里有精品 | 亚洲97在线 | 黄色的网站在线观看 | 久久国产柳州莫菁门 | 国产成人精品一区二区 | 久久精品黄aa片一区二区三区 | 黄色男人的天堂 | 黄色免费视屏 | 激情片网站 | 一个色综合导航 | 一区二区三区视频免费在线观看 | 日本r级电影在线观看 | 九九综合久久 | 午夜精品成人毛片非洲 | 日韩欧美精品在线播放 | 亚洲热视频 | 男女洗澡互摸私密部位视频 | 国产精品99久久久久久久女警 | 97人人模人人爽人人少妇 | 禁断介护老人中文字幕 | youjizz.com最新| 日韩人体视频 | 日韩免费电影一区 | 久久久精品视频在线 | 91免费成人 | 农村少妇久久久久久久 | 欧美激情综合色综合啪啪五月 | 香蕉网站在线 | 欧美巨乳美女 | 日韩精品www | 亚洲精品一区二区三区四区五区 | 自拍亚洲国产 | 中文写幕一区二区三区免费观成熟 | 亚洲自拍偷拍精品 | 亚洲在线视频播放 | 性欧美又大又长又硬 | 亚洲男人的天堂网站 | 台湾swag在线观看 | 日韩视频免费播放 | 精品人妻一区二区免费 | 九色tv| 91精品国产综合久久福利软件 | 四虎午夜| 大尺度av在线 | 丰满少妇xbxb毛片日本 | www.黄色大片 | 国产中出视频 | 9l视频自拍九色9l视频 | 国产精品久久久久91 | 色图18p | 午夜丰满寂寞少妇精品 | 禁漫天堂免费网站 | 黄色毛毛片| 亚洲天堂成人在线观看 | 免费无码毛片一区二区app | 亚洲精品成人在线 | 亚洲欧美a| 婷婷在线视频观看 | 视频久久 | 久久精品视频免费播放 | 爱情岛亚洲首页论坛小巨 | 色多多导航 | 天堂成人在线 | 午夜播放| 久久精品一区二区免费播放 | h视频在线免费观看 | 在线日韩亚洲 | 中国黄色在线视频 |