Go library for generating and using One Time Passwords.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Justin Judd 6ad513fa31 Adding language hint for markdown examples. 6 years ago
.gitignore initial commit 7 years ago
LICENSE initial commit 7 years ago
README.md Adding language hint for markdown examples. 6 years ago
common.go Adding otp code and updated README. 6 years ago
hotp.go Adding otp code and updated README. 6 years ago
hotp_client_example_test.go Updating some of the examples. 6 years ago
hotp_example_test.go Updating some of the examples. 6 years ago
hotp_server_example_test.go Updating some of the examples. 6 years ago
hotp_test.go Adding otp code and updated README. 6 years ago
otp.go Adding otp code and updated README. 6 years ago
otp_test.go Adding otp code and updated README. 6 years ago
totp.go Adding otp code and updated README. 6 years ago
totp_example_test.go Adding otp code and updated README. 6 years ago
totp_test.go Adding otp code and updated README. 6 years ago

README.md

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.

GoDoc

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
}