-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore: update to new ceramic_event builder api
- Loading branch information
1 parent
ffa1482
commit 0c52e8e
Showing
3 changed files
with
184 additions
and
61 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
use std::{collections::BTreeMap, str::FromStr}; | ||
|
||
use ceramic_event::{ | ||
ssi, unvalidated::signed::Signer, Base64String, Base64UrlString, Cid, MultiBase32String, | ||
}; | ||
use serde::{Deserialize, Serialize}; | ||
|
||
/// The fields associated with the signature used to sign a JWS | ||
#[derive(Debug, Serialize, Deserialize)] | ||
pub struct JwsSignature { | ||
/// Protected header | ||
pub protected: Option<Base64String>, | ||
/// Signature | ||
pub signature: Base64UrlString, | ||
} | ||
|
||
/// Builder used to create JWS | ||
pub struct JwsBuilder<S> { | ||
signer: S, | ||
additional: BTreeMap<String, serde_json::Value>, | ||
} | ||
|
||
impl<S: Signer> JwsBuilder<S> { | ||
pub fn new(signer: S) -> Self { | ||
Self { | ||
signer, | ||
additional: BTreeMap::new(), | ||
} | ||
} | ||
|
||
pub fn with_additional(mut self, key: String, value: serde_json::Value) -> Self { | ||
self.additional.insert(key, value); | ||
self | ||
} | ||
|
||
pub fn replace_additional(mut self, additional: BTreeMap<String, serde_json::Value>) -> Self { | ||
self.additional = additional; | ||
self | ||
} | ||
|
||
pub fn build_for_cid(self, cid: &Cid) -> anyhow::Result<Jws> { | ||
let cid_str = Base64UrlString::from_cid(cid); | ||
let link = MultiBase32String::try_from(cid)?; | ||
Jws::new(&self.signer, cid_str, Some(link), self.additional) | ||
} | ||
|
||
pub fn build_for_data<T: Serialize>(self, input: &T) -> anyhow::Result<Jws> { | ||
let input = serde_json::to_vec(input)?; | ||
let input = Base64UrlString::from(input); | ||
Jws::new(&self.signer, input, None, self.additional) | ||
} | ||
} | ||
|
||
/// A JWS object | ||
#[derive(Debug, Serialize, Deserialize)] | ||
pub struct Jws { | ||
/// Link to CID that contains encoded data | ||
#[serde(skip_serializing_if = "Option::is_none")] | ||
pub link: Option<MultiBase32String>, | ||
/// Encoded data | ||
pub payload: Base64UrlString, | ||
/// The signatures of the JWS | ||
pub signatures: Vec<JwsSignature>, | ||
} | ||
|
||
impl Jws { | ||
/// Create a builder for Jws objects | ||
pub fn builder<S: Signer>(signer: S) -> JwsBuilder<S> { | ||
JwsBuilder::new(signer) | ||
} | ||
|
||
/// Creates a new JWS from a payload that has already been serialized to Base64UrlString | ||
pub fn new( | ||
signer: &impl Signer, | ||
input: Base64UrlString, | ||
link: Option<MultiBase32String>, | ||
additional_parameters: BTreeMap<String, serde_json::Value>, | ||
) -> anyhow::Result<Self> { | ||
let alg = signer.algorithm(); | ||
let header = ssi::jws::Header { | ||
algorithm: alg, | ||
type_: Some("JWT".to_string()), | ||
key_id: Some(signer.id().id.clone()), | ||
additional_parameters, | ||
..Default::default() | ||
}; | ||
// creates compact signature of protected.signature | ||
let header_str = Base64String::from(serde_json::to_vec(&header)?); | ||
let signing_input = format!("{}.{}", header_str.as_ref(), input.as_ref()); | ||
let signed = signer.sign(signing_input.as_bytes())?; | ||
Ok(Self { | ||
link, | ||
payload: input, | ||
signatures: vec![JwsSignature { | ||
protected: Some(header_str), | ||
signature: signed.into(), | ||
}], | ||
}) | ||
} | ||
|
||
/// Get the payload of this jws | ||
pub fn payload(&self) -> &Base64UrlString { | ||
&self.payload | ||
} | ||
|
||
/// Get the additional parameters of the jws signature | ||
pub fn additional(&self) -> anyhow::Result<BTreeMap<String, serde_json::Value>> { | ||
let first = self | ||
.signatures | ||
.first() | ||
.ok_or_else(|| anyhow::anyhow!("No signatures"))?; | ||
let protected = first | ||
.protected | ||
.as_ref() | ||
.ok_or_else(|| anyhow::anyhow!("No protected header"))?; | ||
let protected = serde_json::from_slice::<ssi::jws::Header>(&protected.to_vec()?)?; | ||
Ok(protected.additional_parameters) | ||
} | ||
|
||
/// Get the capability field for this jws | ||
pub fn capability(&self) -> anyhow::Result<Cid> { | ||
let additional = self.additional()?; | ||
let cap = additional | ||
.get("cap") | ||
.ok_or_else(|| anyhow::anyhow!("No cap"))? | ||
.as_str() | ||
.ok_or_else(|| anyhow::anyhow!("cap is not a string"))?; | ||
let cid = Cid::from_str(cap)?; | ||
Ok(cid) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters