 Okay. Hi. So, like they mentioned, I'm Marina Moore. I'm a PhD student at NYU with Dr. Justin Kappos in the Secure Systems Lab there. And I contribute to TUF and various other open search projects. And they talk a little bit today about some of the lessons I've learned through working in the secure software supply chain space about cryptographic signatures and what they do and don't provide for your systems. So, if you're here today at Cloud Native Security Conference, you've probably heard a little bit about these cryptographic signature things. It's a bunch of math that provides a cryptographic guarantee that a particular private key signs a data, and you can verify this using a public key with that private key. Some of you may have heard of include ED25519, EDDSA, RSA, and many others that aren't listed here. So, make sure we're on the same page in case this is the first you've ever heard of a cryptographic signature. Kind of an overview of how these work is that you have one entity with a private key that signs an artifact or really any message that contains some content that they're signing. This is the artifact and the signature that's attached to that artifact is then sent to a verifier or to anyone who then can use a public key that's cryptographically linked to this private key. They can use that key to then verify the artifact and really ensure that the signature came from the private key like it was supposed to. What does this actually mean for us making secure systems? The main guarantee that is this still working? Okay. The main guarantee that is given by a cryptographic signature is that at one point in time, some entity that controlled this private key decided to sign this message or this artifact. But it doesn't really say like that's the only guarantee you really get. And you can do a lot of really powerful things with this mechanism. But on its own, it doesn't have a lot of semantic meaning by itself. But if we put these signatures in context with a lot of other policies and rules and kind of formulations, you can really get a lot out of the system. So some of the things to kind of think about and we're going to go into a lot more detail about some of these is who should sign? Like who controls this private key that is then signing information? How do you know that they actually control this private key? What is each key allowed to sign? What should you do if something is not signed? Or if the verification fails, like what are your next steps? What do you do then? And what do you do if this key ends up in the hands of the wrong person and you find out that this went wrong? And how should you store both the public and the private keys to ensure that they're properly accessed? So the first step in answering a lot of these questions is looking at why you actually want to use cryptographic signatures. I think a lot of people look at distribution of artifacts or messages and say we need to sign them so that they're secure when they're sent across. But I think it's important to think about what meaning you're hoping to get from that signature. Does the signature just mean that the correct person wrote the software that you're then receiving? Or does it mean that a security team reviewed this software and really ensured that that was also done? You can make various other guarantees around it, but you have to decide up front what it is you want to get from this signature on a piece of data. And another kind of general principle that I'm going to talk a lot about later on is this idea of compromise resilience. Or what do you do when something goes wrong? So especially for the more critical assets that you find when you look at a threat model of your system, it's important to think of if any one piece of the system is compromised, if any one key is lost, if any one server is compromised, or any other piece of whatever system is being secured, what can you do to make sure that you can both recover from that compromise and maybe prevent a single compromise from getting bigger than it needs to? So I'm going to talk a little bit about some various properties that you can put around cryptographic signatures to really give them some more meaning. And I think the first most important one of these properties is verification. It gets great to have a signature on an artifact, but it's surprisingly common to have a repository full of software artifacts and signatures, and then client systems that download the artifacts and ignore the signatures, in which case the signatures aren't really providing any semantic meaning at all, they're just there to make people feel like the code has been signed. And so through verification, you can use the public keys to ensure that the artifact that you're downloading is the correct artifact. And a couple of questions to look at here are, which public key are you using for verification? And how do you know this is the public key that is correct? How do you get that? And what are you going to do when this verification fails? Are you going to fail open and download the software anyway or fail closed and potentially leave the attacker away to denial of service or application by just issuing really bad signatures for a lot of different content? There are definitely pros and cons to both of those approaches, but so they need to think about upfront to not just default to one of them. The next topic is storage. Specifically, this is storage of the private keys that are used to sign artifacts. And the first kind of big decision is whether these keys should be online or offline. And the big advantage to having them be online is that you can have things be automatically signed. And this can really make for seamless adoption because if signing happens automatically, you know that people won't just skip this step and it can happen without any kind of user interaction needed. However, because the keys are on some server on the internet, they are more vulnerable to compromise than a key that's stored offline on something like a, you know, you have a key HSM or something that's that requires some kind of human interaction to then connect it to another device to use it to create that signature. So these keys are harder to compromise, but they do require, you know, that actual human step of connecting them, which might make it so that these signatures are used a little bit less often. And whether you're using online or offline keys, it's important to manage who has access to these keys. For online keys, managing like credentials to access the servers where these keys are stored. And for offline keys, you know, deciding, you know, if there's a safe who has keys to that safe, or if there's like just like, you know, a drawer in the office, who's, who's, who's offices that drawer in that kind of situation. The next issue is establishing trust. So how do you, once you have these private keys that are signing the data, you have these associated public keys, which, you know, you can distribute these widely because they're public keys, they don't need to be kept secret. But you do want to ensure that, you know, you know what public key you have, and you know that this public key is associated with an identity that you trust for a particular operation. And there are various ways to do this. I think there's a lot of very cool technologies out there that can establish kind of a trusted channel to communicate this. I think the, you know, the classical fashion method would just be to meet up in person and say, you know, this, this is the key that, that I control. This is the public key. You know, you know, I'm, you know, it's mine because I'm giving it to you in person. And you can kind of fake these online through a variety of different methods. And then there's another method that gets, it's got, it's a lot of, you know, bad press, but it's a surprisingly useful one, which can be trust on first use. I think the dangerous thing about trust on first use is when you look at, like, ephemeral clients and other things, wherever use is a first use. But if it's, you know, a client system that's going to be accessing the same repository over and over again, trusting that the first time you connect to it, you happen to get the correct, you know, the correct key and then using that key over and over again can actually be a reasonable method to ensure this as well. And it's actually very commonly used when connecting to servers over, you know, like authenticating to servers on the internet, because often says, it gives you a fingerprint, you know, the first time you connect, it's like, you know, does this look like the correct server? And if you, and if you say yes, then you can, from then on, your computer recognizes that server that you're connecting to. So next is placing limitations on the trust of each public key that you're using. So there's some dangers to having kind of a universal trust where you have a single queuing that has every single public key that you use for, throughout your application, because of any single private key associated with one of those public keys that you trust is compromised. Then the person who compromises that key can then sign anything in the entire system and you'll, you'll interpret it as valid because you trust that key for any of these different pieces. There's a couple of different ways that you can add some limitations on the trust so that a key compromise isn't as big of a deal. And you can achieve a little bit more of this compromise resilience that I talked about earlier. So the first way you can place limitations on trust is through the use of delegations. One of the kind of nice pieces of delegations is they can be used to, also used to be used to prevent sharing of keys between members of an organization. So the idea of a delegation is that if you trust a particular private key or a particular identity to sign something, that identity can then pass on some amount of that trust to another entity. So in general, you want them to pass on a subset or at least, you know, only what they are allowed to sign, right? So you say, you know, in this example I have here, if you have a person trusted to sign the Ubuntu project and they have an intern who joins the team, instead of doing this intern, the power to also sign anything in the Ubuntu project, you can just give them a specific key that can be used for the documentation or for whatever project or subset of this project that they're actually using. The next kind of big way to prevent or to add this sense of limiting trust is through the use of multi signatures or threshold signature signing. And the idea here is that you require multiple different keys, just multiple different private keys to sign the same artifact. And then as a verifier, you ensure that both, like multiple different public keys that you use to then verify it come up with the same results that you can see that, you know, that the hash is matched basically that both of these keys sign the same artifact and therefore you have this kind of additional level of assurance that you can trust it. And you can set these thresholds to, you know, to whatever you want depending on the criticality of the particular piece or of the process. And there's also ways you can achieve similar multi signature properties using different cryptographic primitives if you want like a fancy way to do this with variations of like starting of keys and other technologies to achieve kind of a more enforceable version of the same property. And I'm going to talk a little bit about a few projects that I work on or at least I'm adjacent to you that have used signatures in practice and talk a bit about some of these decisions that were made in these projects and maybe hopefully give you some context if you ever have to make some of these decisions. But you're in projects about like the kinds of trade-offs that you have to make. So the first project I want to talk about is notation which is kind of a subset of the NerdReview2 effort. And specifically it's kind of the signing solution. It's the piece that really just provides signatures that can go on registries and it uses this artifact manifest reference type in order to achieve that. And the notation really focuses on the signing aspect and having the signatures and artifacts on sorry having signatures that are attached to artifacts on a registry and it leaves a lot of this context and kind of policy decisions up to the end user and kind of allows each user of the system to set kind of their own policy decisions about like the number of keys that need to be used in order to sign a particular artifact or which keys should be used to verify in all these different pieces. And this is partly to add some flexibility so that notation can be used across different kinds of registries that have different kinds of users with different needs. And so it kind of allows people to do all of those different things. Another signing solution in kind of a similar vein is Cosign which I think which is a six-door signing solution which is in many ways similar to notation. It adds signatures to artifacts on OCI registries using slightly different APIs and it really focuses on this idea of usability. And one of the big pieces of context that Cosign kind of adds in is this integration with another six-door project called Recor which is a transparency log. So any artifact that is signed with Cosign that signature is automatically uploaded to Recor which means that it is fully auditable on the immutable log. So anyone in the future can go through and see when this artifact was signed and make sure there was no tampering going on in that situation. Next we're talking about a couple projects that focus a lot more on the context around these signatures. So first of all is the update framework or TAF which is a compromise resilient framework for secure software update and distribution. And this really adds in a lot of these different mechanisms that I've talked about on top of just signatures themselves including things like delegations. There are delegations that chain all the way up to these offline root keys that TAF kind of mandates and it also includes the option for thresholds at all the different levels of the TAF framework. There's actually ongoing integrations of TAF both into both notation and Cosign just to to be clear for those who's watching and so these things aren't mutually exclusive this is just some additional policy that's added on here. There's also some flexibility in TAF which includes how developers actually manage the keys so like that kind of online versus offline decision. TAF mandates that the root keys of the system are stored offline because this is kind of the root of trust for the system and so the most critical piece. But developers can decide whether it makes more sense for them at the developer level to store these keys online or offline and how to manage them themselves. Another piece of context that TAF adds in that TAF leaves to individual users is how to do root key distribution. So TAF actually handles the distribution of all non-root keys through the framework itself it has policies and mechanisms that basically use delegations in order to distribute keys but these all train back up to these root keys which then still need to be distributed. A lot of systems using TAF do use trust on first use but there it also supports any other kind of key distribution mechanism you know depending on what can be set up in a particular context and this kind of depends on the kind of the closeness between the person downloading the software and the person like uploading the the the software to be downloaded and how much they're able to communicate in order to do this secure root key distribution. And also as TAF supports these thresholds but deciding you know whether you should have a threshold of one or a threshold of 50 really depends on your particular uses and whether for a particular role it makes more sense to set it in a different place. The final piece I want to talk a bit about is Intodo. There's a framework for software supply chain security. Intodo allows users to set policies for all the different stages of the software supply chain and what they expect to happen at these different stages and then allows the users to verify that all these different steps happened. And one of the really interesting kind of pieces of context that Intodo adds is really about this identity because because Intodo goes across the entire supply chain it needs to keep track of the public keys that should be used to verify each step in the supply chain and it really it does a great job I think of tying the identity to the specific step that that identity should be used to sign to really ensure that each key is used for the thing that it's supposed to be used for. It's similar to TAF it supports thresholds for each of these stages as well so in certain cases for example you may want the code to be you know signed off by more than one different developer to ensure that you know you've had more than one set of eyes on the code and you can enforce that using thresholds in Intodo. Yeah and this really defines those identities across this section. That's kind of what I have here's some contact info for me we know if you have any questions or anything else I think you went a little under time but we know if anything else you want to talk about yes thank you. Okay. Andres. Marina great presentation say someone starting off with Intodo can you elaborate what's an approach to formulate a layout what does that entail? Yeah I did get that a little fast so yeah basically what it means is looking at how your software goes from the developer to the end user looking at all the different stages it usually involves some kind of you know code being uploaded some kind of CICD system some kind of build system some kind of distribution system plus maybe some other steps depending on on what you do. So the first step is really defining what those steps are for you what systems are you using what machines or people are responsible for each of those different steps and then I don't have pictures of it or anything but Intodo has you know specific formats basically that you just put all that information into and then it can and then if you actually follow those steps of the supply chain you can then use Intodo to verify that each of these steps happened. So you don't map like pseudocode from those steps you actually just fill out parameters into an Intodo template let's say. Yeah exactly Intodo template that's what you would use. Have you seen that work you know I was following on CNCF Slack and I saw someone had posted a tool that took a tecton chains and turned that into an Intodo layout what do you think about that type of method for generating these layouts? I think that's a great idea yeah I think that being able to kind of automate that process and use the tools that already exist to do it is a great idea. Any more questions? Yeah. All right well hey thank you so much and you know Marina's been such a she's been giving so much to the open source community and I just really want to thank her for the work she's been doing and great talk thank you.