Skip to content
Open
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
35 changes: 34 additions & 1 deletion Library/Sources/Manifest/AssertionDefinition.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import Foundation
/// - SeeAlso: [AssertionDefinition Reference](https://opensource.contentauthenticity.org/docs/manifest/json-ref/manifest-definition-schema#assertiondefinition)

/// The standard C2PA assertions are currently available:
/// - SeeAlso: [C2PA Specification: Standard C2PA Assertion Summary](https://spec.c2pa.org/specifications/specifications/2.2/specs/C2PA_Specification.html#_standard_c2pa_assertion_summary)
/// - SeeAlso: [C2PA Specification: Standard C2PA Assertion Summary](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_standard_c2pa_assertion_summary)

/// But only `actions` is actually implemented!
public enum AssertionDefinition: Codable, Equatable {
Expand All @@ -30,7 +30,11 @@ public enum AssertionDefinition: Codable, Equatable {
/// - SeeAlso: [Actions Reference](https://opensource.contentauthenticity.org/docs/manifest/writing/assertions-actions#actions)
case actions(actions: [Action])

/// - SeeAlso: [Actions Reference](https://opensource.contentauthenticity.org/docs/manifest/writing/assertions-actions#actions)
case actionsV2(actions: [Action])

case assertionMetadata
case alternativeContentRepresentation
case assetRef
case assetType
case bmffBasedHash
Expand All @@ -40,9 +44,11 @@ public enum AssertionDefinition: Codable, Equatable {
case dataHash
case depthmap
case embeddedData
case externalReference
case fontInfo
case generalBoxHash
case ingredient
case ingredientV3
case metadata
case multiAssetHash
case softBinding
Expand All @@ -61,9 +67,17 @@ public enum AssertionDefinition: Codable, Equatable {

self = .actions(actions: actions["actions"] ?? [])

case .actionsV2:
let actions = try container.decode([String: [Action]].self, forKey: .data)

self = .actionsV2(actions: actions["actions"] ?? [])

case .assertionMetadata:
self = .assertionMetadata

case .alternativeContentRepresentation:
self = .alternativeContentRepresentation

case .assetRef:
self = .assetRef

Expand Down Expand Up @@ -91,6 +105,9 @@ public enum AssertionDefinition: Codable, Equatable {
case .embeddedData:
self = .embeddedData

case .externalReference:
self = .externalReference

case .fontInfo:
self = .fontInfo

Expand All @@ -100,6 +117,9 @@ public enum AssertionDefinition: Codable, Equatable {
case .ingredient:
self = .ingredient

case .ingredientV3:
self = .ingredientV3

case .metadata:
self = .metadata

Expand Down Expand Up @@ -128,9 +148,16 @@ public enum AssertionDefinition: Codable, Equatable {
try container.encode(StandardAssertionLabel.actions, forKey: .label)
try container.encode(["actions": actions], forKey: .data)

case .actionsV2(let actions):
try container.encode(StandardAssertionLabel.actionsV2, forKey: .label)
try container.encode(["actions": actions], forKey: .data)

case .assertionMetadata:
try container.encode(StandardAssertionLabel.assertionMetadata, forKey: .label)

case .alternativeContentRepresentation:
try container.encode(StandardAssertionLabel.alternativeContentRepresentation, forKey: .label)

case .assetRef:
try container.encode(StandardAssertionLabel.assetRef, forKey: .label)

Expand Down Expand Up @@ -158,6 +185,9 @@ public enum AssertionDefinition: Codable, Equatable {
case .embeddedData:
try container.encode(StandardAssertionLabel.embeddedData, forKey: .label)

case .externalReference:
try container.encode(StandardAssertionLabel.externalReference, forKey: .label)

case .fontInfo:
try container.encode(StandardAssertionLabel.fontInfo, forKey: .label)

Expand All @@ -167,6 +197,9 @@ public enum AssertionDefinition: Codable, Equatable {
case .ingredient:
try container.encode(StandardAssertionLabel.ingredient, forKey: .label)

case .ingredientV3:
try container.encode(StandardAssertionLabel.ingredientV3, forKey: .label)

case .metadata:
try container.encode(StandardAssertionLabel.metadata, forKey: .label)

Expand Down
2 changes: 1 addition & 1 deletion Library/Sources/Manifest/HashedUri.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
import Foundation

/// 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.
/// - SeeAlso: [C2PA Specification: URI References](https://c2pa.org/specifications/specifications/2.1/specs/C2PA_Specification.html#_uri_references)
/// - SeeAlso: [C2PA Specification: URI References](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_uri_references)

/// - SeeAlso: [HashedUri Reference](https://opensource.contentauthenticity.org/docs/manifest/json-ref/manifest-definition-schema/#hasheduri)
open class HashedUri: UriOrResource {
Expand Down
20 changes: 19 additions & 1 deletion Library/Sources/Manifest/PredefinedAction.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

import Foundation

/// - SeeAlso: [C2PA Specification: Actions](https://spec.c2pa.org/specifications/specifications/2.2/specs/C2PA_Specification.html#_actions)
/// - SeeAlso: [C2PA Specification: Actions](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_actions)
public enum PredefinedAction: String, Codable {

/// (visible) Textual content was inserted into the asset, such as on a text layer or as a caption.
Expand All @@ -25,6 +25,9 @@ public enum PredefinedAction: String, Codable {
/// Reduced or increased playback speed of a video or audio track
case changedSpeed = "c2pa.changedSpeed"

/// The asset was captured from a camera or recording device.
case captured = "c2pa.captured"

/// [DEPRECATED] Changes to tone, saturation, etc.
@available(*, deprecated)
case colorAdjustments = "c2pa.color_adjustments"
Expand Down Expand Up @@ -83,6 +86,9 @@ public enum PredefinedAction: String, Codable {
/// Changes to either content dimensions, its file size or both
case resized = "c2pa.resized"

/// Content was segmented into multiple parts or clips.
case segmented = "c2pa.segmented"

/// A conversion of one encoding to another, including resolution scaling, bitrate adjustment and encoding format change. This action is considered as a non-editorial transformation of the parentOf ingredient.
case transcoded = "c2pa.transcoded"

Expand All @@ -97,4 +103,16 @@ public enum PredefinedAction: String, Codable {

/// An invisible watermark was inserted into the digital content for the purpose of creating a soft binding.
case watermarked = "c2pa.watermarked"

/// Content was compressed using a compression algorithm.
case compressed = "c2pa.compressed"

/// Content was decompressed from a compressed representation.
case decompressed = "c2pa.decompressed"

/// Content was converted between stereo and another channel configuration.
case stereoConverted = "c2pa.stereoConverted"

/// Content was generated or synthesized using automated or algorithmic means (e.g., generative AI).
case synthesized = "c2pa.synthesized"
}
34 changes: 33 additions & 1 deletion Library/Sources/Manifest/StandardAssertionLabel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,46 +14,78 @@
import Foundation

/// The standard C2PA assertions.
/// - SeeAlso: [C2PA Specification: Standard C2PA Assertion Summary](https://spec.c2pa.org/specifications/specifications/2.2/specs/C2PA_Specification.html#_standard_c2pa_assertion_summary)
/// - SeeAlso: [C2PA Specification: Standard C2PA Assertion Summary](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_standard_c2pa_assertion_summary)
public enum StandardAssertionLabel: String, Codable {

/// Describes actions performed on the asset.
case actions = "c2pa.actions"

/// Version 2 of the actions assertion schema.
case actionsV2 = "c2pa.actions.v2"

/// Metadata about another assertion.
case assertionMetadata = "c2pa.assertion.metadata"

/// Provides an alternate representation of the content (for example an EXIF preservation image).
case alternativeContentRepresentation = "c2pa.alternative-content-representation"

/// Reference to a location where the asset may be obtained.
case assetRef = "c2pa.asset-ref"

/// Describes the media type and classification of the asset.
case assetType = "c2pa.asset-type.v2"

/// Hash of a BMFF-based asset structure.
case bmffBasedHash = "c2pa.hash.bmff.v3"

/// Information about the certificate used for signing.
case certificateStatus = "c2pa.certificate-status"

/// Reference to externally stored assertion data.
case cloudData = "c2pa.cloud-data"

/// Hash of a collection of assets.
case collectionDataHash = "c2pa.hash.collection.data"

/// Hash of byte ranges of the asset.
case dataHash = "c2pa.hash.data"

/// Google depth map metadata assertion.
case depthmap = "c2pa.depthmap.GDepth"

/// Embedded binary data such as images, prompts, or other files.
case embeddedData = "c2pa.embedded-data"

/// Reference to an externally stored assertion.
case externalReference = "c2pa.external-reference"

/// Font metadata describing fonts used in the asset.
case fontInfo = "font.info"

/// Hash of specific boxes in a container format.
case generalBoxHash = "c2pa.hash.boxes"

/// Ingredient describing an input asset used to create the current asset.
case ingredient = "c2pa.ingredient"

/// Version 3 of the ingredient assertion.
case ingredientV3 = "c2pa.ingredient.v3"

/// Structured metadata about the asset (for example EXIF or IPTC).
case metadata = "c2pa.metadata"

/// Hash referencing multiple assets.
case multiAssetHash = "c2pa.hash.multi-asset"

/// Soft binding information between content and manifest.
case softBinding = "c2pa.soft-binding"

/// Thumbnail representing the asset at claim creation.
case thumbnailClaim = "c2pa.thumbnail.claim"

/// Thumbnail representing an imported ingredient.
case thumbnailIngredient = "c2pa.thumbnail.ingredient"

/// Signed timestamp token associated with the claim.
case timeStamps = "c2pa.time-stamp"
}
70 changes: 69 additions & 1 deletion Library/Sources/Manifest/ValidationStatusCode.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,29 @@

import Foundation

/// - SeeAlso: [C2PA Specification: returning_validation_results](https://spec.c2pa.org/specifications/specifications/2.2/specs/C2PA_Specification.html#_returning_validation_results)
/// - SeeAlso: [C2PA Specification: returning_validation_results](https://spec.c2pa.org/specifications/specifications/2.3/specs/C2PA_Specification.html#_returning_validation_results)
public enum ValidationStatusCode: String, Codable {

// MARK: - Success codes

/// The claim signature referenced in the ingredient’s claim validated.
case claimSignatureValidated = "claimSignature.validated"

/// The claim signature was created within the validity window of the signing certificate.
case claimSignatureInsideValidity = "claimSignature.insideValidity"

/// The signing credential is listed on the validator’s trust list.
case signingCredentialTrusted = "signingCredential.trusted"

/// The signing credential was checked via OCSP and was not revoked.
case signingCredentialOCSPNotRevoked = "signingCredential.ocsp.notRevoked"

/// The time-stamp credential is listed on the validator’s trust list.
case timeStampTrusted = "timeStamp.trusted"

/// The time-stamp token was successfully validated.
case timeStampValidated = "timeStamp.validated"

/// The hash of the the referenced assertion in the ingredient’s manifest matches the corresponding hash in the assertion’s hashed URI in the claim.
case assertionHashedUriMatch = "assertion.hashedURI.match"

Expand All @@ -34,9 +45,54 @@ public enum ValidationStatusCode: String, Codable {
/// Hash of a box-based asset matches the hash declared in the BMFF hash assertion.
case assertionBmffHashMatch = "assertion.bmffHash.match"

/// Hash of the specified boxes matches the hash declared in the boxes hash assertion.
case assertionBoxesHashMatch = "assertion.boxesHash.match"

/// Hash of a collection of assets matches the value declared in the collection hash assertion.
case assertionCollectionHashMatch = "assertion.collectionHash.match"

/// The alternative content representation assertion hash matched the expected value.
case assertionAlternativeContentRepresentationMatch = "assertion.alternativeContentRepresentation.match"

/// Hash of multiple referenced assets matches the hash declared in the multi-asset hash assertion.
case assertionMultiAssetHashMatch = "assertion.multiAssetHash.match"

/// A non-embedded (remote) assertion was accessible at the time of validation.
case assertionAccessible = "assertion.accessible"

/// The claim signature referenced by an ingredient validated successfully.
case ingredientClaimSignatureValidated = "ingredient.claimSignature.validated"

/// The ingredient’s manifest validated successfully.
case ingredientManifestValidated = "ingredient.manifest.validated"


// MARK: - Informational codes

/// The algorithm used is deprecated but still recognized by the validator.
case algorithmDeprecated = "algorithm.deprecated"

/// A BMFF hash assertion contained additional exclusions that were ignored during validation.
case assertionBmffHashAdditionalExclusionsPresent = "assertion.bmffHash.additionalExclusionsPresent"

/// A boxes hash assertion contained additional exclusions that were ignored during validation.
case assertionBoxesHashAdditionalExclusionsPresent = "assertion.boxesHash.additionalExclusionsPresent"

/// A data hash assertion contained additional exclusions that were ignored during validation.
case assertionDataHashAdditionalExclusionsPresent = "assertion.dataHash.additionalExclusionsPresent"

/// The provenance of an ingredient could not be determined.
case ingredientUnknownProvenance = "ingredient.unknownProvenance"

/// The OCSP responder for the signing credential could not be reached.
case signingCredentialOCSPInaccessible = "signingCredential.ocsp.inaccessible"

/// OCSP checking for the signing credential was skipped.
case signingCredentialOCSPSkipped = "signingCredential.ocsp.skipped"


// MARK: - Failure codes

/// The referenced claim in the ingredient’s manifest cannot be found.
case claimMissing = "claim.missing"

Expand All @@ -55,6 +111,9 @@ public enum ValidationStatusCode: String, Codable {
/// The claim signature referenced in the ingredient’s claim failed to validate.
case claimSignatureMismatch = "claimSignature.mismatch"

/// The claim signature timestamp is outside the validity window of the signing certificate.
case claimSignatureOutsideValidity = "claimSignature.outsideValidity"

/// The manifest has more than one ingredient whose relationship is parentOf.
case manifestMultipleParents = "manifest.multipleParents"

Expand Down Expand Up @@ -118,6 +177,15 @@ public enum ValidationStatusCode: String, Codable {
/// An update manifest contains a cloud data assertion referencing an actions assertion.
case assertionCloudDataActions = "assertion.cloud-data.actions"

/// More than one hard binding assertion was present when only one is permitted.
case assertionMultipleHardBindings = "assertion.multipleHardBindings"

/// An assertion contained metadata that is not permitted by the specification.
case assertionMetadataDisallowed = "assertion.metadata.disallowed"

/// A timestamp assertion is malformed or cannot be parsed.
case assertionTimestampMalformed = "assertion.timestamp.malformed"

/// The value of an alg header, or other header that specifies an algorithm used to compute the value of another field, is unknown or unsupported.
case algorithmUnsupported = "algorithm.unsupported"
}
Loading