@@ -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+ }
0 commit comments