2.2 KiB
2.2 KiB
otp
Go library for generating and using One Time Passwords. Supports both HOTP (RFC4226) and TOTP (RFC6238). Can be used for both server and client roles.
Examples
OTP Server
import (
"dev.justinjudd.org/justin/otp"
)
var Issuer = "example.com"
func CreateKeyForUser(user string) {
opts := otp.NewHOTPKeyOptions()
opts.Issuer = Issuer
opts.Label = user
key := otp.NewHOTPKey(opts)
keyURL := key.URL()
Store(user, keyURL)
// Provide the URL to the customer so they can include it in their 2FA client.
// Can email URL, or present QR code encoding of the URL
}
// Store this string variable in your database
func Store(user, url string) {
}
// Retrieve the url string variable from your database
func GetURL(user string) string {
return ""
}
func CheckUsersCode(user string, code string) (bool, error) {
keyURL := GetURL(user)
key, err := otp.FromURL(keyURL)
if err != nil {
return false, err
}
// Ensure you are using the correct key
if key.Label() != user {
return false, nil
}
success := key.Verify(code)
// Counter has been updated, update this info in the database
// Don't need this step for TOTP keys as the counter is time-based
keyURL = key.URL()
return success, nil
}
OTP Client
import (
"dev.justinjudd.org/justin/otp"
)
// Just an example for storing OTP keys on the client
var keys map[Key]string
// Key is used as keys for the otp key storing map
type Key struct {
Issuer, Label string
}
func GetCode(issuer, username string) (string, error) {
mapKey := Key{issuer, username}
// Get the stored Key URL
keyURL, ok := keys[mapKey]
if !ok {
return "", nil
}
// Build the key from the URL
key, err := otp.FromURL(keyURL)
if err != nil {
return "", err
}
// Verify Issuer and Label are correct
if key.Issuer() != issuer || key.Label() != username {
return "", nil
}
code := key.OTP()
// If using HOTP, than need to save the state
keyURL = key.URL()
keys[mapKey]= keyURL
return code, nil
}