1use anyhow::{anyhow, Result};
2use async_trait::async_trait;
3
4use p256::ecdsa::{
5 self,
6 signature::{Signer, Verifier},
7 Signature, SigningKey as P256PrivateKey, VerifyingKey as P256PublicKey,
8};
9
10use ucan::crypto::KeyMaterial;
11
12pub use ucan::crypto::{did::P256_MAGIC_BYTES, JwtSignatureAlgorithm};
13
14pub fn bytes_to_p256_key(bytes: Vec<u8>) -> Result<Box<dyn KeyMaterial>> {
15 let public_key = P256PublicKey::try_from(bytes.as_slice())?;
16 Ok(Box::new(P256KeyMaterial(public_key, None)))
17}
18
19#[derive(Clone)]
21pub struct P256KeyMaterial(pub P256PublicKey, pub Option<P256PrivateKey>);
22
23#[cfg_attr(target_arch="wasm32", async_trait(?Send))]
24#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
25impl KeyMaterial for P256KeyMaterial {
26 fn get_jwt_algorithm_name(&self) -> String {
27 JwtSignatureAlgorithm::ES256.to_string()
28 }
29
30 async fn get_did(&self) -> Result<String> {
31 let bytes = [P256_MAGIC_BYTES, &self.0.to_encoded_point(true).to_bytes()].concat();
32 Ok(format!("did:key:z{}", bs58::encode(bytes).into_string()))
33 }
34
35 async fn sign(&self, payload: &[u8]) -> Result<Vec<u8>> {
36 match self.1 {
37 Some(ref private_key) => {
38 let signature: ecdsa::Signature = private_key.sign(payload);
39 Ok(signature.to_vec())
40 }
41 None => Err(anyhow!("No private key; cannot sign data")),
42 }
43 }
44
45 async fn verify(&self, payload: &[u8], signature: &[u8]) -> Result<()> {
46 let signature = Signature::try_from(signature)?;
47 self.0
48 .verify(payload, &signature)
49 .map_err(|error| anyhow!("Could not verify signature: {:?}", error))
50 }
51}
52
53#[cfg(test)]
54mod tests {
55 use super::{bytes_to_p256_key, P256KeyMaterial, P256_MAGIC_BYTES};
56 use p256::ecdsa::{SigningKey as P256PrivateKey, VerifyingKey as P256PublicKey};
57 use ucan::{
58 builder::UcanBuilder,
59 crypto::{did::DidParser, KeyMaterial},
60 ucan::Ucan,
61 };
62
63 #[cfg_attr(not(target_arch = "wasm32"), tokio::test)]
64 async fn it_can_sign_and_verify_a_ucan() {
65 let private_key = P256PrivateKey::random(&mut p256::elliptic_curve::rand_core::OsRng);
66 let public_key = P256PublicKey::from(&private_key);
67
68 let key_material = P256KeyMaterial(public_key, Some(private_key));
69 let token_string = UcanBuilder::default()
70 .issued_by(&key_material)
71 .for_audience(key_material.get_did().await.unwrap().as_str())
72 .with_lifetime(60)
73 .build()
74 .unwrap()
75 .sign()
76 .await
77 .unwrap()
78 .encode()
79 .unwrap();
80
81 let mut did_parser = DidParser::new(&[(P256_MAGIC_BYTES, bytes_to_p256_key)]);
82
83 let ucan = Ucan::try_from(token_string).unwrap();
84 ucan.check_signature(&mut did_parser).await.unwrap();
85 }
86}