zoukankan      html  css  js  c++  java
  • 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);
            }
        }
    }
    复制代码

     运行结果:

    Android 开发讨论群:84778336 
    iOS 开发讨论群:82873648 

    知识共享许可协议
    本作品采用知识共享署名-非商业性使用 3.0 许可协议进行许可。
    转载请署名李震(博客地址:http://www.cnblogs.com/dyingbleed/),且不得用于商业目的。
  • 相关阅读:
    unix网络编程源码编译问题
    ubuntu15.04下安装docker
    hexo博客的相关配置
    hexo的jacman主题配置
    使用github和hexo搭建静态博客
    操作系统简单认识
    github for windows安装以及教程
    编译原理第五单元习题
    python3入门之列表和元组
    Python3入门之软件安装
  • 原文地址:https://www.cnblogs.com/jiftle/p/6793060.html
Copyright © 2011-2022 走看看