forked from opencoff/go-srp
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsrp_test.go
156 lines (118 loc) · 3.62 KB
/
srp_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
// self test for srp
//
// Copyright 2013-2023 arag0re <arag0re.eth-at-protonmail-dot-com>
// License: MIT
//
package srp
import (
"fmt"
"runtime"
"testing"
"crypto/subtle"
)
func newAsserter(t *testing.T) func(cond bool, msg string, args ...interface{}) {
return func(cond bool, msg string, args ...interface{}) {
if cond {
return
}
_, file, line, ok := runtime.Caller(1)
if !ok {
file = "???"
line = 0
}
s := fmt.Sprintf(msg, args...)
t.Fatalf("%s: %d: Assertion failed: %s\n", file, line, s)
}
}
type userdb struct {
s *SRP
u map[string]string
}
func newUserDB(user, pass []byte, p int) (*userdb, error) {
s, err := New()
if err != nil {
return nil, err
}
v, err := s.Verifier(user, pass)
if err != nil {
return nil, err
}
ih, vh := v.Encode()
db := &userdb{
s: s,
u: make(map[string]string),
}
db.u[ih] = vh
return db, nil
}
// simulated user lookup
func (db *userdb) lookup(ih string) (bool, string) {
u, ok := db.u[ih]
return ok, u
}
func (db *userdb) verify(t *testing.T, user, pass []byte, goodPw bool) {
assert := newAsserter(t)
s := db.s // SRP Instance
// Start an SRP Client instance
c, err := s.NewClient(user, pass)
assert(err == nil, "NewClient: %s", err)
// Credentials to send to server
creds := c.Credentials() // this is what we send to server
// client --> sends 'creds' to server
// In actuality, this is done on the server.
ih, A, err := ServerBegin(creds)
assert(err == nil, "ServerBegin: %s", err)
// Using identity 'ih', lookup the user-db and fetch the encoded verifier.
ok, vs := db.lookup(ih)
assert(ok, "can't find user in db")
// On the server, we create the SRP instance afresh from the verifier.
s, v, err := MakeSRPVerifier(vs)
assert(err == nil, "SRPVerifier: %s", err)
// create a SRP server instance using the verifier and public key
srv, err := s.NewServer(v, A)
assert(err == nil, "NewServer: %s", err)
// Send the salt and Server public Key to client
sCreds := srv.Credentials()
// Server --> sends 'sCreds' to client
// Marshal the server for use later as-if the client can't remain connected
srv_m := srv.Marshal()
// Client generates a mutual auth and sends to server
mauth, err := c.Generate(sCreds)
assert(err == nil, "Client.Generate: %s", err)
// Client --> sends 'mauth' to server
// Unmarshal the previously marshaled server for use after the client reconnects
srv_um, err := UnmarshalServer(srv_m)
assert(err == nil, "UnmarshalServer: %s", err)
// Server validates the mutual authenticator and creates its proof of having derived
// the same key. This proof is sent to the client.
proof, ok := srv_um.ClientOk(mauth)
if goodPw {
assert(ok, "server: bad client proof")
} else {
assert(!ok, "server: validated bad password")
return
}
// Server --> sends 'proof' to client
// finally, the client should verify the server's proof
ok = c.ServerOk(proof)
assert(ok, "client: bad client proof")
// both client and server are authenticated. Now, we generate a
// mutual secret -- which should be identical
kc := c.RawKey()
ks := srv_um.RawKey()
assert(subtle.ConstantTimeCompare(kc, ks) == 1, "key mismatch;\nclient %x, server %x", kc, ks)
}
func TestSRP(t *testing.T) {
assert := newAsserter(t)
var user []byte = []byte("user00")
var goodpass []byte = []byte("secretpassword")
var badpass []byte = []byte("badpassword")
bits := []int{1024, 2048, 3072, 4096, 6144, 8192}
for _, p := range bits {
t.Logf("Prime bits %d ..\n", p)
db, err := newUserDB(user, goodpass, p)
assert(err == nil, "expected err to be nil; saw %s", err)
db.verify(t, user, goodpass, true)
db.verify(t, user, badpass, false)
}
}