-
Notifications
You must be signed in to change notification settings - Fork 2
Circuits used for TLSNotary's 2PC
License
tlsnotary/circuits
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
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.
About
Circuits used for TLSNotary's 2PC
Resources
License
Stars
Watchers
Forks
Releases
No releases published
Packages 0
No packages published