-
Notifications
You must be signed in to change notification settings - Fork 25
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
Support Signing #136
Comments
So here is a very rough example of what For package sign
import (
protobundle "github.com/sigstore/protobuf-specs/gen/pb-go/bundle/v1"
protocommon "github.com/sigstore/protobuf-specs/gen/pb-go/common/v1"
)
// this is just a convienient way to bundle the information from the signer to the witness(es)
type SignedEntity struct{
dataDigest []byte
signature []byte
ephemeralPublicKey []byte
envelope []byte
}
func Sign(data []byte, signer *Signer, witnesses []Witness, bundleVersion string) (*protobundle.Bundle, error) {
bundle := Bundle{}
signerResult, err := signer.SignData(data)
if err != nil {
return nil, err
}
// Put signerResult into SignedEntity, depending on type
// Put signerResult into bundle, depending on type
for _, witness := range witnesses {
witnessResult, err := witness.Witness(se)
if err != nil {
return nil, err
}
// Put witnessResult into bundle, depending on type
}
return bundle, nil
} For package sign
import (
"crypto"
"crypto/x509"
)
type Signer struct{}
type SignerResult struct{
// Populate these fields if you are signing with a key
signature []byte
publicKeyHint []byte
// Populate these fields if you are signing with Fulcio
ephemeralPublicKey []byte
signingCertificate *x509.Certificate
}
func (s *Signer) SignData(data) (*SignerResult, error) {
return nil, errors.New("not implemented")
}
type Fulcio struct {
baseUrl string
}
type Keypair struct {
crypto.PublicKey
crypto.PrivateKey
publicKeyHint []byte
}
func (f *Fulcio) SignData(data) (*SignerResult, error) {}
func (k *Keypair) SignData(data) (*SignerResult, error) {} For package sign
import (
"errors"
protocommon "github.com/sigstore/protobuf-specs/gen/pb-go/common/v1"
protorekor "github.com/sigstore/protobuf-specs/gen/pb-go/rekor/v1"
)
type Witness struct{}
type WitnessResult struct {
*protocommon.RFC3161SignedTimestamp
*protorekor.TransparencyLogEntry
}
func (w *Witness) Witness(se *SignedEntity) (*WitnessResult, error) {
return nil, errors.New("not implemented")
}
type TimestampAuthority struct{
baseUrl string
}
type Rekor struct {
baseUrl string
entryType string
}
func (ta *TimestampAuthority) Witness(se *SignedEntity) (*WitnessResult, error) {
// uses se.signature
}
func (r *Rekor) Witness(se *SignedEntity) (*WitnessResult, error) {
// hashedrekord uses se.signature and se.dataDigest
// dsse uses se.envelope and se.ephemeralPublicKey
} |
I'll leave comments on the PR for the interface! One quick comment is that "witness" needs a different name to avoid conflicting with the concept of witnessing from the tlog ecosystem. I also want to not conflate timestamping and auditability. It just so happens that the log can be used for both currently, but we would like to move towards timestamping being a requirement independent of the log so that you never have to trust the log. +1 to "batteries included" Fulcio and private key support.
As long as other clients support 0.3.x bundles, SGTM. A few more goals I think we need to tackle:
|
I don't think we should enforce the latter because in the case of private key signing in a private environment, neither logging nor a timestamp is needed. As a CLI, not logging should be discouraged, but as an API, I don't think it should be opinionated. |
@vishal-chdhry asked me today "what's left on signing?" so I thought I'd write it down here.
|
I'm new to sigstore-go and was curious about a few things here:
Can confirm, I was confused by this on first read. It looks like this term is already used in sigstore-js https://github.com/sigstore/sigstore-js/blob/main/packages/sign/README.md#witness so the train might have left the station on that one. For my education, could you clarify what a witness is supposed to be used for in this context? Does it have an equivalent concept in cosign?
With sigstore-go being mainly an API library, I wonder if it's really necessary to have built-in provider support the way cosign does - couldn't a
Is it typical for other client libraries to have an interactive mode? What is the use case for using sigstore-go in interactive mode versus just using the cosign CLI?
I think it's not a bad idea to at least add a basic smoke test for integration with the services, that way the skeleton is there and someone who wants to add a riskier feature has a starting point for more complex testing. |
Hi @cmurphy, and welcome to sigstore-go!
I think the sigstore-js packages/sign/README.md#witness says it pretty well:
So basically it's a Rekor entry or a RFC3161 timestamp (or possibly both). Inside GitHub, we use the term "witness" as a shorthand for "a Rekor entry if you're working with the Sigstore Public Good Instance (like in the case of npm build provenance) or a RFC3161 Timestamp if you're using GitHub's internal Sigstore instance (like in the case of Artifact Attestations in a private repository)". This shorthand has definitely been useful inside GitHub, but I don't think it has caught on in the wider Sigstore community. For sigstore-go we decided to use pkg/sign/transparency.go and pkg/sign/timestamping.go instead of combining them in the proposed
I knew cosign supported Rekor, but I had to double check on the RFC3161 Timestamp, which it looks like it does support with
Exactly; we ended up deciding that
Yeah, once we decided
Agreed! |
Yes, Cosign supports RFC3161 timestamp authorities. Those timestamps can be persisted in OCI or as detached metadata.
To add some more context, what's missing is a "batteries included" configuration. I agree that interactive signing doesn't need to be a part of sigstore-go, though the question is, where should that logic live? How do we avoid integrators needing to reimplement the logic in Go to fetch identity tokens per platform? I would like this implemented somewhere in the Sigstore org, to minimize adoption burden and maximize the number of supported platforms. We've got a few options:
My two cents, if not sigstore-go, let's move the "provider" logic from Cosign into sigstore/sigstore and demonstrate with an example application how to compose sigstore-go and sigstore/sigstore for signing blobs either interactively or on an automated platform. Does this seem reasonable?
One other feature would be support for the |
What about either of:
|
Sorry, missed responding! Given the complexity of adding repos into the org and finding active maintainers for each, having a single repo with a set of providers seems like a good approach. We can revisit this as part of Cosign refactoring. |
Figuring out how to extract the IDToken is where I'm at now, as ossf/scorecard-action considers dropping sigstore/cosign in favor of sigstore/sigstore-go.
If we switched today, I would likely copy Cosign's GitHub provider, but using a library would be nice. |
Yea, you'll need Cosign's GitHub provider if you're fetching the token as part of a Go binary, or if you're running in an action, getting the token following https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-cloud-providers#adding-permissions-settings and passing that to the Scorecard binary. cc @ramonpetgrave64 since we had chatted about this |
Description
It would be great if sigstore-go could not just verify, but also sign bundles.
There aren't many libraries that support signing bundles today (just sigstore-js?) This would also allow sigstore-go to support the full range of tests in sigstore-conformance.
Goals
sigstore-go/pkg/sign/
supports signing Sigstore bundlescmd/conformance/main.go
is updated to supportsign-bundle
andsign
(similar toverify
,sign
will "wrap" the bundle flow).Anti-Goals
cmd/sigstore-go/main.go
, it should not compete with cosignsigstore-go
itselfReferences
The text was updated successfully, but these errors were encountered: