forked from Kong/go-srp
-
Notifications
You must be signed in to change notification settings - Fork 0
/
server.go
106 lines (83 loc) · 2.14 KB
/
server.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
package srp
import (
"bytes"
"errors"
"math/big"
)
type SRPServer struct {
Params *SRPParams
Verifier *big.Int
Secret2 *big.Int
B *big.Int
M1 []byte
M2 []byte
K []byte
u *big.Int
s *big.Int
}
func NewServer(params *SRPParams, Vb []byte, S2b []byte) *SRPServer {
multiplier := getMultiplier(params)
V := intFromBytes(Vb)
secret2 := intFromBytes(S2b)
Bb := getB(params, multiplier, V, secret2)
B := intFromBytes(Bb)
return &SRPServer{
Params: params,
Secret2: secret2,
Verifier: V,
B: B,
}
}
func (s *SRPServer) ComputeB() []byte {
return intToBytes(s.B)
}
func (s *SRPServer) SetA(A []byte) {
AInt := intFromBytes(A)
U := getu(s.Params, AInt, s.B)
S := serverGetS(s.Params, s.Verifier, AInt, s.Secret2, U)
s.K = getK(s.Params, S)
//changed S in getM1(s.Params, A, intToBytes(s.B), S) to s.K to make
//it compatible with jsrp (https://github.com/alax/jsrp)
s.M1 = getM1(s.Params, A, intToBytes(s.B), s.K)
s.M2 = getM2(s.Params, A, s.M1, s.K)
s.u = U // only for tests
s.s = intFromBytes(S) // only for tests
}
func (s *SRPServer) CheckM1(M1 []byte) ([]byte, error) {
if !bytes.Equal(s.M1, M1) {
return nil, errors.New("Client did not use the same password")
} else {
return s.M2, nil
}
}
func (s *SRPServer) ComputeK() []byte {
return s.K
}
// Helpers
func serverGetS(params *SRPParams, V, A, S2, U *big.Int) []byte {
ALessThan0 := A.Cmp(big.NewInt(0)) <= 0
NLessThanA := params.N.Cmp(A) <= 0
if ALessThan0 || NLessThanA {
panic("invalid client-supplied 'A', must be 1..N-1")
}
result1 := new(big.Int)
result1.Exp(V, U, params.N)
result2 := new(big.Int)
result2.Mul(A, result1)
result3 := new(big.Int)
result3.Exp(result2, S2, params.N)
result4 := new(big.Int)
result4.Mod(result3, params.N)
return padToN(result4, params)
}
func getB(params *SRPParams, multiplier, V, b *big.Int) []byte {
gModPowB := new(big.Int)
gModPowB.Exp(params.G, b, params.N)
kMulV := new(big.Int)
kMulV.Mul(multiplier, V)
leftSide := new(big.Int)
leftSide.Add(kMulV, gModPowB)
final := new(big.Int)
final.Mod(leftSide, params.N)
return padToN(final, params)
}