Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Public keys as part of trust root #236

Open
haydentherapper opened this issue Feb 22, 2024 · 5 comments
Open

Public keys as part of trust root #236

haydentherapper opened this issue Feb 22, 2024 · 5 comments

Comments

@haydentherapper
Copy link
Collaborator

Currently the trust root specifies roots of trust from services (CA, CT log, Rekor, and TSA). For bring-your-own-PKI use cases where verifiers trust a set of keys, rather than certificates, it is not possible to specify the trusted keys via the trust root bundle. sigstore-go shows an example of adding trusted public keys to a parsed trust root, but this is not standardized across clients.

I propose adding repeated PublicKey public_keys (message) to the TrustedRoot message.

cc @kommendorkapten @codysoyland @woodruffw @bdehamer @loosebazooka

@kommendorkapten
Copy link
Member

This was discussed earlier and decided against. My view is that raw public keys are to hard to manage on a "global level", such as in a trust root. What we have in the trust root today is "global services" only, i,e the CA, transparency log or the TSA. These are services that normally operate on a per environment level, which usually would translate into a single trust root.

Public keys on the other hand is more treated as an identity, and so they only are weakly referenced in the bundle (verifier is expected to have a key ring provided OOB). This would so identity the signer, compare this with how a certificate is embedded in the bundle to identity the signer.

For a certificate it's not enough to generally accept a signature from a signing certificate that chains up to a trusted certificate, we need to apply a policy too, that verifies things like SAN and issuer. These are properties part of the per artifact specific verification policy. This can be seen in the ArtifactVerificationOptions, the public keys are listed there, complete, not just the details on their algorithm, i.e values that can be used to actually verify a signature.

So I think the current design is as intended, as adding public keys to the trust root can open up to a situation were we would have a key-ring, but weak semantics around how they are supposed to be used, that would need an application layer to figure that out before verification can happen.

So IMHO we are not gaining anything by having the keys in the trust root, the client would still need to manage their key ring, collect the expected key given a policy for an artifact, then prepare the options and verify.

But you are raising a good question on unclarity of how to deal withpublic keys. I think we should document this, that clients using public keys are expected to bring their own keyring, manage a selection interface that may depend on the provided key hint to provide a key to use during verification and policy evaluation.

For npm we are doing this via a delegation in the TUF repo to provide the key-ring. That can be listed as one example on how to do it, many deployments probably have their own key-ring implementations already, so with proper documentation I think we can explain how to integrate them.

Thoughts?

@haydentherapper
Copy link
Collaborator Author

I think we should document this, that clients using public keys are expected to bring their own keyring, manage a selection interface that may depend on the provided key hint to provide a key to use during verification and policy evaluation.

Yea, this is the gap that I’ve noticed. Maybe another way to put it is, what are the required values in order to verify a signature? Currently, it’s the trust root, and either the identity of the signer or the public key.

I could envision a simple structure that is not meant for global verification values, but per-verification values including identity and keys. There may be some value in defining this so there’s consistency across clients and we mandate what is required for a verification event (eg identity means an identity plus an identity provider, using a key hint for a key ring).

Given that there are currently only two verification values, documentation could suffice for now without adding another struct.

@haydentherapper
Copy link
Collaborator Author

haydentherapper commented Feb 26, 2024

As you linked in the other thread on sigstore-go, https://github.com/sigstore/protobuf-specs/blob/main/protos/sigstore_verification.proto#L92 is what I'm looking for in terms of a struct.

Part of my motivation for raising this was after looking at how we initialize a verifier in sigstore-go, that public keys are loaded into a trust root structure (not the same as trusted_root.proto), which feels strange given the proto does not define keys as part of its content. I think when clients start using the verification proto, this issue goes away.

I'm good to close this out once we add some documentation, that seems sufficient.

@kommendorkapten
Copy link
Member

I'm good to close this out once we add some documentation, that seems sufficient.

That seems good. Do you think of a higher level document, like extend the readme with the different files and their purpose? I think that would help to onboard folks, and if needed add more documentation in each protobuf file too. I can take a look this week at extending the readme with a summary of what is documented in this repo if that sounds good.

@haydentherapper
Copy link
Collaborator Author

Yes, that sounds great! We can also link each file to steps in the client specification.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants