How do I generate One time passwords (OTP / HOTP)?

后端 未结 2 1387
闹比i
闹比i 2021-02-01 08:45

We have decided to start work on Multi-factor authentication, by way of releasing an iPhone, Android and Blackberry app for our customers.

Think Google Authenticator\'s

相关标签:
2条回答
  • 2021-02-01 09:26

    Well, it doesn't have to be unique. It just has to have a fair bit of entropy. Meaning that the chances of getting the same string are fairly low.

    One way of doing this is taking your hash and cutting off a certain number of integers:

    var hash = sha1(salt + device + secretKey);
    var numbers = base_convert(hash, 16, 10); // Convert hex string to a integer
    var key = numbers % 100000; // Limit to 5 digits (you can change this on need)
    

    Just remember to left pad the number out so that it starts with literal 0 if it's too short.

    0 讨论(0)
  • 2021-02-01 09:30

    In the end I found that this was very well documented in RFC 4226 and regarding the integer conversion, this can be done using the bitwise operation shown on page 7, essentially it is the same as that shown in the answer below.

    There was another post on stackoverflow regarding this in a C# context, which may be worth a read if you are in a similar position.

    In C# I basically, hashed a time identifier (i.e. the current time in seconds divided by 30 - to get a long which is valid for the current 30-second interval). Then hashed this using my secret key as the SALT.

    And then...

    // Use a bitwise operation to get a representative binary code from the hash
    // Refer section 5.4 at http://tools.ietf.org/html/rfc4226#page-7            
    int offset = hashBytes[19] & 0xf;
    int binaryCode = (hashBytes[offset] & 0x7f) << 24
        | (hashBytes[offset + 1] & 0xff) << 16
        | (hashBytes[offset + 2] & 0xff) << 8
        | (hashBytes[offset + 3] & 0xff);
    
    // Generate the OTP using the binary code. As per RFC 4426 [link above] "Implementations MUST extract a 6-digit code at a minimum 
    // and possibly 7 and 8-digit code"
    int otp = binaryCode % (int)Math.Pow(10, 6); // where 6 is the password length
    
    return otp.ToString().PadLeft(6, '0');
    

    For those of you who didn't know, Google Authenticator is an open source project - you can browse the source code here.

    0 讨论(0)
提交回复
热议问题