Skip to content

Instantly share code, notes, and snippets.

@charsyam
Created January 13, 2021 13:54
Show Gist options
  • Save charsyam/d0635be901176b884703a83a2a505eef to your computer and use it in GitHub Desktop.
Save charsyam/d0635be901176b884703a83a2a505eef to your computer and use it in GitHub Desktop.
Go Timebased OTP Code Generator
package main
import (
"crypto/rand"
"crypto/hmac"
"crypto/sha1"
"encoding/base32"
"time"
"fmt"
)
func encodeHMACSHA1(data []byte, secret []byte) []byte {
h := hmac.New(sha1.New, []byte(secret))
h.Write(data)
sha := h.Sum(nil)
return sha
}
func secret() string {
secretKey := make([]byte, 5)
rand.Read(secretKey)
return base32.StdEncoding.EncodeToString(secretKey)
}
func makeTimestamp() int64 {
return time.Now().UnixNano() / int64(time.Millisecond)
}
func generate(secretKey string) (string, error) {
key, err := base32.StdEncoding.DecodeString(secretKey)
if err != nil {
return "", err
}
l := makeTimestamp() / (1000 * 30)
return getHash(key, l), nil
}
func getHash(secretKey []byte, l int64) (string) {
data := make([]byte, 8)
for i := 7; i >= 0; i-- {
data[i] = byte(l)
l = l >> 8
}
hash := encodeHMACSHA1(data, secretKey)
offset := int(hash[20 - 1] & 0xF)
truncatedHash := 0
for i := 0; i < 4; i++ {
truncatedHash <<= 8
truncatedHash |= int(hash[offset + i] & 0xFF)
}
truncatedHash &= 0x7FFFFFFF
truncatedHash %= 1000000
return fmt.Sprintf("%06d", truncatedHash)
}
func main() {
secretKey := secret()
println(secretKey)
otp, _ := generate(secretKey)
println(otp)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment