Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -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 )
6 changes: 3 additions & 3 deletions rust/c509-certificate/examples/cli/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<u8>,
/// Optional serial number of the certificate,
/// if not provided, a random number will be generated.
Expand Down Expand Up @@ -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(())
Expand Down Expand Up @@ -264,7 +264,7 @@ fn parse_or_default_date(date_option: Option<String>, default: u64) -> Result<u6
.try_into()
.map_err(|_| anyhow::anyhow!("Timestamp is invalid"))
})?
.map_err(|e| anyhow::anyhow!(format!("Failed to parse date {date}: {e}",)))
.map_err(|e| anyhow::anyhow!("Failed to parse date {date}: {e}"))
},
None => Ok(default),
}
Expand Down
4 changes: 2 additions & 2 deletions rust/c509-certificate/src/algorithm_identifier.rs
Original file line number Diff line number Diff line change
@@ -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/)
Expand Down
9 changes: 8 additions & 1 deletion rust/c509-certificate/src/attributes/attribute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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/)

Expand Down Expand Up @@ -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())
};
Expand Down
2 changes: 1 addition & 1 deletion rust/c509-certificate/src/attributes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
//!
//! Use case:
//! ```cddl
//! SubjectDirectoryAttributes = [+Attributes]
//! SubjectDirectoryAttributes = [+Attributes]
//! ```
//!
//! For more information about `Attributes`,
Expand Down
9 changes: 5 additions & 4 deletions rust/c509-certificate/src/cert_tbs.rs
Original file line number Diff line number Diff line change
@@ -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};
Expand Down Expand Up @@ -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.
Expand Down
7 changes: 3 additions & 4 deletions rust/c509-certificate/src/extensions/mod.rs
Original file line number Diff line number Diff line change
@@ -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,
Expand Down
4 changes: 4 additions & 0 deletions rust/c509-certificate/src/general_names/general_name.rs
Original file line number Diff line number Diff line change
@@ -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/)

Expand Down
4 changes: 4 additions & 0 deletions rust/c509-certificate/src/general_names/mod.rs
Original file line number Diff line number Diff line change
@@ -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/)

Expand Down
5 changes: 4 additions & 1 deletion rust/c509-certificate/src/issuer_sig_algo/mod.rs
Original file line number Diff line number Diff line change
@@ -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;

Expand Down
24 changes: 15 additions & 9 deletions rust/c509-certificate/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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`
//!
Expand All @@ -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;
Expand Down Expand Up @@ -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<Vec<u8>> {
// Encode the TbsCert
Expand Down
2 changes: 1 addition & 1 deletion rust/c509-certificate/src/name/mod.rs
Original file line number Diff line number Diff line change
@@ -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
Expand Down
3 changes: 2 additions & 1 deletion rust/c509-certificate/src/oid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}

Expand Down
6 changes: 4 additions & 2 deletions rust/c509-certificate/src/subject_pub_key_algo/mod.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down