A DIY Two-Factor Authenticator in Golang

How Google Authenticator works, and a simple way to implement your own 2FA

A DIY Two-Factor Authenticator in Golang

By Tilak Lodha

Google Authenticator uses Two-Factor Authentication (2FA) to help verify a user’s identity. The primary advantage of using 2FA over SMS-based verification is, should your mobile sim be stolen, or the sms intercepted via your network provider because of security breaches, you still won’t be able to get the password. Regardless of the network provider, Google Authenticator solves the sms-based verification problem by removing the dependency on the network provider. You also don’t have to wait to receive the sms from a potentially choppy network or type the number manually. Instead, just copy it with a click.

Google Authenticator is used for two-step verification based on Time-based One Time Password(TOTP) and HMAC-based One Time Password(HOTP) for authenticating users.

TOTP is an algorithm that computes a one-time password from a shared secret key and the current time.

HTOP is an algorithm which uses hmac algorithm to generate a one-time password.

A simple pseudo code for generating an OTP is:

function GoogleAuthenticatorCode(string secret)
      key := base32decode(secret)
      message := floor(current Unix time / 30)
      hash := HMAC-SHA1(key, message)
      offset := last nibble of hash
      truncatedHash := hash[offset..offset+3]  //4 bytes starting at the offset
      Set the first bit of truncatedHash to zero  //remove the most significant bit
      code := truncatedHash mod 1000000
      pad code with 0 from the left until length of code is 6
      return code
  1. The Secret is the 16 digit token — generated by authenticator itself.
  2. Decode it in base32 (Allowing characters form [A-Z] and [0–9])
  3. Time used is the current epoch time and take the quotient when we divide it by 30. (30 is used as we need a new code every 30 seconds)
  4. Generate a hash using both of these. Hashing algorithm is HMAC-SHA1
  5. Choose the offset (last element of hash). Remove most significant bit. Take modulo with one million and append “0” in front, if needed.

Consider an example:

Consider our secret token is “dummySECRETdummy”
Since for base32 decoding it requires characters in [A-Z], our key will be: “DUMMYSECRETDUMMY”.
Let’s consider current UNIX time is: 1523822557
Our message is int(1523822297/30): 50794085
Generated hash when encoded to string in base32 is: TEQI4DHFALLWYWX3JAXJAAGQGLLEGGOQ
truncatedHash is: 421563916
Taking modulo with 1000000 : 563916 (no padding needed in this case)
desire otp: 563916

Here is the simple Golang script to do the job:

The method getHOTPToken needs the secret and interval as its arguments.

func getTOTPToken(secret string) string {
    //The TOTP token is just a HOTP token seeded with every 30 seconds.
    interval := time.Now().Unix() / 30
    return getHOTPToken(secret, interval)

This completes the script since it takes the secret as input from a file, calculates interval from current time and generates an OTP. You can add more commands to copy it your clipboard.

If this generated OTP doesn’t work for you, you might want to check for a secret token or whether the time is in sync as per network time protocol (ntp).

ntpdate time.nist.gov

Run this command to sync time as per ntp.

You can find complete go program for this here. [https://github.com/tilaklodha/google-authenticator].
Gist here.

Hope you found this helpful 🙏. Leave a comment if you know more hacks 😝We’re hiring! Check out gojek.jobs for more.