Skip to content

Commit 298ff27

Browse files
committed
Refactor step crypto otp tests into using testscript
1 parent f641332 commit 298ff27

5 files changed

Lines changed: 128 additions & 101 deletions

File tree

integration/otp_test.go

Lines changed: 0 additions & 74 deletions
This file was deleted.

integration/script/crypto_test.go

Lines changed: 91 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ import (
1414
"testing"
1515
"time"
1616

17+
"github.com/pquerna/otp"
18+
"github.com/pquerna/otp/totp"
1719
"github.com/rogpeppe/go-internal/testscript"
1820
"github.com/stretchr/testify/require"
1921

@@ -74,40 +76,76 @@ func TestCryptoKeyPair(t *testing.T) {
7476
})
7577
}
7678

77-
func TestCryptoHelp(t *testing.T) {
79+
func TestCryptoOTP(t *testing.T) {
7880
testscript.Run(t, testscript.Params{
79-
Files: []string{"testdata/crypto/help.txtar"},
81+
Files: []string{"testdata/crypto/otp.txtar"},
82+
Setup: func(e *testscript.Env) error {
83+
secret := "UPCTJYT7MUR4RWOUJ3TGTUB43IYCBJ76"
84+
err := os.WriteFile(filepath.Join(e.Cd, "secret.txt"), []byte(secret), 0600)
85+
require.NoError(t, err)
86+
code, err := totp.GenerateCode(secret, time.Now())
87+
require.NoError(t, err)
88+
err = os.WriteFile(filepath.Join(e.Cd, "code.txt"), []byte(code), 0600)
89+
require.NoError(t, err)
90+
err = os.WriteFile(filepath.Join(e.Cd, "invalid.txt"), []byte("aaaaaa"), 0600)
91+
require.NoError(t, err)
92+
urlSecret := "EW32D2CFTAIRTEAWTRQZZXAITVA4U6K4"
93+
url := fmt.Sprintf("otpauth://totp/example.com:[email protected]?algorithm=SHA1&digits=6&issuer=example.com&period=30&secret=%s", urlSecret)
94+
err = os.WriteFile(filepath.Join(e.Cd, "urlsecret.txt"), []byte(urlSecret), 0600)
95+
require.NoError(t, err)
96+
key, err := otp.NewKeyFromURL(url)
97+
require.NoError(t, err)
98+
urlCode, err := totp.GenerateCode(key.Secret(), time.Now())
99+
require.NoError(t, err)
100+
err = os.WriteFile(filepath.Join(e.Cd, "urlcode.txt"), []byte(urlCode), 0600)
101+
require.NoError(t, err)
102+
return nil
103+
},
104+
Cmds: map[string]func(ts *testscript.TestScript, neg bool, args []string){
105+
"check_otp": checkOTP,
106+
},
80107
})
81108
}
82109

83-
func keyLength(jwk *jose.JSONWebKey) (int, error) {
84-
switch key := jwk.Key.(type) {
85-
case []byte:
86-
return len(key) * 8, nil
87-
case *rsa.PrivateKey:
88-
return key.N.BitLen(), nil
89-
case *rsa.PublicKey:
90-
return key.N.BitLen(), nil
91-
case *ecdsa.PrivateKey:
92-
return key.Params().BitSize, nil
93-
case *ecdsa.PublicKey:
94-
return key.Params().BitSize, nil
95-
default:
96-
return 0, fmt.Errorf("unsupported key type: %T", key)
110+
func checkOTP(ts *testscript.TestScript, neg bool, args []string) {
111+
out := strings.TrimSpace(ts.ReadFile(args[0]))
112+
113+
length, err := strconv.Atoi(args[1])
114+
ts.Check(err)
115+
116+
if out == "" {
117+
ts.Fatalf("expected OTP not be empty")
97118
}
98-
}
99119

100-
func keyCurve(jwk *jose.JSONWebKey) (elliptic.Curve, error) {
101-
switch key := jwk.Key.(type) {
102-
case *ecdsa.PrivateKey:
103-
return key.Curve, nil
104-
case *ecdsa.PublicKey:
105-
return key.Curve, nil
106-
default:
107-
return nil, fmt.Errorf("unsupported key type: %T", key)
120+
if length != -1 {
121+
if len(out) != length {
122+
ts.Fatalf("expected OTP to be %d characters long; got %d", length, len(out))
123+
}
124+
}
125+
126+
if strings.HasPrefix(out, "otpauth://") {
127+
key, err := otp.NewKeyFromURL(out)
128+
ts.Check(err)
129+
130+
switch {
131+
case key.Type() != "totp":
132+
ts.Fatalf("expected OTP to be type totp; got %s", key.Type())
133+
case key.Issuer() != "example.com":
134+
ts.Fatalf("expected issuer to be example.com; got %s", key.Issuer())
135+
case key.AccountName() != "[email protected]":
136+
ts.Fatalf("expected account name to be [email protected]; got %s", key.AccountName())
137+
case len(key.Secret()) != 32:
138+
ts.Fatalf("expected secret to be 32 bytes; got %d", len(key.Secret()))
139+
}
108140
}
109141
}
110142

143+
func TestCryptoHelp(t *testing.T) {
144+
testscript.Run(t, testscript.Params{
145+
Files: []string{"testdata/crypto/help.txtar"},
146+
})
147+
}
148+
111149
// checkKeyPair checks that the public/private key pair is valid. It performs
112150
// the following checks:
113151
//
@@ -183,3 +221,31 @@ func checkKeyPair(ts *testscript.TestScript, neg bool, args []string) {
183221
ts.Fatalf("unknown curve %q", crv)
184222
}
185223
}
224+
225+
func keyLength(jwk *jose.JSONWebKey) (int, error) {
226+
switch key := jwk.Key.(type) {
227+
case []byte:
228+
return len(key) * 8, nil
229+
case *rsa.PrivateKey:
230+
return key.N.BitLen(), nil
231+
case *rsa.PublicKey:
232+
return key.N.BitLen(), nil
233+
case *ecdsa.PrivateKey:
234+
return key.Params().BitSize, nil
235+
case *ecdsa.PublicKey:
236+
return key.Params().BitSize, nil
237+
default:
238+
return 0, fmt.Errorf("unsupported key type: %T", key)
239+
}
240+
}
241+
242+
func keyCurve(jwk *jose.JSONWebKey) (elliptic.Curve, error) {
243+
switch key := jwk.Key.(type) {
244+
case *ecdsa.PrivateKey:
245+
return key.Curve, nil
246+
case *ecdsa.PublicKey:
247+
return key.Curve, nil
248+
default:
249+
return nil, fmt.Errorf("unsupported key type: %T", key)
250+
}
251+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# generate
2+
exec step crypto otp generate --issuer example.com --account [email protected]
3+
cp stdout stdout.txt
4+
check_otp stdout.txt 32
5+
6+
7+
# generate with URL
8+
exec step crypto otp generate --issuer example.com --account [email protected] --url
9+
cp stdout stdout.txt
10+
check_otp stdout.txt -1
11+
12+
13+
# verify ok
14+
stdin code.txt
15+
exec step crypto otp verify --secret secret.txt
16+
stdout 'ok'
17+
18+
19+
# verify fails without code
20+
! exec step crypto otp verify --secret secret.txt
21+
stderr 'error while validating TOTP'
22+
23+
24+
# verify fails with invalid code
25+
stdin invalid.txt
26+
! exec step crypto otp verify --secret secret.txt
27+
stdout 'fail'
28+
29+
30+
# verify with URL
31+
stdin urlcode.txt
32+
exec step crypto otp verify --secret urlsecret.txt
33+
34+
35+
# verify with URL fails without code
36+
! exec step crypto otp verify --secret urlsecret.txt
37+
stderr 'error while validating TOTP'

integration/testdata/totp.secret

Lines changed: 0 additions & 1 deletion
This file was deleted.

integration/testdata/totp.url

Lines changed: 0 additions & 1 deletion
This file was deleted.

0 commit comments

Comments
 (0)