Thank you very much. So hi, I'm Kobi. I work in Bank Capital Crypto. And today I want to talk about what I titled as account logic in Add Proto using trusted execution environments. So it's a bunch of things, so let's break them down. A short disclaimer before I start. Um Ben Capital Crypto is an investor in Turnkey and Bluesky, both of which I'll mention in the talk. So yeah, let's go to the actual stuff. So first of all, before we kind of get into what this does, I want to give an overview of how accounts look like in AdProto.
And specifically I am a cryptographer or I guess applied cryptographer. And I want to talk about those aspects of accounts. So accounts in AdProto, they have users and users like kind of called decentralized identifiers. And each decentralized identifier basically has cryptographic keys attached to it. And these cryptographic keys control what is authorized by each user to be posted or done in their name. There are different kinds of deeds, and we will talk about a couple of them later and what guarantees each of them gives you. But what you have to know is just this fact. Each user has this decentralized identifier attached to them, and each of them has what's called a repos signing key.
This repo signing key basically authenticates every operation that your deeds make. So that means posting, that means doing likes, that means doing everything else that other apps do on your on your account, so it could be anything. What is the guarantee that you get? This is a signing key, this is a digital signature. So the guarantee that you get is this DID agreed for this record to be published or for this operation to be performed. But that's kind of what you get, which is already very powerful.
So a DID that is published on that is used on the network has these keys, so whenever you want to verify a post is valid, you can go to the post, you can see which did posted it, you can then take what's called the DID document, which then lists what cryptographic keys it has, you can get those keys, you can verify the signature on something, let's call it verify the signature on the record, and pretty much done. So this is a very nice property of AdProto in general. But what if you wanted a bit more from this guarantee?
So not only this DID authorized is supposed to be published, what if you want more? So what we want to have some logic attached to each operation that is performed in your name. An example, like a few examples would be let's say that each post that is published in your account, you want it to be verified by some LLM that runs some analysis and check that it's like a non-toxic post that runs an LLM that runs on your computer. What if we want to get a guarantee that the images that you're posting or that someone else is posting are coming from a trusted source?
So for example, you have cameras today that have digital signatures on them. So you can verify that these are images that have not been tampered with, for example. What about a kind of multi-signature accounts or an organizational account? Each post has to be authorized by two out of three people. So that you know. If you want some more trust in those posts, you can add that kind of logic. Or maybe you want some verified bot account. So that for example could be a bot account that runs with a given system prompt because we don't want just any random both bots posting everything.
Maybe we want to limit them to some things that are more positive. So generally, what if we attach logic to record authorization? If we're talking about signatures, then the limits is the the limits are that what I've mentioned, which is you just can say that the D agreed for something to be published, but with logic, you can say the DID ran this program before publishing. And this is a stronger guarantee that you can get. You can do that with signatures if you trust the signer. So you know, if you trust the people who runs the the people who run the DID to run this program for you or run this program by themselves, then we can get this guarantee.
But in a big network with lots of people, sometimes in an adversarial scenarios, you want some third-party guarantee that this program ran. And this acts as a filter to the operation you perform. So now let's talk about what trusted execution execution environments are. It's a bit of a mouthful, at least for me. Trusted execution environments or TEs are special kind of hardware that are built in a way that allows you to get a guarantee of what's running inside it. Specifically these machines or these machines with special security chips allow you to measure or get some measurements of what's running inside it.
So you can get the guarantee of what code is running inside them. You can do that really all the way down. You can do that to the base OS that's running inside the TE. You can say what binary is running there, and even more it you can even get a more powerful guarantee, which is even what source code is running there. In the way that let's say that you have some source code published on GitHub, Tangle, whatever. You can build in a special way that is called a reproducible build that gets you the same binary each time.
You can then check that this binary is what's running in the TE. One downside of TE is that it adds some trust assumption on the TE provider or the TE manufacturer more correctly. Concretely, you need to trust that the TE manufacturer built the trusted platform in a way that is robust, that does give you this guarantee that these measurements are correct. That's unavoidable, but that's the trust assumption that you would have to make. Okay. So what we want to talk about is how these two areas connect. How atproto that has keys connect to TEs. So there is this concept called key encumbrance.
And key encumbrance means a public private keeper for let's say digital signatures, where the private key is never known to the public. It is only generated inside this TE, and the T does not provide a way for you to extract it outside. What we can do now, we can think about, okay, we have a T that runs a specific program, and we have a key that's only locked that's locked inside it and will never be put outside. What if we add specific conditions under which signatures can be done? So basically what we can do is we can tie a key to a specific program.
And the really nice property that you get with this kind of setup is that you can convert logic to digital signatures. And what I mean here is the following.
You then have a key that is generated inside this TE. Then you have the program that you know what are the conditions it would sign under that uses that specific key. And you get the you get this kind of chain of verifiability where you only need to verify this attestation or this proof that this key came from a valid TEE once, and once you do that, you can just verify signatures. You don't have to do anything else anymore. So this is the kind of um minimal overhead that you can have while still getting a very powerful guarantee.
So this is this verifiability all the way down. You usually have from this T manufacturer a root certificate that certifies this is the correct hardware, this is valid hardware that is secure. You then have proof of what program is running, so you know this is the expected logic that runs there. And then you know that whenever the TE produces signatures, the logic agrees with whatever you wanted to run there. Now maybe you can think about okay, but that means I now have to start verifying these weird TE proofs all the time. No, because you can maybe assume that some people verify them.
As long as enough people in the world go ahead and verify TE proofs about these keys, other people relays other actors in the network can just verify signatures. Okay. Now let's talk about a specific concrete application. Um where here we want to talk about this example of two out of three people need to authorize each record that is posted on your account. One way to do it would be to say, okay, when we launch the TE, one of the arguments of the program would be a set of three keys, and these three keys have to have a quorum of two of them signing each time.
That's one way. Another way would be to use the natural elements that we already have in add proto and specifically DIDs. So like Matt uh showed in his talk, there are multiple kinds of DIDs. There is DID web, there is DPLC. DID web basically trusts at some trust of the neon DNS provider, and you just go to some specific URL under your domain name, and you get the DID document and it has a field which describes the keys. Okay, so that's what you can get from DidWeb. And DID PLC has a bit of more comp more of a complex structure, and concretely DPLC is what's used by the main Bluesky network.
And it works in a way that when an account is created, it's created with some genesis state. And then when whenever you want to make updates to this state, you have to sign them cryptographically as well. And you submit them to PLC, and then you create some sort of chain. Each update in PLC references the previous state of your DID buttons. Okay. And we are done. Is that me?
Okay.
Okay, solve magically. So that's what's called in PLC the audit log, and it looks something like this. You have the Genesis state which has this field called prev to be null because there is no previous previous state. But every time you make an update, you have a reference to the previous state. So if you want to know the current state of a DID, you ask to see the audit log, and you can verify this audit log uh audit log up until the current stuff. Okay. Now you may you might think you might already guess where I'm going with this.
And I will say that a lot of these ideas are not new. I'm just like trying to show how potentially we can apply them in net proto. And even we've seen uses of T's in things like privacy preserving analytics, we've seen them in delegating access to online accounts. So this is a combination of these ideas here. So what now you might ask yourself what key should I encumber. One maybe obvious choice would be this add product key or what I call the repo signing key. And this add product key controls every operation that you make in your account.
But that's also its downside. And again, I'm referring to SMEs talk because we've seen every time that he made an operation and every time something happened, you need to add a record to your PDS. So that's a good choice if you want everything to be really really protected, but it also adds this friction. So what we did here is we instead worked with what's called a proof attestation key, or like this hashtag sign key that only signs attestations on records that are posts.
And concretely we created the proof of concept, and this proof of concept draws on proof and attestation work that Nick Jarakines worked on. And this specific work also includes contributions from Nick Jarakines, Andrian Novakovic from my team, and also the Turnkey team. So concretely what we did here is we created a new app, like a B set app. You can imagine just as any other app that you could be logging into. And an author in this app would be creating a post draft. So okay, there is a post draft. Now signers would start adding signatures to this post draft.
They would say, okay, we are agreeing to sign this post if it is also signed by one of the keys that we know are locked in a TE. Okay. So the signer one would do that, signer two would do that, sign A3 is offline, but it's fine. We have two out of three. Once we have that, that's where the interesting part gets in. We send this collection of signatures with a post draft to the TE. The T also gets this audit log from PLC and runs the following logic. Is the audit log correct? What is the list of three keys that the audit log results with?
And do I have at least two signatures that come from these keys? If so, only and only then it signs with its own encumbered key, sends it to the app, and the app publishes it to your PDS. And concretely, we even have here.tz.com. And what we can see here is that it has a few nice things. This is the proof of attestation work that Nick Jarakiness had. It adds this signatures field. And the interesting part is this one. These are part of the proof draft of the post draft, but this is where we have a signature that came from an actually encumbered TE.
So whenever someone reads the record that is attached to this post, they can go and verify the signature of this. And then they can go and verify that this list of keys here have a TE at the or sorry, a root certificate at the station attached to them. And therefore you can get end-to-end verifiability still preserved. Let's think. So yeah, that's that's uh the main thing I wanted to talk about. Maybe I'll touch on the two related concepts. One is this concept of reproducible build, because something that this is something that we're not always thinking about when developing software usually.
So when we're creating an Node.js code, C code, RAS code, whatever, whenever we compile it, we sometimes get a different binary for many reasons. Sometimes versions change of our dependencies, sometimes just our compilers add timestamps, and which is reasonable, but it changes the binary that we get eventually. And that is a bit uh disastrous when you want to get the guarantee that a specific program is running in a TE. But luckily a lot of people have thought about that, and it's something that people have worked on for decades, and there are there is good infrastructure to do that.
So you can take code in C, you can take code in Rust or whatever is still reasonable to do it in and build it, and you can get something that translates source code to binary in a way that you always get the same hash. So that means that we don't add trust on whoever deploys the program to the TE. Anyone could go and fetch the source code and rebuild it themselves, which is nice. Like this is this uh preserve the decentralized nature of what we're trying to get. Um yeah, and this is a whole verifiability chain that I mentioned.
I'll just look at it briefly. So we have a published post, we have signatures on this post. We have a DID that lives on PLC and has TE keys that it allows to sign. And we also have attestation that these keys came from the right manufacturer and are actually secure keys, and the verification that this happens, that this whole chain happened correctly. So now because I know I I'm still cryptographer, like I want to kind of give alternatives that maybe some of you would want to utilize uh instead. And two alternatives that might get you to similar concepts would be something called multi-party computation, which is a concept that allows you to split a cryptographic key in a way that whenever it's used, it still seems like a single person signature, like we know to verify, but instead you split it to let's say two out of three people, so that they have to run a very complex cryptographic protocol and then produce this signature that looks like any other signature.
You could do that, but now you don't have the guarantee that some specific program is running. You have to trust that an honest majority of people in this committee of signers are running the correct program. Reasonable, but that's the trade-off. And there is also another complex complex concept of zero knowledge proofs, which is again allows you to take a program, convert it to some different kind of math, and then get a guarantee that specific logic ran on specific inputs. That's nice, but what it produces is not signatures. What it produces is proofs, and these proofs can sometimes be large.
These proofs can also be slower to verify sometimes. So also powerful, different trade-offs. Another thing that TEs could give you is the fact that they can also interact with the real world. So for example, some of them can also make requests from inside the TE and fetch data, for example. Which this, let's say in ZK proofs, it's not really possible, maybe in some different ways. MPC is possible, but then you run into some race conditions, maybe every time you fetch and different parties would fetch different things, load balancing, whatever. Something you can do. And yeah, I will say that I used a very specific implementation of TEs here, but most of these concepts are transferable to other TE systems as well.
And yeah, before I wrap up, I'll just also put some glaring open questions that exist in this proof of concept. One of them is what about protecting the DID itself? So if you remember what I was saying is that we take the take the list of keys that are authorized to sign from the DID document. And that can be updated. That can be updated in PLC, that can be updated in DID web. So maybe we need stronger protections on the DID itself because otherwise it could just put any keys it wants. And then maybe the verifiability becomes meaningless.
But that's also okay because in some sense you can say that updates to the DID should be rare. Like it's not something that needs to happen every day. So you can think about stronger protections that you can add to DIDs. And maybe the rotation key, which is what controls updates to the DID in PLC, can be under really strong guard or whatever. So that's one thing. Another thing is if you you might remember that I said that in order to know what are the keys that are authorized to sign, we send the whole audit log to the TE.
And but what if we didn't send the entire audit log? What if we stopped before the last update? So it might not have the most fresh list of keys. So this is a problem. Like you can think about solving it in different ways, maybe making requests out of the TE to fetch the audit log, and then you not don't need to trust the input audit log. Maybe there is a solution that can be done on PLC itself. Maybe PLC could start signing responses. That's different ways. And yeah, many, many other things that are left open here, and when people look at it, they're welcome to discuss this with me or others.
But yeah, many other things are open in this proof of concept. But yeah, I hope that it opened some new notion for at least some of you. Thank you.