-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathREADME
165 lines (119 loc) · 6.35 KB
/
README
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
157
158
159
160
161
162
163
164
165
This repo contains macros to be assembled into circuits for use in TLSNotary's 2PC.
The main entrypoints are 6 circuits c1.casm ... c7.casm.
Each macro contains a description about what it does.
To assemble the macros into Bristol Fashion circuits
(https://homes.esat.kuleuven.be/~nsmart/MPC/), run:
node assemble.js
SOURCES:
casmbundle.js was created from:
git clone https://github.com/wyatt-howe/macro-circuit-assembler
cd macro-circuit-assembler/
git pull origin pull/3/head
# (this PR hasn't been merged at the time of writing)
# then comment out line 4 in casm.js --> //const fs = require('fs');
browserify --ignore fs --standalone CASM casm.js > casmbundle.js
adder64.txt --> https://homes.esat.kuleuven.be/~nsmart/MPC/adder64.txt
aes-128-reverse.txt --> https://github.com/multiparty/jigg/blob/master/circuits/bristol/aes-128-reverse.txt
sha256.txt --> https://homes.esat.kuleuven.be/~nsmart/MPC/sha256.txt
## License
All circuits in this repository are licensed under either of
- [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0)
- [MIT license](http://opensource.org/licenses/MIT)
at your option.
The circuits c1, c2, c3, c4, c5 compute TLS's PRF starting from the pre-master
secret and computing "master secret", "expanded keys", "verify_data" for
Client_Finished, "verify_data" for Server_Finished.
The reason why there are separate circuits instead of one monolithic circuit is
that some intermediate computations can be done outside of the circuit,
significantly reducing the size of the circuit.
Here is the description of the all the steps to compute TLS PRF both inside and
outside the circuit:
1. Parties, having their shares of PMS (the pre-master secret) will compute MS
(master secret). The corresponding python code is:
seed = str.encode("master secret") + client_random + server_random
a0 = seed
a1 = hmac.new(pms, a0, hashlib.sha256).digest()
a2 = hmac.new(pms, a1, hashlib.sha256).digest()
p1 = hmac.new(pms, a1+seed, hashlib.sha256).digest()
p2 = hmac.new(pms, a2+seed, hashlib.sha256).digest()
ms = (p1+p2)[0:48]
We will be using the notation from https://en.wikipedia.org/wiki/HMAC to explain
the internals of the HMAC function. HMAC computes an inner hash and an outer hash.
2. Parties provide their inputs for circuit c1. N provides his PMS share and C
provides his PMS share. The circuit outputs H(pms xor opad) called "pms outer
hash state" to N and also outputs H(pms xor ipad) called "pms inner hash state"
to C.
3. The following steps happen outside of the circuit: C computes
H((pms xor ipad) || a0) called "inner hash" of a1 and passes it to N.
4. N computes a1 and passes it to C.
5. C computes inner hash of a2 and passes it to N.
6. N computes a2 and passes it to C.
7. C computes inner hash of p2 and passes it to N.
8. N computes p2 and passes it to C.
Note that p2 is obtained in the clear, thus both parties know the last 16 bytes
of MS. It is possible to put this step inside the circuit if needed. But we
think that revealing 16 bytes of MS while keeping the other 32 bytes secret
provides adequate security.
9. C computes inner hash of p1.
10. Parties provide their inputs for circuit c2. N provides "pms outer hash
state" and C provides p2 and inner hash of p1. The circuit computes the master
secret (MS).
11. The parties proceed to compute the expanded keys (EK). The corresponding
python code is:
seed = str.encode("key expansion") + server_random + client_random
a0 = seed
a1 = hmac.new(ms , a0, hashlib.sha256).digest()
a2 = hmac.new(ms , a1, hashlib.sha256).digest()
p1 = hmac.new(ms, a1+seed, hashlib.sha256).digest()
p2 = hmac.new(ms, a2+seed, hashlib.sha256).digest()
ek = (p1 + p2)[:40]
client_write_key = ek[:16]
server_write_key = ek[16:32]
client_write_IV = ek[32:36]
server_write_IV = ek[36:40]
12. While still inside the circuit, having computed MS, the circuit now outputs
H(ms xor opad) called "ms outer hash state" to N and also outputs H(ms xor ipad)
called "ms inner hash state" to C.
13. The following steps happen outside of the circuit: C computes inner hash of
a1 and sends it to N.
14. N computes a1 and sends it to C.
15. C computes inner hash of a2 and sends it to N.
16. N computes a2 and sends it to C.
17. C computes inner state of p1 and inner state of p2.
18. The parties provide their inputs to circuit c3. N provides "ms outer hash
state" (from Step 10) and C provides inner state of p1 and inner state of p2.
Inside the circuit, p1 and p2 are computed. The circuit outputs xor shares of
keys and IVs to each party.
The parties provide their shares of keys and IVs to circuit c4. The circuit
outputs data needed to encrypt and authenticate the Client_Finished.
19. The parties proceed to compute verify_data for the Client_Finished message
outside of the circuit. The corresponding python code is:
(handshake_hash) is a sha256 hash of all TLS handshake message up to this point
seed = str.encode('client finished') + handshake_hash
a0 = seed
a1 = hmac.new(ms, a0, hashlib.sha256).digest()
p1 = hmac.new(ms, a1+seed, hashlib.sha256).digest()
verify_data = p1[:12]
20. C computes inner hash of a1 and sends it to N.
21. N (who has "ms outer hash state" from Step 10) computes a1 and sends it to C.
22. C computes inner hash of p1 and sends it to N.
23. N computes p1 and gets verify_data and sends it to C.
Note that N's knowing the verify_data for CF does not pose a threat of N
impersonating the webserver. In the next step C will check the Server_Finished
for correctness. Since N does not know server_write_key and server_write_iv,
N cannot forge the Server_Finished.
24. Upon C's receiving the Server_Finished (SF), the parties proceed to compute
verify_data for SF to check that the received SF is correct. The corresponding
python code is:
(handshake_hash) is a sha256 hash of all TLS handshake message up to this point
seed = str.encode('server finished') + handshake_hash
a0 = seed
a1 = hmac.new(ms, a0, hashlib.sha256).digest()
p1 = hmac.new(ms, a1+seed, hashlib.sha256).digest()
verify_data = p1[:12]
25. Outside of the circuit, C computes inner hash of a1 and sends it to N.
26. N (who has "ms outer hash state" from Step 10) computes a1 and sends it to C.
27. C computes inner hash of p1.
28. The parties provide their inputs to circuit c5. N provides "ms outer hash
state" (from Step 10) and C provides inner hash of p1. The circuit outputs
verify_data for Server_Finished to C.