Skip to content
This repository has been archived by the owner on Apr 29, 2024. It is now read-only.

Require specific first resource #7

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
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
22 changes: 17 additions & 5 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -155,22 +155,29 @@ <h2><a href="#cacao-zcap-mapping">CACAO-ZCAP Mapping</a></h2>

<tr>
<td>p.resources[0]</td>
<td><a href="#CacaoZcapResource2022">"https://demo.didkit.dev/2022/cacao-zcap/#CacaoZcapResource2022"</a></td>
<td>&ndash;</td>
<td>yes</td>
</tr>

<tr>
<td>p.resources[1]</td>
<td>=</td>
<td>invocationTarget</td>
<td>yes</td>
</tr>

<tr>
<td>p.resources[0]</td>
<td>p.resources[1]</td>
<td><a href="#root-zcap-mapping">URL &harr; ZCAP Root URN</a></td>
<td>proof.capabilityChain[0]</td>
<td>no</td>
</tr>

<tr>
<td>p.resources[1..n-2]</td>
<td>p.resources[2..n-2]</td>
<td><a href="#intermediate-zcap-mapping">=</a></td>
<td>proof.capabilityChain[1..n-2]</td>
<td>proof.capabilityChain[2..n-2]</td>
<td>no</td>
</tr>

Expand Down Expand Up @@ -206,12 +213,12 @@ <h3><a href="#iss-vm-mapping">issuer-verificationMethod mapping</a></h3>

<section id="root-zcap-mapping">
<h3><a href="#root-zcap-mapping">Root ZCAP mapping</a></h3>
<p>The first value of the CACAO payload resources array is used as the invocation target URI, that is the value of the zcap delegation's <code>invocationTarget</code> property. The invocation target URI is encoded into a root zcap URN to become the root capability id. The root zcap URN is constructed as the concatenation of <code>"urn:zcap:root:"</code> with <code>encodeURIComponent(invocationTarget)</code>. To transform the root zcap URN to the invocation target URI, the prefix <code>"urn:zcap:root:"</code> is removed and the remaining value is URL-decoded to return the invocation target id.</p>
<p>The second value of the CACAO payload resources array is used as the invocation target URI, that is the value of the zcap delegation's <code>invocationTarget</code> property. The invocation target URI is encoded into a root zcap URN to become the root capability id, which appears as the first value in the ZCAP <code>capabilityChain</code>. The root zcap URN is constructed as the concatenation of <code>"urn:zcap:root:"</code> with <code>encodeURIComponent(invocationTarget)</code>. To transform the root zcap URN to the invocation target URI, the prefix <code>"urn:zcap:root:"</code> is removed and the remaining value is URL-decoded to return the invocation target id.</p>
</section>

<section id="intermediate-zcap-mapping">
<h3><a href="#intermediate-zcap-mapping">Intermediate ZCAP mapping</a></h3>
<p>If the proof <code>capabilityChain</code> array / CACAO resources array (<code>p.resources</code>) contain more than two elements,
<p>If the proof <code>capabilityChain</code> array contains three or more elements (<a href="#previous-zcap-mapping">root id</a>, [...], <a href="#previous-zcap-mapping">previous delegation</a>) / CACAO resources array (<code>p.resources</code>) contains four or more elements (<a href="#CacaoZcapResource2022">type identifier</a>, <a href="#root-zcap-mapping">invocation target</a>, [...], <a href="#previous-zcap-mapping">previous delegation</a>),
the intermediate elements are passed through as URIs.</p>
</section>

Expand Down Expand Up @@ -272,6 +279,11 @@ <h3><a href="#CacaoZcapProof2022">CacaoZcapProof2022</a></h3>
</dl>
</section>

<section id="CacaoZcapResource2022">
<h3><a href="#CacaoZcapResource2022">CacaoZcapResource2022</a></h3>
<p>This type URI when used as the first value of a CACAO resources array indicates that the CACAO may be converted to a ZCAP according to this specification.</p>
</section>

<section id="cacaoPayloadType">
<h3><a href="#cacaoPayloadType">cacaoPayloadType</a></h3>
<p>CACAO payload format type (CACAO header "t" value). e.g. "eip4361".</p>
Expand Down
53 changes: 40 additions & 13 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use thiserror::Error;

pub const PROOF_TYPE_2022: &str = "CacaoZcapProof2022";
pub const CONTEXT_URL_V1: &str = "https://demo.didkit.dev/2022/cacao-zcap/context/v1.json";
pub const FIRST_RESOURCE: &str = "https://demo.didkit.dev/2022/cacao-zcap/#CacaoZcapResource2022";

#[derive(Debug, Serialize, Deserialize, Clone)]
#[serde(rename_all = "camelCase")]
Expand Down Expand Up @@ -231,11 +232,24 @@ pub enum CacaoToZcapError {

/// Missing first resource
///
/// CACAO-zcap must have at least one resource URI.
/// The first resource URI is the invocation target.
/// CACAO-ZCAP must have at least two resource URIs.
/// The first resource URI is the CACAO-ZCAP type URI.
#[error("Missing first resource")]
MissingFirstResource,

/// Missing second resource
///
/// CACAO-ZCAP must have at least two resource URIs.
/// The second resource URI is the invocation target.
#[error("Missing second resource")]
MissingSecondResource,

/// Unexpected first resource.
///
/// Expected CACAO-ZCAP type identifier [FIRST_RESOURCE]
#[error("Unexpected first resource: {0}")]
UnexpectedFirstResource(String),

/// Missing last resource
///
/// CACAO-zcap must have last resource URI for the embedded previous delegation, unless
Expand Down Expand Up @@ -298,15 +312,25 @@ where
let request_id = req_id_opt.as_ref().ok_or(CacaoToZcapError::MissingId)?;
let id = URI::String(request_id.to_string());
let mut iter = resources.iter();
let (first_resource, last_resource, intermediate_resources) = (
let (first_resource, second_resource, last_resource, intermediate_resources) = (
iter.next().ok_or(CacaoToZcapError::MissingFirstResource)?,
iter.next().ok_or(CacaoToZcapError::MissingSecondResource)?,
iter.next_back(),
iter,
);

let invocation_target = first_resource;
match first_resource.as_str() {
FIRST_RESOURCE => {
// Continue with the only type currently supported.
}
other => {
return Err(CacaoToZcapError::UnexpectedFirstResource(other.to_string()));
}
}

let invocation_target = second_resource;
let root_cap_urn = ZcapRootURN {
target: first_resource.clone(),
target: invocation_target.clone(),
};
let root_cap_urn_string = root_cap_urn.to_string();
let root_cap_urn_uri = UriString::try_from(root_cap_urn_string.as_str())
Expand Down Expand Up @@ -706,14 +730,17 @@ where
.as_resource_uri()
.map_err(ZcapToCacaoError::CapToResource)?)],
};
let resources =
vec![Ok(root_target.clone())]
.into_iter()
.chain(intermediate_caps.map(|cap| {
UriString::try_from(cap.id()).map_err(ZcapToCacaoError::ResourceURIParse)
}))
.chain(last_cap_resources.into_iter())
.collect::<Result<Vec<UriString>, ZcapToCacaoError>>()?;
let resources = vec![
UriString::try_from(FIRST_RESOURCE).map_err(ZcapToCacaoError::ResourceURIParse),
Ok(root_target.clone()),
]
.into_iter()
.chain(
intermediate_caps
.map(|cap| UriString::try_from(cap.id()).map_err(ZcapToCacaoError::ResourceURIParse)),
)
.chain(last_cap_resources.into_iter())
.collect::<Result<Vec<UriString>, ZcapToCacaoError>>()?;

if invocation_target != root_target.as_str() {
return Err(ZcapToCacaoError::InvocationTargetInternalMismatch {
Expand Down
1 change: 1 addition & 0 deletions tests/delegation0.siwe
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ Expiration Time: 2022-03-14T13:32:42.763Z
Not Before: 2022-03-14T13:31:42.763Z
Request ID: urn:uuid:5fa2f8cc-fea0-4280-b98c-99f0acecf0e1
Resources:
- https://demo.didkit.dev/2022/cacao-zcap/#CacaoZcapResource2022
- kepler://my_orbit
1 change: 1 addition & 0 deletions tests/delegation1.siwe
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ Expiration Time: 2049-01-01T00:00:00Z
Not Before: 2022-03-29T14:40:00Z
Request ID: urn:uuid:457d190c-c0ad-4b03-a14c-b6bec0dd5792
Resources:
- https://demo.didkit.dev/2022/cacao-zcap/#CacaoZcapResource2022
- kepler://my_orbit
- data:application/json;base64,eyJAY29udGV4dCI6WyJodHRwczovL3czaWQub3JnL3NlY3VyaXR5L3YyIiwiaHR0cHM6Ly9kZW1vLmRpZGtpdC5kZXYvMjAyMi9jYWNhby16Y2FwL2NvbnRleHQvdjEuanNvbiJdLCJjYWNhb1BheWxvYWRUeXBlIjoiZWlwNDM2MSIsImNhY2FvU3RhdGVtZW50IjoiQWxsb3cgYWNjZXNzIHRvIHlvdXIgS2VwbGVyIG9yYml0IiwiZXhwaXJlcyI6IjIwMjItMDMtMTRUMTM6MzI6NDIuNzYzWiIsImlkIjoidXJuOnV1aWQ6NWZhMmY4Y2MtZmVhMC00MjgwLWI5OGMtOTlmMGFjZWNmMGUxIiwiaW52b2NhdGlvblRhcmdldCI6ImtlcGxlcjovL215X29yYml0IiwiaW52b2tlciI6ImRpZDprZXk6ejZNa2lUQnoxeW11ZXBBUTRIRUhZU0YxSDhxdUc1R0xWVlFSM2RqZFgzbURvb1dwI3o2TWtpVEJ6MXltdWVwQVE0SEVIWVNGMUg4cXVHNUdMVlZRUjNkamRYM21Eb29XcCIsInBhcmVudENhcGFiaWxpdHkiOiJ1cm46emNhcDpyb290OmtlcGxlciUzQSUyRiUyRm15X29yYml0IiwicHJvb2YiOnsiY2FjYW9TaWduYXR1cmVUeXBlIjoiZWlwMTkxIiwiY2FwYWJpbGl0eUNoYWluIjpbInVybjp6Y2FwOnJvb3Q6a2VwbGVyJTNBJTJGJTJGbXlfb3JiaXQiXSwiY3JlYXRlZCI6IjIwMjItMDMtMTRUMTM6MzA6NDIuNzYzWiIsImRvbWFpbiI6ImFwcC5kb21haW4uY29tIiwibm9uY2UiOiJoOHlRVGRTY3d0OXBUeWFRYSIsInByb29mUHVycG9zZSI6ImNhcGFiaWxpdHlEZWxlZ2F0aW9uIiwicHJvb2ZWYWx1ZSI6ImYwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwIiwidHlwZSI6IkNhY2FvWmNhcFByb29mMjAyMiIsInZlcmlmaWNhdGlvbk1ldGhvZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHg5ODYyNjE4N0QzQjhlMUY3QzViMjQ2ZUU0NDNhMDc1NzliNTkyM0FjI2Jsb2NrY2hhaW5BY2NvdW50SWQifSwidHlwZSI6IkNhY2FvWmNhcDIwMjIiLCJ2YWxpZEZyb20iOiIyMDIyLTAzLTE0VDEzOjMxOjQyLjc2M1oifQ==