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

First commit of the new bundle format. #1

Merged
merged 16 commits into from
Oct 31, 2022
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*~
51 changes: 51 additions & 0 deletions protos/envelope.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// https://raw.githubusercontent.com/secure-systems-lab/dsse/9c813476bd36de70a5738c72e784f123ecea16af/envelope.proto
kommendorkapten marked this conversation as resolved.
Show resolved Hide resolved

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

syntax = "proto3";

package io.intoto;

option go_package = "github.com/secure-systems-lab/dsse";

// An authenticated message of arbitrary type.
message Envelope {
// Message to be signed. (In JSON, this is encoded as base64.)
// REQUIRED.
bytes payload = 1;

// String unambiguously identifying how to interpret payload.
// REQUIRED.
string payloadType = 2;

// Signature over:
// PAE(type, body)
// Where PAE is defined as:
// PAE(type, body) = "DSSEv1" + SP + LEN(type) + SP + type + SP + LEN(body) + SP + body
// + = concatenation
// SP = ASCII space [0x20]
// "DSSEv1" = ASCII [0x44, 0x53, 0x53, 0x45, 0x76, 0x31]
// LEN(s) = ASCII decimal encoding of the byte length of s, with no leading zeros
// REQUIRED (length >= 1).
repeated Signature signatures = 3;
}

message Signature {
// Signature itself. (In JSON, this is encoded as base64.)
// REQUIRED.
bytes sig = 1;

// *Unauthenticated* hint identifying which public key was used.
// OPTIONAL.
string keyid = 2;
}
77 changes: 77 additions & 0 deletions protos/sigstore_bundle.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// Copyright 2022 The Sigstore Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

syntax = "proto3";
package dev.sigstore.bundle.v1;

// https://raw.githubusercontent.com/secure-systems-lab/dsse/9c813476bd36de70a5738c72e784f123ecea16af/envelope.proto
import "envelope.proto";
import "sigstore_common.proto";
import "sigstore_rekor.proto";

option go_package = "github.com/sigstore/proto/bundle/v1";
option java_package = "dev.sigstore.proto.bundle.v1";
option java_multiple_files = true;
option java_outer_classname = "BundleProto";

// Notes on versioning.
// The primary message ('Bundle') MUST be versioned, by populating the
// 'media_type' field. Semver-ish (only major/minor versions) scheme MUST
// be used. The current version as specified by this file is:
// application/vnd.dev.sigstore.bundle+json;version=0.1
// The semantic version is thus '0.1'.

// Various timestamped counter signatures over the artifacts signature.
// Currently only RFC3161 signatures are provided. More formats may be added
// in the future.
message TimestampVerificationData {
// A list of RFC3161 signed timestamps provided by the user.
// This can be used when the entry has not been stored on a
// transparency log, or in conjuction for a stronger trust model.
// Clients MUST verify the hashed message in the message imprint
// against the signature in the bundle.
repeated dev.sigstore.common.v1.RFC3161SignedTimestamp rfc3161_timestamps = 1;
}

// VerificationData contains extra data that can be used to verify things
// such as transparency and timestamp of the signature creation.
// As this message can be either empty (no inclusion proof or timestamps), or a combination of
// an arbitrarily number of transparency log entries and signed timestamps,
// it is the client's responsibility to implement any required verification
// policies.
message VerificationData {
// This is the inclusion promise and/or proof, where
// the timestamp is coming from the transparency log.
repeated dev.sigstore.rekor.v1.TransparencyLogEntry tlog_entries = 1;
// Timestamp verification data, over the artifact's signature.
TimestampVerificationData timestamp_verification_data = 2;
}

message Bundle {
// MUST be application/vnd.dev.sigstore.bundle+json;version=0.1
// when encoded as JSON.
string media_type = 1;
VerificationData verification_data = 2;
dev.sigstore.common.v1.VerificationMaterial verification_material = 3;
oneof content {
dev.sigstore.common.v1.MessageSignature message_signature = 4;
// A DSSE envelope can contain arbitrary payloads.
// Verifiers must verify that the payload type is a
// supported and expected type. This is part of the DSSE
// protocol which is defined here https://github.com/secure-systems-lab/dsse/blob/master/protocol.md
io.intoto.Envelope dsse_envelope = 5;
}
// Reserved for future additions of artifact types.
reserved 6 to 50;
kommendorkapten marked this conversation as resolved.
Show resolved Hide resolved
}
106 changes: 106 additions & 0 deletions protos/sigstore_common.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
// Copyright 2022 The Sigstore Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

syntax = "proto3";
package dev.sigstore.common.v1;

option go_package = "github.com/sigstore/proto/common/v1";
option java_package = "dev.sigstore.proto.common.v1";
option java_multiple_files = true;
option java_outer_classname = "CommonProto";

// This package defines commonly used message types within the Sigstore
// community.

// Only a subset of the secure hash standard algorithms are supported.
// See https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf for more
// details.
// UNSPECIFIED SHOULD not be used, primary reason for inclusion is to force
// any proto JSON serialization to emit the used hash algorithm, as default
// option is to *omit* the default value of an emum (which is the first
// value, represented by '0'.
enum HashAlgorithm {
HASH_ALGORITHM_UNSPECIFIED = 0;
SHA2_256 = 1;
SHA2_512 = 2;
}

// HashOutput captures a digest of a 'message' (generic octet sequence)
// and the corresponding hash algorithm used.
message HashOutput {
HashAlgorithm algorithm = 1;
// This is the raw octets of the message digest as computed by
// the hash algorithm.
bytes digest = 2;
}

// MessageSignature stores the computed signature over a message.
message MessageSignature {
// Message digest can be used to identify the artifact.
kommendorkapten marked this conversation as resolved.
Show resolved Hide resolved
HashOutput message_digest = 1;
// The raw bytes as returned from the signature algorithm.
// The signature algorithm (and so the format of the signature bytes)
// are determined by the contents of the 'verification_material',
// either a key-pair or a certificate. If using a certificate, the
// certificate contains the required information on the signature
// algorithm.
// When using a key pair, the algorithm MUST be part of the public
// key, which MUST be communicated out-of-band.
bytes signature = 2;
}

// This message holds a RFC 3161 timestamp.
message RFC3161SignedTimestamp {
// Signed timestamp is the DER encoded TimeStampResponse.
// See https://www.rfc-editor.org/rfc/rfc3161.html#section-2.4.2
bytes signed_timestamp = 1;
}


// PublicKeyIdentifier can be used to identify an (out of band) delivered
// key, to verify a signature.
message PublicKeyIdentifier {
// Optional unauthenticated hint on which key to use.
// The format of the hint must be agreed upon out of band by the
// signer and the verifiers, and so is not subject to this
// specification.
// Example use-case is to specify the public key to use, from a
// trusted key-ring. Formats may differ depending on implementation,
// but a hex encoded digest of the public key is one example.
string hint = 1;
kommendorkapten marked this conversation as resolved.
Show resolved Hide resolved
}

message X509Certificate {
// DER-encoded X.509 certificate.
bytes raw_bytes = 1;
}

// A chain of X.509 certificates.
message X509CertificateChain {
// The chain of certificates, with indices 0 to n.
// The first certificate in the array must be the leaf
// certificate used for signing. Any intermediate certificates
// must be stored as offset 1 to n-1, and the root certificate at
// position n.
repeated X509Certificate certificates = 1;
}

// VerificationMaterial captures details on the materials used to verify
// signatures.
message VerificationMaterial {
oneof content {
PublicKeyIdentifier public_key = 1;
kommendorkapten marked this conversation as resolved.
Show resolved Hide resolved
X509CertificateChain x509_certificate_chain = 2;
}
}
kommendorkapten marked this conversation as resolved.
Show resolved Hide resolved
109 changes: 109 additions & 0 deletions protos/sigstore_rekor.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
// Copyright 2022 The Sigstore Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

syntax = "proto3";
package dev.sigstore.rekor.v1;

option go_package = "github.com/sigstore/proto/rekor/v1";
option java_package = "dev.sigstore.proto.rekor.v1";
option java_multiple_files = true;
option java_outer_classname = "RekorProto";

// KindVersion contains the entry's kind and api version.
message KindVersion {
// Kind is the type of entry being stored in the log.
// See here for a list: https://github.com/sigstore/rekor/tree/main/pkg/types
string kind = 1;
// The specific api version of the type.
string version = 2;
}

// The checkpoint contains a signature of the tree head (root hash),
// size of the tree, the transparency log's unique identifier (log ID),
// hostname and the current time.
// The result is a string, the format is described here
// https://github.com/transparency-dev/formats/blob/main/log/README.md
// The details are here https://github.com/sigstore/rekor/blob/a6e58f72b6b18cc06cefe61808efd562b9726330/pkg/util/signed_note.go#L114
// The signature has the same format as
// TransparencyLogEntry.inclusion_proof. See below for more details.
kommendorkapten marked this conversation as resolved.
Show resolved Hide resolved
message Checkpoint {
string envelope = 1;
}

// InclusionProof is the proof returned from the transparency log. Can
// be used for on line verification against the log.
message InclusionProof {
// The index of the entry in the log.
int64 log_index = 1;
// The hash digest stored at the root of the merkle tree at the time
// the proof was generated.
bytes root_hash = 2;
// The size of the merkle tree at the time the proof was generated.
int64 tree_size = 3;
// A list of hashes required to compute the inclusion proof, sorted
// in order from leaf to root.
kommendorkapten marked this conversation as resolved.
Show resolved Hide resolved
repeated bytes hashes = 4;
// Signature of the tree head, as of the time of this proof was
// generated. See above info on 'Checkpoint' for more details.
Checkpoint checkpoint = 5;
}

// The inclusion promise is calculated by Rekor. It's calculated as a
// signature over a canonical JSON serialization of the persisted entry, the
// log ID, log index and the integration timestamp.
asraa marked this conversation as resolved.
Show resolved Hide resolved
// See https://github.com/sigstore/rekor/blob/a6e58f72b6b18cc06cefe61808efd562b9726330/pkg/api/entries.go#L54
// The format of the signature depends on the transparency log's public key.
// If the signature algorithm requires a hash function and/or a signature
// scheme (e.g. RSA) those has to be retrieved out-of-band from the log's
// operators, together with the public key.
// This is used to verify the integration timestamp's value and that the log has promised to include the entry.
message InclusionPromise {
bytes signed_entry_timestamp = 1;
}

// LogId captures the identity of a transparency log.
message LogId {
kommendorkapten marked this conversation as resolved.
Show resolved Hide resolved
// The unique id of the log, represented as the SHA-256 hash
// of the log's public key, computed over the DER encoding.
// This is similar to how it works for certificate transparency logs:
// https://www.rfc-editor.org/rfc/rfc6962#section-3.2
bytes key_id = 1;
}

// TransparencyLogEntry captures all the details required from Rekor to
// reconstruct an entry, given that the payload is provided via other means.
// This type can easily be created from the existing response from Rekor.
// Future iterations could rely on Rekor returning the minimal set of
// attributes (excluding the payload) that are required for verifying the
// inclusion promise. The inclusion promise (called SignedEntryTimestamp in
// the response from Rekor) is similar to a Signed Certificate Timestamp
// as described here https://www.rfc-editor.org/rfc/rfc9162#name-signed-certificate-timestam.
message TransparencyLogEntry {
// The index of the entry in the log.
int64 log_index = 1;
// The unique identifier of the log.
LogId log_id = 2;
// The kind (type) and version of the object associated with this
// entry. These values are required to construct the entry during
// verification.
KindVersion kind_version = 3;
// The UNIX timestamp from the log when the entry was persisted.
int64 integrated_time = 4;
// The inclusion promise/signed entry timestamp from the log.
InclusionPromise inclusion_promise = 5;
// The inclusion proof can be used for online verification that the
// entry was appended to the log, and that the log has not been
// altered.
InclusionProof inclusion_proof = 6;
}