 So today we'll be giving a talk about how to batch base oblivious transfers correctly. Before we get into things, I'd just like to thank my two co-authors, Mike Frazelec and Lance Roy. So what are we going to be talking about in this talk? Well, we're going to largely be talking about oblivious transfer, or we'll often use for shorthand OT. Some people may have heard of chosen message oblivious transfer, but for this talk we're going to be looking at uniform message oblivious transfer. In uniform message oblivious transfer, we have a protocol where two parties interact with each other. A sender who, through the course of the protocol, will receive two messages, and the receiver will input a choice bit and then receive the message corresponding to that choice bit. For instance, if the receiver inputs a choice bit of zero, they should receive message zero as the output. What security properties do we see from this protocol? Well, the receiver should learn no information about the message that they did not choose. So for instance, if the receiver inputs a zero, they receive message zero, but they learn no information about message one. The sender should learn no information about the receiver's choice bit. And finally, as we stated, we're interested in uniform oblivious transfer. So both the messages output from the system will be uniformly and independently distributed. Where do we see oblivious transfer being used in the current landscape? Finally we see it being used in multi-party computation, more specifically, possibly in garbled circuits, where certain constructions require an oblivious transfer for every AND gate, or private-set intersection. A lot of these situations require millions of oblivious transfers. And we know that we can't realize oblivious transfer from symmetric operations alone. We will eventually have to use these expensive asymmetric operations, for instance, key exchange, in order to realize these millions of OTs. Now, before we get into the meat of things, let's just talk a little bit about the notation we'll be seeing through these slides. We often will use for key agreements protocols one of these two notations, either the elliptic crypt if you home in notation, where we're working over a usually prime order group. The two parties have their corresponding private keys, a low case A and lower case B. And then their two messages that they send to each other will be their privates multiplied by the generator for that group. Then finally, using the properties of the underlying group, they can arrive at the same key in the end. Now, since this is really specific to a certain type of key agreement, we sometimes want to be a bit more abstract. And in that case, we'll use just sending key agreement message one and key agreement message two. Now, one thing to notice is that when we expand out into the generalized notation, the second key group message may rely on the first message sent in the protocol. Now this is not the case for Diffie-Hillman, but maybe the case for other key agreement protocols. Now, recall what I said earlier about a lot of the protocols we use OTs in, requiring millions of OTs. If we had to perform a key agreement protocol for every single one of these OTs, a lot of these protocols would end up being prohibitively expensive. What we want to do is we want to take some small number of what we call base OTs, for instance 128 or the size of our security parameter, and then we want to put those into a protocol and extend those into some polynomial size number of realized OTs, somewhere on the order of a million OTs that we need for these protocols, using cheap symmetric operations instead of the expensive asymmetric ones. Then of course, since we're going to eventually have to do these expensive operations for our base OTs, we can think about optimizing them as a cohesive unit in what we call the batch setting, or we're sending a batch of base OTs that we extend into these polynomial sized realized OTs. As it turns out, the natural way of optimizing these base oblivious transfers lacked a principal treatment, even in the academic literature, and that often led to incorrect implementations which had their own security wall. So what we will do in this talk is talk about the treatment of how we correctly optimize the oblivious transfers for the batch setting. We also will expand on the known oblivious transfers construction from our previous paper in CCS 2020, and we will optimize the resulting OTs constructions to the batch setting. And how we're going to do this is we're going to first introduce the original protocol from our CCS paper. We're going to talk about the tools we use to build the protocol. We're going to then talk about how the natural way of batching doesn't get the security guarantees that we need, and then we're going to talk about how to fix this problem. Let's start off with a simple oblivious transfer protocol. We start off just as we would normally sending a key agreement message between the two parties. Then the receiver is going to have their choice bit see, and they're going to encrypt their key agreement message, whereas in normal Diffie-Hillman we would just send the key agreement message over in the plane. We're now going to encrypt that key agreement message under our choice bit, and send that over to the other party. Then the receiver is going to treat this just as a normal Diffie-Hillman key agreement, and they're going to output their key as they would normally send her on the other hand, is going to have two possible key agreement messages from this protocol. They're going to have the key agreement message decrypting under zero, and the key agreement message decrypting under one. Now these are going to then be the outputs of our oblivious transfer. The receiver is going to have his choice bit, which is going to correspond to his message, and then the sender is going to have two possible key agreement messages, one of them corresponding to the one the receiver has, and then the second one, which is going to be a key agreement message that the receiver can't have a knowledge of the secret to. So in that situation, the sender will end up with two key agreement key outputs, whereas the receiver can only possibly have one. What's actually going on here? As we said earlier, the sender is going to send their key agreement message. They're going to sample their secret and send their key agreement message as they would normally. The receiver is going to sample their key agreement message as they would normally, and they're going to have their choice bit. They're then going to wrap their key agreement message inside, for instance, in this case, an ideal cipher, and then they're going to send it over to the other party. This is a very specific example, but when we said earlier is that we're just taking our second key agreement message and wrapping it inside of something. An ideal cipher is a very strong primitive that we can use, but what about something a bit weaker? What about something like a weak cipher? In this situation, we may want to change our notation a little bit. Instead of encrypting a message, we're going to program a message. Basically, we're saying that at this input, we have this other output. And then, of course, during the output time, we're going to evaluate that function that we send across. We're going to take our function programmed at C, and we're going to evaluate it at the two possible choice bits. What could some of the properties be that we need from this weaker ideal cipher? On the first hand, we have that we send a message, specifically the key agreement message, encrypted under C, and then we output the corresponding key under each of the two choice bits. Looking at this again, we're going to have our ideal cipher's encryption. Basically, we're creating a cipher text, and we are sending it over to the other party. In this case, we just want to have some weak property, which we call programming, where we say that at C, we have our key agreement output. And then finally, as we saw earlier, since we're thinking of this kind of as a function that we're sending across, or a representation of a function, we program at an input, and then we evaluate at another input. So in this case, we're going to evaluate our message at one of the possible keys, and then we're going to treat it as we would normally as a key agreement message. Well, what do we actually need to make this proof work? Well, if we recall correctly, we have to hide the receiver's choice bit. We have to hide the message that wasn't chosen from the receiver. Then for simulateability properties, we need to extract the adversary's choice bit and have a backdoor so that we can program on both choice bits. So for instance, we can know the key agreement messages for both evaluation at zero and evaluation at one. For the first of these, we need to hide the receiver's choice bit. What we need is that if we program on or we create, we construct this message we're sending across on a uniform key agreement message or a uniform bit string that when it comes to evaluation time, both of the outputs look like a uniform function. The reason this is important is because if the sender can distinguish between a key agreement message, for instance, and a non-key agreement message, then it will be trivial for them to tell which of the two bits receiver chose as its choice bit. We need to hide the non-chosen message. So for instance, if the receiver chooses other choice bit zero, we need to hide the message they didn't choose. We need to hide message one. In this situation, thinking of this still as key agreement, we need it to be the case that the sender's output, for instance, after sending it through the key phase of their key-dream scheme, we need that that message is uniform after they send it through their weak random function. In this case, the key output part of their key agreement. If this weren't the case, of course, then the receiver may be able to learn extra information about the second message. Finally, we need some simulation properties. We need to be able to look at the message that we received from the receiver and extract the choice bit, even though we've hidden the choice bit by our other property. Similarly, we need to have it so that we can affect the outputs of the evaluation of these functions, even though we specifically stated that those outputs should be outside of our control. Now, this is just simulator magic. We can use the properties of, for instance, a random oracle or an ideal cipher, for instance, to achieve these. Now, this tool that we've been working with is what we call a programmable once public function. Now, this seems like a mouthful to start, but let's break down why we call it this. So we call it programmable once because, as we saw earlier, a party can program the output of the function for exactly one input. In other words, they choose an input and they choose the corresponding output. But for any other input, they should not be able to control the output of the function. Finally, it's a public function because, as we saw in our protocol, we send the function in the clear, so to say, so that anybody who sees the function can evaluate it on their own. What are some of the restrictions? We spoke earlier about some restrictions on the input-output pairs for our oblivious transfer scheme. As we stated earlier, if the adversary can distinguish between a key agreement message and a non-key agreement message, for instance, looking over uniform bit strings, then they'll easily be able to determine whether or not the receiver chose one or the other choice bits. What this means is, is that the key messages that we wrap before sending it across should be uniform so we can hide that choice bit. The thing is here is that we need this to be the case looking at this from our generalized key agreement schemes where the second message may rely on the first message that's sent in the key agreement. This still needs to be the case even if there is some correlation between the first message sent in the protocol and the response message, which is certainly the case for Diffie Hillman where the two messages sent are independent of each other. We've been talking a lot about this tool, a programmable once public function, but what do they look like? Well, start, let's go over the seminal construction from our paper from CCS. Let's start with something we're familiar with. Let's start with just a normal two-round Feistel network. We have that this can realize an ideal cipher at eight rounds, but of course with security loss. Now, but remember, we may not need the strong properties of an ideal cipher. We may be looking at this from the direction of a weak cipher. As it turns out, we can take this two-round Feistel network which we know doesn't realize an ideal cipher, but since we have these weaker properties we need from the system, we actually can use this to design the tools we need to realize this ability as transfer protocol. What we've done here is that in the original protocol, we send in the first part of the key to the first and then the second part of the key to the second. But in this situation, we've replaced these with just random oracles, two different random oracles to be specific. And the keys have just been replaced with the choice bits for the receiver. And then finally, our output, what we actually send from the receiver to the sender, these wrapping of our key agreement message is just the two parts of the output of the Feistel cipher. What we've shown in our paper is that we can optimize this construction. Where in the original paper, we were looking at the situation for large inputs, specifically our keys that we use can be exponentially large. But now that we're working with just two choices for our keys, we've optimized the situation by replacing the second random oracle with an injection to the finite field, which ends up giving us a much more efficient implementation. Here's a new one. In this case, we're looking at the usual double exor, evin monsoor cipher. And of course in this situation, we're going to be instantiating with an ideal permutation. And just as we saw earlier, these stronger properties that we need aren't always going to be necessary when just building this weaker cipher, this programmable once public function. In this situation, we can drop the first exor. As we saw over here, before we have two parts of the key, which we send in at different parts of the different points of the cipher. In this situation, we're replacing the key with just the choice bit that the receiver uses. And then our output from the cipher is what we send as our message, our wrapping of our key agreement message. In our paper, we actually showed that this construction realized the properties we need to give us our oblivious transfer protocol. Finally, we have a construction that was introduced by Mosny and Rindahl in their endemic OT paper. In this situation, we have what looks like a one round Fistel cipher. However, it extends a little bit differently. Basically, this is looking for one out of two OT. Whereas, if we want to extend this to one out of N OT, it's going to expand differently than what we saw from the Fistel construction. As we see here, there are two messages, message one and message zero. But when we extend this to one out of N OT, we extend this to N messages, which means that it doesn't efficiently extend to exponentially sized N as we may see for the two previous constructions. Then in our paper, we showed this construction, presented by Mosny and Rindahl, was actually a special case of the protocol from our previous paper. Now, stepping back a little bit, we talked about how often we need millions of OTs in order to realize these protocols that we want to use oblivious transfers in. And as such, we use this what we call OT extension to take a small number of OTs in and output a large number of OTs. Then, of course, we're going to want to look at how do we optimize those base oblivious transfers in what we call the batch setting. So looking just at our running protocol, we notice that we're going to be sending a lot of messages back and forth. We're going to have key agreement message one, key agreement message two, key agreement message three, so on and so forth up to Kappa or security parameter key agreement messages. This is pretty expensive. We're going to have to do Kappa full key agreements, but what's this? We're sending a new key agreement message for each of the individual transfers from the sender. Now, we may recall that a lot of protocols, for instance, instantiations of the Diffie-Hulman protocol, will reuse a public key for multiple connections. And this, of course, leads to what we are going to call the naive way of batching the abilities transfer protocols, where what we do is, is we just send one key agreement message. Which we then use across all of the oblivious transfers in the batch. Although the receiver may vary their key agreement message, specifically sampling a new secret each time, the sender only sends one key agreement message at the very beginning. This not only drops the number of group elements sent from two Kappa to one Kappa plus one, but it also makes it so that they send us to perform fewer group operations to start. As we teased at earlier, there is actually a problem with this style of naive or natural batching. So let's walk through that. As we saw earlier, the sender is going to give their key agreement message over to the receiver. The receiver is going to generate two key agreement messages as outputs. Then, of course, it's going to send the same message for each oblivious transfer instance in a batch. So remember, as we saw earlier, the messages sent from the receiver had a different key each time in the honest evaluation. But in this evaluation, we're going to be sending the same secret. So for instance, the same key agreement message, same wrapping of that key agreement message for each instance of oblivious transfer inside of a batch. But wait a second, this caused something weird to happen. When the sender evaluates the message that are received from the receiver, then the sender is going to get the same two outputs for each of the oblivious transfers. Now this is very different from our original situation where in the original without any optimization, each of the oblivious transfer protocols that we had in the batch were independent. There was no way to cause any hard correlations between each of the protocols. Now what we've done is allowed the receiver to cause every one of those OTA outputs to be the same across each of the protocol instances, which could be disastrous. We could cause some more complex correlations if we wanted to, but as it turns out, this simple attack on the protocol affects certain oblivious transfer extension protocols in a devastating way. Let's actually see this in action. What we're going to be looking at as a case study is the OOS OT extension protocol. In this situation, as we saw earlier, Bob in this and the OT protocols acting as the sender, but in the larger OT extension protocol acting as the receiver is going to engage with Alice in series of OT protocols. Then what Bob's going to do is he's going to take the output of each of these protocol evaluations. For instance, of course, in uniform OT, Bob's going to receive two uniform messages, Alice is going to receive one of them. What Bob's going to do is he's going to take his two received messages from each of the protocols. He's going to shove them into two PRGs, XOR the output, and then put it in a column of an array. So using our colors, we have that the first OT protocol defines the first column of the matrix. The second OT protocol defines the second column of the matrix, and so on until we reach the last evaluation of the protocol, which then defines the last column of the matrix. Using our attack that we have previously, where Bob can cause both the messages to be the same across all of the protocols. So internally to a single OT protocol, the messages are uniform and independent. Now across all the protocol evaluations, the messages are going to be the same. It can be the same message zero across all the protocols and the same message one across all the protocols. Looking just at a single protocol, we're still going to have that uniform and independence property. What this causes is it causes all of the columns of our matrix to be the same. What we then do is we're going to take another matrix of our choice bits. In this case, it's going to be an error correcting code of our choice bits. So for instance, an error correcting code evaluated at zero, an error correcting code evaluated at one, which then populate the rows of a second matrix. And then we're going to send their XOR over to Alice. But wait, since every single column in K is the same, then let's say column one has a zero in the first index, then column two will have a zero in the first index since they're identical. Column three will have a zero in the first index, so on and so forth. Which means that the first index across all columns will be zero. But what that means is that every single row in this matrix is going to be identical. So when we XOR it with our choice bit matrix, either if the rows all zeros, it'll leave our choice bit code alone. And if it's all ones, it'll do the bitwise complement of the choice bit code. But wait a second. If the two messages are not bitwise complements, then it's immediately obvious which of the two code words we're looking at in each of the rows can use this information to learn which of the two choice bits corresponds to each row. This specifically relies on the two code words, the code word for zero and the code word for one, not being complements. Because if they are complements, then we learn either the code word or it's complement for each one. But since we can't discern between the two, we aren't able to learn the choice bits. This is a specific attack on the OOS OT extension. However, the KOS OT extension does use repetition codes as their error correcting code, which are complements of each other. But maybe there could be more complex correlations that can be induced by a malicious receiver. So how do we solve this problem? What we did was is we bash it in a naive way, but we allowed for strong correlations between each of the OT instances. Specifically in this case, we allowed each of the OT instances to be influenced in a way that they output in the same value across each one of the OT instances. This of course wasn't possible in the original case because in the original protocol, we had each of the OT instances independent of each other. What we wanna do is we want to stop the adversary from creating these correlations by separating each of the oblivious transfer instances. And how did we do this? We just took our key agreement protocol and supplemented it with tagged key agreement. Specifically where we would originally just have key agreement of private public. We now have it so that it's key agreement of private public and tag. Just to look back at our notation here, we have that the parties sample their privates. They then send their public messages and then they get their keys output, taking their private and the corresponding message from the other party with this new tag. In the context of our OT, we're going to let this tag be the OT index in a batch. So for instance, if we're running 128 OTs in a batch, then the first OT will use the one tag, second OT will use the two tag, then so on and so forth till the last protocol, for instance the CAPA protocol, will use CAPA as its tag. What this allows us to do is it allows the simulator to program each of the outputs separately to maintain the separation. Now that we know how to properly batch, what can we do to further optimize the batching process? What we saw earlier is that the original protocol from our previous paper required key agreement with uniform messages for both parties. Specifically, this was in the context of password authenticated key exchange where both parties wrapped their key agreement messages before sending it to each other. But what we were able to do in the previous protocol is take the stock elliptic curved Diffie-Hillman protocol, which does not satisfy this property. And we were able to transform it into one that does. Specifically looking at an ideal cipher compatible process where the cipher works over bit strings, we were able to translate the elliptic curved Diffie-Hillman messages into uniform bit strings using process known as alligator. Similarly, to make it random oracle compatible, we had to have a random oracle that hashed or output into the group that we were performing Diffie-Hillman over, specifically in this case elliptic curves. And we were able to use, for instance, SSWU's hash to curve method. Now we're looking at OT and we no longer need that both parties wrap their key agreement messages before sending it to each other. Now we only need that the receiver wraps their key agreement message before sending it over. The sender's message is sent in the clear unwrapped, which means we now only need uniform bit strings for a single party. This allows us to use a trick attributed to molar. As we hinted at earlier, elliptic curve elements really don't look like uniform bit strings. Even all of their x-coordinates don't lie on the curve. So if you look at all the possible x-coordinates over a field, it's not the case that all of those lie on a given curve. In this situation, thinking of this from the perspective of our OT protocol, this would allow an adversary to discern between a key agreement message and a non-key agreement message. And then, of course, learn the corresponding choice bit. So where do all these other x-coordinates end up? Where do they lie? Well, it turns out they all lie on the curve's twist. This means that if you were to take a bit string representation of one of the finite field elements, this choice of a bit string, interpreted, of course, will either lie on the curve itself or it will lie on the curve's twist. So if both the curve and the curve's twist are secure and approximately the same size, then we might be able to use uniform messages by sending the x-coord. So what does this key agreement look like using this intuition of x-coordinates for a curve and its twist? Well, Alice starts off by taking the base elliptic curve C0 and its twist, its quadratic twist, which we're gonna call C1, and it's going to send a message for both of those. So it's gonna sample a private, it's going to generate an element on the curve, it's gonna sample a private, it's gonna generate an element on the twist, just like if it were doing two key agreements. I'm just gonna send both of those messages to Bob. Bob, on the other hand, is going to flip a coin in his head. And if it comes up heads, then it's going to send a message on the base curve. And if it comes up tails, it's going to send a message on the twist. Finally, since Alice can determine whether a point is on the curve or its twist, Alice knows which private to use when generating its shared key. And of course, Bob, who flipped the coin himself, will know whether or not the element's on the curve or the twist, and can generate the same key that way. So Alice and Bob either end up with a key on the base curve together, or they end up with a key on the twist together. Because of this, we need strong security for both the curve and for the twist. At the end, since we're still in the mindset of tagged key agreement, we're going to take the output and send it through a random oracle using the tag for the key exchange. It's going to be the index of our OT. Before we go on further, you may notice that we're actually increasing the number of group elements sent between the two parties. If we recall, the first message sent by Alice is exactly the message that is reused across all of the abilities transfer instances. So instead of doubling the number of group elements sent by Alice, we're actually overall decreasing the number of elements sent by the security parameter, up minus two, looking at our protocol since B is just a random element chosen from the base field, of course, assuming that the size of the curve and its twist are approximately the same, then B is going to be uniformly distributed in the base field. Now, all of these optimizations together, so first off, we're going to be looking at reusing the sender's message, specifically in the batch setting, and then looking at taking these protocols that require uniform messages and supplementing them by using molar's key exchange. What type of improvements are we going to see? We measured the difference between different versions of our protocol using molar and not using molar, as well as looking at other protocols that exist out in the wild. We looked at both the local area network setting, where we have low latency and high bandwidth, and we were looking over 128 of these base OTs, which is where we may see this batching process. We also did the same evaluations for the wireless area network setting, where we have high latency and low bandwidth. And what we found is, is that we had a 18% and 11% increase in performance when we decided to use optimization in batching, or we re-send the original message. Now, why do we see an increase like this? Well, of course, we have 126 fewer exponentiations from the sender, and we have 126 fewer group elements sent from the sender. We didn't use this optimization when we were testing our results. However, one may notice, since the receiver is going to be performing exponentiations when driving the keys, using the same base key message from the sender, then they can actually reuse some of their computation to reduce the amount of weight behind computing those keys. Then, when moving from non-molar's key agreement, for instance, using, as we showed earlier, hashed to curves or alligator, over to using molar, we saw a increase of 31% and 12% respectively. This is on the same order as what we saw as an increase from reusing the first message, which is the original optimization for the batch setting. Now, we see this because we no longer have to do these expensive mapping operations. Hashed to curve is somewhere around the order of one quarter of a exponentiation or alligator. And finally, since we're working over curves that will likely support x coordinate operations, for instance, curve 25519, we can take advantage of these Montgomery ladders which allows to perform faster computation. What are some things that were left over from our studies? As we pointed out earlier, we have a specific attack on a specific protocol. The main point was, is that a lot of these protocols didn't think about correlations between messages in the way that we could have induced. Could there be attacks on other OT extension protocols using these sorts of methods? We also looked at instantiations of this protocol. In all these situations, we looked at elliptic curve Diffie-Hillman as the base key exchange for a protocol. But are there any post-quantum key agreements that meet our properties specifically looking at strong randomness? I mean, are there other key agreements that meet these properties? If so, then we have easy candidates for post-quantum oblivious transfer. And finally, we've seen a lot of places that programmable once public functions can be used. In this talk, we looked at its use in oblivious transfer, but in our previous paper, we looked at its use in PAKE protocols, password authenticity exchange. And we also looked at its use in oblivious pseudo-random functions, OPRF protocols. But where else can POPs be used at? Maybe there are situations where we normally use ideal ciphers with very strong properties that we might be able to draw it back a little bit and use these weaker constructions for more efficient and often actually instantiable constructions.