Skip to content

Commit c62dc58

Browse files
Add Algorithm and Digits methods (pquerna#74)
* Add Algorithm and Digits methods This commit adds two new methods that expose the Algorithm and the Digits parameters from the Key URL. This is useful for users of the GenerateCustomCode methods. Signed-off-by: Dominik Schulz <[email protected]> * Make Digits return Digits not unit64 Signed-off-by: Dominik Schulz <[email protected]>
1 parent 60112ee commit c62dc58

File tree

2 files changed

+44
-10
lines changed

2 files changed

+44
-10
lines changed

otp.go

+39-7
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,6 @@
1818
package otp
1919

2020
import (
21-
"github.com/boombuler/barcode"
22-
"github.com/boombuler/barcode/qr"
23-
2421
"crypto/md5"
2522
"crypto/sha1"
2623
"crypto/sha256"
@@ -30,8 +27,11 @@ import (
3027
"hash"
3128
"image"
3229
"net/url"
33-
"strings"
3430
"strconv"
31+
"strings"
32+
33+
"github.com/boombuler/barcode"
34+
"github.com/boombuler/barcode/qr"
3535
)
3636

3737
// Error when attempting to convert the secret from base32 to raw bytes.
@@ -61,7 +61,6 @@ func NewKeyFromURL(orig string) (*Key, error) {
6161
s := strings.TrimSpace(orig)
6262

6363
u, err := url.Parse(s)
64-
6564
if err != nil {
6665
return nil, err
6766
}
@@ -81,7 +80,6 @@ func (k *Key) String() string {
8180
// to enroll a user's TOTP/HOTP key.
8281
func (k *Key) Image(width int, height int) (image.Image, error) {
8382
b, err := qr.Encode(k.orig, qr.M, qr.Auto)
84-
8583
if err != nil {
8684
return nil, err
8785
}
@@ -146,11 +144,45 @@ func (k *Key) Period() uint64 {
146144
if u, err := strconv.ParseUint(q.Get("period"), 10, 64); err == nil {
147145
return u
148146
}
149-
147+
150148
// If no period is defined 30 seconds is the default per (rfc6238)
151149
return 30
152150
}
153151

152+
// Digits returns a tiny int representing the number of OTP digits.
153+
func (k *Key) Digits() Digits {
154+
q := k.url.Query()
155+
156+
if u, err := strconv.ParseUint(q.Get("digits"), 10, 64); err == nil {
157+
switch u {
158+
case 8:
159+
return DigitsEight
160+
default:
161+
return DigitsSix
162+
}
163+
}
164+
165+
// Six is the most common value.
166+
return DigitsSix
167+
}
168+
169+
// Algorithm returns the algorithm used or the default (SHA1).
170+
func (k *Key) Algorithm() Algorithm {
171+
q := k.url.Query()
172+
173+
a := strings.ToLower(q.Get("algorithm"))
174+
switch a {
175+
case "md5":
176+
return AlgorithmMD5
177+
case "sha256":
178+
return AlgorithmSHA256
179+
case "sha512":
180+
return AlgorithmSHA512
181+
default:
182+
return AlgorithmSHA1
183+
}
184+
}
185+
154186
// URL returns the OTP URL as a string
155187
func (k *Key) URL() string {
156188
return k.url.String()

otp_test.go

+5-3
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,20 @@
1818
package otp
1919

2020
import (
21-
"github.com/stretchr/testify/require"
22-
2321
"testing"
22+
23+
"github.com/stretchr/testify/require"
2424
)
2525

2626
func TestKeyAllThere(t *testing.T) {
27-
k, err := NewKeyFromURL(`otpauth://totp/Example:[email protected]?secret=JBSWY3DPEHPK3PXP&issuer=Example`)
27+
k, err := NewKeyFromURL(`otpauth://totp/Example:[email protected]?secret=JBSWY3DPEHPK3PXP&issuer=Example&algorithm=sha256&digits=8`)
2828
require.NoError(t, err, "failed to parse url")
2929
require.Equal(t, "totp", k.Type(), "Extracting Type")
3030
require.Equal(t, "Example", k.Issuer(), "Extracting Issuer")
3131
require.Equal(t, "[email protected]", k.AccountName(), "Extracting Account Name")
3232
require.Equal(t, "JBSWY3DPEHPK3PXP", k.Secret(), "Extracting Secret")
33+
require.Equal(t, AlgorithmSHA256, k.Algorithm())
34+
require.Equal(t, DigitsEight, k.Digits())
3335
}
3436

3537
func TestKeyIssuerOnlyInPath(t *testing.T) {

0 commit comments

Comments
 (0)