Notarization Phase

During the Notarization Phase the Requester, otherwise referred to as the User, and the Notary work together to generate an authenticated Transcript of a TLS session with a Server.

Listed below are some key points regarding this process:

  • The identity of the Server is not revealed to the Notary, but the Requester is capable of proving the Server identity to a Verifier later.
  • The Notary only ever sees the encrypted application data of the TLS session.
  • The protocol guarantees that the Requester is not solely capable of constructing requests, nor can they forge responses from the Server.


The Requester is the party which runs the TLS connection with the Server. The Requester constructs application payloads, eg. HTTP requests, and coordinates with the Notary to encrypt them with the TLS session keys prior to sending them. Subsequently, the Requester works with the Notary to decrypt responses from the Server. The plaintext of the application data is only ever revealed to the Requester.


The Notary is the party of which the authenticity of the Transcript relies on. During the session the Notary withholds its' shares of the TLS keys and participates in a series of secure 2-party computation protocols with the Requester to operate the TLS connection.


The Server can be any server which supports TLS. The TLSNotary protocol is entirely transparent to the Server, thus it can not be censored nor does it have to support any additional functionality.


The primary artifact generated from this phase is called the Transcript. It contains session meta-data, handshake data, and commitments to all the requests and responses. Typically the Transcript is signed by the Notary, however that is not necessary in the case where the Notary will also act as the Verifier in the selective disclosure phase.

Note that the server ephemeral key does not reveal the identity of the server to the Notary.

Key Exchange

In TLS, the first step towards obtaining TLS session keys is to compute a shared secret between the client and the server by running the ECDH protocol. The resulting shared secret in TLS terms is called the pre-master secret PMS.

Using the notation from Wikipedia, below is the 3-party ECDH protocol between the Server the Requester and the Notary, enabling the Requester and the Notary to arrive at shares of PMS.

  1. Server sends its public key to Requester, and Requester forwards it to Notary
  2. Requester picks a random private key share and computes a public key share
  3. Notary picks a random private key share and computes a public key share
  4. Notary sends to Requester who computes and sends to Server
  5. Requester computes an EC point
  6. Notary computes an EC point
  7. Addition of points and results in the coordinate , which is PMS. (The coordinate is not used in TLS)

Using the notation from here, our goal is to compute in such a way that

  1. Neither party learns the other party's value
  2. Neither party learns , only their respective shares of .

We will use two maliciously secure protocols described on p.25 in the paper Efficient Secure Two-Party Exponentiation:

  • A2M protocol, which converts additive shares into multiplicative shares, i.e. given shares a and b such that a + b = c, it converts them into shares d and e such that d * e = c
  • M2A protocol, which converts multiplicative shares into additive shares

We apply A2M to to get and also we apply A2M to to get . Then the above can be rewritten as:

Then the first party locally computes the first factor and gets , the second party locally computes the second factor and gets . Then we can again rewrite as:

Now we apply M2A to to get , which leads us to two final terms each of which is the share of of the respective party:


The pre-master secret (PMS) must be put through a PRF (pseudo-random function) defined by the TLS spec in order to compute the symmetric TLS keys and also to compute the verify_data for the Client_Finished and the Server_Finished messages.

Below we describe how the parties (N stands for Notary and U stands for User) who have their shares of PMS can use 2PC to compute the PRF.

Since the TLSNotary protocol already uses Garbled Circuits and Oblivious Transfer which give 128-bit computational security for the parties against each other, we argue that it is acceptable to perform some PRF computations outside of 2PC as long as it is done with at least 128-bit security. Performing some PRF computations outside of 2PC allows to save on computation and bandwidth.

Note that the User's TLS connection retains the standard TLS security guarantees against any third-party adversary.

To elaborate, recall how HMAC is computed (assuming |k| <= block size):

HMAC(k, m) = H((k ⊕ opad) | H((k ⊕ ipad) | m))

Notice that both H(k ⊕ opad) and H(k ⊕ ipad) can be computed separately prior to finalization. In this document we name these units as such:

  • outer hash state: H(k ⊕ opad)
  • inner hash state: H(k ⊕ ipad)
  • inner hash: H((k ⊕ ipad) | m)

In TLS, the master secret is computed like so:

seed = "master secret" | client_random | server_random
a0 = seed
a1 = HMAC(pms, a0)
a2 = HMAC(pms, a1)
p1 = HMAC(pms, a1 | seed)
p2 = HMAC(pms, a2 | seed)
ms = (p1 | p2)[:48]

Notice that in each step the key, in this case PMS, is constant. Thus both the outer and inner hash state can be reused for each step.

Below is the description of the all the steps to compute the PRF both inside and outside the 2PC circuit.

---- Computing the master secret

-- Inside the circuit

  1. To evaluate the circuit, the parties input their PMS shares. The circuit outputs:
  • H(PMS ⊕ opad) called PMS outer hash state to N and
  • H(PMS ⊕ ipad) called PMS inner hash state to U

-- Outside the circuit

  1. U computes H((PMS ⊕ ipad) || a0) called inner hash of a1 and passes it to N.

  2. N computes a1 and passes it to U.

  3. U computes the inner hash of a2 and passes it to N.

  4. N computes a2 and passes it to U.

  5. U computes the inner hash of p2 and passes it to N.

  6. N computes p2 and passes it to U. >Note that now both parties know p2 which is the last 16 bytes of the master secret. They still don't know the other 32 bytes of the master secret, which ensures adequate security.

  7. U computes the inner hash of p1.

-- Inside the circuit

  1. To evaluate the circuit, N inputs the PMS outer hash state and U inputs p2 and the inner hash of p1. The circuit computes the master secret (MS).

---- Computing the expanded keys

The parties proceed to compute the expanded keys. The corresponding python code is:

seed = str.encode("key expansion") + server_random + client_random
a0 = seed
a1 = , a0, hashlib.sha256).digest()
a2 = , a1, hashlib.sha256).digest()
p1 =, a1+seed, hashlib.sha256).digest()
p2 =, 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]

-- Inside the circuit

  1. Having computed MS, the circuit outputs:
  • H(MS ⊕ opad) called the MS outer hash state to N and
  • H(MS ⊕ ipad) called the MS inner hash state to U

-- Outside the circuit

  1. U computes the inner hash of a1 and sends it to N.

  2. N computes a1 and sends it to U.

  3. U computes the inner hash of a2 and sends it to N.

  4. N computes a2 and sends it to U.

  5. U computes the inner hash state of p1 and the inner hash state of p2.

-- Inside the circuit

  1. To evaluate the circuit, N inputs MS outer hash state (from Step 10) and U inputs inner hash state of p1 and inner hash state of p2. The circuit computes p1 and p2. The circuit outputs xor shares of the expanded keys to each party.

---- Computing the encrypted Client_Finished

-- Inside the circuit

  1. To evaluate the circuit, the parties input their shares of the expanded keys. The circuit outputs data needed to encrypt and authenticate the Client_Finished (CF) message.

-- Outside the circuit

The parties proceed to compute verify_data for the CF message. 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 =, a0, hashlib.sha256).digest()
p1 =, a1+seed, hashlib.sha256).digest()
verify_data = p1[:12]
  1. U computes inner hash of a1 and sends it to N.

  2. N (who has MS outer hash state from Step 10) computes a1 and sends it to U.

  3. U computes inner hash of p1 and sends it to N.

  4. N computes p1 and gets verify_data and sends it to U.

Note that it is safe for N to know verify_data for CF.

Using the data from Step 17, U proceeds to encrypt and authenticate CF and sends it to the webserver.

---- Verifying the Server_Finished

Upon U's receiving the encrypted Server_Finished (SF) from the webserver, the parties proceed to compute verify_data for SF, to enable U 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 =, a0, hashlib.sha256).digest()
p1 =, a1+seed, hashlib.sha256).digest()
verify_data = p1[:12]

-- Outside the circuit

  1. U computes inner hash of a1 and sends it to N.

  2. N (who has MS outer hash state from Step 10) computes a1 and sends it to U.

  3. U computes inner hash of p1.

-- Inside the circuit

  1. To evaluate the circuit, N inputs MS outer hash state (from Step 10) and U inputs inner hash of p1. The circuit outputs verify_data for SF to U.

The parties proceed to decrypt and authenticate the SF in 2PC. U checks that verify_data from SF matches verify_data from Step 25.

At the end of the TLSNotary protocol, the User has the authenticated AES ciphertext which can be thought of as a commitment to the plaintext. This form of commitment is not amenable to use cases when the User wants to make part of the plaintext public while keeping another part private. Naively, the User's option is to prove the decryption of the ciphertext in zero-knowledge which is computationally expensive.

We describe two less computationally heavy approaches for converting the AES ciphertext commitments.

The first approach is useful for commitments to the data which the User intends to make public. It is based on decrypting the ciphertext with Garbled Circuits and producing a hash commitment to the wire labels.

The second approach is useful for commitments to the private data which the User later intends to prove statements about in zero-knowledge. This approach produces a Poseidon hash over the private data.

We describe an interactive protocol between the User U and the Notary N, whereby U can convert the authenticated AES ciphertext into a hash commitment to Garbled Circuits wire labels.

---- Creating the new commitment

  1. At the end of the TLSNotary session, both U and N know the authenticated AES ciphertext.

  2. N reveals his TLS session key shares to U.

  3. U decrypts the ciphertext in the clear and learns the plaintext p.

  4. N picks a seed and uses it as the source of randomness to generate (in the semi-honest model) a privacy-free garbled circuit whose functionality is to accept the plaintext input, encrypt it, and output the ciphertext.

  5. With p as her circuit input, U receives input wire labels IWLs via Oblivious Transfer and then evaluates the circuit on those IWLs. The result of the evaluation are output wire labels OWLs which U does not know the decoding for.

  6. U sends two commitments: commitment to IWLs and commitment to OWLs to N.

  7. N reveals the seed and U checks that the circuit (including its IWLs and OWLs) was generated correctly and, if successful, reveals her OWLs.

  8. N verifies commitment to OWLs and then checks that decoded OWLs match the ciphertext (from Step 0) and, if successful, signs (seed + commitment to IWLs).

Now, (seed + commitment to IWLs) become U's new commitment to p.

---- Verifying the commitment

Verifier performs the following steps:

  1. Receives the following from U: plaintext p, signature for (seed + commitment to IWLs), seed, commitment to IWLs.

  2. (using a trusted Ns pubkey) Verifies the signature.

  3. Re-generates the IWLs from the seed.

  4. Picks only those IWLs which correspond to p and checks that the commitment to those IWLs matches commitment to IWLs.

  5. Accepts p as authentic.

---- Dynamic commitment using a Merkle tree

In situations where U does not know in advance which subset of the public data she will be revealing later to the Verifier, U can commit to the Merkle tree of all her input wire labels (from Step 4 above). Later, U can reveal only those Merkle leaves which she wants to make public to the Verifier.

Secure 2-Party Computation

To ensure malicious security of the Garbled Circuits 2PC, TLSNotary uses the Dual Execution protocol (see Section 7.6).

DualEX inherently leaks n bits of private input with probability . This is not a problem during the TLS handshake when the private inputs are symmetric keys or hash pre-images. Leaking n bits does not give the adversary any advantage, since with the same probability the adversary may have guessed those bits while brute-forcing the key or the pre-image.

However, the leakage becomes a problem when encrypting the request or decrypting the response, since leaking even 1 bit of the plaintext may be catastrophic for the User's privacy. To overcome this leakage, we use a variant of DualEx where privacy is guaranteed only for the User.


When encrypting the plaintext request in Dual Execution 2PC, the User can avoid the inherent 1-bit leakage of her plaintext by having the Notary give up his private inputs at the end of the TLSNotary session and also introducing some correctness checks. The technical steps of this approach are given below.


The User wants to encrypt a TLS request with some server, but she doesn't have the encryption key. Rather she has just one share of the key. The Notary has the other share. The Notary needs to know that the only ciphertext sent to the TLS server is the ciphertext he has seen (it would be bad, e.g., if the User had the full key because she'd lie to the Notary about the request she sent). We want a 2PC scheme that will allow the User and Notary to collaboratively compute the ciphertext such that: the User does not reveal her plaintext or key share, and the Notary does not reveal his key share.


We make two observations. Firstly, a small amount of keyshare leakage is tolerable. For example, if the Notary leaks 3 bits of their keyshare, it gives the User no meaningful advantage in any attack, as she could have simply guessed the bits correctly with % probability and mounted the same attack.

Secondly, we observe that the Notary's keyshare is an ephemeral secret: it is only private for the duration of the User's TLS session. This implies two things:

  1. The User is free to learn the encryption key after she has received and committed to the TLS response. Thus, if the parties wait until the end of the TLS session to do maliciousness checks, then they can reap the benefits of the Notary having no private inputs.
  2. Since the encryption key is not a long-term secret, it is okay if a malicious User prematurely learns the entire key, so long as it is detected. Thus, the parties are free to engage in potentially leaky MPC early on, so long as checks are performed at some point.


  • is the User's plaintext request
  • is the AES key
  • and are the User's and Notary's AES keyshares, respectively. That is, .
  • denotes the encryption algorithm used by the TLS session
  • denotes a pseudorandom generator
  • denotes a binding commitment to the value

Ideal functionality

We define the ideal functionality we wish to instantiate. In words, the functionality uses the parties' keyshares to encrypt the User's TLS request, and send the ciphertext to both parties. The functionality then waits for the user to get and commit to the TLS response, and then releases the encryption key to the User.

Ideal functionality for ONESHOTENC:

  1. User → ℱ:
  2. Notary → ℱ:
  3. ℱ → User:
  4. ℱ → Notary:
  5. User → ℱ:
  6. ℱ → User:
  7. ℱ → Notary:


We now describe the protocol at a high level. It is based on Figure 1 of the Dual-Execution (DualEx) technique with a relaxation (see Step 3 below). We overcome DualEx's inherent leakage by introducing a consistency check which the User performs on the Notary, thus removing the ability to leak the User's input. It is still possible for a malicious User to leak the Notary's input (i.e. the AES key share), but it gives her no meaningful advantage as per the first observation above.

Part 1

To set up for dual-execution, the parties set up the OTs. Because we have a privacy-free step later, the Notary's OT needs to be opened up later, so we have the notary do a "committed OT" (see section 2 of JKO13), so that he can be forced to open the labels later on.

In the first step of the protocol, the User has to get her AES ciphertext from the Notary. The User does not trust the Notary (for privacy or integrity), and the User's data is far more sensitive to leakage than the Notary's. So the parties do an ordinary DualEx:

  1. The User and Notary both garble a copy of the encryption circuit, and do OTs for each other. For committed OT the Notary constructs the input wire labels and OT encryption keys as where is a randomly sampled PRG seed, and sends to the User after the OT is done.

  2. The User sends her garbled encryption circuit and garbled wires for and . She also sends the output decoding information.

  3. The Notary uses his OT values to evaluate the circuit on . He derives the encoded ciphertext and decodes it into ciphertext using output decoding information.1

    Since the encoding itself may leak the Notary's private input, we need to briefly describe how the encoding is constructed and how we prevent the leakage.

    In garbled circuits, the garbler assigns a pair of encodings (called "labels") to each output bit : the "zero label" when is 0 and the "one label" when is 1. Upon the evaluation, the evaluator will learn only one of those two labels - the so-called evaluator's "active label".

    To prevent the leakage, the Notary will receive from the User a hash commitment to each label. Then the Notary will hash his active label and check that the hash matches one of the two commitments for that output bit. Note that this commitment approach leaks Notary's input bits (the input is the keyshare) with probability , which is acceptable for our case as explained in the first observation above.

  4. The Notary sends to the User.2

    Step 3 is a relaxation of DualEx. In DualEx, the User would not learn the Notary's evaluation output at this point. As mentioned earlier, in TLSNotary protocol's setting, we are not worried that may leak the Notary's input, as long as this behaviour will be detected later. Also we are not worried about DualEx's inherent 1-bit leakage since it gives no meaningful advantage to the User as explained earlier.

    There is no wiggle room for the User to exploit this relaxation because she is locked into using the inputs she received via OT in Step 0 and she has to pass the DualEx equality check which will follow later in Step 14.

  5. As per DualEx, now the Notary knows what the User's encoded output should be, so the Notary computes and keeps it.

  6. The User decodes and derives the ciphertext .


Note that it is in keeping with the DualEx paper to allow a party to send the wrong output decoding information, or to provide different inputs to the two circuit evaluations. This does not affect the security of DualEx.


A question may arise at this point re Step 3: why doesn't the Notary simply send to the User. The reason is that the Notary could send a maliciously crafted : the Notary could flip a bit in (which translates into flipping a bit in the plaintext). The User would then forward the malicious to the server.

At this point, the Notary (even if malicious) has learned nothing about the key or the plaintext. He has only learned the ciphertext.

Also at this point, the User has learned the ciphertext, and, if malicious, has potentially learned the entire key . As mentioned in the second observation above, it is okay if the User was malicious and learned , but the Notary has to detect it and then abort the rest of the TLSNotary protocol. Before this step, the Notary waits for the User to complete their TLS session:

Part 2

  1. The User completes her TLS session and sends

Part 3

Now that the session is over and is no longer secret, the Notary can switch to privacy-free garbling for the second part of DualEx.

  1. The Notary sends his garbled encryption circuit to the User, as well as the garbled wires for . He also sends the output decoding information.

  2. The User evaluates the circuit on and , using the OT values from step 0, derives the encoded ciphertext and decodes it into ciphertext using output decoding information.

  3. As per DualEx, she computes and sends a commitment to the Notary.

    Note that at this stage the Notary could reveal and the User would make sure that . Then likewise the User would reveal and the Notary would make sure that . As per the DualEx's inherent 1-bit leakage, the very act of performing the equality check would leak 1 bit of the User's input to a malicious Notary. To avoid the leakage, the User must first check the consistency of the Notary's OT and garbled circuits:

  4. The Notary reveals all the wire labels and OT encryption keys by opening .

  5. The User checks that the opening is correct, and that is consistent with the OT ciphertexts sent earlier by the Notary. On success, she opens her commitment, sending and the commitment's randomness to the notary.

    With the consistency check passed, the parties resume the DualEx's equality check:

  6. The Notary send .

  7. The User asserts that . The User decommits by sending .

  8. The Notary checks the decommitment and asserts that .

Computing MAC in 2PC

  1. What is a MAC
  2. How a MAC is computed in AES-GCM
  3. Computing MAC using secure two-party computation (2PC)

1. What is a MAC

When sending an encrypted ciphertext to the Webserver, the User attaches a checksum to it. The Webserver uses this checksum to check whether the ciphertext has been tampered with while in transit. This checksum is known as the "authentication tag" and also as the "Message Authentication Code" (MAC).

In order to create a MAC for some ciphertext not only the ciphertext but also some secret key is used as an input. This makes it impossible to forge some ciphertext without knowing the secret key.

The first few paragraphs of this article explain what would happen if there was no MAC: it would be possible for a malicious actor to modify the plaintext by flipping certain bits of the ciphertext.

2. How a MAC is computed in AES-GCM

In TLS the plaintext is split up into chunks called "TLS records". Each TLS record is encrypted and a MAC is computed for the ciphertext. The MAC (in AES-GCM) is obtained by XORing together the GHASH output and the GCTR output. Let's see how each of those outputs is computed:

2.1 GCTR output

The GCTR output is computed by simply AES-ECB encrypting a counter block with the counter set to 1 (the iv, nonce and AES key are the same as for the rest of the TLS record).

2.2 GHASH output

The GHASH output is the output of the GHASH function described in the NIST publication in section 6.4 in this way: "In effect, the GHASH function calculates ". and are elements of the extension field .

  • "•" is a special type of multiplication called multiplication in a finite field described in section 6.3 of the NIST publication.
  • ⊕ is addition in a finite field and it is defined as XOR.

In other words, GHASH splits up the ciphertext into 16-byte blocks, each block is numbered etc. There's also which is called the GHASH key, which just is the AES-encrypted zero-block. We need to raise to as many powers as there are blocks, i.e. if we have 5 blocks then we need 5 powers: . Each block is multiplied by the corresponding power and all products are summed together.

Below is the pseudocode for multiplying two 128-bit field elements x and y in :

1. result = 0
2. R = 0xE1000000000000000000000000000000
3. bit_length = 128
4. for i=0 upto bit_length-1
5.    if y[i] == 1
6.       result ^= x
7. x = (x >> 1) ^ ((x & 1) * R)
8. return result

Standard math properties hold in finite field math, viz. commutative: and distributive: .

3. Computing MAC using secure two-party computation (2PC)

The goal of the protocol is to compute the MAC in such a way that neither party would learn the other party's share of i.e. the GHASH key share. At the start of the protocol each party has:

  1. ciphertext blocks .
  2. XOR share of : the User has and the Notary has .
  3. XOR share of the GCTR output: the User has and the Notary has .

Note that 2. and 3. were obtained at an earlier stage of the TLSNotary protocol.

3.1 Example with a single ciphertext block

To illustrate what we want to achieve, we consider the case of just having a single ciphertext block . The GHASH_output will be:

The User and the Notary will compute locally the left and the right terms respectively. Then each party will XOR their result to the GCTR output share and will get their XOR share of the MAC:

User :


Finally, the Notary sends to the User who obtains:

For longer ciphertexts, the problem is that higher powers of the hashkey cannot be computed locally, because we deal with additive sharings, i.e..

3.2 Computing ciphertexts with an arbitrary number of blocks

We now introduce our 2PC MAC protocol for computing ciphertexts with an arbitrary number of blocks. Our protocol can be divided into the following steps.

  1. First, both parties convert their additive shares and into multiplicative shares and .
  2. This allows each party to locally compute the needed higher powers of these multiplicative shares, i.e for blocks of ciphertext:
    • the user computes
    • the notary computes
  3. Then both parties convert each of these multiplicative shares back to additive shares
    • the user ends up with
    • the notary ends up with
  4. Each party can now locally compute their additive MAC share .

The conversion steps (1 and 3) require communication between the user and the notary. They will use A2M (Addition-to-Multiplication) and M2A (Multiplication-to-Addition) protocols, which make use of oblivious transfer, to convert the shares. The user will be the sender and the notary the receiver.

2PC MAC Overview

3.2.1 (A2M) Convert additive shares of H into multiplicative share

At first (step 1) we have to get a multiplicative share of , so that notary and user can locally compute the needed higher powers. For this we use an adapted version of the A2M protocol in chapter 4 of Efficient Secure Two-Party Exponentiation.

The user will decompose his share into individual oblivious transfers , where

  • is some random value used for all oblivious transfers
  • is a random mask used per oblivious transfer, with
  • depending on the receiver's choice.

The notary's choice in the i-th OT will depend on the bit value in the i-th position of his additive share . In the end the multiplicative share of the user will simply be the inverse of the random value, and the notary will sum all his OT outputs, so that all the will vanish and hence he gets his multiplicative share .

3.2.2 (M2A) Convert multiplicative shares into additive shares

In step 3 of our protocol, we use the oblivious transfer method described in chapter 4.1 of the Gilboa paper Two Party RSA Key Generation to convert all the multiplicative shares back into additive shares . We only show how the method works for the share , because it is the same for higher powers.

The user will be the OT sender and decompose his shares into individual oblivious transfers , where , depending on the receiver's choices. Each of these OTs is masked with a random value . He will then obliviously send them to the notary. Depending on the binary representation of his multiplicative share, the notary will choose one of the choices and do this for all 128 oblivious transfers.

After that the user will locally XOR all his and end up with his additive share , and the notary will do the same for all the results of the oblivious transfers and get .

3.3 Free Squaring

In the actual implementation of the protocol we only compute odd multiplicative shares, i.e. , so that we only need to share these odd shares in step 3. This is possible because we can compute even additive shares from odd additive shares. We observe that for even :

So we only need to convert odd multiplicative shares into odd additive shares, which gives us a 50% reduction in cost. The remaining even additive shares can then be computed locally.

3.3 Creating a robust protocol

Both the A2M and M2A protocols on their own only provide semi-honest security. They are secure against a malicious receiver, but the sender has degrees of freedom to cause leakage of the MAC keyshares. However, for our purposes this does not present a problem as long as leakage is detected.

To detect a malicious sender, we require the sender to commit to the PRG seed used to generate the random values in the share conversion protocols. After the TLS session is closed the MAC keyshares are no longer secret, which allows the sender to reveal this seed to the receiver. Subsequently, the receiver can perform a consistency check to make sure the sender followed the protocol honestly.

3.3.1 Malicious notary

The protocol is secure against a malicious notary, because he is the OT receiver, which means that there is actually no input from him during the protocol execution except for the final MAC output. He just receives the OT input from the user, so the only thing he can do is to provide a wrong MAC keyshare. This will cause the server to reject the MAC when the user sends the request. The protocol simply aborts.

3.3.2 Malicious user

A malicious user could actually manipulate what he sends in the OT and potentially endanger the security of the protocol by leaking the notary's MAC key. To address this we force the user to reveal his MAC key after the server response so that the notary can check for the correctness of the whole MAC 2PC protocol. Then if the notary detects that the user cheated, he would simply abort the protocol.

The only problem when doing this is, that we want the whole TLSNotary protocol to work under the assumption that the notary can intercept the traffic between the user and the server. This would allow the notary to trick the user into thinking that the TLS session is already terminated, if he can force the server to respond. The user would send his MAC key share too early and the notary could, now having the complete MAC key, forge the ciphertext and create a valid MAC for it. He would then send this forged request to the server and forward the response of the server to the user.

To prevent this scenario we need to make sure that the TLS connection to the server is terminated before the user sends his MAC key share to the notary. Following the TLS RFC, we leverage close_notify to ensure all messages sent to the server have been processed and the connection is closed. Unfortunately, many server TLS implementations do not support close_notify. In these cases we instead send an invalid message to the server which forces it to respond with a fatal alert message and close the connection.