diff --git a/docs/release-notes.md b/docs/release-notes.md index fcac31fe5..891dcf77f 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -24,7 +24,7 @@ An `AssetType` assertion is now supported. ### C2PA v2 claims -**NOTE**: The library now supports [C2PA v2 claims](https://c2pa.org/specifications/specifications/2.2/specs/C2PA_Specification.html#_claims) by default. V2 claims have many new checks and status codes. Additionally: +**NOTE**: The library now supports [C2PA v2 claims](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_claims) by default. V2 claims have many new checks and status codes. Additionally: - The `title()` and `format()` methods of both `Manifest` and `Ingredient` objects now return an `Option` because in v2 claims, `title` is optional and `format` does not exist. - The first `action` must be `c2pa.created` or `c2pa.opened` (which requires an ingredient). diff --git a/sdk/src/assertions/actions.rs b/sdk/src/assertions/actions.rs index 75d1dd5c7..2d481316d 100644 --- a/sdk/src/assertions/actions.rs +++ b/sdk/src/assertions/actions.rs @@ -32,9 +32,7 @@ pub const INGREDIENT_IDS: &str = "ingredientIds"; /// Description of the source of an asset. /// -/// The full list of possible digital source types are found below: -/// -/// +/// The digital source type must be either a value from the [IPTC Digital Source Types](https://cv.iptc.org/newscodes/digitalsourcetype) or a C2PA-specific value as given in [the C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_digital_source_type). #[non_exhaustive] #[derive(Deserialize, Serialize, Clone, Debug, PartialEq)] #[cfg_attr(feature = "json_schema", derive(JsonSchema))] @@ -43,7 +41,7 @@ pub enum DigitalSourceType { #[serde(alias = "empty", rename = "http://c2pa.org/digitalsourcetype/empty")] Empty, /// Data that is the result of algorithmically using a model derived from sampled content and data. - /// Differs from trainedAlgorithmicMedia in that + /// Differs from [IPTC Digital Source Type](http://cv.iptc.org/newscodes/digitalsourcetype/) `trainedAlgorithmicMedia` in that /// the result isn’t a media type (e.g., image or video) but is a data format (e.g., CSV, pickle). #[serde( alias = "trainedAlgorithmicData", @@ -326,7 +324,7 @@ pub struct ActionParameters { /// along with possible other information such as what software performed /// the action. /// -/// See . +/// See [Action - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_actions). #[cfg_attr(feature = "json_schema", derive(JsonSchema))] #[derive(Deserialize, Serialize, Clone, Debug, Default, PartialEq)] pub struct Action { @@ -493,7 +491,7 @@ impl Action { /// Returns the list of related actions. /// /// This is only present in C2PA v2. - /// See . + /// See [Related actions - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_related_actions). pub fn related(&self) -> Option<&[Action]> { self.related.as_deref() } @@ -501,7 +499,7 @@ impl Action { /// Returns the reason why this action was performed. /// /// This is only present in C2PA v2. - /// See . + /// See [Reason - C2PA Technical Specificaiton](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_reason). pub fn reason(&self) -> Option<&str> { self.reason.as_deref() } @@ -606,13 +604,13 @@ impl Action { /// Sets the description of the action. /// /// This is only present in the v2 actions assertion. - /// See + /// See [Actions - C2PA Technical Specification](ttps://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_actions). pub fn set_description>(mut self, description: S) -> Self { self.description = Some(description.into()); self } - /// Set a digitalSourceType URI as defined at . + /// Set a digitalSourceType URI as defined at [Digital Source Type - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_digital_source_type). pub fn set_source_type>(mut self, source_type: T) -> Self { self.source_type = Some(source_type.into()); self @@ -621,7 +619,7 @@ impl Action { /// Sets the list of related actions. /// /// This is only present in C2PA v2. - /// See . + /// See [Related actions - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_related_actions). pub fn set_related(mut self, related: Option<&Vec>) -> Self { self.related = related.cloned(); self @@ -630,7 +628,7 @@ impl Action { /// Sets the reason why this action was performed. /// /// This is only present in C2PA v2. - /// See . + /// See [Related actions - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_reason). pub fn set_reason>(mut self, reason: S) -> Self { self.reason = Some(reason.into()); self @@ -746,7 +744,7 @@ impl ActionTemplate { /// what took place on the asset, when it took place, along with possible /// other information such as what software performed the action. /// -/// See . +/// See [Actions - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_actions) #[derive(Deserialize, Serialize, Debug, PartialEq)] #[non_exhaustive] pub struct Actions { @@ -773,7 +771,7 @@ pub struct Actions { impl Actions { /// Label prefix for an [`Actions`] assertion. /// - /// See . + /// See [Actions - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_actions) pub const LABEL: &'static str = labels::ACTIONS; pub const LABEL_VERSIONED: &'static str = "c2pa.actions.v2"; pub const VERSION: Option = Some(ASSERTION_CREATION_VERSION); diff --git a/sdk/src/assertions/assertion_metadata.rs b/sdk/src/assertions/assertion_metadata.rs index ec90aa2b8..346a3f95a 100644 --- a/sdk/src/assertions/assertion_metadata.rs +++ b/sdk/src/assertions/assertion_metadata.rs @@ -54,7 +54,7 @@ pub struct AssertionMetadata { impl AssertionMetadata { /// Label prefix for an assertion metadata assertion. /// - /// See . + /// See [Metadata About Assertions - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_metadata_about_assertions). pub const LABEL: &'static str = labels::ASSERTION_METADATA; pub fn new() -> Self { @@ -330,7 +330,7 @@ pub enum ReviewCode { /// A rating on an Assertion. /// -/// See . +/// See [C2PA Specification - Review Ratings](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_review_ratings). #[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)] #[cfg_attr(feature = "json_schema", derive(JsonSchema))] pub struct ReviewRating { diff --git a/sdk/src/assertions/asset_reference.rs b/sdk/src/assertions/asset_reference.rs index 2156f3a31..8efbc21cf 100644 --- a/sdk/src/assertions/asset_reference.rs +++ b/sdk/src/assertions/asset_reference.rs @@ -25,7 +25,7 @@ use crate::{ /// This assertion contains a list of references, each one declaring a location expressed as a URI and /// optionally a description. The URI may be either a single asset or it may reference a directory. /// -/// +/// See [Asset reference - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_asset_reference). #[derive(Deserialize, Serialize, Debug, PartialEq)] pub struct AssetReference { pub references: Vec, diff --git a/sdk/src/assertions/asset_types.rs b/sdk/src/assertions/asset_types.rs index 758ff896e..c2a790e90 100644 --- a/sdk/src/assertions/asset_types.rs +++ b/sdk/src/assertions/asset_types.rs @@ -106,7 +106,7 @@ pub struct AssetTypes { #[allow(dead_code)] impl AssetTypes { - /// See . + /// See [Asset type - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_asset_type). pub const LABEL: &'static str = labels::ASSET_TYPE; pub fn new(at: AssetType) -> Self { diff --git a/sdk/src/assertions/certificate_status.rs b/sdk/src/assertions/certificate_status.rs index 3a6611779..d7554b26b 100644 --- a/sdk/src/assertions/certificate_status.rs +++ b/sdk/src/assertions/certificate_status.rs @@ -35,7 +35,7 @@ pub struct CertificateStatus { impl CertificateStatus { /// Label prefix for a [`CertificateStatus`] assertion. /// - /// See . + /// See [certificate status assertion - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#certificate_status_assertion) pub const LABEL: &'static str = labels::CERTIFICATE_STATUS; pub fn new(ocsp_vals: Vec>) -> Self { diff --git a/sdk/src/assertions/creative_work.rs b/sdk/src/assertions/creative_work.rs index 28caea352..f33b1bf32 100644 --- a/sdk/src/assertions/creative_work.rs +++ b/sdk/src/assertions/creative_work.rs @@ -42,9 +42,9 @@ const CW_AUTHOR: &str = "author"; pub struct CreativeWork(SchemaDotOrg); impl CreativeWork { - /// Label prefix for a creative work assertion. + /// Label prefix for a creative work assertion. NOTE: This is deprecated. /// - /// See . + /// See [Creative_work assertion - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/1.4/specs/C2PA_Specification.html#_creative_work). NOTE: This is an old version of the spec. pub const LABEL: &'static str = labels::CREATIVE_WORK; pub fn new() -> CreativeWork { @@ -128,7 +128,7 @@ pub mod tests { const IDENTITY_URI: &str = "https://some_identity/service/"; // example CreativeWork from - // https://c2pa.org/specifications/specifications/1.0/specs/C2PA_Specification.html#_claim_review + // https://spec.c2pa.org/specifications/specifications/1.0/specs/C2PA_Specification.html#_claim_review const SAMPLE_CREATIVE_WORK: &str = r#"{ "@context": [ "http://schema.org/", diff --git a/sdk/src/assertions/embedded_data.rs b/sdk/src/assertions/embedded_data.rs index d26f657b4..d4dcffa80 100644 --- a/sdk/src/assertions/embedded_data.rs +++ b/sdk/src/assertions/embedded_data.rs @@ -24,7 +24,7 @@ use crate::{ /// It replaces the old Thumbnail assertion type. /// The label is used to identify the type of data, and the content type specifies the format. /// The data is stored as a binary vector. -/// +/// [embedded_data - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_embedded_data) #[derive(Serialize)] pub struct EmbeddedData { pub label: String, diff --git a/sdk/src/assertions/ingredient.rs b/sdk/src/assertions/ingredient.rs index 6512f7a06..b2bedb449 100644 --- a/sdk/src/assertions/ingredient.rs +++ b/sdk/src/assertions/ingredient.rs @@ -97,7 +97,7 @@ impl Serialize for Ingredient { impl Ingredient { /// Label prefix for an ingredient assertion. /// - /// See . + /// See [ingredient_assertion - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#ingredient_assertion) pub const LABEL: &'static str = labels::INGREDIENT; pub fn new(title: &str, format: &str, instance_id: &str, document_id: Option<&str>) -> Self { diff --git a/sdk/src/assertions/labels.rs b/sdk/src/assertions/labels.rs index 8d7b00c41..17a325efb 100644 --- a/sdk/src/assertions/labels.rs +++ b/sdk/src/assertions/labels.rs @@ -17,171 +17,169 @@ //! //! These constants do not include version suffixes. //! -//! See . +//! See [C2PA Standard assertions - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_c2pa_standard_assertions). use std::sync::LazyLock; use regex::Regex; /// Label prefix for a claim assertion. /// -/// See . +/// See [Claims- C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_claims). pub const CLAIM: &str = "c2pa.claim"; /// Label prefix for an assertion metadata assertion. /// -/// See . +/// See [Metadata about assertions - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_metadata_about_assertions). pub const ASSERTION_METADATA: &str = "c2pa.assertion.metadata"; /// Label prefix for a data hash assertion. /// -/// See . +/// See [Data hash - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_data_hash). pub const DATA_HASH: &str = "c2pa.hash.data"; /// Label prefix for a box hash assertion. /// -/// See . +/// See [General boxes hash - C2PA Technical Specification](https://spec.c2pa.org/specifications/C2PA_Specification.html#_general_boxes_hash). pub const BOX_HASH: &str = "c2pa.hash.boxes"; /// Label prefix for a BMFF-based hash assertion. /// -/// See . +/// See [BMFF-based hash - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_bmff_based_hash). pub const BMFF_HASH: &str = "c2pa.hash.bmff"; /// Label prefix for a collection hash assertion. /// -/// See . +/// See [Collection data hash - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_collection_data_hash). pub const COLLECTION_HASH: &str = "c2pa.hash.collection.data"; /// Label prefix for a soft binding assertion. /// -/// See . +/// See [Soft binding - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_soft_binding_2). pub const SOFT_BINDING: &str = "c2pa.soft-binding"; /// Label prefix for a cloud data assertion. /// -/// See . +/// See [Cloud data - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_cloud_data). pub const CLOUD_DATA: &str = "c2pa.cloud-data"; /// Label prefix for a thumbnail assertion. /// -/// See . +/// See [Thumbnail - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_thumbnail). pub const THUMBNAIL: &str = "c2pa.thumbnail"; /// Label prefix for a claim thumbnail assertion. /// -/// See . +/// See [Thumbnail - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_thumbnail). pub const CLAIM_THUMBNAIL: &str = "c2pa.thumbnail.claim"; /// Label prefix for an ingredient thumbnail assertion. /// -/// See . +/// See [Thumbnail - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_thumbnail). pub const INGREDIENT_THUMBNAIL: &str = "c2pa.thumbnail.ingredient"; /// Label prefix for a JPEG claim thumbnail assertion. /// -/// See . +/// See [Thumbnail - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_thumbnail). pub const JPEG_CLAIM_THUMBNAIL: &str = "c2pa.thumbnail.claim.jpeg"; /// Label prefix for a JPEG ingredient thumbnail assertion. /// -/// See . +/// See [Thumbnail - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_thumbnail). pub const JPEG_INGREDIENT_THUMBNAIL: &str = "c2pa.thumbnail.ingredient.jpeg"; /// Label prefix for a PNG claim thumbnail assertion. /// -/// See . +/// See [Thumbnail - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_thumbnail). pub const PNG_CLAIM_THUMBNAIL: &str = "c2pa.thumbnail.claim.png"; /// Label prefix for a PNG ingredient thumbnail assertion. /// -/// See . +/// See [Thumbnail - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_thumbnail). pub const PNG_INGREDIENT_THUMBNAIL: &str = "c2pa.thumbnail.ingredient.png"; /// Label prefix for a SVG claim thumbnail assertion. /// -/// See . +/// See [Thumbnail - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_thumbnail). pub const SVG_CLAIM_THUMBNAIL: &str = "c2pa.thumbnail.claim.svg"; /// Label prefix for a SVG ingredient thumbnail assertion. /// -/// See . +/// See [Thumbnail - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_thumbnail). pub const SVG_INGREDIENT_THUMBNAIL: &str = "c2pa.thumbnail.ingredient.svg"; /// Label prefix for an actions assertion. /// -/// See . +/// See [Actions - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_actions). pub const ACTIONS: &str = "c2pa.actions"; /// Label prefix for an ingredient assertion. /// -/// See . +/// See [Ingredient - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_ingredient). pub const INGREDIENT: &str = "c2pa.ingredient"; /// Label prefix for a depthmap assertion. /// -/// See . +/// See [Depthmap - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_depthmap). pub const DEPTHMAP: &str = "c2pa.depthmap"; /// Label prefix for a asset type assertion. /// -/// See . +/// See [Asset type - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_asset_type). pub const ASSET_TYPE: &str = "c2pa.asset-type"; /// Label prefix for a embedded data assertion. /// -/// See . +/// See [Embedded data - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_embedded_data). pub const EMBEDDED_DATA: &str = "c2pa.embedded-data"; /// Label prefix for a Icon assertion. /// -/// See . +/// See [Generator info map - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_generator_info_map). pub const ICON: &str = "c2pa.icon"; /// Label prefix for a GDepth assertion. /// Label prefix for a GDepth depthmap assertion. /// -/// See . +/// See [GDepth Depthmap - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_gdepth_depthmap). pub const DEPTHMAP_GDEPTH: &str = "c2pa.depthmap.GDepth"; /// Label prefix for an EXIF information assertion. /// Hidden because it's now part of standard metadata assertions. /// -/// See . +/// See [EXIF information - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_exif_information). #[doc(hidden)] pub const EXIF: &str = "stds.exif"; /// Label prefix for an IPTC photo metadata assertion. /// Hidden because it's now part of standard metadata assertions. /// -/// See . +/// See [IPTC photo metadata - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_iptc_photo_metadata). #[doc(hidden)] pub const IPTC_PHOTO_METADATA: &str = "stds.iptc.photo-metadata"; /// Label prefix for any assertion based on a schema.org grammar. /// Hidden because it's now part of standard metadata assertions. /// -/// See . +/// See [Use of Schema.org - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_use_of_schema_org). #[doc(hidden)] pub const SCHEMA_ORG: &str = "schema.org"; /// Label prefix for a claim review assertion. /// -/// See . +/// See [Claim review - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_claim_review). pub const CLAIM_REVIEW: &str = "stds.schema-org.ClaimReview"; -/// Label prefix for a creative work assertion. -/// -/// See . +/// Label prefix for a creative work assertion. Deprecated. pub const CREATIVE_WORK: &str = "stds.schema-org.CreativeWork"; /// Label prefix for a timestamp assertion. /// -/// See . +/// See [Timestamp assertion - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#timestamp_assertion). pub const TIMESTAMP: &str = "c2pa.time-stamp"; /// Label prefix for a certificate status assertion. /// -/// See . +/// See [Certificate status assertion - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#certificate_status_assertion). pub const CERTIFICATE_STATUS: &str = "c2pa.certificate-status"; // Assertion store label @@ -192,31 +190,26 @@ pub(crate) const DATABOX_STORE: &str = "c2pa.databoxes"; /// Label prefix for asset reference assertion. /// -/// See . +/// See [Asset reference - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_asset_reference). pub const ASSET_REFERENCE: &str = "c2pa.asset-ref"; /// extension to indicate a multipart hash /// -/// See . +/// See [Multi asset hash - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_multi_asset_hash). pub const PART: &str = ".part"; /// Label prefix for a C2PA metadata assertion. /// -/// A C2PA metadata assertion can only be used for [specific metadata fields] +/// A [metadata assertion](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_metadata) +/// can only be used for [specific metadata fields](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#metadata_annex) /// as described in the C2PA Technical Specification and only if those fields /// are generated from a hardware or software source. -/// -/// See . -/// -/// [specific metadata fields]: https://spec.c2pa.org/specifications/specifications/2.2/specs/C2PA_Specification.html#metadata_annex pub const METADATA: &str = "c2pa.metadata"; -/// Label prefix for a [CAWG metadata assertion]. +/// Label prefix for a [CAWG metadata assertion](https://cawg.io/metadata/). /// -/// The CAWG metadata assertion is intended for human-generated metadata +/// The [CAWG metadata assertion](https://cawg.io/metadata/) is intended for human-generated metadata /// and may contain metadata from any documented schema. -/// -/// [CAWG metadata assertion]: https://cawg.io/metadata/ pub const CAWG_METADATA: &str = "cawg.metadata"; /// Array of all hash labels because they have special treatment @@ -310,7 +303,7 @@ pub fn base(label: &str) -> &str { /// Returns the version number, or 1 if no version suffix is present /// (since version 1 is the default and never explicitly included). /// -/// See . +/// See [versioning - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_versioning). /// /// # Examples /// diff --git a/sdk/src/assertions/metadata.rs b/sdk/src/assertions/metadata.rs index da0ae6a8a..965ef457e 100644 --- a/sdk/src/assertions/metadata.rs +++ b/sdk/src/assertions/metadata.rs @@ -31,7 +31,7 @@ const ASSERTION_CREATION_VERSION: usize = 1; ///of metadata fields. For `c2pa.metadata` assertions, only specific schemas and fields /// are allowed as defined in the C2PA specification. /// -/// +/// See [metadata_assertions - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_metadata_assertions) #[derive(Serialize, Deserialize, Debug, PartialEq)] pub struct Metadata { /// JSON-LD context mapping prefixes to namespace URIs. @@ -69,7 +69,7 @@ impl Metadata { /// Validates that each field in the assertion has a namespace within the '@context'. /// For 'c2pa.metadata' assertions, ensures only allowed fields are present. /// - /// See . + /// See [_c2pa_metadata_validation - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_c2pa_metadata_validation) /// # Returns /// * Returns `true` if the metadata assertion passes validation. pub fn is_valid(&self) -> bool { @@ -147,7 +147,7 @@ impl AssertionBase for Metadata { lazy_static! { /// The c2pa.metadata assertion shall only contain certain schemas. /// - /// See . + /// See [metadata_annex - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#metadata_annex) static ref ALLOWED_SCHEMAS: HashMap<&'static str, &'static str> = vec![ ("xmp", "http://ns.adobe.com/xap/1.0/"), ("xmpMM", "http://ns.adobe.com/xap/1.0/mm/"), @@ -176,7 +176,7 @@ lazy_static! { /// The c2pa.metadata assertion shall only contain certain fields. /// -/// See . +/// See [metadata_annex - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#metadata_annex) static ALLOWED_FIELDS: [&str; 292] = [ // xmp: "xmp:CreateDate", diff --git a/sdk/src/assertions/schema_org.rs b/sdk/src/assertions/schema_org.rs index 27046c3f1..e64f099d1 100644 --- a/sdk/src/assertions/schema_org.rs +++ b/sdk/src/assertions/schema_org.rs @@ -229,7 +229,7 @@ pub mod tests { const IDENTITY_URI: &str = "https://some_identity/service/"; // Example review rating from - // https://c2pa.org/specifications/specifications/1.0/specs/C2PA_Specification.html#_claim_review + // https://spec.c2pa.org/specifications/specifications/1.0/specs/C2PA_Specification.html#_claim_review const RATING: &str = r#"{ "@context": "http://schema.org", "@type": "ClaimReview", diff --git a/sdk/src/assertions/soft_binding.rs b/sdk/src/assertions/soft_binding.rs index f793bfb08..3fb98467f 100644 --- a/sdk/src/assertions/soft_binding.rs +++ b/sdk/src/assertions/soft_binding.rs @@ -10,7 +10,7 @@ use crate::{ /// The data structure used to store one or more soft bindings across some or all of the asset's content. /// -/// +/// See [Soft binding assertion - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#soft_binding_assertion). #[derive(Serialize, Deserialize, Debug, Default, PartialEq)] pub struct SoftBinding { /// A string identifying the soft binding algorithm and version of that algorithm used to compute the value, @@ -56,7 +56,7 @@ impl SoftBinding { /// Zero-filled bytes used for filling up space. /// /// This field is not applicable to `c2pa-rs` as it employs a single step processing approach to precompute assertion sizes, unlike the - /// "[Multiple Step Processing](https://spec.c2pa.org/specifications/specifications/2.2/specs/C2PA_Specification.html#_multiple_step_processing)" + /// "[Multiple Step Processing](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_multiple_step_processing)" /// approach described by the spec. pub fn pad(&self) -> &[u8] { &self.pad diff --git a/sdk/src/assertions/timestamp.rs b/sdk/src/assertions/timestamp.rs index 9ccdb5671..6110f2e93 100644 --- a/sdk/src/assertions/timestamp.rs +++ b/sdk/src/assertions/timestamp.rs @@ -36,7 +36,7 @@ pub struct TimeStamp(pub HashMap); impl TimeStamp { /// Label prefix for a [`TimeStamp`] assertion. /// - /// See . + /// See [Actions - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_actions). pub const LABEL: &'static str = labels::TIMESTAMP; /// Construct a new, empty [`TimeStamp`] assertion. diff --git a/sdk/src/asset_handlers/pdf.rs b/sdk/src/asset_handlers/pdf.rs index ce9e7f25d..699962e69 100644 --- a/sdk/src/asset_handlers/pdf.rs +++ b/sdk/src/asset_handlers/pdf.rs @@ -213,7 +213,7 @@ impl C2paPdf for Pdf { /// /// A `Vec<&[u8]>` is returned because it's possible for a PDF's manifests to be stored /// separately, due to PDF's "Incremental Update" feature. See the spec for more details: - /// + /// [embedding_manifests_into_pdfs - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/1.3/specs/C2PA_Specification.html#_embedding_manifests_into_pdfs) fn read_manifest_bytes(&self) -> Result>, Error> { let Some(id) = self.c2pa_file_spec_object_id() else { return Ok(None); diff --git a/sdk/src/builder.rs b/sdk/src/builder.rs index 8b83ff1f1..8da4b3d2e 100644 --- a/sdk/src/builder.rs +++ b/sdk/src/builder.rs @@ -388,10 +388,10 @@ pub struct Builder { /// In most cases, you create this from a JSON manifest definition. pub definition: ManifestDefinition, - /// Optional remote URL for the manifest + /// Optional remote URL for the manifest. pub remote_url: Option, - /// If true, the manifest store will not be embedded in the asset on sign + /// If true, the manifest store will not be embedded in the asset on sign. pub no_embed: bool, /// Base path to search for resources. @@ -523,13 +523,13 @@ impl Builder { /// Sets the [`BuilderIntent`] for this [`Builder`]. /// /// An intent lets the API know what kind of manifest to create. - /// Intents are `Create`, `Edit`, or `Update`. - /// This allows the API to check that you are doing the right thing. + /// and check that you are doing the right thing. /// It can also do things for you, like add parent ingredients from the source asset /// and automatically add required c2pa.created or c2pa.opened actions. - /// Create requires a `DigitalSourceType`. It is used for assets without a parent ingredient. - /// Edit requires a parent ingredient and is used for most assets that are being edited. - /// Update is a special case with many restrictions but is more compact than Edit. + /// Intents are `Create`, `Edit`, or `Update`: + /// - `Create` requires a `DigitalSourceType` and is used for assets without a parent ingredient. + /// - `Edit` requires a parent ingredient and is used for most assets that are being edited. + /// - `Update` is a special case with many restrictions but is more compact than `Edit`. /// # Arguments /// * `intent` - The [`BuilderIntent`] for this [`Builder`]. /// # Returns @@ -617,7 +617,7 @@ impl Builder { Ok(self) } - /// Returns a [Vec] of mime types that [c2pa-rs] is able to sign. + /// Returns a [Vec] of MIME types that the API is able to sign. pub fn supported_mime_types() -> Vec { jumbf_io::supported_builder_mime_types() } @@ -630,7 +630,17 @@ impl Builder { } /// Sets the [`ClaimGeneratorInfo`] for this [`Builder`]. - // TODO: Add example of a good ClaimGeneratorInfo. + /// + /// # Examples + /// + /// ``` + /// # use c2pa::{Builder, ClaimGeneratorInfo, Result}; + /// # fn main() -> Result<()> { + /// let mut builder = Builder::new(); + /// builder.set_claim_generator_info(ClaimGeneratorInfo::new("my_app")); + /// # Ok(()) + /// # } + /// ``` pub fn set_claim_generator_info(&mut self, claim_generator_info: I) -> &mut Self where I: Into, @@ -1560,7 +1570,7 @@ impl Builder { actions: &mut Actions, ) -> Result<()> { let settings = self.context.settings(); - // https://spec.c2pa.org/specifications/specifications/2.2/specs/C2PA_Specification.html#_mandatory_presence_of_at_least_one_actions_assertion + // https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_mandatory_presence_of_at_least_one_actions_assertion let auto_created = settings.builder.actions.auto_created_action.enabled; let auto_opened = settings.builder.actions.auto_opened_action.enabled; @@ -1633,7 +1643,7 @@ impl Builder { } } - // https://spec.c2pa.org/specifications/specifications/2.2/specs/C2PA_Specification.html#_relationship + // https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_relationship if settings.builder.actions.auto_placed_action.enabled { // Get a list of ingredient URIs referenced by "c2pa.placed" actions. let mut referenced_uris = HashSet::new(); diff --git a/sdk/src/context.rs b/sdk/src/context.rs index 16da30390..e5b239926 100644 --- a/sdk/src/context.rs +++ b/sdk/src/context.rs @@ -100,9 +100,9 @@ impl IntoSettings for serde_json::Value { /// /// Context replaces the global Settings pattern with a more flexible, thread-safe approach. /// It encapsulates: -/// - **Settings**: Configuration options for C2PA operations -/// - **HTTP Resolvers**: Customizable sync and async HTTP resolvers for fetching remote manifests -/// - **Signer**: The cryptographic signer used to sign manifests +/// - **Settings**: Configuration options for C2PA operations. +/// - **HTTP Resolvers**: Customizable sync and async HTTP resolvers for fetching remote manifests. +/// - **Signer**: The cryptographic signer used to sign manifests. /// /// # Creating a Signer /// @@ -135,7 +135,9 @@ impl IntoSettings for serde_json::Value { /// 2. **Custom Signer**: Use [`with_signer()`](Context::with_signer) to provide a custom signer /// directly. This is useful for HSMs, remote signing services, or custom signing logic. /// -/// # Usage with Builder and Reader +/// # Examples +/// +/// ## Usage with Builder and Reader /// /// Both [`Builder`](crate::Builder) and [`Reader`](crate::Reader) can be created with a Context: /// @@ -155,8 +157,6 @@ impl IntoSettings for serde_json::Value { /// # } /// ``` /// -/// # Examples -/// /// ## Basic usage with default settings /// /// ``` @@ -173,20 +173,6 @@ impl IntoSettings for serde_json::Value { /// # Ok(()) /// # } /// ``` -/// -/// ## Configure with TOML settings -/// -/// ``` -/// # use c2pa::{Context, Result}; -/// # fn main() -> Result<()> { -/// let toml = r#" -/// [verify] -/// verify_after_sign = true -/// "#; -/// let context = Context::new().with_settings(toml)?; -/// # Ok(()) -/// # } -/// ``` pub struct Context { settings: Settings, sync_resolver: SyncResolverState, diff --git a/sdk/src/crypto/cose/certificate_profile.rs b/sdk/src/crypto/cose/certificate_profile.rs index 744f60ee6..2f5f2b361 100644 --- a/sdk/src/crypto/cose/certificate_profile.rs +++ b/sdk/src/crypto/cose/certificate_profile.rs @@ -33,7 +33,7 @@ use crate::{ /// Verify that an end-entity X.509 certificate meets the requirements stated in /// [§14.5. X.509 Certificates]. /// -/// [§14.5. X.509 Certificates]: https://c2pa.org/specifications/specifications/2.1/specs/C2PA_Specification.html#x509_certificates +/// [§14.5. X.509 Certificates]: https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#x509_certificates pub fn check_end_entity_certificate_profile( certificate_der: &[u8], ctp: &CertificateTrustPolicy, @@ -75,7 +75,7 @@ pub fn check_end_entity_certificate_profile( /// Verify that an X.509 certificate meets the requirements stated in [§14.5.1, /// Certificate Profiles]. /// -/// [§14.5.1, Certificate Profiles]: https://c2pa.org/specifications/specifications/2.1/specs/C2PA_Specification.html#_certificate_profiles +/// [§14.5.1, Certificate Profiles]: https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_certificate_profiles pub fn check_certificate_profile( certificate_der: &[u8], ctp: &CertificateTrustPolicy, diff --git a/sdk/src/crypto/cose/certificate_trust_policy.rs b/sdk/src/crypto/cose/certificate_trust_policy.rs index 499a49fba..b648bba46 100644 --- a/sdk/src/crypto/cose/certificate_trust_policy.rs +++ b/sdk/src/crypto/cose/certificate_trust_policy.rs @@ -202,7 +202,7 @@ impl CertificateTrustPolicy { /// /// The function can be called multiple times to add multiple trust anchors. For example, /// the C2PA trust anchors and timestamping trust anchors can be added separately. - /// [§14.4.1, C2PA Signers]: + /// [§14.4.1, C2PA Signers]: pub fn add_trust_anchors( &mut self, trust_anchor_pems: &[u8], @@ -271,7 +271,7 @@ impl CertificateTrustPolicy { /// /// Lines that match neither format (PEM or hash) are ignored. /// - /// [§14.4.3, Private Credential Storage]: https://c2pa.org/specifications/specifications/2.1/specs/C2PA_Specification.html#_private_credential_storage + /// [§14.4.3, Private Credential Storage]: https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_private_credential_storage pub fn add_end_entity_credentials( &mut self, end_entity_cert_pems: &[u8], @@ -338,7 +338,7 @@ impl CertificateTrustPolicy { /// input or lines within the input such as comments or blank lines that can /// not be parsed as OIDs. /// - /// [§14.4.1, C2PA Signers]: https://c2pa.org/specifications/specifications/2.1/specs/C2PA_Specification.html#_c2pa_signers + /// [§14.4.1, C2PA Signers]: https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_c2pa_signers pub fn add_valid_ekus(&mut self, eku_oids: &[u8]) { let Ok(eku_oids) = std::str::from_utf8(eku_oids) else { return; diff --git a/sdk/src/crypto/cose/sign.rs b/sdk/src/crypto/cose/sign.rs index f1b6071ff..305a4a927 100644 --- a/sdk/src/crypto/cose/sign.rs +++ b/sdk/src/crypto/cose/sign.rs @@ -74,7 +74,7 @@ use crate::crypto::{ /// > * If multiple certificates are conveyed, a CBOR array of byte strings is /// > used, with each certificate being in its own byte string. /// -/// [§14.5, X.509 Certificates]: https://c2pa.org/specifications/specifications/2.1/specs/C2PA_Specification.html#x509_certificates +/// [§14.5, X.509 Certificates]: https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#x509_certificates /// [RFC 9360]: https://datatracker.ietf.org/doc/html/rfc9360 #[async_generic(async_signature( signer: &dyn AsyncRawSigner, @@ -271,7 +271,7 @@ pub enum CosePayload { /// > * If multiple certificates are conveyed, a CBOR array of byte strings is /// > used, with each certificate being in its own byte string. /// -/// [§14.5, X.509 Certificates]: https://c2pa.org/specifications/specifications/2.1/specs/C2PA_Specification.html#x509_certificates +/// [§14.5, X.509 Certificates]: https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#x509_certificates /// [RFC 9360]: https://datatracker.ietf.org/doc/html/rfc9360 #[async_generic(async_signature( signer: &dyn AsyncRawSigner, diff --git a/sdk/src/crypto/cose/time_stamp_storage.rs b/sdk/src/crypto/cose/time_stamp_storage.rs index b5a30ff91..58b496675 100644 --- a/sdk/src/crypto/cose/time_stamp_storage.rs +++ b/sdk/src/crypto/cose/time_stamp_storage.rs @@ -17,7 +17,7 @@ /// This is as defined in [§10.3.2.5.4, Storing the time-stamp], of version 2.1 /// of the C2PA Technical Specification. /// -/// [§10.3.2.5.4, Storing the time-stamp]: https://c2pa.org/specifications/specifications/2.1/specs/C2PA_Specification.html#_storing_the_time_stamp +/// [§10.3.2.5.4, Storing the time-stamp]: https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_storing_the_time_stamp /// [RFC 3161]: https://datatracker.ietf.org/doc/html/rfc3161 #[allow(non_camel_case_types)] // We choose to match the exact header names as used in the C2PA specification. #[derive(Copy, Clone, Debug, Eq, PartialEq)] @@ -29,7 +29,7 @@ pub enum TimeStampStorage { /// in reply from the TSA shall be stored as the value of the `val property /// of an element of `tstTokens`. /// - /// [Example 2, “CDDL for `tstContainer`”]: https://c2pa.org/specifications/specifications/2.1/specs/C2PA_Specification.html#tstContainer-CDDL + /// [Example 2, “CDDL for `tstContainer`”]: https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#tstContainer-CDDL V1_sigTst, /// v2 time-stamps shall be stored in a COSE unprotected header whose label @@ -45,7 +45,7 @@ pub enum TimeStampStorage { /// thus enabling the time-stamp to serve as a countersignature on the /// entire signature structure, including the actual certificate. /// - /// [Example 2, “CDDL for `tstContainer`”]: https://c2pa.org/specifications/specifications/2.1/specs/C2PA_Specification.html#tstContainer-CDDL + /// [Example 2, “CDDL for `tstContainer`”]: https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#tstContainer-CDDL /// [COSE Header parameter for RFC 3161 Time-Stamp Tokens Draft]: https://datatracker.ietf.org/doc/draft-ietf-cose-tsa-tst-header-parameter/ V2_sigTst2_CTT, } diff --git a/sdk/src/crypto/raw_signature/signing_alg.rs b/sdk/src/crypto/raw_signature/signing_alg.rs index b64f09d25..faafd531a 100644 --- a/sdk/src/crypto/raw_signature/signing_alg.rs +++ b/sdk/src/crypto/raw_signature/signing_alg.rs @@ -25,7 +25,7 @@ use serde::{Deserialize, Serialize}; /// > specification shall be generated using one of the digital signature /// > algorithms and key types listed as described in this section. /// -/// [§13.2, “Digital Signatures”]: https://c2pa.org/specifications/specifications/2.1/specs/C2PA_Specification.html#_digital_signatures +/// [§13.2, “Digital Signatures”]: https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_digital_signatures #[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] #[cfg_attr(feature = "json_schema", derive(JsonSchema))] pub enum SigningAlg { diff --git a/sdk/src/hashed_uri.rs b/sdk/src/hashed_uri.rs index ce9e6de21..00e831ac0 100644 --- a/sdk/src/hashed_uri.rs +++ b/sdk/src/hashed_uri.rs @@ -22,10 +22,8 @@ use crate::utils::DebugByteSlice; /// A `HashedUri` provides a reference to content available within the same /// manifest store. /// -/// This is described in [§8.3, URI References], of the C2PA Technical -/// Specification. -/// -/// [§8.3, URI References]: https://c2pa.org/specifications/specifications/2.1/specs/C2PA_Specification.html#_uri_references +/// This is described in [URI References in the C2PA Technical +/// Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_uri_references). #[derive(Clone, Deserialize, Eq, PartialEq, Serialize)] #[cfg_attr(feature = "json_schema", derive(JsonSchema))] pub struct HashedUri { diff --git a/sdk/src/jumbf/labels.rs b/sdk/src/jumbf/labels.rs index c84aba03a..8beffb8a9 100644 --- a/sdk/src/jumbf/labels.rs +++ b/sdk/src/jumbf/labels.rs @@ -15,7 +15,7 @@ //! Labels for JUMBF boxes as defined in C2PA Specification. //! -//! See . +//! See [C2PA box details - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_c2pa_box_details). use std::fmt::Display; @@ -24,37 +24,37 @@ use std::fmt::Display; /// This value should be used when possible, since it may contain a version suffix /// when needed to support a future version of the spec. /// -/// See . +/// See [C2PA box details - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_c2pa_box_details). pub const MANIFEST_STORE: &str = "c2pa"; /// Label for the C2PA assertion store box. /// -/// See . +/// See [C2PA box details - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_c2pa_box_details). pub const ASSERTIONS: &str = "c2pa.assertions"; /// Label for the C2PA claim box. /// -/// See . +/// See [C2PA box details - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_c2pa_box_details). pub const CLAIM: &str = "c2pa.claim"; /// Label for the C2PA claim signature box. /// -/// See . +/// See [C2PA box details - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_c2pa_box_details). pub const SIGNATURE: &str = "c2pa.signature"; /// Label for the credentials store box. /// -/// See . +/// See [Private credential_storage - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_private_credential_storage). pub const CREDENTIALS: &str = "c2pa.credentials"; /// Label for the DataBox box. /// -/// See . +/// See [Data boxes - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#__data_boxes). pub const DATABOX: &str = "c2pa.data"; /// Label for the DataBox store box. /// -/// See . +/// See [Data storage - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#__data_storage). pub const DATABOXES: &str = "c2pa.databoxes"; const JUMBF_PREFIX: &str = "self#jumbf"; diff --git a/sdk/src/lib.rs b/sdk/src/lib.rs index 3541a9c8f..d394eb66c 100644 --- a/sdk/src/lib.rs +++ b/sdk/src/lib.rs @@ -25,6 +25,8 @@ //! The library has a Builder/Reader API that focuses on simplicity //! and stream support. //! +//! For more information, see [CAI open source SDK - Rust library](https://opensource.contentauthenticity.org/docs/rust-sdk/) +//! //! # Examples //! //! ## Reading a manifest @@ -48,12 +50,40 @@ //! # } //! ``` //! +//! ## Reading a manifest using Context, Settings, and trust list +//! +//! Download the official [C2PA trust list](https://opensource.contentauthenticity.org/docs/conformance/trust-lists) PEM and +//! point `trust.trust_anchors` to its contents. +//! +//! ```no_run +//! use c2pa::{settings::Settings, Context, Reader, Result}; +//! +//! # fn main() -> Result<()> { +//! #[cfg(feature = "file_io")] +//! { +//! // Load the official C2PA trust list (PEM bundle) from a local file you downloaded. +//! let trust_pem = std::fs::read_to_string("path/to/C2PA-TRUST-LIST.pem")?; +//! +//! // Build Settings enabling certificate trust verification against the C2PA trust anchors. +//! let settings = Settings::new().with_value("trust.trust_anchors", trust_pem)?; +//! +//! // Create a Context with these settings and read an asset. +//! let context = Context::new().with_settings(settings)?; +//! let reader = Reader::from_context(context).with_file("path/to/asset.jpg")?; +//! +//! println!("{}", reader.json()); +//! } +//! # Ok(()) +//! # } +//! ``` +//! //! ## Adding a signed manifest to a file +//! //! ``` //! # use c2pa::Result; //! use std::io::Cursor; //! -//! use c2pa::{Builder, Context}; +//! use c2pa::{Builder, BuilderIntent, Context}; //! use serde::Serialize; //! use serde_json::json; //! @@ -70,6 +100,8 @@ //! // Build manifest. //! let mut builder = Builder::from_context(context) //! .with_definition(json!({"title": "Test"}))?; +//! // Use Edit intent so the parent ingredient is captured from the source stream. +//! builder.set_intent(BuilderIntent::Edit); //! builder.add_assertion("org.contentauth.test", &Test { my_tag: 42 })?; //! //! // Save with automatic signer from context (created from settings). @@ -80,33 +112,80 @@ //! # } //! ``` //! -//! # WASM +//! ## Adding an ingredient and signing //! -//! The only supported HTTP features for WASM (not WASI) are `http_reqwest`. This means WASM -//! only supports the async API for network requests. +//! ``` +//! # use c2pa::Result; +//! use std::io::Cursor; //! -//! ## WASI +//! use c2pa::{Builder, BuilderIntent, Context, DigitalSourceType}; +//! use serde_json::json; //! -//! The only supported HTTP features for WASI are `http_wasi` and `http_wstd`. The former -//! enables sync network requests, while the latter enables async network requests. +//! # fn main() -> Result<()> { +//! // Create context with signer configuration. +//! let context = +//! Context::new().with_settings(include_str!("../tests/fixtures/test_settings.toml"))?; +//! +//! // Build manifest. +//! let mut builder = Builder::from_context(context) +//! .with_definition(json!({"title": "Created Asset"}))?; +//! // Use Create intent with a source type and add a component ingredient. +//! builder.set_intent(BuilderIntent::Create(DigitalSourceType::DigitalCapture)); +//! +//! // Add an ingredient using Builder helper (no direct Ingredient struct). +//! let ingredient_json = json!({ +//! "title": "My ingredient", +//! "relationship": "componentOf" +//! }).to_string(); +//! let mut ingredient = std::fs::File::open("tests/fixtures/sample1.png")?; +//! builder.add_ingredient_from_stream(ingredient_json, "image/png", &mut ingredient)?; +//! +//! // Sign and embed using the context's signer. +//! let mut source = std::fs::File::open("tests/fixtures/C.jpg")?; +//! let mut dest = Cursor::new(Vec::new()); +//! let _c2pa_data = builder.save_to_stream("image/jpeg", &mut source, &mut dest)?; +//! # Ok(()) +//! # } +//! ``` //! //! # Features //! -//! You can enable any of the following features: +//! The crate provides the following features: //! -//! - **default_http** *(enabled by default)*: Enables default HTTP features for sync and async HTTP resolvers (`http_req`, `http_reqwest`, `http_wasi`, and `http_std`). -//! - **openssl** *(enabled by default)*: Use the vendored `openssl` implementation for cryptography. -//! - **rust_native_crypto**: Use Rust native cryptography. +//! These features are enabled by default: +//! - **default_http**: Enables default HTTP features for sync and async HTTP resolvers (`http_req`, `http_reqwest`, `http_wasi`, and `http_std`). +//! - **openssl**: Use the vendored `openssl` implementation for cryptography. +//! +//! One of `openssl` or `rust_native_crypto` must be enabled. +//! If both are enabled, `rust_native_crypto` is used. +//! +//! Other features: //! - **add_thumbnails**: Adds the [`image`](https://github.com/image-rs/image) crate to enable auto-generated thumbnails, if possible and enabled in settings. //! - **fetch_remote_manifests**: Fetches remote manifests over the network when no embedded manifest is present and that option is enabled in settings. //! - **file_io**: Enables APIs that use filesystem I/O. //! - **json_schema**: Adds the [`schemars`](https://github.com/GREsau/schemars) crate to derive JSON schemas for JSON-compatible structs. //! - **pdf**: Enables basic PDF read support. +//! - **rust_native_crypto**: Use Rust native cryptography. +//! +//! ## HTTP features +//! WARNING: These features are for advanced users. Most people can ignore them. +//! These features toggle compilation with different HTTP libraries, depending on the one you use. +//! Some are async-only and others are sync-only. +//! Disabling all of them will disable HTTP, speed up compilation, and decrease build size. +//! //! - **http_ureq**: Enables `ureq` for sync HTTP requests. //! - **http_reqwest**: Enables `reqwest` for async HTTP requests. //! - **http_reqwest_blocking**: Enables the `blocking` feature of `reqwest` for sync HTTP requests. //! - **http_wasi**: Enables `wasi` for sync HTTP requests on WASI. //! - **http_wstd**: Enables `wstd` for async HTTP requests on WASI. +//! +//! ## WASM and WASI +//! +//! For WASM the only supported HTTP feature is `http_reqwest`. This means WASM +//! only supports the async API for network requests. +//! +//! For WASI the only supported HTTP features are `http_wasi`, which enables sync network requests, +//! and `http_wstd` which enables async network requests. /// The internal name of the C2PA SDK. pub const NAME: &str = "c2pa-rs"; @@ -115,15 +194,13 @@ pub const NAME: &str = "c2pa-rs"; pub const VERSION: &str = env!("CARGO_PKG_VERSION"); // Public modules -/// The assertions module contains the definitions for the assertions that are part of the C2PA specification. +/// The `assertions` module contains the definitions for the assertions that are part of the C2PA specification. pub mod assertions; -pub mod context; - -/// The cose_sign module contains the definitions for the COSE signing algorithms. +/// The `cose_sign` module contains the definitions for the COSE signing algorithms. pub mod cose_sign; -/// The create_signer module contains the definitions for the signers that are part of the C2PA specification. +/// The `create_signer` module contains the definitions for the signers that are part of the C2PA specification. pub mod create_signer; /// Cryptography primitives. @@ -135,14 +212,14 @@ pub mod crypto; pub mod dynamic_assertion; // TODO: pub it when we expose in high-level API -/// The http module contains generic traits for configuring sync and async http resolvers. +/// The `http` module contains generic traits for configuring sync and async HTTP resolvers. pub(crate) mod http; /// The `identity` module provides support for the [CAWG identity assertion](https://cawg.io/identity). #[doc(hidden)] pub mod identity; -/// The jumbf_io module contains the definitions for the JUMBF data in assets. +/// The `jumbf_io` module contains the definitions for the JUMBF data in assets. pub mod jumbf_io; /// The settings module provides a way to configure the C2PA SDK. @@ -152,35 +229,39 @@ pub mod settings; #[doc(hidden)] pub mod status_tracker; -/// Contains the definitions for the validation results that are part of the C2PA specification. +/// The `validation_results` module contains the definitions for the validation results that are part of the C2PA specification. pub mod validation_results; -/// The validation_status module contains the definitions for the validation status that are part of the C2PA specification. +/// The `validation_status` module contains the definitions for the validation status that are part of the C2PA specification. #[doc(hidden)] pub mod validation_status; // Public exports +#[doc(inline)] pub use assertions::DigitalSourceType; #[doc(inline)] pub use assertions::Relationship; pub use builder::{Builder, BuilderIntent, ManifestDefinition}; pub use callback_signer::{CallbackFunc, CallbackSigner}; pub use claim_generator_info::ClaimGeneratorInfo; +#[doc(inline)] pub use context::Context; pub use crypto::raw_signature::SigningAlg; pub use error::{Error, Result}; -#[doc(inline)] +#[doc(hidden)] pub use external_manifest::ManifestPatchCallback; pub use hash_utils::{hash_stream_by_alg, HashRange}; pub use hashed_uri::HashedUri; pub use ingredient::Ingredient; #[cfg(feature = "file_io")] +#[doc(hidden)] pub use ingredient::{DefaultOptions, IngredientOptions}; pub use manifest::{Manifest, SignatureInfo}; pub use manifest_assertion::{ManifestAssertion, ManifestAssertionKind}; pub use reader::Reader; #[doc(inline)] pub use resource_store::{ResourceRef, ResourceStore}; +#[doc(inline)] pub use settings::Settings; pub use signer::{AsyncSigner, BoxedAsyncSigner, BoxedSigner, Signer}; pub use utils::mime::format_from_path; @@ -195,6 +276,7 @@ pub(crate) mod builder; pub(crate) mod callback_signer; pub(crate) mod claim; pub(crate) mod claim_generator_info; +pub(crate) mod context; pub(crate) mod cose_validator; pub(crate) mod error; pub(crate) mod external_manifest; diff --git a/sdk/src/reader.rs b/sdk/src/reader.rs index 164eec7c6..f89e8fcdb 100644 --- a/sdk/src/reader.rs +++ b/sdk/src/reader.rs @@ -165,11 +165,11 @@ impl Reader { /// # Examples /// /// ``` - /// # use c2pa::{Context, Reader, Result}; + /// # use c2pa::{Context, Reader, Result, Settings}; /// # use std::sync::Arc; /// # fn main() -> Result<()> { /// // Create a shared Context once - /// let ctx = Arc::new(Context::new().with_settings(r#"{"verify": {"verify_after_sign": true}}"#)?); + /// let ctx = Context::new().with_settings(Settings::new())?.into_shared(); /// /// // Share it across multiple Readers (even across threads!) /// let reader1 = Reader::from_shared_context(&ctx); @@ -186,7 +186,7 @@ impl Reader { } } - /// Add manifest store from a stream to the [`Reader`] + /// Add manifest store from a stream to the [`Reader`]. /// # Arguments /// * `format` - The format of the stream. MIME type or extension that maps to a MIME type. /// * `stream` - The stream to read from. Must implement the Read and Seek traits. @@ -223,9 +223,7 @@ impl Reader { /// # Returns /// A [`Reader`] for the manifest store. /// # Note - /// [CAWG identity] assertions require async calls for validation. - /// - /// [CAWG identity]: https://cawg.io/identity/ + /// [CAWG identity assertions](https://cawg.io/identity/) require async calls for validation. #[async_generic] pub fn from_stream(format: &str, stream: impl Read + Seek + MaybeSend) -> Result { // Legacy behavior: explicitly get global settings for backward compatibility @@ -267,9 +265,7 @@ impl Reader { /// ``` /// /// # Note - /// [CAWG identity] assertions require async calls for validation. - /// - /// [CAWG identity]: https://cawg.io/identity/ + /// [CAWG identity assertions](https://cawg.io/identity/) require async calls for validation. #[async_generic] pub fn with_file>(mut self, path: P) -> Result { let path = path.as_ref(); @@ -353,9 +349,7 @@ impl Reader { /// ``` /// /// # Note - /// [CAWG identity] assertions require async calls for validation. - /// - /// [CAWG identity]: https://cawg.io/identity/ + /// [CAWG identity assertions](https://cawg.io/identity/) require async calls for validation. #[cfg(feature = "file_io")] #[async_generic] pub fn from_file>(path: P) -> Result { @@ -806,20 +800,23 @@ impl Reader { /// The number of bytes written. /// # Errors /// Returns [`Error`] if the resource does not exist. - /// /// # Example /// ```no_run + /// use std::io::Cursor; + /// /// use c2pa::Reader; - /// #[cfg(feature = "file_io")] - /// { - /// let stream = std::io::Cursor::new(Vec::new()); - /// let reader = Reader::from_file("path/to/file.jpg").unwrap(); - /// let manifest = reader.active_manifest().unwrap(); - /// let uri = &manifest.thumbnail_ref().unwrap().identifier; - /// let bytes_written = reader.resource_to_stream(uri, stream).unwrap(); - /// } + /// // Create a Reader from an in-memory stream (placeholder bytes shown here). + /// let input = Cursor::new(Vec::new()); + /// let reader = Reader::from_stream("image/jpeg", input).unwrap(); + /// + /// // Get a resource identifier from the active manifest (e.g., a thumbnail). + /// let manifest = reader.active_manifest().unwrap(); + /// let uri = &manifest.thumbnail_ref().unwrap().identifier; + /// + /// // Write that resource to an output stream. + /// let out = Cursor::new(Vec::new()); + /// let bytes_written = reader.resource_to_stream(uri, out).unwrap(); /// ``` - /// TODO: Fix the example to not read from a file. pub fn resource_to_stream( &self, uri: &str, diff --git a/sdk/src/resource_store.rs b/sdk/src/resource_store.rs index bf921d7b9..493a8c31b 100644 --- a/sdk/src/resource_store.rs +++ b/sdk/src/resource_store.rs @@ -401,7 +401,7 @@ impl ResourceResolver for ResourceStore { pub fn mime_from_uri(uri: &str) -> String { if let Some(label) = assertion_label_from_uri(uri) { if label.starts_with(labels::THUMBNAIL) { - // https://c2pa.org/specifications/specifications/1.0/specs/C2PA_Specification.html#_thumbnail + // https://spec.c2pa.org/specifications/specifications/1.0/specs/C2PA_Specification.html#_thumbnail if let Some(ext) = label.rsplit('.').next() { return format!("image/{ext}"); } diff --git a/sdk/src/settings/builder.rs b/sdk/src/settings/builder.rs index 52e16c60e..5865000d9 100644 --- a/sdk/src/settings/builder.rs +++ b/sdk/src/settings/builder.rs @@ -399,18 +399,18 @@ pub struct ActionsSettings { pub(crate) actions: Option>, /// Whether to automatically generate a c2pa.created [Action] assertion or error that it doesn't already exist. /// - /// For more information about the mandatory conditions for a c2pa.created action assertion, see here: - /// + /// For more information about the mandatory conditions for a c2pa.created action assertion, see the + /// [C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_mandatory_presence_of_at_least_one_actions_assertion). pub auto_created_action: AutoActionSettings, /// Whether to automatically generate a c2pa.opened [Action] assertion or error that it doesn't already exist. /// - /// For more information about the mandatory conditions for a c2pa.opened action assertion, see here: - /// + /// For more information about the mandatory conditions for a c2pa.opened action assertion, see the + /// [C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_mandatory_presence_of_at_least_one_actions_assertion). pub auto_opened_action: AutoActionSettings, /// Whether to automatically generate a c2pa.placed [Action] assertion or error that it doesn't already exist. /// - /// For more information about the mandatory conditions for a c2pa.placed action assertion, see: - /// + /// For more information about the mandatory conditions for a c2pa.placed action assertion, see + /// [Relationship - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_relationship) pub auto_placed_action: AutoActionSettings, } @@ -531,8 +531,7 @@ pub struct BuilderSettings { /// /// The default is to not fetch them at all. /// - /// See more information in the spec here: - /// + /// For more information, see [Certificate status assertion - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#certificate_status_assertion). /// /// [`CertificateStatus`]: crate::assertions::CertificateStatus pub(crate) certificate_status_fetch: Option, @@ -559,7 +558,7 @@ pub struct BuilderSettings { /// Note that the label should be a **base label**, not including the assertion version nor instance. /// /// See more information on the difference between created vs gathered assertions in the spec here: - /// + /// [fields - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_fields) pub created_assertion_labels: Option>, /// Whether to generate a C2PA archive (instead of zip) when writing the manifest builder. /// Now always defaults to true - the ability to disable it will be removed in the future. diff --git a/sdk/src/settings/mod.rs b/sdk/src/settings/mod.rs index c58396bed..a24f1d95c 100644 --- a/sdk/src/settings/mod.rs +++ b/sdk/src/settings/mod.rs @@ -196,7 +196,7 @@ pub struct Core { /// This option is associated with the [`MerkleMap::fixed_block_size`] field. /// /// See more information in the spec here: - /// + /// [bmff_based_hash - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_bmff_based_hash) /// /// [`MerkleMap::fixed_block_size`]: crate::assertions::MerkleMap::fixed_block_size /// [`BmffHash`]: crate::assertions::BmffHash @@ -206,7 +206,7 @@ pub struct Core { /// This option defaults to 5. /// /// See more information in the spec here: - /// + /// [bmff_based_hash - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_bmff_based_hash) /// /// [`BmffHash`]: crate::assertions::BmffHash pub merkle_tree_max_proofs: usize, @@ -224,7 +224,7 @@ pub struct Core { pub decode_identity_assertions: bool, ///
/// The CAWG identity assertion does not currently respect this setting. - /// See issue #1645. + /// See [Issue #1645](https://github.com/contentauth/c2pa-rs/issues/1645). ///
/// /// List of host patterns that are allowed for network requests. @@ -359,7 +359,7 @@ pub struct Verify { /// The default value is false. /// /// See more information in the spec here: - /// + /// [versioning_manifests_due_to_conflicts - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_versioning_manifests_due_to_conflicts) pub(crate) skip_ingredient_conflict_resolution: bool, /// Whether to do strictly C2PA v1 validation or otherwise the latest validation. /// @@ -419,6 +419,7 @@ impl Settings { #[cfg(feature = "file_io")] /// Load thread-local [Settings] from a file. /// to be deprecated - use [Settings::with_file] instead + #[doc(hidden)] pub fn from_file>(settings_path: P) -> Result { let ext = settings_path .as_ref() @@ -433,6 +434,7 @@ impl Settings { /// Load thread-local [Settings] from string representation of the configuration. /// Format of configuration must be supplied (json or toml). /// to be deprecated - use [Settings::with_json] or [Settings::with_toml] instead + #[doc(hidden)] pub fn from_string(settings_str: &str, format: &str) -> Result { let f = match format.to_lowercase().as_str() { "json" => FileFormat::Json, @@ -752,12 +754,14 @@ impl Settings { } /// Serializes the thread-local [Settings] into a toml string. + #[doc(hidden)] pub fn to_toml() -> Result { let settings = get_thread_local_settings(); Ok(toml::to_string(&settings)?) } /// Serializes the thread-local [Settings] into a pretty (formatted) toml string. + #[doc(hidden)] pub fn to_pretty_toml() -> Result { let settings = get_thread_local_settings(); Ok(toml::to_string_pretty(&settings)?) diff --git a/sdk/src/utils/hash_utils.rs b/sdk/src/utils/hash_utils.rs index 29e1edc07..37823ad6f 100644 --- a/sdk/src/utils/hash_utils.rs +++ b/sdk/src/utils/hash_utils.rs @@ -189,6 +189,7 @@ pub fn hash_asset_by_alg_with_inclusions( The data is again split into range sets breaking at the exclusion points and now also the markers. */ +/// May be used to generate hashes in combination with embeddable APIs. pub fn hash_stream_by_alg( alg: &str, data: &mut R, diff --git a/sdk/src/validation_results.rs b/sdk/src/validation_results.rs index 497f4d9d2..a07fc48ed 100644 --- a/sdk/src/validation_results.rs +++ b/sdk/src/validation_results.rs @@ -29,9 +29,7 @@ use crate::{ /// Represents the levels of assurance a manifest store achives when evaluated against the C2PA /// specifications structural, cryptographic, and trust requirements. /// -/// See [§14.3. Validation states]. -/// -/// [§14.3. Validation states]: https://spec.c2pa.org/specifications/specifications/2.2/specs/C2PA_Specification.html#_validation_states +/// See [Validation states - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_validation_states). #[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] #[cfg_attr(feature = "json_schema", derive(JsonSchema))] pub enum ValidationState { @@ -42,16 +40,12 @@ pub enum ValidationState { Invalid, /// The manifest store is well-formed and the cryptographic integrity checks succeed. /// - /// See [§14.3.5. Valid Manifest]. - /// - /// [§14.3.5. Valid Manifest]: https://spec.c2pa.org/specifications/specifications/2.2/specs/C2PA_Specification.html#_valid_manifest + /// See [Valid Manifest - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_valid_manifest). Valid, /// The manifest store is valid and signed by a certificate that chains up to a trusted root or known /// authority in the trust list. /// - /// See [§14.3.6. Trusted Manifest]. - /// - /// [§14.3.6. Trusted Manifest]: https://spec.c2pa.org/specifications/specifications/2.2/specs/C2PA_Specification.html#_trusted_manifest + /// See [Trusted Manifest - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_trusted_manifest). Trusted, } @@ -205,9 +199,7 @@ impl ValidationResults { /// Returns the [ValidationState] of the manifest store based on the validation results. /// - /// See [§14.3. Validation states]. - /// - /// [§14.3. Validation states]: https://spec.c2pa.org/specifications/specifications/2.2/specs/C2PA_Specification.html#_validation_states + /// See [Validation states - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_validation_states). pub fn validation_state(&self) -> ValidationState { if let Some(active_manifest) = self.active_manifest.as_ref() { let success_codes: HashSet<&str> = active_manifest @@ -222,7 +214,7 @@ impl ValidationResults { .any(|idv| !idv.validation_deltas().failure().is_empty()) }); - // https://spec.c2pa.org/specifications/specifications/2.2/specs/C2PA_Specification.html#_valid_manifest + // https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_valid_manifest let is_valid = success_codes.contains(validation_status::CLAIM_SIGNATURE_VALIDATED) && success_codes.contains(validation_status::CLAIM_SIGNATURE_INSIDE_VALIDITY) && (failure_codes.is_empty() @@ -231,7 +223,7 @@ impl ValidationResults { })) && !ingredient_failure; - // https://spec.c2pa.org/specifications/specifications/2.2/specs/C2PA_Specification.html#_trusted_manifest + // https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_trusted_manifest let is_trusted = success_codes.contains(validation_status::SIGNING_CREDENTIAL_TRUSTED) && failure_codes.is_empty() && is_valid; @@ -378,9 +370,7 @@ impl IngredientDeltaValidationResult { /// Implements validation status for specific parts of a manifest. /// -/// See [§15.2.1, “Standard Status Codes.”] -/// -/// [§15.2.1, “Standard Status Codes.”]: https://c2pa.org/specifications/specifications/2.2/specs/C2PA_Specification.html#_standard_status_codes +/// See [Standard Status Codes - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_standard_status_codes). pub mod validation_codes { use crate::status_tracker::LogKind; diff --git a/sdk/src/validation_status.rs b/sdk/src/validation_status.rs index dbae60fc2..e75f99b2e 100644 --- a/sdk/src/validation_status.rs +++ b/sdk/src/validation_status.rs @@ -13,7 +13,7 @@ //! Implements validation status for specific parts of a manifest. //! -//! See . +//! See [Existing Manifests - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_existing_manifests). #![deny(missing_docs)] @@ -32,7 +32,7 @@ use crate::{ /// A `ValidationStatus` struct describes the validation status of a /// specific part of a manifest. /// -/// See . +/// See [Existing Manifests - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_existing_manifests). #[derive(Clone, Debug, Deserialize, Serialize, Eq)] #[cfg_attr(feature = "json_schema", derive(JsonSchema))] pub struct ValidationStatus { @@ -79,7 +79,7 @@ impl ValidationStatus { /// Returns the validation status code. /// /// Validation status codes are the labels from the "Value" - /// column in . + /// column in [Existing Manifests - C2PA Technical Specification](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_existing_manifests). /// /// These are also defined as constants in the /// [`validation_status`](crate::validation_status) mod.