Skip to content

Instantly share code, notes, and snippets.

@Dank-del
Created December 5, 2022 18:23
Show Gist options
  • Select an option

  • Save Dank-del/25c099b1916c6dff3b50e89190bd718b to your computer and use it in GitHub Desktop.

Select an option

Save Dank-del/25c099b1916c6dff3b50e89190bd718b to your computer and use it in GitHub Desktop.
In this example, we first define a totp function that takes a secret key as an argument. The function then generates a HMAC-SHA1 hash of the secret key and the current time, and uses the last 4 bits of the hash as an offset to extract a 4-byte slice. This slice is then converted to a uint32 value, and the last 6 digits of the value are returned …
package main
import (
"crypto/hmac"
"crypto/sha1"
"encoding/base32"
"encoding/binary"
"fmt"
"time"
)
func main() {
// Generate a secret key
secret := []byte("my-secret-key")
// Generate a TOTP code for the current time
code, err := totp(secret)
if err != nil {
panic(err)
}
// Print the TOTP code
fmt.Printf("TOTP code: %06d\n", code)
}
func totp(secret []byte) (int, error) {
// Convert the secret key to base32
encoded := base32.StdEncoding.EncodeToString(secret)
// Generate a HMAC-SHA1 hash of the encoded secret key and the current time
mac := hmac.New(sha1.New, []byte(encoded))
if err := binary.Write(mac, binary.BigEndian, uint64(time.Now().Unix()/30)); err != nil {
return 0, err
}
hash := mac.Sum(nil)
// Extract the 4 least significant bits of the hash as an offset
offset := int(hash[len(hash)-1] & 0x0f)
// Extract a 4-byte slice from the hash starting at the offset
bytes := hash[offset : offset+4]
// Convert the 4-byte slice to a uint32
var value uint32
if err := binary.Read(bytes, binary.BigEndian, &value); err != nil {
return 0, err
}
// Return the last 6 digits of the uint32 as a TOTP code
return int(value % 1000000), nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment