Time-based one-time password

jdc The following code generates a time-based one-time password (TOTP) for use with Google's 2-step verification. You'll need to pass in your secret key. After enabling 2-step verification, you can obtain this key by going to the Google Authenticator for BlackBerry.

package require sha1
package require base32

# Given a secret key, return a time-base one-time password (TOTP).
# Based on google-authenticator.c from http://code.google.com/p/google-authenticator/
proc totp {key} {
    set SHA1_DIGEST_LENGTH 20
    set VERIFICATION_CODE_MODULUS 1000000
    set challenge [binary format W [expr {[clock seconds]/30}]]
    set secret [base32::decode $key]
    binary scan [sha1::hmac -bin -key $secret $challenge] c* hash
    set offset [expr {[lindex $hash end] & 0xF}]
    set totp 0
    for {set i 0} {$i < 4} {incr i; incr offset} {
        set totp [expr {($totp << 8) | ([lindex $hash $offset] & 0xff)}]
    }
    return [format {%06d} [expr {($totp & 0x7FFFFFFF) % $VERIFICATION_CODE_MODULUS}]]
}

A warning, as included with the Google authenticator source code:

  • You should never store, process or otherwise access the secret key on the same machine that you use for accessing your account. Doing so completely defeats the security of two-step verification.