diff --git a/docs/src/catalyst-standards/draft-cips/c509-plutus-restricted-certificate/c509-cert-plutus-restricted.cddl b/docs/src/catalyst-standards/draft-cips/c509-plutus-restricted-certificate/c509-cert-plutus-restricted.cddl index 6247eaa0892..69eed33abe7 100644 --- a/docs/src/catalyst-standards/draft-cips/c509-plutus-restricted-certificate/c509-cert-plutus-restricted.cddl +++ b/docs/src/catalyst-standards/draft-cips/c509-plutus-restricted-certificate/c509-cert-plutus-restricted.cddl @@ -1,73 +1,64 @@ ; This c509 Certificate format is based upon: ; https://datatracker.ietf.org/doc/draft-ietf-cose-cbor-encoded-cert/11/ ; And is restricted/customized to better enable compatibility with Plutus scripts -; that would consume them, without loosing necessary features of x509 +; that would consume them, without losing necessary features of x509 ; Not all x509 features are supported and some fields have different semantics to improve ; certificate size and ability to be processed by Plutus Scripts. -; cspell: words reencoded, biguint +; cspell: words reencoded, biguint, stake1uyehkck0lajq8gr28t9uxnuvgcqrc6070x3k9r8048z8y5gh6ffgw -C509CertificatePlutusRestrictedSubset = [ TBSCertificate, issuerSignatureValue: ed25519Signature, ] +C509CertificatePlutusRestrictedSubset = [ + TBSCertificate, + issuerSignatureValue: ed25519Signature +] ; The elements of the following group are used in a CBOR Sequence: TBSCertificate = ( - c509CertificateType: int, ; Always 2 as natively signed C509 certificate following X.509 v3 - certificateSerialNumber: CertificateSerialNumber, ; Can be ignored/set to 0 or used as intended. - issuerSignatureAlgorithm: AlgorithmIdentifier, ; Must be int(12) = Ed25519 - issuer: Name / null, ; If set to null, use the `subject`. This could be an on-chain reference to - the issuer cert, what would be the best way? Transaction hash/cert hash? - validityNotBefore: ~time, ; UTC - validityNotAfter: ~time / null, ; UTC - subject: Name, ; Reference to on-chain keys related to this certificate - subjectPublicKeyAlgorithm: AlgorithmIdentifier, ; Must be int(12) = Ed25519 - subjectPublicKey: any, ; Ed25519 public key - extensions: Extensions, ; Currently support extensions with basic CBOR types and Alternative Name + c509CertificateType: int, ; Always 2 as a natively signed + certificateSerialNumber: CertificateSerialNumber, ; Can be ignored/set to 0 or used as intended. + issuerSignatureAlgorithm: AlgorithmIdentifier, ; Must be int(12) = Ed25519 + issuer: Name / null, ; If the 'issuer' field is identical to the 'subject' field (in case of self-signed), then it must be encoded as CBOR null + ; This could be an on-chain reference to the issuer cert. What would be the best way? Transaction hash/cert hash? + validityNotBefore: ~time, ; c509 uses UTC + validityNotAfter: ~time / null, ; c509 uses UTC, no expiration date must be set to null + subject: Name, ; Reference to on-chain keys related to this certificate + subjectPublicKeyAlgorithm: AlgorithmIdentifier, ; Must be int(12) = Ed25519 + subjectPublicKey: subjectPublicKey, ; Ed25519 public key + extensions: Extensions ; Set to [] if no Extensions provided ) CertificateSerialNumber = ~biguint -Name = [ * Attribute ] / text / bytes - -Attribute = ( - ( attributeType: int, attributeValue: text ) - // ( attributeType: oid, attributeValue: bytes ) - // CardanoPublicKey -) - -subjectPublicKey = bytes .size (32..32); Ed25519 public key stored in bytes, adjust size of this if other key types are supported. +; Currently ONLY AlgorithmIdentifier int(12) - Ed25519 is supported. +; oid and [ algorithm: oid, parameters: bytes ] are not supported by Plutus. +AlgorithmIdentifier = int / ~oid / [ algorithm: ~oid, parameters: bytes ] -; This is a completely custom Attribute, which is only for use with Plutus scripts. -; attributeType = The type of Cardano key we associate with this certificate. -; proof = Does the transaction require proof that the key is owned by the transaction signer? -; attributeValue = The Cardano public key hash of the attribute type +Name = [ * Attribute ] / text / bytes -CardanoPublicKey = ( attributeType: &cardanoKeyTypes proof: bool, attributeValue: bytes .size (28..28) ) +Attribute = ( attributeType: int, attributeValue: text ) + // ( attributeType: ~oid, attributeValue: bytes ) -cardanoKeyTypes = ( - paymentKeyHash: 0, - stakeKeyHash: 1, - drepVerificationKeyHash: 2, - ccColdVerificationKeyHash: 3, - ccHotVerificationKeyHash: 4, -) +subjectPublicKey = bytes .size (32..32) ; Ed25519 public key stored in bytes, adjust size if other key types are supported. -; For `~time` Plutus will need to convert the Unix epoch timestamp to the nearest slot number +; For ~time, Plutus will need to convert the Unix epoch timestamp to the nearest slot number ; validityNotBefore rounds up to the next Slot after that time. ; validityNotAfter rounds down to the next Slot before that time. -ed25519Signature = bstr .size 64; Ed25519 signature must be tagged to identify their type. +ed25519Signature = bstr .size 64 ; Ed25519 signature must be tagged to identify their type. -; Currently ONLY AlgorithmIdentifier int(12) - Ed25519 is supported. -; oid and [ algorithm: oid, parameters: bytes ] are not supported by Plutus. -AlgorithmIdentifier = (int - / ~oid - / [ algorithm: ~oid, parameters: bytes ]) +; The only Extension supported is int(3) = SubjectAltName where GeneralNames need to be +; int(6) = uniformResourceIdentifier. +; This uniformResourceIdentifier must conform to the URI based line in CIP-0134: +; https://github.com/input-output-hk/catalyst-CIPs/tree/cip13-simple-cardano-address-extension/CIP-0134 +; for example, web+cardano://addr/stake1uyehkck0lajq8gr28t9uxnuvgcqrc6070x3k9r8048z8y5gh6ffgw -; Extensions are not currently supported by plutus and should be set to [] -; Any extensions present in the certificate will be ignored by plutus scripts. Extensions = [ * Extension ] / int Extension = ( - ( extensionID: int, extensionValue: any ) - // ( extensionID: ~oid, ? critical: true, extensionValue: bytes ) + ( extensionID: int, extensionValue: any ) + // ( extensionID: ~oid, ? critical: true, extensionValue: bytes ) ) + +SubjectAltName = GeneralNames / text +GeneralNames = [ + GeneralName ] +GeneralName = ( GeneralNameType: int, GeneralNameValue: any ) \ No newline at end of file diff --git a/rust/c509-certificate/examples/cli/main.rs b/rust/c509-certificate/examples/cli/main.rs index e636b76c89c..ddc750f8e78 100644 --- a/rust/c509-certificate/examples/cli/main.rs +++ b/rust/c509-certificate/examples/cli/main.rs @@ -98,7 +98,7 @@ impl Cli { struct C509Json { /// Indicate whether the certificate is self-signed. self_signed: bool, - /// Optional certificate type, if not provided, set to 0 as self-signed. + /// Optional certificate type, if not provided, set to 2 as self-signed. certificate_type: Option, /// Optional serial number of the certificate, /// if not provided, a random number will be generated. @@ -234,7 +234,7 @@ fn validate_certificate_type( ) -> anyhow::Result<()> { if self_signed && certificate_type.unwrap_or(SELF_SIGNED_INT) != SELF_SIGNED_INT { return Err(anyhow::anyhow!( - "Certificate type must be 0 if self-signed is true" + "Certificate type must be {SELF_SIGNED_INT} if self-signed is true" )); } Ok(()) @@ -264,7 +264,7 @@ fn parse_or_default_date(date_option: Option, default: u64) -> Result Ok(default), } diff --git a/rust/c509-certificate/src/algorithm_identifier.rs b/rust/c509-certificate/src/algorithm_identifier.rs index 1d2e8c26644..c30d7d32bf7 100644 --- a/rust/c509-certificate/src/algorithm_identifier.rs +++ b/rust/c509-certificate/src/algorithm_identifier.rs @@ -1,14 +1,14 @@ //! C509 Algorithm Identifier //! //! This module handle the `AlgorithmIdentifier` type where OID does not fall into the -//! table. +//! registry table. //! //! ```cddl //! AlgorithmIdentifier = int / ~oid / [ algorithm: ~oid, parameters: bytes ] //! ``` //! //! **Note** `AlgorithmIdentifier` that have the same OID with different parameters are -//! not implemented yet. +//! not supported yet. //! //! For more information about `AlgorithmIdentifier`, //! visit [C509 Certificate](https://datatracker.ietf.org/doc/draft-ietf-cose-cbor-encoded-cert/11/) diff --git a/rust/c509-certificate/src/attributes/attribute.rs b/rust/c509-certificate/src/attributes/attribute.rs index 60da994d00f..5eb871fd9e8 100644 --- a/rust/c509-certificate/src/attributes/attribute.rs +++ b/rust/c509-certificate/src/attributes/attribute.rs @@ -5,6 +5,13 @@ //! ( attributeType: ~oid, attributeValue: bytes ) // //! ``` //! +//! In some case attributeValue can have multiple values. +//! +//! ```cddl +//! Attributes = ( attributeType: int, attributeValue: [+text] ) // +//! ( attributeType: ~oid, attributeValue: [+bytes] ) +//! ``` +//! //! For more information about Attribute, //! visit [C509 Certificate](https://datatracker.ietf.org/doc/draft-ietf-cose-cbor-encoded-cert/11/) @@ -145,7 +152,7 @@ impl Decode<'_, ()> for Attribute { let oid = get_oid_from_int(i).map_err(minicbor::decode::Error::message)?; Attribute::new(oid.clone()) } else { - // Handle unwrapped CBOR OID or CBOR PEN + // Handle unwrapped CBOR OID let c509_oid: C509oid = d.decode()?; Attribute::new(c509_oid.oid().clone()) }; diff --git a/rust/c509-certificate/src/attributes/mod.rs b/rust/c509-certificate/src/attributes/mod.rs index ef4dd5a8fb4..d56ee25a245 100644 --- a/rust/c509-certificate/src/attributes/mod.rs +++ b/rust/c509-certificate/src/attributes/mod.rs @@ -7,7 +7,7 @@ //! //! Use case: //! ```cddl -//! SubjectDirectoryAttributes = [+Attributes] +//! SubjectDirectoryAttributes = [+Attributes] //! ``` //! //! For more information about `Attributes`, diff --git a/rust/c509-certificate/src/cert_tbs.rs b/rust/c509-certificate/src/cert_tbs.rs index c909c53ae17..fb80182ed8a 100644 --- a/rust/c509-certificate/src/cert_tbs.rs +++ b/rust/c509-certificate/src/cert_tbs.rs @@ -1,4 +1,4 @@ -//! To Be Sign Certificate (TBS Certificate) use to construct a C509 certificate. +//! C509 certificate To Be Sign Certificate (TBS Certificate) use minicbor::{encode::Write, Decode, Decoder, Encode, Encoder}; use serde::{Deserialize, Serialize}; @@ -184,9 +184,10 @@ impl Decode<'_, ()> for TbsCert { // ------------------Test---------------------- // Notes -// - Test is modified to match the current encode and decode where `subject_public_key` -// doesn't support -// special case for rsaEncryption and id-ecPublicKey. +// - The test from https://datatracker.ietf.org/doc/draft-ietf-cose-cbor-encoded-cert/11/ +// currently uses `subject_public_key` id-ecPublicKey, which has special encoding and +// decoding that this crate does not yet support. Hence, this test has +// been modified to align with the current encoding and decoding. // - Currently support natively signed c509 certificate, so all text strings // are UTF-8 encoded and all attributeType SHALL be non-negative // - Some Extension values are not supported yet. diff --git a/rust/c509-certificate/src/extensions/mod.rs b/rust/c509-certificate/src/extensions/mod.rs index 1f5ac45801e..a93eff2ca02 100644 --- a/rust/c509-certificate/src/extensions/mod.rs +++ b/rust/c509-certificate/src/extensions/mod.rs @@ -1,11 +1,10 @@ -//! C509 Extension as a part of `TBSCertificate` used in C509 Certificate. +//! C509 Extensions //! //! Extension fallback of C509 OID extension -//! Given OID if not found in the registered OID table, it will be encoded as an unwrapped -//! OID. +//! Given OID, if it is found in the registered OID table, int value of the +//! associated OID will be used, if not, it will be encoded as an unwrapped OID (~oid). //! //! ```cddl -//! Extensions and Extension can be encoded as the following: //! Extensions = [ * Extension ] / int //! Extension = ( extensionID: int, extensionValue: any ) // //! ( extensionID: ~oid, ? critical: true, diff --git a/rust/c509-certificate/src/general_names/general_name.rs b/rust/c509-certificate/src/general_names/general_name.rs index 98b10bd9835..9cce5cc59df 100644 --- a/rust/c509-certificate/src/general_names/general_name.rs +++ b/rust/c509-certificate/src/general_names/general_name.rs @@ -1,5 +1,9 @@ //! C509 General Name //! +//! ```cddl +//! GeneralName = ( GeneralNameType : int, GeneralNameValue : any ) +//! ``` +//! //! For more information about `GeneralName`, //! visit [C509 Certificate](https://datatracker.ietf.org/doc/draft-ietf-cose-cbor-encoded-cert/11/) diff --git a/rust/c509-certificate/src/general_names/mod.rs b/rust/c509-certificate/src/general_names/mod.rs index a36530333e6..86f6e3488a4 100644 --- a/rust/c509-certificate/src/general_names/mod.rs +++ b/rust/c509-certificate/src/general_names/mod.rs @@ -1,5 +1,9 @@ //! C509 General Names //! +//! ```cddl +//! GeneralNames = [ + GeneralName ] +//! ``` +//! //! For more information about `GeneralNames`, //! visit [C509 Certificate](https://datatracker.ietf.org/doc/draft-ietf-cose-cbor-encoded-cert/11/) diff --git a/rust/c509-certificate/src/issuer_sig_algo/mod.rs b/rust/c509-certificate/src/issuer_sig_algo/mod.rs index ce31e8b23fd..3fb049d2fae 100644 --- a/rust/c509-certificate/src/issuer_sig_algo/mod.rs +++ b/rust/c509-certificate/src/issuer_sig_algo/mod.rs @@ -1,9 +1,12 @@ -//! C509 Issuer Signature Algorithm as a part of `TBSCertificate` used in C509 +//! C509 Issuer Signature Algorithm //! Certificate. //! //! ```cddl //! issuerSignatureAlgorithm: AlgorithmIdentifier //! ``` +//! +//! For more information about `issuerSignatureAlgorithm`, +//! visit [C509 Certificate](https://datatracker.ietf.org/doc/draft-ietf-cose-cbor-encoded-cert/11/) mod data; diff --git a/rust/c509-certificate/src/lib.rs b/rust/c509-certificate/src/lib.rs index 9bda6002151..b60c0cade77 100644 --- a/rust/c509-certificate/src/lib.rs +++ b/rust/c509-certificate/src/lib.rs @@ -2,7 +2,11 @@ //! //! This crate provides a functionality for generating C509 Certificate. //! -//! ## C509 certificate contains 2 parts +//! Please refer to the [C509 Certificate](https://datatracker.ietf.org/doc/draft-ietf-cose-cbor-encoded-cert/11/) for more information. +//! +//! ## C509 certificate structure +//! +//! A C509 certificate is a CBOR encoded X.509 certificate. It consists of two main parts: //! 1. `TBSCertificate` //! 2. `issuerSignatureValue` //! @@ -13,27 +17,29 @@ //! # TBS Certificate //! //! The To Be Sign Certificate contains the following fields: -//! * c509CertificateType: A certificate type, whether 0 a natively signed C509 -//! certificate following X.509 v3 or 1 a CBOR re-encoded X.509 v3 DER certificate. +//! * c509CertificateType: A certificate type, where 2 indicates a natively signed C509 +//! certificate following X.509 v3 or 3 indicates CBOR re-encoded X.509 v3 DER +//! certificate. //! * certificateSerialNumber: A unique serial number for the certificate. -//! * issuer: The entity that issued the certificate. +//! * subjectPublicKeyAlgorithm: Specifies the cryptographic algorithm used for the +//! `subjectPublicKey`. +//! * issuer: The entity that issued the certificate. In the case of a self-signed +//! certificate, the issuer is identical to the subject. //! * validityNotBefore: The duration for which the Certificate Authority (CA) //! guarantees it will retain information regarding the certificate's status on which //! the period begins. //! * validityNotAfter: The duration for which the Certificate Authority (CA) //! guarantees it will retain information regarding the certificate's status on which -//! the period ends. +//! the period ends. This can be set to no expiry date. //! * subject: The entity associated with the public key stored in the subject public //! key field. -//! * subjectPublicKeyAlgorithm: The algorithm that the public key is used. //! * subjectPublicKey: The public key of the subject. //! * extensions: A list of extensions defined for X.509 v3 certificate, providing //! additional attributes for users or public keys, and for managing relationships //! between Certificate Authorities (CAs). //! * issuerSignatureAlgorithm: The algorithm used to sign the certificate (must be the //! algorithm uses to create `IssuerSignatureValue`). -//! -//! Please refer to the [C509 Certificate](https://datatracker.ietf.org/doc/draft-ietf-cose-cbor-encoded-cert/11/) for more information. +// use anyhow::anyhow; use c509::C509; @@ -68,7 +74,7 @@ pub mod wasm_binding; /// /// # Errors /// -/// Returns an error if tne data cannot be converted to CBOR bytes. +/// Returns an error if the generated data is invalid. pub fn generate(tbs_cert: &TbsCert, private_key: Option<&PrivateKey>) -> anyhow::Result> { // Encode the TbsCert diff --git a/rust/c509-certificate/src/name/mod.rs b/rust/c509-certificate/src/name/mod.rs index 78d1c404e36..e385926f7d6 100644 --- a/rust/c509-certificate/src/name/mod.rs +++ b/rust/c509-certificate/src/name/mod.rs @@ -1,7 +1,7 @@ //! C509 type Name //! //! Currently only support natively signed c509 certificate, so all text strings -//! are UTF-8 encoded and all attributeType should be non-negative. +//! are UTF-8 encoded and all attributeType should be positive. //! //! ```cddl //! Name = [ * Attribute ] / text / bytes diff --git a/rust/c509-certificate/src/oid.rs b/rust/c509-certificate/src/oid.rs index 52ba8e37781..a3f45be75d7 100644 --- a/rust/c509-certificate/src/oid.rs +++ b/rust/c509-certificate/src/oid.rs @@ -21,7 +21,8 @@ use crate::{ pub struct C509oidRegistered { /// The `C509oid`. c509_oid: C509oid, - /// The registration table. + /// The registration lookup table for associated int to OID. + /// Each C509 field or type can have different registration table. registration_table: &'static IntegerToOidTable, } diff --git a/rust/c509-certificate/src/subject_pub_key_algo/mod.rs b/rust/c509-certificate/src/subject_pub_key_algo/mod.rs index 380b2675196..b3d923bd1c7 100644 --- a/rust/c509-certificate/src/subject_pub_key_algo/mod.rs +++ b/rust/c509-certificate/src/subject_pub_key_algo/mod.rs @@ -1,10 +1,12 @@ -//! C509 Issuer Signature Algorithm as a part of `TBSCertificate` used in C509 +//! C509 Issuer Signature Algorithm //! Certificate. //! //! ```cddl //! subjectPublicKeyAlgorithm: AlgorithmIdentifier //! ``` - +//! +//! For more information about `subjectPublicKeyAlgorithm`, +//! visit [C509 Certificate](https://datatracker.ietf.org/doc/draft-ietf-cose-cbor-encoded-cert/11/) // cspell: words spka mod data;