본문 바로가기
#포트폴리오 [Portfolio]

[🔒 Security] HOTP (HMAC-based One-time Password algorithm)

by cy_mos 2020. 7. 31.
반응형

 

HOTP (HMAC based OTP algorithm) - https://www.protectimus.com/blog/hotp-algorithm/

HMAC-based One-time Password algorithm (HOTP) is a one-time password (OTP) algorithm based on hash-based message authentication codes (HMAC). It is a cornerstone of the Initiative for Open Authentication (OATH).

 

HOTP was published as an informational IETF RFC 4226 in December 2005, documenting the algorithm along with a Java implementation. Since then, the algorithm has been adopted by many companies worldwide (see below). The HOTP algorithm is a freely available open standard.

 

이벤트 기반의 OTP (또는 HMAC 기반의 HMAC-based One-Time Password)는 일반적인 One-Time Password 알고리즘이며 두개의 신뢰할 수 있는 정보의 조각을 가지고 있습니다.  첫번째 암호키는 "SEED"라고 불리며 오직 토큰에 의해서만 알 수 있으며 서버는 토큰에 의해 유효한 OTP 코드를 제출합니다. 두번째 정보 조각은 event-based OTP 내부에서 카운터로서 이동 요소입니다. 카운터는 토큰 내부 또는 서버에 저장이 됩니다. 토큰 내부에 있는 카운터는 토큰에 대해 버튼을 눌렀을 때에 카운터 값이 증가하며, 서버에 있는 카운터는 오직 OTP 유효하게 성공적으로 검증이 되었을 때에만 카운터 값이 증가합니다.


🗂 HOTP (HMAC-based One-time Password algorithm) with Java

더보기
   /*
    * OneTimePasswordAlgorithm.java
    * OATH Initiative,
    * HOTP one-time password algorithm
    *
    */

   /* Copyright (C) 2004, OATH.  All rights reserved.
    *
    * License to copy and use this software is granted provided that it
    * is identified as the "OATH HOTP Algorithm" in all material
    * mentioning or referencing this software or this function.
    *
    * License is also granted to make and use derivative works provided
    * that such works are identified as
    *  "derived from OATH HOTP algorithm"
    * in all material mentioning or referencing the derived work.
    *
    * OATH (Open AuTHentication) and its members make no
    * representations concerning either the merchantability of this
    * software or the suitability of this software for any particular
    * purpose.
    *
    * It is provided "as is" without express or implied warranty
    * of any kind and OATH AND ITS MEMBERS EXPRESSaLY DISCLAIMS
    * ANY WARRANTY OR LIABILITY OF ANY KIND relating to this software.
    *
    * These notices must be retained in any copies of any part of this
    * documentation and/or software.
    */

   package org.openauthentication.otp;

   import java.io.IOException;
   import java.io.File;
   import java.io.DataInputStream;
   import java.io.FileInputStream ;
   import java.lang.reflect.UndeclaredThrowableException;

   import java.security.GeneralSecurityException;
   import java.security.NoSuchAlgorithmException;
   import java.security.InvalidKeyException;

   import javax.crypto.Mac;
   import javax.crypto.spec.SecretKeySpec;

   /**
    * This class contains static methods that are used to calculate the
    * One-Time Password (OTP) using
    * JCE to provide the HMAC-SHA-1.
    *
    * @author Loren Hart
    * @version 1.0
    */
   public class OneTimePasswordAlgorithm {
       private OneTimePasswordAlgorithm() {}

       // These are used to calculate the check-sum digits.
       //                                0  1  2  3  4  5  6  7  8  9
       private static final int[] doubleDigits =
                       { 0, 2, 4, 6, 8, 1, 3, 5, 7, 9 };

       /**
        * Calculates the checksum using the credit card algorithm.
        * This algorithm has the advantage that it detects any single
        * mistyped digit and any single transposition of
        * adjacent digits.
        *
        * @param num the number to calculate the checksum for
        * @param digits number of significant places in the number
        *
        * @return the checksum of num
        */
       public static int calcChecksum(long num, int digits) {
           boolean doubleDigit = true;
           int     total = 0;
           while (0 < digits--) {
               int digit = (int) (num % 10);
               num /= 10;
               if (doubleDigit) {
                   digit = doubleDigits[digit];
               }
               total += digit;
               doubleDigit = !doubleDigit;
           }
           int result = total % 10;
           if (result > 0) {
               result = 10 - result;
           }
           return result;
       }

       /**
        * This method uses the JCE to provide the HMAC-SHA-1
        * algorithm.
        * HMAC computes a Hashed Message Authentication Code and
        * in this case SHA1 is the hash algorithm used.
        *
        * @param keyBytes   the bytes to use for the HMAC-SHA-1 key
        * @param text       the message or text to be authenticated.
        *
        * @throws NoSuchAlgorithmException if no provider makes
        *       either HmacSHA1 or HMAC-SHA-1
        *       digest algorithms available.
        * @throws InvalidKeyException
        *       The secret provided was not a valid HMAC-SHA-1 key.
        *
        */

       public static byte[] hmac_sha1(byte[] keyBytes, byte[] text)
           throws NoSuchAlgorithmException, InvalidKeyException
       {
   //        try {
               Mac hmacSha1;
               try {
                   hmacSha1 = Mac.getInstance("HmacSHA1");
               } catch (NoSuchAlgorithmException nsae) {
                   hmacSha1 = Mac.getInstance("HMAC-SHA-1");
               }
               SecretKeySpec macKey =
           new SecretKeySpec(keyBytes, "RAW");
               hmacSha1.init(macKey);
               return hmacSha1.doFinal(text);
   //        } catch (GeneralSecurityException gse) {
   //            throw new UndeclaredThrowableException(gse);
   //        }
       }

       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 an OTP value for the given
        * set of parameters.
        *
        * @param secret       the shared secret
        * @param movingFactor the counter, time, or other value that
        *                     changes on a per use basis.
        * @param codeDigits   the number of digits in the OTP, not
        *                     including the checksum, if any.
        * @param addChecksum  a flag that indicates if a checksum digit
        *                     should be appended to the OTP.
        * @param truncationOffset the offset into the MAC result to
        *                     begin truncation.  If this value is out of
        *                     the range of 0 ... 15, then dynamic
        *                     truncation  will be used.
        *                     Dynamic truncation is when the last 4
        *                     bits of the last byte of the MAC are
        *                     used to determine the start offset.
        * @throws NoSuchAlgorithmException if no provider makes
        *                     either HmacSHA1 or HMAC-SHA-1
        *                     digest algorithms available.
        * @throws InvalidKeyException
        *                     The secret provided was not
        *                     a valid HMAC-SHA-1 key.
        *
        * @return A numeric String in base 10 that includes
        * {@link codeDigits} digits plus the optional checksum
        * digit if requested.
        */
       static public String generateOTP(byte[] secret,
                  long movingFactor,
             int codeDigits,
                  boolean addChecksum,
             int truncationOffset)
           throws NoSuchAlgorithmException, InvalidKeyException
       {
           // put movingFactor value into text byte array
     String result = null;
     int digits = addChecksum ? (codeDigits + 1) : codeDigits;
           byte[] text = new byte[8];
           for (int i = text.length - 1; i >= 0; i--) {
               text[i] = (byte) (movingFactor & 0xff);
               movingFactor >>= 8;
           }

           // compute hmac hash
           byte[] hash = hmac_sha1(secret, text);

           // put selected bytes into result int
           int offset = hash[hash.length - 1] & 0xf;
     if ( (0<=truncationOffset) &&
            (truncationOffset<(hash.length-4)) ) {
         offset = truncationOffset;
     }
           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];
     if (addChecksum) {
         otp =  (otp * 10) + calcChecksum(otp, codeDigits);
     }
     result = Integer.toString(otp);
     while (result.length() < digits) {
         result = "0" + result;
     }
     return result;
       }
   }

🗂 HOTP (HMAC-based One-time Password algorithm) with Swift

더보기
/**
        OTP (One Time Password) 값을 생성하는 함수입니다.
     
        - Parameters:
            - hsshData: `HMAC SHA`을 바탕으로 생성한 Hash Message 입력받는 매개변수
            - digits: OTP (One Time Password) 값을 생성하기 위한 자릿수를 입력받는 매개변수 `[Default]`
        - Returns: String
    */
    func createOTPValue(hashData: Data, digits: Int = 6) -> String {

        let hmac: [UInt32] = Array(hashData).compactMap { UInt32($0) }

        let offset: Int = Int((hmac.last ?? 0x00) & 0x0f)

        var value: UInt32 = ((hmac[offset] & 0x7f)     << 24) |
                            ((hmac[offset + 1] & 0xff) << 16) |
                            ((hmac[offset + 2] & 0xff) << 8)  |
                            (hmac[offset + 3] & 0xff)

        let cipher = pow(10, Float(digits))
        value %= UInt32(cipher)

        // OTP (One Time Password) 값에 대한 자릿수를 확인하여 적은경우에는 ZERO 값을 추가합니다.
        let strOTP = String(value)
        if strOTP.count < digits {
            let prefix = String(repeating: "0", count: digits - strOTP.count)
            return prefix + strOTP
        }

        // OTP (One Time Password) 값에 대한 자릿수가 동인한 경우에는 String 변환 후 반환합니다.
        return strOTP
    }

🚀 REFERENCE

 

RFC 4226 - HOTP: An HMAC-Based One-Time Password Algorithm

[Docs] [txt|pdf] [draft-mraihi-oa...] [Tracker] [Diff1] [Diff2] [IPR] [Errata] INFORMATIONAL Errata Exist Network Working Group D. M'Raihi Request for Comments: 4226 VeriSign Category: Informational M. Bellare UCSD F. Hoornaert Vasco D. Naccache Gemplus O.

tools.ietf.org

 

HMAC-based One-time Password algorithm - Wikipedia

From Wikipedia, the free encyclopedia Jump to navigation Jump to search Password authentication algorithm HMAC-based One-time Password algorithm (HOTP) is a one-time password (OTP) algorithm based on hash-based message authentication codes (HMAC). It is a

en.wikipedia.org

 

HOTP Algorithm Explained - Protectimus Solutions

 

www.protectimus.com

반응형

댓글