-
Notifications
You must be signed in to change notification settings - Fork 0
/
client.go
112 lines (90 loc) · 2.99 KB
/
client.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
package spake2plus
import (
"errors"
"github.com/jtejido/spake2plus/internal/suite"
)
type Client struct {
suite suite.CipherSuite
x suite.Scalar
clientIdentity []byte
serverIdentity []byte
verifierW0 []byte
verifierW1 []byte
msg []byte
}
func NewClient(s suite.CipherSuite, clientIdentity, serverIdentity, password, salt []byte) (*Client, error) {
x, err := s.Group().RandomScalar()
if err != nil {
return nil, err
}
w0, w1, err := computeW0W1(s, clientIdentity, serverIdentity, password, salt)
if err != nil {
return nil, err
}
return &Client{s, x, clientIdentity, serverIdentity, w0, w1, nil}, nil
}
// Send this to server during Registration part
func (c *Client) Verifier() (*Verifier, error) {
w1Scalar := c.suite.Group().Scalar()
err := w1Scalar.FromBytes(padScalarBytes(c.verifierW1, c.suite.Group().ScalarLen()))
if err != nil {
return nil, err
}
L := c.suite.Group().Element().ScalarMult(w1Scalar, nil)
return &Verifier{
I: c.clientIdentity,
Verifier: VerifierPair{
V1: c.verifierW0,
V2: L.Bytes(),
},
}, nil
}
// EphemeralPublic returns A.
// This will be sent to the server.
func (c *Client) EphemeralPublic() ([]byte, error) {
w0Scalar := c.suite.Group().Scalar()
err := w0Scalar.FromBytes(padScalarBytes(c.verifierW0, c.suite.Group().ScalarLen()))
if err != nil {
return nil, err
}
// X=x*P+w0*M
x := c.suite.Group().Element().ScalarMult(c.x, nil)
x.Add(x, c.suite.Group().Element().ScalarMult(w0Scalar, c.suite.Group().M()))
XBytes := x.Bytes()
c.msg = XBytes
return XBytes, nil
}
func (c *Client) CompleteHandshake(m *ServerMaterial) (*SharedSecret, error) {
incomingElement := c.suite.Group().Element()
err := incomingElement.FromBytes(m.B)
if err != nil {
return nil, err
}
if isElementSmall(c.suite, incomingElement) {
return nil, errors.New("Corrupt Message")
}
w0Scalar := c.suite.Group().Scalar()
err = w0Scalar.FromBytes(padScalarBytes(c.verifierW0, c.suite.Group().ScalarLen()))
if err != nil {
return nil, err
}
w1Scalar := c.suite.Group().Scalar()
err = w1Scalar.FromBytes(padScalarBytes(c.verifierW1, c.suite.Group().ScalarLen()))
if err != nil {
return nil, err
}
// A computes Z as h*x*(Y-w0*N), and V as h*w1*(Y-w0*N).
tmp := c.suite.Group().Element().ScalarMult(c.suite.Group().Scalar().Negate(w0Scalar), c.suite.Group().N())
tmp.Add(incomingElement, tmp)
ZElement := c.suite.Group().Element().ScalarMult(c.x, tmp)
ZElement = c.suite.Group().ClearCofactor(ZElement)
ZBytes := ZElement.Bytes()
VElement := c.suite.Group().Element().ScalarMult(w1Scalar, tmp)
VElement = c.suite.Group().ClearCofactor(VElement)
VBytes := VElement.Bytes()
return newClientSharedSecret(c.clientIdentity, c.serverIdentity, c.msg, m.B, ZBytes, VBytes, c.verifierW0, c.suite), nil
}
func newClientSharedSecret(idA, idB, X, Y, Z, V, w0 []byte, s suite.CipherSuite) *SharedSecret {
Ke, Ka, kcA, kcB := generateSharedSecrets(s, idA, idB, X, Y, Z, V, w0)
return newSharedSecret(Ke, Ka, X, Y, kcA, kcB, s)
}