# otp Go library for generating and using One Time Passwords. Supports both HOTP ([RFC4226](https://tools.ietf.org/html/rfc4226)) and TOTP ([RFC6238](https://tools.ietf.org/html/rfc6238)). Can be used for both server and client roles. [![GoDoc](https://godoc.org/dev.justinjudd.org/justin/otp?status.svg)](https://godoc.org/dev.justinjudd.org/justin/otp) ## Examples ### OTP Server ```go 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 ```go 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 } ```