// 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;

import "google/api/field_behavior.proto";
import "google/protobuf/timestamp.proto";

option go_package = "github.com/sigstore/protobuf-specs/gen/pb-go/common/v1";
option java_package = "dev.sigstore.proto.common.v1";
option java_multiple_files = true;
option java_outer_classname = "CommonProto";
option ruby_package = "Sigstore::Common::V1";

// 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 enum (which is the first
// value, represented by '0'.
enum HashAlgorithm {
        HASH_ALGORITHM_UNSPECIFIED = 0;
        SHA2_256 = 1;
        SHA2_384 = 2;
        SHA2_512 = 3;
        // Used for LMS
        SHA3_256 = 4 [deprecated = true];
        // Used for LMS
        SHA3_384 = 5 [deprecated = true];
}

// Details of a specific public key, capturing the the key encoding method,
// and signature algorithm.
//
// PublicKeyDetails captures the public key/hash algorithm combinations
// recommended in the Sigstore ecosystem.
//
// This is modelled as a linear set as we want to provide a small number of
// opinionated options instead of allowing every possible permutation.
//
// Any changes to this enum MUST be reflected in the algorithm registry.
//
// See: <https://github.com/sigstore/architecture-docs/blob/main/algorithm-registry.md>
//
// To avoid the possibility of contradicting formats such as PKCS1 with
// ED25519 the valid permutations are listed as a linear set instead of a
// cartesian set (i.e one combined variable instead of two, one for encoding
// and one for the signature algorithm).
enum PublicKeyDetails {
        PUBLIC_KEY_DETAILS_UNSPECIFIED = 0;
        // RSA
        PKCS1_RSA_PKCS1V5 = 1 [deprecated = true]; // See RFC8017
        PKCS1_RSA_PSS = 2 [deprecated = true]; // See RFC8017
        PKIX_RSA_PKCS1V5 = 3 [deprecated = true];
        PKIX_RSA_PSS = 4 [deprecated = true];
        // RSA public key in PKIX format, PKCS#1v1.5 signature
        PKIX_RSA_PKCS1V15_2048_SHA256 = 9;
        PKIX_RSA_PKCS1V15_3072_SHA256 = 10;
        PKIX_RSA_PKCS1V15_4096_SHA256 = 11;
        // RSA public key in PKIX format, RSASSA-PSS signature
        PKIX_RSA_PSS_2048_SHA256 = 16; // See RFC4055
        PKIX_RSA_PSS_3072_SHA256 = 17;
        PKIX_RSA_PSS_4096_SHA256 = 18;

        // ECDSA
        PKIX_ECDSA_P256_HMAC_SHA_256 = 6 [deprecated = true]; // See RFC6979
        PKIX_ECDSA_P256_SHA_256 = 5; // See NIST FIPS 186-4
        PKIX_ECDSA_P384_SHA_384 = 12;
        PKIX_ECDSA_P521_SHA_512 = 13;

        // Ed 25519
        PKIX_ED25519 = 7; // See RFC8032
        PKIX_ED25519_PH = 8;

        // These algorithms are deprecated and should not be used, but they
        // were/are being used by most Sigstore clients implementations.
        PKIX_ECDSA_P384_SHA_256 = 19 [deprecated = true];
        PKIX_ECDSA_P521_SHA_256 = 20 [deprecated = true];

        // LMS and LM-OTS
        // 
        // These algorithms are deprecated and should not be used.
        // There are no plans to support SLH-DSA at this time.
        //
        // USER WARNING: LMS and LM-OTS are both stateful signature schemes.
        // Using them correctly requires discretion and careful consideration
        // to ensure that individual secret keys are not used more than once.
        // In addition, LM-OTS is a single-use scheme, meaning that it
        // MUST NOT be used for more than one signature per LM-OTS key.
        // If you cannot maintain these invariants, you MUST NOT use these
        // schemes.
        LMS_SHA256 = 14 [deprecated = true];
        LMOTS_SHA256 = 15 [deprecated = true];

        // ML-DSA
        //
        // These ML_DSA_44, ML_DSA_65 and ML-DSA_87 algorithms are the pure variants
        // that take data to sign rather than the prehash variants (HashML-DSA), which
        // take digests. While considered quantum-resistant, their usage
        // involves tradeoffs in that signatures and keys are much larger, and
        // this makes deployments more costly.
        //
        // USER WARNING: ML_DSA_44, ML_DSA_65 and ML_DSA_87 are experimental algorithms.  
        // In the future they MAY be used by private Sigstore deployments, but
        // they are not yet fully functional. This warning will be removed when 
        // these algorithms are widely supported by Sigstore clients and servers, 
        // but care should still be taken for production environments.
        //
        // See NIST FIPS 204, RFC 9881 for algorithm identifiers
        ML_DSA_44 = 23;
        ML_DSA_65 = 21;
        ML_DSA_87 = 22;

        // Reserved for future additions of public key/signature algorithm types.
        reserved 24 to 50;
}

// 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.
        // Clients MUST NOT attempt to use this digest to verify the associated
        // signature; it is intended solely for identification.
        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 [(google.api.field_behavior) = REQUIRED];
}

// LogId captures the identity of a transparency log.
message LogId {
        // The unique identity of the log, represented by its public key.
        bytes key_id = 1 [(google.api.field_behavior) = REQUIRED];
}

// 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 [(google.api.field_behavior) = REQUIRED];
}

message PublicKey {
        // DER-encoded public key, encoding method is specified by the
        // key_details attribute.
        optional bytes raw_bytes = 1;
        // Key encoding and signature algorithm to use for this key.
        PublicKeyDetails key_details = 2;
        // Optional validity period for this key, *inclusive* of the endpoints.
        optional TimeRange valid_for = 3;
}

// 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.
        // Implementors are RECOMMENDED to derive the value from the public
        // key as described in RFC 6962.
        // See: <https://www.rfc-editor.org/rfc/rfc6962#section-3.2>
        string hint = 1;
}

// An ASN.1 OBJECT IDENTIFIER
message ObjectIdentifier {
        repeated int32 id = 1 [(google.api.field_behavior) = REQUIRED];
}

// An OID and the corresponding (byte) value.
message ObjectIdentifierValuePair {
        ObjectIdentifier oid = 1;
        bytes value = 2;
}

message DistinguishedName {
        string organization = 1;
        string common_name = 2;
}

message X509Certificate {
        // DER-encoded X.509 certificate.
        bytes raw_bytes = 1 [(google.api.field_behavior) = REQUIRED];
}

enum SubjectAlternativeNameType {
        SUBJECT_ALTERNATIVE_NAME_TYPE_UNSPECIFIED = 0;
        EMAIL = 1;
        URI = 2;
        // OID 1.3.6.1.4.1.57264.1.7
        // See https://github.com/sigstore/fulcio/blob/main/docs/oid-info.md#1361415726417--othername-san
        // for more details.
        OTHER_NAME = 3;
}

message SubjectAlternativeName {
        SubjectAlternativeNameType type = 1;
        oneof identity {
                // A regular expression describing the expected value for
                // the SAN.
                string regexp = 2;
                // The exact value to match against.
                string value = 3;
        }
}

// A collection of X.509 certificates.
//
// This "chain" can be used in multiple contexts, such as providing a root CA
// certificate within a TUF root of trust or multiple untrusted certificates for
// the purpose of chain building.
message X509CertificateChain {
        // One or more DER-encoded certificates.
        //
        // In some contexts (such as `VerificationMaterial.x509_certificate_chain`), this sequence
        // has an imposed order. Unless explicitly specified, there is otherwise no
        // guaranteed order.
        repeated X509Certificate certificates = 1;
}

// The time range is closed and includes both the start and end times,
// (i.e., [start, end]).
// End is optional to be able to capture a period that has started but
// has no known end.
message TimeRange {
        google.protobuf.Timestamp start = 1;
        optional google.protobuf.Timestamp end = 2;
}
