diff options
Diffstat (limited to 'vendor/github.com/pquerna/otp/hotp')
-rw-r--r-- | vendor/github.com/pquerna/otp/hotp/hotp.go | 33 |
1 files changed, 28 insertions, 5 deletions
diff --git a/vendor/github.com/pquerna/otp/hotp/hotp.go b/vendor/github.com/pquerna/otp/hotp/hotp.go index 62cdc87f41..5e99e2218e 100644 --- a/vendor/github.com/pquerna/otp/hotp/hotp.go +++ b/vendor/github.com/pquerna/otp/hotp/hotp.go @@ -70,6 +70,17 @@ func GenerateCode(secret string, counter uint64) (string, error) { // GenerateCodeCustom uses a counter and secret value and options struct to // create a passcode. func GenerateCodeCustom(secret string, counter uint64, opts ValidateOpts) (passcode string, err error) { + // As noted in issue #10 and #17 this adds support for TOTP secrets that are + // missing their padding. + secret = strings.TrimSpace(secret) + if n := len(secret) % 8; n != 0 { + secret = secret + strings.Repeat("=", 8-n) + } + + // As noted in issue #24 Google has started producing base32 in lower case, + // but the StdEncoding (and the RFC), expect a dictionary of only upper case letters. + secret = strings.ToUpper(secret) + secretBytes, err := base32.StdEncoding.DecodeString(secret) if err != nil { return "", otp.ErrValidateSecretInvalidBase32 @@ -135,12 +146,16 @@ type GenerateOpts struct { AccountName string // Size in size of the generated Secret. Defaults to 10 bytes. SecretSize uint + // Secret to store. Defaults to a randomly generated secret of SecretSize. You should generally leave this empty. + Secret []byte // Digits to request. Defaults to 6. Digits otp.Digits // Algorithm to use for HMAC. Defaults to SHA1. Algorithm otp.Algorithm } +var b32NoPadding = base32.StdEncoding.WithPadding(base32.NoPadding) + // Generate creates a new HOTP Key. func Generate(opts GenerateOpts) (*otp.Key, error) { // url encode the Issuer/AccountName @@ -156,16 +171,24 @@ func Generate(opts GenerateOpts) (*otp.Key, error) { opts.SecretSize = 10 } + if opts.Digits == 0 { + opts.Digits = otp.DigitsSix + } + // otpauth://totp/Example:alice@google.com?secret=JBSWY3DPEHPK3PXP&issuer=Example v := url.Values{} - secret := make([]byte, opts.SecretSize) - _, err := rand.Read(secret) - if err != nil { - return nil, err + if len(opts.Secret) != 0 { + v.Set("secret", b32NoPadding.EncodeToString(opts.Secret)) + } else { + secret := make([]byte, opts.SecretSize) + _, err := rand.Read(secret) + if err != nil { + return nil, err + } + v.Set("secret", b32NoPadding.EncodeToString(secret)) } - v.Set("secret", base32.StdEncoding.EncodeToString(secret)) v.Set("issuer", opts.Issuer) v.Set("algorithm", opts.Algorithm.String()) v.Set("digits", opts.Digits.String()) |