1use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout, Unaligned};
6
7pub const VEP_MAGIC: [u8; 3] = *b"VEP";
9pub const VEP_VERSION_V2: u8 = 2; pub const VEP_VERSION_V3: u8 = 3; pub const VEP_HEADER_SIZE: usize = 76;
12
13#[derive(FromBytes, IntoBytes, KnownLayout, Immutable, Unaligned, Debug, Clone, Copy)]
16#[repr(C)]
17pub struct VepHeader {
18 pub magic: [u8; 3],
19 pub version: u8,
20 pub aid: [u8; 32],
21 pub capsule_root: [u8; 32],
22 pub nonce: [u8; 8], }
24
25#[derive(Debug, Clone, Copy, PartialEq, Eq)]
29pub enum VepSegmentType {
30 Intent = 1,
31 Authority = 2,
32 Identity = 3,
33 Payload = 4,
34 Witness = 5,
35 Signature = 6, MagpieAst = 7, }
38
39pub struct VepPacket<'a> {
41 buffer: &'a [u8],
42}
43
44impl<'a> VepPacket<'a> {
45 pub fn new(buffer: &'a [u8]) -> Result<Self, &'static str> {
46 if buffer.len() < VEP_HEADER_SIZE {
47 return Err("Buffer too small for VEP header");
48 }
49
50 let (header, _) =
51 VepHeader::ref_from_prefix(buffer).map_err(|_| "Failed to parse VEP header")?;
52
53 if header.magic != VEP_MAGIC {
54 return Err("Invalid VEP magic bytes");
55 }
56
57 Ok(Self { buffer })
58 }
59
60 pub fn header(&self) -> &VepHeader {
61 VepHeader::ref_from_prefix(self.buffer).unwrap().0
62 }
63
64 pub fn get_segment_data(&self, segment_type: VepSegmentType) -> Option<&[u8]> {
67 let mut offset = 0;
68 let data = &self.buffer[VEP_HEADER_SIZE..];
69
70 while offset + 5 <= data.len() {
71 let t = data[offset];
72 let len_bytes: [u8; 4] = data[offset + 1..offset + 5].try_into().ok()?;
73 let len = u32::from_be_bytes(len_bytes) as usize;
74 offset += 5;
75
76 if offset + len > data.len() {
77 break;
78 }
79
80 if t == segment_type as u8 {
81 return Some(&data[offset..offset + len]);
82 }
83 offset += len;
84 }
85 None
86 }
87
88 pub fn verify(&self, chora_public_key_bytes: &[u8]) -> Result<bool, String> {
91 use ed25519_dalek::{Signature, Verifier, VerifyingKey};
92
93 let capsule = self.to_capsule()?;
95 let capsule_root = capsule.to_composite_hash()?;
96
97 let signature_bytes = self
99 .get_segment_data(VepSegmentType::Signature)
100 .ok_or("Missing Signature segment")?;
101
102 let public_key = VerifyingKey::from_bytes(
104 chora_public_key_bytes
105 .try_into()
106 .map_err(|_| "Invalid public key length")?,
107 )
108 .map_err(|e| format!("Invalid public key: {}", e))?;
109
110 let signature = Signature::from_slice(signature_bytes)
111 .map_err(|e| format!("Invalid signature format: {}", e))?;
112
113 match public_key.verify(&capsule_root.0, &signature) {
114 Ok(_) => Ok(true),
115 Err(_) => Ok(false),
116 }
117 }
118
119 pub fn to_capsule(&self) -> Result<crate::segment::Capsule, String> {
121 use crate::segment::{
122 AuthorityData, Capsule, CryptoData, IdentityData, IntentData, WitnessData,
123 };
124 use serde::Serialize;
125
126 let intent_bytes = self
127 .get_segment_data(VepSegmentType::Intent)
128 .ok_or("Missing Intent segment")?;
129 let auth_bytes = self
130 .get_segment_data(VepSegmentType::Authority)
131 .ok_or("Missing Authority segment")?;
132 let ident_bytes = self
133 .get_segment_data(VepSegmentType::Identity)
134 .ok_or("Missing Identity segment")?;
135 let witness_bytes = self
136 .get_segment_data(VepSegmentType::Witness)
137 .ok_or("Missing Witness segment")?;
138 let sig_bytes = self
139 .get_segment_data(VepSegmentType::Signature)
140 .ok_or("Missing Signature segment")?;
141
142 let mut intent: IntentData = serde_json::from_slice(intent_bytes)
143 .map_err(|e| format!("Failed to parse Intent segment: {}", e))?;
144 let authority: AuthorityData = serde_json::from_slice(auth_bytes)
145 .map_err(|e| format!("Failed to parse Authority segment: {}", e))?;
146 let identity: IdentityData = serde_json::from_slice(ident_bytes)
147 .map_err(|e| format!("Failed to parse Identity segment: {}", e))?;
148 let witness: WitnessData = serde_json::from_slice(witness_bytes)
149 .map_err(|e| format!("Failed to parse Witness segment: {}", e))?;
150
151 if let IntentData::Transparent {
152 ref mut magpie_source,
153 ..
154 } = intent
155 {
156 if magpie_source.is_none() {
157 let source = self
158 .get_segment_data(VepSegmentType::MagpieAst)
159 .map(|b| String::from_utf8_lossy(b).to_string());
160 *magpie_source = source;
161 }
162 }
163
164 let intent_hash = intent.to_jcs_hash()?.to_hex();
165
166 fn hash_seg<T: Serialize>(seg: &T) -> Result<String, String> {
167 let jcs = serde_jcs::to_vec(seg).map_err(|e| e.to_string())?;
168 let mut hasher = sha2::Sha256::new();
169 use sha2::Digest;
170 hasher.update(&jcs);
171 Ok(hex::encode(hasher.finalize()))
172 }
173
174 let authority_hash = hash_seg(&authority)?;
175 let identity_hash = hash_seg(&identity)?;
176 let witness_hash = witness.to_commitment_hash()?.to_hex();
177
178 let mut capsule = Capsule {
179 capsule_id: authority.capsule_id.clone(),
180 intent,
181 authority,
182 identity,
183 witness,
184 intent_hash,
185 authority_hash,
186 identity_hash,
187 witness_hash,
188 capsule_root: String::new(),
189 crypto: CryptoData {
190 algo: "ed25519".to_string(),
191 public_key_endpoint: "/public_key".to_string(),
192 signature_scope: "capsule_root".to_string(),
193 signature_b64: base64::Engine::encode(
194 &base64::engine::general_purpose::STANDARD,
195 sig_bytes,
196 ),
197 },
198 request_commitment: None,
199 };
200
201 let root = capsule.to_composite_hash()?;
202 let root_hex = root.to_hex();
203
204 if root_hex != hex::encode(self.header().capsule_root) {
206 return Err("VEP Integrity Failure: Capsule root mismatch".to_string());
207 }
208
209 capsule.capsule_root = root_hex;
210
211 Ok(capsule)
212 }
213}
214#[cfg(test)]
215mod tests {
216 use super::*;
217
218 #[test]
219 fn test_vep_parsing() {
220 let mut buffer = vec![0u8; 128];
221
222 let header = VepHeader {
224 magic: VEP_MAGIC,
225 version: VEP_VERSION_V2,
226 aid: [0xAA; 32],
227 capsule_root: [0; 32],
228 nonce: [0; 8],
229 };
230
231 buffer[0..76].copy_from_slice(header.as_bytes());
233
234 let payload_offset = 76;
236 buffer[payload_offset] = 1; buffer[payload_offset + 1..payload_offset + 5].copy_from_slice(&(5u32.to_be_bytes()));
238 buffer[payload_offset + 5..payload_offset + 10].copy_from_slice(b"HELLO");
239
240 let packet = VepPacket::new(&buffer).unwrap();
241 assert_eq!(packet.header().aid[0], 0xAA);
242
243 let data = packet.get_segment_data(VepSegmentType::Intent).unwrap();
244 assert_eq!(data, b"HELLO");
245 }
246
247 #[test]
248 fn test_chora_v03_binary_parity() {
249 let mut buffer = Vec::new();
251
252 let header = VepHeader {
254 magic: VEP_MAGIC,
255 version: VEP_VERSION_V3,
256 aid: [0x55; 32],
257 capsule_root: [0x77; 32],
258 nonce: [0x11; 8],
259 };
260 buffer.extend_from_slice(header.as_bytes());
261
262 let intent = b"{\"mock\":\"intent\"}";
265 buffer.push(1);
266 buffer.extend_from_slice(&(intent.len() as u32).to_be_bytes());
267 buffer.extend_from_slice(intent);
268
269 let sig = vec![0xBBu8; 64];
271 buffer.push(6);
272 buffer.extend_from_slice(&(sig.len() as u32).to_be_bytes());
273 buffer.extend_from_slice(&sig);
274
275 let packet = VepPacket::new(&buffer).expect("Valid VEP packet");
276
277 assert_eq!(packet.header().version, 3, "George's 0x03 version mismatch");
279 assert_eq!(packet.header().magic, *b"VEP");
280
281 let intent_data = packet.get_segment_data(VepSegmentType::Intent).unwrap();
282 assert_eq!(intent_data, intent);
283
284 let sig_data = packet.get_segment_data(VepSegmentType::Signature).unwrap();
285 assert_eq!(sig_data, &sig);
286
287 println!("Factual Audit: VEP Binary Protocol (v0x03) is 100% compliant.");
288 }
289}