 Hi everyone, good morning again. So today I'll be talking about incremental program authorization, and this is joint work with Omkantpani. So since this is the first talk in the authorization session, maybe I'll start by recalling a little bit about the notion and the definitions. So the goal of software authorization is to make computer programs unintelligible, but without affecting their functionality. So let's say you have a program P written in your favorite programming language. You would like to obfuscate the program so that this obfuscated version works just like the original one. So you could execute on this obfuscated version on your computer just as you could have executed the original program P. But I want this obfuscated version to hide the secrets that were embedded inside the original program P. So defining what it means to hide the secrets turns out to be rather tricky. And sort of one of the first efforts to define this formally was done by Barakatol, who defined this very natural notion of obfuscation, which they call virtual black box obfuscation. So this notion roughly says that an obfuscated version of the program leaks only whatever could be learned from the input-output behavior of the program P. In particular, if I give the obfuscated program to an adversary, then whatever you could learn from this obfuscated version, you could learn the same things from an oracle that implements the same functionality. So this is a very natural notion that Barakatol defined. But unfortunately, this turns out to be a bit too strong. And there are impossibility results showing that this strong notion cannot be realized in general. So you cannot obfuscate arbitrary programs satisfying the security notion. There are positive results in the case of restricted programs or functionality, specifically that we know how to obfuscate point functions with VBB security. There are some recent results which achieve such strong security properties as well. One point I want to mention is that if you were to restrict to certain idealized models, in particular where such as the generic multi-linear map model, then we can indeed realize VBB security for all circuits. An alternative weaker notion of security, which is very commonly used, is the indistinguishability obfuscation notion. What this notion says is that if you have two programs, P0 and P1, which are functionally equivalent, by which I mean that on every input, the two programs output the same exact output, then if I was to obfuscate one of the two programs, the distributions of the obfuscations are computationally indistinguishable. This notion has recently gained a lot of popularity. And we have general proper construction of obfuscations satisfying the security notion, at least plausible candidates. It might seem like if I'm trying to obfuscate two circuits that already implement the same functionality, what am I really trying to hide? It might seem like a weak notion. But there's been a long line of work that suggests that this notion is indeed very powerful and can hide cryptographic secrets inside programs. And a number of applications have been demonstrated. The strongest formal justification comes from this work of Goldwasser and Rotlem, which says that this notion of indistinguishability obfuscation is, in fact, the best possible obfuscation. In other words, whatever this notion hides about the program is the best that you could hope to hide. So with this background, let me move on to the motivation of our work, which is in the case of software updates. So if you ever use the computer, which I assume all of you have, then you've all used software which got updated. And these updates are released for many reasons. So for example, there might be a bug in your software that's fixed, or it could be a security vulnerability that exists and needs to be patched. Or you might have bought a software which comes with these locked features. And you're trying to, you paid to some service provider to unlock that feature, or you got the key from your friend, to unlock that feature. And you're trying to use that feature, and that now needs to be unlocked. So for any of these features to work, there would need to be a patch or an update that will need to be applied to the software that you have. If you were doing the same thing in the obfuscation setting, so let's say you had the program that was obfuscated, and I wanted to apply an update, what it would translate into to apply any update, the person who gave you the software will actually, if you used known techniques, you will have to generate a fresh copy of the updated program and give it to you. So typically on your computer, when you apply the update, it's applied locally, but if you were to use this in the case of obfuscated software, the person who provided you with the software would have to re-office the fresh copy and give it to you. And this is a problem, and this is what we want to change in this work. In particular, as I said, the updates are typically small, much smaller than the size of the program that you're trying to update. And we want the update time to be proportional to the time it takes to update the un-offuscated program in both the communication and the computational code. The guy who is updating, his work should be less. The communication that happened should be small. And the amount of time you spend updating software at your local end should be small. The obfuscated software at your end. Especially we want this to be independent of the program size, more the low polylog factors. This is something this is not completely new. This notion of incremental cryptography has been well studied. There's a lot of work on the topic. For example, in the setting of hashing, digital signatures, or deterministic encryption. And this is sort of inspired by this line of work. So the key point I want to drive across in this talk is the definitions that we've provided. I'll talk about some of the constructions that we have towards the end. But I really want to drive across the definitions that we have, so I'll go over them first. So before I can tell you the definitions, I need to have some modeling of how we define an update. We define an update, think of any program it can be taught of as a string. I'm going to define an update by a set S, which is a subset of the bit locations. If the program is of size n, it's a subset of 1 to n. And for each bit location in this set S, say I, we're associated with the function fi. Where the function fi could be the flip function, where you reverse the bit. It's a set function. Could set it to 1, reset set it to 0, or do nothing. In this case, you might not have included it, but you can include it there as well. So this is how I'm going to model an update. And note that this way of modeling an update makes sense for the un-office-cated program, as well as the office-cated version. These are the bit locations I want to change, and this is how I want to change. That's all this modeling is specifying. Now let's say I, as a server, have a program p. And I want to give you an office-cated version of this program, o of p, which I denote by p prime. When I provide you this office-cated version, I'm going to keep an update key locally at my end. We'll require this update key small. I just want to keep it with me. Whenever I want to later update this office-cated program that you have, I'll get as input a set S, which describes the increment that's being done on the un-office-cated program p. And I will use an oracle access to the office-cation of p prime. I didn't say that it's an oracle access because I don't want to touch every single bit of this office-cated program p prime. I'll use the update key and output a subset S prime of the locations of p prime. Along with the associated functions, I'm not going to write the functions every single time. Just every time I just say an update set S, it implicitly also means there are associated functions. So I will generate the subset S prime locally, and I send you the set S prime. And now you can, on your end, update the office-cated program. So this is how we're going to model the updates that are being done on office-cated programs. So what is the correctness and efficiency properties that we want here? The correctness property that we want is that the office-cation p1 prime that's obtained by you applying the update on your office-cated program implements the same function as p1, which is the updated program on my end. So in particular, if you have p and p prime is the office-cated version of p, then after applying the update S on p, if you get p1, and if you compute the update, as I described on the last slide, you got the set S prime, you could apply the update S prime to p prime to get p1 prime, then this p1 prime implements the desired function p1. And we want this to work for arbitrary polynomially many updates. I apply an update. I found that software doesn't need one update. It needs a lot more updates. So I apply an update, and I send the update to you. Now you're done. I have a next update. I want to keep doing this in arbitrary polynomially many times. And I want that for every single update that I do, the computational cost on my end and your end and the communication cost is proportional only to Pauline S and the security parameter ignoring polylog factors. And it's independent of the number of updates I provide. So if I'm providing the 10th update, it will, again, depend only on the number of changes that I'm making in that step. So if I'm making the first updated changes n bits, then I will send an update that's proportional to some polynomial in n, making the second update which makes far fewer changes, then I only need to communicate correspondingly fewer number of bits. So what about security? So now with that modeling in mind and the sort of definition and the efficiency properties, I want to define what security are we seeking? So there are several notions of security, in particular two that I'm going to talk about now. Let me start with the basic one. So the basic IIO security, which stands for Incremental Indistinguishable Office Cation, security is that if you have two equivalent programs, p and q, and you have a sequence of updates, s1 to sd. So these are unofficecated programs. And I could apply the update s1 to p and get p1, and then s2 get p2, and so on. Or I could apply these updates to q to get q1, and so on. I'm in this case assuming that the same update is being applied in the two cases. So that's a starting point. We'll get rid of that later. So I'm going to apply the same update in the two cases. And I require that after every update, the two programs remain functional equivalent. So the functional equivalence property holds forever when these updates are applied. Then I require that if I was to take offcations of these programs, then they together remain computationally indistinguishable. Note here that this p1 prime is not a fresh offcation of p1. It's also obtained by updating p prime. So this pp1 prime will differ from p prime in a few number, only a few bit locations. So on p2 prime will differ from p1 prime in a few bit locations, and so on, which will all be proportion or polynomial to the changes that are being made going from p to p1, and so on. Specifically the size of the sets s1 to sd. So this is the basic notion of security. And as I said, here we were restricting ourselves to applying the same update to the both programs. This might seem artificial, because if you have a program with two implementations, you're probably going to apply different patches. You're not going to change the same bit location in the same way. And not just in terms of having a restricted functionality, it also has security consequences, because if you're applying a patch, this definition will leak the locations that are being updated, or also in what way they are being updated. And that might, if you're applying a security patch, that might already leak the vulnerability that's there in the software that you're trying to protect, which could be bad as well, against other pieces of code out there which have not been patched so far. So to account for that, we define a stronger notion of security. I won't define it formally, but sort of as a very natural extension of what I defined on the previous slide, is that we would like to define a notion where you can apply a different set of updates. You still need functional equivalence. So if I apply an update to p1 or n to q1, those updates themselves could be different, but the resulting programs need to be functionally equivalent. Furthermore, if the updates that I apply are roughly the same size, then we want to argue that the computational indistinguishability, as was on this slide, still holds. So that's the stronger, what we call increment private IIO, or increment private IIO security notion. So the reason why indistinguishability obfuscation has been that useful is because this, as I mentioned before, is sort of the best possible notion of obfuscation you could hope for. And we wanted to understand what is the best achievable security in the case of incremental indistinguishability obfuscation. So are we really achieving that, or there is a gap? Towards that goal, we define in the paper, again, I won't do this formally in the talk, but we define this incremental best possible obfuscation. It's sort of analogous to indistinguishability best possible obfuscation definition. And we're able to prove that the increment is sort of a result analogous to the relationship between ION best possible obfuscation, that the increment private IIO that I just defined on the previous slide is actually equivalent with the increment best possible obfuscation. So it sort of provides some evidence that maybe this is the right definition to work with. And so we use this definition and we sort of think that it's a good one. So now that we have our definitions and the model in mind, let me tell you our results. The first result is sort of on the negative side. Note that I didn't talk about a VBB security in the context of incrementality. And the result for there is, again, negative. And in fact, even for sort of as simple as point functions. Here the problem is that if you even have a point function obfuscation, and if you're trying to obfuscate a point function and then later trying to update, let's say I was trying to obfuscate an n-bit point function, and I want to update n bits of it or 100 bits of it of all the entire point function. Then in this case, achieving VBB security is hard because the size of the update already leaks the number of locations that I'm updating the point function on. So there's this sort of inherent tension and even the sort of weaker notion, even for this special functionality of point function, we're not able to achieve any kind of meaningful incrementality. And the issues are sort of similar to the prior works on incremental deterministic public encryption. More specifically, we're able to prove that VBB or VGB obfuscation of point functions must have an incrementality which is almost as close as to the size of the function. So this was sort of a deviation. Let me come back to the positive results about the two notions of incremental obfuscation that I defined. The first result that we have is for the basic notion of IIO. Just give me IIO and a bunch of other things like one-way functions. We can construct basic IIO for all programs, and you can have them as circuit, tuning machines, or RAM programs. We can also upgrade the security. Once you have the basic IIO, you can upgrade security to incremental private IIO, additionally using oblivious RAM techniques of Goldreich and Astrosky. Again, this result also works for circuit, tuning machines, or RAM programs. And so this is the positive results that we have. So finally, I don't want to go into details of it because it gets messy, but just to give you some idea of what kind of techniques that we use, especially because I think that they might be useful in other contexts. In particular, they could help simplify something else that you might be trying to prove. So the techniques might be useful. And before getting into the details, I want to note that obfuscation inherently is a very incrementally updateable primitive. So if I want to make it updateable, what I'm going to do is I'm going to separate the obfuscation part of it with a sort of a universal circuit obfuscation thing, and the program that I want to obfuscate separately. So I can update the program incrementally, and sort of the two at execution time can be fit together to work. So let's see how that works. What I'm going to do this is I'm going to do this via a general-purpose obfuscation and a standard public encryption. And I'm going to use an incremental signature scheme, which is going to be an incremental hash, think of the Markle hash, with special properties, and a Nizik proof system. With some properties, it's special, I won't go into sort of detail, but it's going to serve as sort of a signature here. So the construction idea is it uses the two key trick. I'm going to think of the program as a sequence of N bits, p1 to pn. I'm going to encrypt each bit twice. So using two separate public keys, pk and pk prime. So e is going to be the collection of the encryption of the bit of pi under pk, and e prime is going to be the encryption of the bits of pi again under public key pk prime. Then I'm going to just hash the two together, and I'm going to sign the root of the hash. So this might seem similar to other construction that you might have previously seen, but the key aspect here is that this Nizik needs to be independent of the sizes of these ciphertexts. It needs to be small. In particular, it will depend only on the hash of the Markle tree rather than the entire tree. So that's sort of the key difference from similar things that you might have seen before. And the obfuscation itself is just going to look at everything that I generated so far, the ciphertext, the hash, the tree, the signature on the root of the hash, and an obfuscation of this program g, which has the public parameters for the Nizik and the secret key for the first public key encryption scheme hardwired. And what this program does, it takes everything as input checks if everything was done correctly. So it checks whether the x is the input you're trying to evaluate it on. It checks whether the Markle hashes generates a Markle hash here. Checks if s is the valid signature on it with parameters pp. And then if it is a decrypt e, using secret key sk that's hardwired, gets p, runs p of x, and there we go. Note here, the key difference, as I pointed earlier, is that the obfuscated program has sort of nothing to do with the actual program that we're trying to obfuscate, which is a part of the ciphertext. And these ciphertexts can be incrementally updated. And that's where the update algorithm comes into play. I have the ciphertext, the hash, and the tree. To update the ciphertext, I only need to update the right locations, then change the root-to-leaf paths for those locations, and sign the root again. So that's all the update looks like. Since I'm running short of time, I'm not going to go into detail the proof idea, which you can look at the paper. One thing I do want to mention is that the hash function, you can't use a generic hash function. We have to use an IO-friendly hash function, specifically the somewhere statistically binding hash. So just some proof ideas, which you can look at the paper for that. Finally, I want to say that there is possibility of future work here. One aspect is that we only get a selectively secure notion of security. So in particular, the update sequence needs to be known before for the indistinguishability hole. It would be interesting to improve the stronger adoptive security notion. We consider specific kinds of updates. You could think of more general updates, which instead of looking at subtits, look at more general updates, which might increase the size of the program and things like that. Finally, I want to also mention a related work on patchable obfuscation by Ananth et al, which also looks at this issue of updating software or updating obfuscated software. But the two directions are fundamentally different, because they consider a larger class of updates. But the running time in their case for the update still grows with the size of the program. So they don't reduce the computational cost on the side of the recipient who's trying to update the obfuscated program. So you can refer to our other paper for details and comparisons and so on. Thanks.