Live video on the AT Protocol
79
fork

Configure Feed

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

at natb/dropdown-stuff 134 lines 3.4 kB view raw
1use std::{io::Cursor, sync::Arc}; 2 3use c2pa::{Builder, CallbackSigner, Reader, settings::Settings}; 4use serde_json; 5 6#[derive(Debug, thiserror::Error, uniffi::Error)] 7#[uniffi(flat_error)] 8pub enum SPError { 9 #[error("No certificate chain found")] 10 NoCertificateChainFound, 11 #[error("C2PA error: {0}")] 12 C2paError(String), 13} 14 15#[uniffi::export] 16pub fn get_manifest_and_cert(data: Vec<u8>) -> Result<String, SPError> { 17 let reader = Reader::from_stream("video/mp4", Cursor::new(data)) 18 .map_err(|e| SPError::C2paError(e.to_string()))?; 19 if let Some(manifest) = reader.active_manifest() { 20 let cert_chain = if let Some(si) = manifest.signature_info() { 21 si.cert_chain() 22 } else { 23 return Err(SPError::NoCertificateChainFound); 24 }; 25 26 let result = serde_json::json!({ 27 "manifest": manifest, 28 "cert": cert_chain 29 }); 30 31 return Ok(result.to_string()); 32 } 33 Err(SPError::NoCertificateChainFound) 34} 35 36#[uniffi::export(with_foreign)] 37pub trait GoSigner: Send + Sync { 38 fn sign(&self, data: Vec<u8>) -> Result<Vec<u8>, SPError>; 39} 40 41// #[derive(uniffi::Object)] 42// struct Authenticator { 43// gosigner: Arc<dyn GoSigner>, 44// } 45 46// impl Authenticator { 47// pub fn new(gosigner: Arc<dyn GoSigner>) -> Self { 48// Self { gosigner } 49// } 50 51// pub fn login(&self) { 52// let username = self.gosigner.get("username".into()); 53// let password = self.gosigner.get("password".into()); 54// } 55// } 56 57const TOML_SETTINGS: &str = r#" 58version_major = 1 59version_minor = 0 60 61[trust] 62 63[core] 64debug = true 65hash_alg = "sha256" 66salt_jumbf_boxes = true 67prefer_box_hash = false 68merkle_tree_max_proofs = 5 69compress_manifests = true 70 71[verify] 72verify_after_reading = false 73verify_after_sign = false 74verify_trust = false 75verify_timestamp_trust = false 76ocsp_fetch = false 77remote_manifest_fetch = false 78check_ingredient_trust = false 79skip_ingredient_conflict_resolution = false 80strict_v1_validation = false 81 82[builder.thumbnail] 83enabled = false 84ignore_errors = true 85long_edge = 1024 86prefer_smallest_format = true 87quality = "medium" 88 89[builder.actions] 90all_actions_included = false 91 92[builder.actions.auto_created_action] 93enabled = true 94source_type = "http://c2pa.org/digitalsourcetype/empty" 95 96[builder.actions.auto_opened_action] 97enabled = true 98 99[builder.actions.auto_placed_action] 100enabled = true 101"#; 102 103#[uniffi::export] 104pub fn sign( 105 manifest: String, 106 data: Vec<u8>, 107 certs: Vec<u8>, 108 gosigner: Arc<dyn GoSigner>, 109) -> Result<Vec<u8>, SPError> { 110 Settings::from_toml(TOML_SETTINGS).map_err(|e| SPError::C2paError(e.to_string()))?; 111 let callback_signer = CallbackSigner::new( 112 move |_context: *const (), data: &[u8]| { 113 gosigner 114 .sign(data.to_vec()) 115 .map_err(|e| c2pa::Error::BadParam(e.to_string())) 116 }, 117 c2pa::SigningAlg::Es256K, 118 certs, 119 ); 120 let mut builder = 121 Builder::from_json(&manifest).map_err(|e| SPError::C2paError(e.to_string()))?; 122 let mut output = Vec::new(); 123 let mut input_cursor = Cursor::new(data); 124 let mut output_cursor = Cursor::new(&mut output); 125 builder 126 .sign( 127 &callback_signer, 128 "video/mp4", 129 &mut input_cursor, 130 &mut output_cursor, 131 ) 132 .map_err(|e| SPError::C2paError(e.to_string()))?; 133 Ok(output) 134}