A better Rust ATProto crate
1

Configure Feed

Select the types of activity you want to include in your feed.

at main 2.6 kB View raw
1use base64::Engine; 2use base64::engine::general_purpose::URL_SAFE_NO_PAD; 3use jacquard_common::bos::BosStr; 4use smol_str::SmolStr; 5 6use super::{Header, jwt::Claims}; 7 8/// Builds the base64url-encoded `header.payload` signing input. 9fn signing_input<S: BosStr + serde::Serialize>( 10 header: &Header<S>, 11 claims: &Claims<&str>, 12) -> serde_json::Result<(String, String)> { 13 let h = URL_SAFE_NO_PAD.encode(serde_json::to_string(header)?); 14 let p = URL_SAFE_NO_PAD.encode(serde_json::to_string(claims)?); 15 Ok((h, p)) 16} 17 18/// Assembles a compact JWS from pre-encoded parts and raw signature bytes. 19fn assemble(header: &str, payload: &str, sig: &[u8]) -> SmolStr { 20 smol_str::format_smolstr!("{header}.{payload}.{}", URL_SAFE_NO_PAD.encode(sig)) 21} 22 23/// Creates a compact-serialized signed JWT using ES256 (P-256 ECDSA with SHA-256). 24pub fn create_signed_jwt_es256<S: BosStr + serde::Serialize>( 25 key: p256::ecdsa::SigningKey, 26 header: Header<S>, 27 claims: Claims<&str>, 28) -> serde_json::Result<SmolStr> { 29 use p256::ecdsa::signature::Signer; 30 let (h, p) = signing_input(&header, &claims)?; 31 let sig: p256::ecdsa::Signature = key.sign(format!("{h}.{p}").as_bytes()); 32 Ok(assemble(&h, &p, &sig.to_bytes())) 33} 34 35/// Creates a compact-serialized signed JWT using ES384 (P-384 ECDSA with SHA-384). 36pub fn create_signed_jwt_es384<S: BosStr + serde::Serialize>( 37 key: p384::ecdsa::SigningKey, 38 header: Header<S>, 39 claims: Claims<&str>, 40) -> serde_json::Result<SmolStr> { 41 use p384::ecdsa::signature::Signer; 42 let (h, p) = signing_input(&header, &claims)?; 43 let sig: p384::ecdsa::Signature = key.sign(format!("{h}.{p}").as_bytes()); 44 Ok(assemble(&h, &p, &sig.to_bytes())) 45} 46 47/// Creates a compact-serialized signed JWT using ES256K (secp256k1 ECDSA with SHA-256). 48pub fn create_signed_jwt_es256k<S: BosStr + serde::Serialize>( 49 key: k256::ecdsa::SigningKey, 50 header: Header<S>, 51 claims: Claims<&str>, 52) -> serde_json::Result<SmolStr> { 53 use k256::ecdsa::signature::Signer; 54 let (h, p) = signing_input(&header, &claims)?; 55 let sig: k256::ecdsa::Signature = key.sign(format!("{h}.{p}").as_bytes()); 56 Ok(assemble(&h, &p, &sig.to_bytes())) 57} 58 59/// Creates a compact-serialized signed JWT using EdDSA (Ed25519). 60pub fn create_signed_jwt_eddsa<S: BosStr + serde::Serialize>( 61 key: ed25519_dalek::SigningKey, 62 header: Header<S>, 63 claims: Claims<&str>, 64) -> serde_json::Result<SmolStr> { 65 use ed25519_dalek::Signer; 66 let (h, p) = signing_input(&header, &claims)?; 67 let sig = key.sign(format!("{h}.{p}").as_bytes()); 68 Ok(assemble(&h, &p, &sig.to_bytes())) 69}