-
Notifications
You must be signed in to change notification settings - Fork 14
/
smp_msg3.go
106 lines (80 loc) · 2.61 KB
/
smp_msg3.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 otr3
import "math/big"
type smp3State struct {
x *big.Int
g3b *big.Int
r4, r5, r6, r7 *big.Int
qaqb, papb *big.Int
msg smp3Message
}
type smp3Message struct {
pa, qa *big.Int
cp *big.Int
d5, d6, d7 *big.Int
ra *big.Int
cr *big.Int
}
func (m smp3Message) tlv() tlv {
return genSMPTLV(uint16(tlvTypeSMP3), m.pa, m.qa, m.cp, m.d5, m.d6, m.ra, m.cr, m.d7)
}
func (c *Conversation) generateSMP3Parameters() (s smp3State, err error) {
b := make([]byte, c.version.parameterLength())
var err1, err2, err3, err4 error
s.r4, err1 = c.randMPI(b)
s.r5, err2 = c.randMPI(b)
s.r6, err3 = c.randMPI(b)
s.r7, err4 = c.randMPI(b)
return s, firstError(err1, err2, err3, err4)
}
func generateSMP3Message(s *smp3State, s1 smp1State, m2 smp2Message, v otrVersion) smp3Message {
var m smp3Message
g2 := modExpP(m2.g2b, s1.a2)
g3 := modExpP(m2.g3b, s1.a3)
m.pa = modExpP(g3, s.r4)
m.qa = mulMod(modExpP(g1, s.r4), modExpP(g2, s.x), p)
s.g3b = m2.g3b
s.qaqb = divMod(m.qa, m2.qb, p)
s.papb = divMod(m.pa, m2.pb, p)
m.cp = hashMPIsBN(v.hash2Instance(), 6, modExpP(g3, s.r5), mulMod(modExpP(g1, s.r5), modExpP(g2, s.r6), p))
m.d5 = generateDZKP(s.r5, s.r4, m.cp)
m.d6 = generateDZKP(s.r6, s.x, m.cp)
m.ra = modExpP(s.qaqb, s1.a3)
m.cr = hashMPIsBN(v.hash2Instance(), 7, modExpP(g1, s.r7), modExpP(s.qaqb, s.r7))
m.d7 = subMod(s.r7, mul(s1.a3, m.cr), q)
return m
}
func (c *Conversation) generateSMP3(secret *big.Int, s1 smp1State, m2 smp2Message) (s smp3State, err error) {
if s, err = c.generateSMP3Parameters(); err != nil {
return s, err
}
s.x = secret
s.msg = generateSMP3Message(&s, s1, m2, c.version)
return
}
func (c *Conversation) verifySMP3(s2 *smp2State, msg smp3Message) error {
if !c.version.isGroupElement(msg.pa) {
return newOtrError("Pa is an invalid group element")
}
if !c.version.isGroupElement(msg.qa) {
return newOtrError("Qa is an invalid group element")
}
if !c.version.isGroupElement(msg.ra) {
return newOtrError("Ra is an invalid group element")
}
if !verifyZKP3(msg.cp, s2.g2, s2.g3, msg.d5, msg.d6, msg.pa, msg.qa, 6, c.version) {
return newOtrError("cP is not a valid zero knowledge proof")
}
qaqb := divMod(msg.qa, s2.qb, p)
if !verifyZKP4(msg.cr, s2.g3a, msg.d7, qaqb, msg.ra, 7, c.version) {
return newOtrError("cR is not a valid zero knowledge proof")
}
return nil
}
func (c *Conversation) verifySMP3ProtocolSuccess(s2 *smp2State, msg smp3Message) error {
papb := divMod(msg.pa, s2.pb, p)
rab := modExpP(msg.ra, s2.b3)
if !eq(rab, papb) {
return newOtrError("protocol failed: x != y")
}
return nil
}