Monorepo for wisp.place. A static site hosting service built on top of the AT Protocol. wisp.place
at redirects 2.2 kB view raw
1use jacquard_common::types::cid::IpldCid; 2use sha2::{Digest, Sha256}; 3 4/// Compute CID (Content Identifier) for blob content 5/// Uses the same algorithm as AT Protocol: CIDv1 with raw codec (0x55) and SHA-256 6/// 7/// CRITICAL: This must be called on BASE64-ENCODED GZIPPED content, not just gzipped content 8/// 9/// Based on @atproto/common/src/ipld.ts sha256RawToCid implementation 10pub fn compute_cid(content: &[u8]) -> String { 11 // Use node crypto to compute sha256 hash (same as AT Protocol) 12 let hash = Sha256::digest(content); 13 14 // Create multihash (code 0x12 = sha2-256) 15 let multihash = multihash::Multihash::wrap(0x12, &hash) 16 .expect("SHA-256 hash should always fit in multihash"); 17 18 // Create CIDv1 with raw codec (0x55) 19 let cid = IpldCid::new_v1(0x55, multihash); 20 21 // Convert to base32 string representation 22 cid.to_string_of_base(multibase::Base::Base32Lower) 23 .unwrap_or_else(|_| cid.to_string()) 24} 25 26#[cfg(test)] 27mod tests { 28 use super::*; 29 use base64::Engine; 30 31 #[test] 32 fn test_compute_cid() { 33 // Test with a simple string: "hello" 34 let content = b"hello"; 35 let cid = compute_cid(content); 36 37 // CID should start with 'baf' for raw codec base32 38 assert!(cid.starts_with("baf")); 39 } 40 41 #[test] 42 fn test_compute_cid_base64_encoded() { 43 // Simulate the actual use case: gzipped then base64 encoded 44 use flate2::write::GzEncoder; 45 use flate2::Compression; 46 use std::io::Write; 47 48 let original = b"hello world"; 49 50 // Gzip compress 51 let mut encoder = GzEncoder::new(Vec::new(), Compression::default()); 52 encoder.write_all(original).unwrap(); 53 let gzipped = encoder.finish().unwrap(); 54 55 // Base64 encode the gzipped data 56 let base64_bytes = base64::prelude::BASE64_STANDARD.encode(&gzipped).into_bytes(); 57 58 // Compute CID on the base64 bytes 59 let cid = compute_cid(&base64_bytes); 60 61 // Should be a valid CID 62 assert!(cid.starts_with("baf")); 63 assert!(cid.len() > 10); 64 } 65} 66