cawg_identity/claim_aggregation/
ica_credential.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
// Copyright 2024 Adobe. All rights reserved.
// This file is licensed to you under the Apache License,
// Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
// or the MIT license (http://opensource.org/licenses/MIT),
// at your option.

// Unless required by applicable law or agreed to in writing,
// this software is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR REPRESENTATIONS OF ANY KIND, either express or
// implied. See the LICENSE-MIT and LICENSE-APACHE files for the
// specific language governing permissions and limitations under
// each license.

use chrono::{DateTime, FixedOffset};
use iref::{Iri, UriBuf};
use non_empty_string::NonEmptyString;
use nonempty_collections::NEVec;
use serde::{Deserialize, Serialize};

use crate::{
    claim_aggregation::w3c_vc::credential::{CredentialV2, VerifiableCredentialSubtype},
    SignerPayload,
};

/// TO DO: Doc -- looks like CredentialV2 for our specific use
/// case.
pub type IcaCredential = CredentialV2<IdentityClaimsAggregationVc>;

/// Identity claims aggregation context IRI.
pub const IDENTITY_CLAIMS_AGGREGATION_CONTEXT_IRI: &Iri =
    static_iref::iri!("https://creator-assertions.github.io/tbd/tbd");

/// Identity claims aggregation credential type name.
pub const IDENTITY_CLAIMS_AGGREGATION_CREDENTIAL_TYPE: &str = "IdentityClaimsAggregationCredential";

/// An **identity claims aggregation** is a [W3C verifiable credential] that
/// binds one or more identity claim attestations regarding the _named actor_ to
/// the _C2PA asset_ in which the **identity assertion** appears.
///
/// [W3C verifiable credential]: https://www.w3.org/TR/vc-data-model-2.0/
#[derive(Debug, Deserialize, Serialize)]
pub struct IdentityClaimsAggregationVc {
    /// ## Verified identities
    ///
    /// The `verifiedIdentities` property MUST be present and MUST be an array.
    /// Every item in the array MUST contain information about the _named actor_
    /// as verified by the _identity assertion generator_ or a service contacted
    /// by the _identity assertion generator._
    #[serde(rename = "verifiedIdentities")]
    pub verified_identities: NEVec<VerifiedIdentity>,

    /// ## Binding to C2PA asset
    ///
    /// The `credentialSubject` field MUST contain a `c2paAsset` entry, which
    /// MUST be the JSON serialization of the `signer_payload` data structure
    /// presented for signature with the following adaptations:
    /// * All CBOR bytestring values in `signer_payload` data structure (for example, `hash` entries in the `hashlink` data structure) MUST be converted to the corresponding base 64 encoding as specified in [Section 4, “Base 64 Encoding,”](https://datatracker.ietf.org/doc/html/rfc4648#section-4) of RFC 4648. The base 64 encoding MUST NOT use the URL-safe variation of base 64. The encoding MUST NOT include line feeds or additional annotations not directly required by the core base 64 specification.
    /// * The JSON encoding MUST use the field names exactly as specified in [Section 5.1, “Overview”](https://creator-assertions.github.io/identity/1.1-draft/#_overview).
    #[serde(rename = "c2paAsset")]
    pub c2pa_asset: SignerPayload,
}

impl VerifiableCredentialSubtype for IdentityClaimsAggregationVc {
    fn required_contexts(&self) -> &[&'static Iri] {
        &[IDENTITY_CLAIMS_AGGREGATION_CONTEXT_IRI]
    }

    fn required_types(&self) -> &[&'static str] {
        &[IDENTITY_CLAIMS_AGGREGATION_CREDENTIAL_TYPE]
    }
}

/// Every item in the `verifiedIdentities` array MUST contain information about
/// the _named actor_ as verified by the _identity assertion generator_ or a
/// service contacted by the _identity assertion generator._
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct VerifiedIdentity {
    /// ## Verified identity type
    ///
    /// The `verifiedIdentities[?].type` property MUST be present and MUST be a
    /// non-empty string that defines the type of verification that was
    /// performed by the identity provider.
    #[serde(rename = "type")]
    pub type_: NonEmptyString,

    /// ## Display name
    ///
    /// The `verifiedIdentities[?].name` property MAY be present. If present, it
    /// MUST NOT be empty and must be a string defining the _named actor’s_ name
    /// as understood by the identity provider.
    ///
    /// If the `type` of this verified identity is `cawg.document_verification`,
    /// the `verifiedIdentities[?].name` property MUST be present and MUST
    /// exactly match the name found on the identity documents.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub name: Option<NonEmptyString>,

    /// ## User name
    ///
    /// The `verifiedIdentities[?].username` property MAY be present. If
    /// present, it MUST be a non-empty text string representing the _named
    /// actor’s_ user name as assigned by the identity provider.
    ///
    /// If the type of this verified identity is `cawg.social_media`, the
    /// `verifiedIdentities[?].username` property MUST be present and MUST be
    /// the unique alphanumeric string that can be used to identity the _named
    /// actor_ within this service.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub username: Option<NonEmptyString>,

    /// ## Address
    ///
    /// The `verifiedIdentities[?].address` property MAY be present. If present,
    /// it MUST be a non-empty text string representing the _named actor’s_
    /// cryptographic address as assigned by the identity provider.
    ///
    /// If the type of this verified identity is `cawg.crypto_wallet`, the
    /// `verifiedIdentities[?].address` property MUST be present and MUST be the
    /// unique alphanumeric string that can be used to identity the _named
    /// actor_ within this service.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub address: Option<NonEmptyString>,

    /// ## URI
    ///
    /// The `verifiedIdentities[?].uri` property MAY be present. If present, it
    /// must be a valid URI which is the primary point of contact for the _named
    /// actor_ as assigned by the _identity provider._
    ///
    /// If the type of this verified identity is `cawg.social_media`, it is
    /// RECOMMENDED that the `verifiedIdentities[?].uri` be the primary web URI
    /// for the _named actor’s_ social media account.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub uri: Option<UriBuf>,

    /// ## Identity verification date
    ///
    /// The `verifiedIdentities[?].verifiedAt` MUST be present and MUST be a
    /// valid date-time as specified by RFC 3339. It represents the date and
    /// time when the relationship between the _named actor_ and the _identity
    /// provider_ was verified by the _identity assertion generator._
    #[serde(rename = "verifiedAt")]
    pub verified_at: DateTime<FixedOffset>,

    /// ## Identity provider details
    ///
    /// The `verifiedIdentities[?].provider` property MUST be an object and MUST
    /// be present. It contains details about the _identity provider_ and the
    /// identity verification process.
    pub provider: IdentityProvider,
}

/// ## Identity provider details
///
/// The `verifiedIdentities[?].provider` property MUST be an object and MUST be
/// present. It contains details about the _identity provider_ and the identity
/// verification process. This specification mentions at least three properties
/// that MAY be used to represent the _named actor’s_ verification details:
/// `id`, `name`, and `proof`.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct IdentityProvider {
    /// ## Identity provider ID
    ///
    /// The `verifiedIdentities[?].provider.id` MUST be present and MUST be a
    /// valid URI that, when dereferenced, MUST result in a proof of
    /// authenticity of the _identity provider._ This proof of authenticity of
    /// the identity provider MUST NOT be confused with the proof of
    /// verification of the _named actor._
    pub id: UriBuf,

    /// ## Identity provider name
    ///
    /// The `verifiedIdentities[?].provider.name` MUST be present and MUST be a
    /// non-empty string. ///The `verifiedIdentities[?].provider.name` property
    /// is the user-visible name of the _identity provider._
    pub name: NonEmptyString,
}