diff options
Diffstat (limited to 'adenosine-pds/src/crypto.rs')
-rw-r--r-- | adenosine-pds/src/crypto.rs | 61 |
1 files changed, 56 insertions, 5 deletions
diff --git a/adenosine-pds/src/crypto.rs b/adenosine-pds/src/crypto.rs index e94c34a..0720c07 100644 --- a/adenosine-pds/src/crypto.rs +++ b/adenosine-pds/src/crypto.rs @@ -1,9 +1,12 @@ +use crate::P256KeyMaterial; use anyhow::{anyhow, ensure, Result}; use k256; -use k256::ecdsa::signature::{Signer, Verifier}; use multibase; use p256; +use p256::ecdsa::signature::{Signer, Verifier}; use std::str::FromStr; +use ucan::builder::UcanBuilder; +use ucan::crypto::KeyMaterial; // Need to: // @@ -16,11 +19,13 @@ use std::str::FromStr; const MULTICODE_P256_BYTES: [u8; 2] = [0x80, 0x24]; const MULTICODE_K256_BYTES: [u8; 2] = [0xe7, 0x01]; +#[derive(Clone, PartialEq, Eq)] pub struct KeyPair { public: p256::ecdsa::VerifyingKey, secret: p256::ecdsa::SigningKey, } +#[derive(Clone, PartialEq, Eq)] pub enum PubKey { P256(p256::ecdsa::VerifyingKey), K256(k256::ecdsa::VerifyingKey), @@ -52,23 +57,55 @@ impl KeyPair { } pub fn sign_bytes(&self, data: &[u8]) -> String { - println!("BYTES: {:?}", data); let sig = self.secret.sign(data); data_encoding::BASE64URL_NOPAD.encode(&sig.to_vec()) } + + fn ucan_keymaterial(&self) -> P256KeyMaterial { + P256KeyMaterial(self.public, Some(self.secret.clone())) + } + + /// This is currently just an un-validated token; we don't actually verify these. + pub fn ucan(&self) -> Result<String> { + let key_material = self.ucan_keymaterial(); + let rt = tokio::runtime::Builder::new_current_thread() + .enable_all() + .build()?; + rt.block_on(build_ucan(key_material)) + } + + pub fn to_hex(&self) -> String { + data_encoding::HEXUPPER.encode(&self.to_bytes()) + } + + pub fn from_hex(hex: &str) -> Result<Self> { + Ok(Self::from_bytes( + &data_encoding::HEXUPPER.decode(&hex.as_bytes())?, + )?) + } +} + +async fn build_ucan(key_material: P256KeyMaterial) -> Result<String> { + let token_string = UcanBuilder::default() + .issued_by(&key_material) + .for_audience(key_material.get_did().await.unwrap().as_str()) + .with_nonce() + .with_lifetime(60 * 60 * 24 * 90) + .build()? + .sign() + .await? + .encode()?; + Ok(token_string) } impl PubKey { pub fn verify_bytes(&self, data: &[u8], sig: &str) -> Result<()> { - println!("BYTES: {:?}", data); let sig_bytes = data_encoding::BASE64URL_NOPAD.decode(sig.as_bytes())?; // TODO: better way other than this re-encoding? let sig_hex = data_encoding::HEXUPPER.encode(&sig_bytes); match self { PubKey::P256(key) => { - println!("pre-parse: {}", sig); let sig = p256::ecdsa::Signature::from_str(&sig_hex)?; - println!("parsed: {}", sig); Ok(key.verify(data, &sig)?) } PubKey::K256(key) => { @@ -137,6 +174,13 @@ impl PubKey { PubKey::K256(key) => key.to_bytes().to_vec(), } } + + pub fn ucan_keymaterial(&self) -> P256KeyMaterial { + match self { + PubKey::P256(key) => P256KeyMaterial(*key, None), + PubKey::K256(_key) => unimplemented!(), + } + } } impl std::fmt::Display for PubKey { @@ -215,3 +259,10 @@ fn test_signing() { let pubkey = PubKey::from_did_key(&did_key).unwrap(); pubkey.verify_bytes(msg, &sig_str).unwrap(); } + +#[test] +fn test_keypair_hex() { + let before = KeyPair::new_random(); + let after = KeyPair::from_hex(&before.to_hex()).unwrap(); + assert!(before == after); +} |