-
Notifications
You must be signed in to change notification settings - Fork 11
/
srp.go
98 lines (88 loc) · 2.56 KB
/
srp.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
// Package srp is port of node-srp to Go.
//
//
// To use SRP, first decide on they parameters you will use. Both client and server must
// use the same set.
// params := srp.GetParams(4096)
//
// From the client... generate a new secret key, initialize the client, and compute A.
// Once you have A, you can send A to the server.
// secret1 := srp.GenKey()
// client := NewClient(params, salt, identity, secret, a)
// srpA := client.computeA()
//
// sendToServer(srpA)
//
// From the server... generate another secret key, initialize the server, and compute B.
// Once you have B, you can send B to the client.
// secret2 := srp.GenKey()
// server := NewServer(params, verifier, secret2)
// srpB := client.computeB()
//
// sendToClient(srpB)
//
// Once the client received B from the server, it can compute M1 based on A and B.
// Once you have M1, send M1 to the server.
// client.setB(srpB)
// srpM1 := client.ComputeM1()
// sendM1ToServer(srpM1)
//
// Once the server receives M1, it can verify that it is correct. If checkM1() returns
// an error, authentication failed. If it succeeds it should be sent to the client.
// srpM2, err := server.checkM1(srpM1)
//
// Once the client receives M2, it can verify that it is correct, and know that authentication
// was successful.
// err = client.CheckM2(serverM2)
//
// Now that both client and server have completed a successful authentication, they can
// both compute K independently. K can now be used as either a key to encrypt communication
// or as a session ID.
// clientK := client.ComputeK()
// serverK := server.ComputeK()
//
package srp
import (
"crypto/rand"
"io"
"math/big"
)
func GenKey() []byte {
bytes := make([]byte, 32)
_, err := io.ReadFull(rand.Reader, bytes)
if err != nil {
panic("Random source is broken!")
}
return bytes
}
func getK(params *SRPParams, S []byte) []byte {
hashK := params.Hash.New()
hashK.Write(S)
return hashToBytes(hashK)
}
func getu(params *SRPParams, A, B *big.Int) *big.Int {
hashU := params.Hash.New()
hashU.Write(A.Bytes())
hashU.Write(B.Bytes())
return hashToInt(hashU)
}
func getM1(params *SRPParams, A, B, S []byte) []byte {
hashM1 := params.Hash.New()
hashM1.Write(A)
hashM1.Write(B)
hashM1.Write(S)
return hashToBytes(hashM1)
}
func getM2(params *SRPParams, A, M, K []byte) []byte {
hashM1 := params.Hash.New()
hashM1.Write(A)
hashM1.Write(M)
hashM1.Write(K)
return hashToBytes(hashM1)
}
func getMultiplier(params *SRPParams) *big.Int {
hashK := params.Hash.New()
hashK.Write(padToN(params.N, params))
hashK.Write(padToN(params.G, params))
return hashToInt(hashK)
}