1use std::fmt;
9
10use arcanum_hash::prelude::{Blake3, Hasher as ArcanumHasher};
11use arcanum_signatures::ed25519::Ed25519BatchVerifier;
12use arcanum_signatures::prelude::{
13 Ed25519Signature, Ed25519SigningKey, Ed25519VerifyingKey, Signature as ArcanumSignature,
14 SigningKey as ArcanumSigningKey, VerifyingKey as ArcanumVerifyingKey,
15};
16use arcanum_signatures::BatchVerifier;
17use serde::{Deserialize, Serialize};
18
19use crate::error::{Error, Result};
20
21#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
23pub struct Hash([u8; 32]);
24
25impl Hash {
26 pub const ZERO: Self = Self([0u8; 32]);
28
29 pub fn from_bytes(bytes: [u8; 32]) -> Self {
31 Self(bytes)
32 }
33
34 pub fn as_bytes(&self) -> &[u8; 32] {
36 &self.0
37 }
38
39 pub fn from_hex(s: &str) -> Result<Self> {
41 let bytes = hex::decode(s)?;
42 if bytes.len() != 32 {
43 return Err(Error::invalid_hash(format!(
44 "expected 32 bytes, got {}",
45 bytes.len()
46 )));
47 }
48 let mut arr = [0u8; 32];
49 arr.copy_from_slice(&bytes);
50 Ok(Self(arr))
51 }
52
53 pub fn to_hex(&self) -> String {
55 hex::encode(self.0)
56 }
57
58 pub fn is_zero(&self) -> bool {
60 self == &Self::ZERO
61 }
62}
63
64impl fmt::Debug for Hash {
65 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
66 write!(f, "Hash({})", &self.to_hex()[..16])
67 }
68}
69
70impl fmt::Display for Hash {
71 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
72 write!(f, "{}", self.to_hex())
73 }
74}
75
76impl AsRef<[u8]> for Hash {
77 fn as_ref(&self) -> &[u8] {
78 &self.0
79 }
80}
81
82pub fn hash(data: &[u8]) -> Hash {
84 let output = Blake3::hash(data);
85 let bytes: [u8; 32] = output.to_array().expect("BLAKE3 always outputs 32 bytes");
86 Hash(bytes)
87}
88
89pub fn hash_pair(left: Hash, right: Hash) -> Hash {
92 let mut hasher = Blake3::new();
93 hasher.update(left.as_bytes());
94 hasher.update(right.as_bytes());
95 let output = hasher.finalize();
96 let bytes: [u8; 32] = output.to_array().expect("BLAKE3 always outputs 32 bytes");
97 Hash(bytes)
98}
99
100pub fn hash_all<T: AsRef<[u8]>>(items: &[T]) -> Hash {
102 let mut hasher = Blake3::new();
103 for item in items {
104 hasher.update(item.as_ref());
105 }
106 let output = hasher.finalize();
107 let bytes: [u8; 32] = output.to_array().expect("BLAKE3 always outputs 32 bytes");
108 Hash(bytes)
109}
110
111#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]
113pub struct PublicKey(#[serde(with = "public_key_serde")] Ed25519VerifyingKey);
114
115mod public_key_serde {
116 use super::*;
117 use serde::{Deserializer, Serializer};
118
119 pub fn serialize<S: Serializer>(
120 key: &Ed25519VerifyingKey,
121 s: S,
122 ) -> std::result::Result<S::Ok, S::Error> {
123 let bytes = ArcanumVerifyingKey::to_bytes(key);
125 let arr: [u8; 32] = bytes
126 .try_into()
127 .map_err(|_| serde::ser::Error::custom("invalid key length"))?;
128 arr.serialize(s)
129 }
130
131 pub fn deserialize<'de, D: Deserializer<'de>>(
132 d: D,
133 ) -> std::result::Result<Ed25519VerifyingKey, D::Error> {
134 let bytes: [u8; 32] = Deserialize::deserialize(d)?;
135 Ed25519VerifyingKey::from_bytes(&bytes).map_err(serde::de::Error::custom)
136 }
137}
138
139impl PublicKey {
140 pub fn from_bytes(bytes: &[u8; 32]) -> Result<Self> {
142 let key = Ed25519VerifyingKey::from_bytes(bytes)
143 .map_err(|e| Error::invalid_key(e.to_string()))?;
144 Ok(Self(key))
145 }
146
147 pub fn as_bytes(&self) -> [u8; 32] {
149 let bytes = ArcanumVerifyingKey::to_bytes(&self.0);
150 bytes
151 .try_into()
152 .expect("Ed25519 public key is always 32 bytes")
153 }
154
155 pub fn id(&self) -> Hash {
157 hash(&self.as_bytes())
158 }
159
160 pub fn verify(&self, message: &[u8], signature: &Sig) -> Result<()> {
162 ArcanumVerifyingKey::verify(&self.0, message, &signature.0)
163 .map_err(|_| Error::invalid_signature())
164 }
165
166 pub(crate) fn inner(&self) -> &Ed25519VerifyingKey {
168 &self.0
169 }
170}
171
172impl fmt::Debug for PublicKey {
173 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
174 write!(f, "PublicKey({})", &hex::encode(&self.as_bytes()[..8]))
175 }
176}
177
178impl std::hash::Hash for PublicKey {
179 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
180 self.as_bytes().hash(state);
181 }
182}
183
184#[derive(Clone)]
186pub struct SecretKey(Ed25519SigningKey);
187
188impl SecretKey {
189 pub fn generate() -> Self {
191 Self(Ed25519SigningKey::generate())
192 }
193
194 pub fn from_bytes(bytes: &[u8; 32]) -> Result<Self> {
196 let key =
197 Ed25519SigningKey::from_bytes(bytes).map_err(|e| Error::invalid_key(e.to_string()))?;
198 Ok(Self(key))
199 }
200
201 pub fn as_bytes(&self) -> [u8; 32] {
203 let bytes = ArcanumSigningKey::to_bytes(&self.0);
204 bytes
205 .try_into()
206 .expect("Ed25519 secret key is always 32 bytes")
207 }
208
209 pub fn public_key(&self) -> PublicKey {
211 PublicKey(ArcanumSigningKey::verifying_key(&self.0))
212 }
213
214 pub fn sign(&self, message: &[u8]) -> Sig {
216 Sig(ArcanumSigningKey::sign(&self.0, message))
217 }
218}
219
220impl fmt::Debug for SecretKey {
221 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
222 write!(f, "SecretKey([redacted])")
223 }
224}
225
226#[derive(Clone, Serialize, Deserialize)]
228pub struct Sig(#[serde(with = "sig_serde")] Ed25519Signature);
229
230impl PartialEq for Sig {
231 fn eq(&self, other: &Self) -> bool {
232 self.to_bytes() == other.to_bytes()
233 }
234}
235
236impl Eq for Sig {}
237
238mod sig_serde {
239 use super::*;
240 use serde::{Deserializer, Serializer};
241
242 pub fn serialize<S: Serializer>(
243 sig: &Ed25519Signature,
244 s: S,
245 ) -> std::result::Result<S::Ok, S::Error> {
246 let bytes = ArcanumSignature::to_bytes(sig);
249 let (first, second) = bytes.split_at(32);
250 let first: [u8; 32] = first
251 .try_into()
252 .map_err(|_| serde::ser::Error::custom("invalid signature length"))?;
253 let second: [u8; 32] = second
254 .try_into()
255 .map_err(|_| serde::ser::Error::custom("invalid signature length"))?;
256 (first, second).serialize(s)
257 }
258
259 pub fn deserialize<'de, D: Deserializer<'de>>(
260 d: D,
261 ) -> std::result::Result<Ed25519Signature, D::Error> {
262 let (first, second): ([u8; 32], [u8; 32]) = Deserialize::deserialize(d)?;
263 let mut bytes = [0u8; 64];
264 bytes[..32].copy_from_slice(&first);
265 bytes[32..].copy_from_slice(&second);
266 Ed25519Signature::from_bytes(&bytes).map_err(serde::de::Error::custom)
267 }
268}
269
270impl Sig {
271 pub fn empty() -> Self {
273 Self(Ed25519Signature::from_bytes(&[0u8; 64]).expect("zero bytes is valid"))
274 }
275
276 pub fn from_bytes(bytes: &[u8; 64]) -> Result<Self> {
278 Ok(Self(
279 Ed25519Signature::from_bytes(bytes).map_err(|_| Error::invalid_signature())?,
280 ))
281 }
282
283 pub fn to_bytes(&self) -> [u8; 64] {
285 ArcanumSignature::to_bytes(&self.0)
286 .try_into()
287 .expect("Ed25519 signature is always 64 bytes")
288 }
289
290 pub fn is_empty(&self) -> bool {
292 self.to_bytes() == [0u8; 64]
293 }
294
295 pub(crate) fn inner(&self) -> &Ed25519Signature {
297 &self.0
298 }
299}
300
301pub fn batch_verify(items: &[(&PublicKey, &[u8], &Sig)]) -> Result<()> {
322 if items.is_empty() {
323 return Ok(());
324 }
325
326 let arcanum_items: Vec<(&Ed25519VerifyingKey, &[u8], &Ed25519Signature)> = items
328 .iter()
329 .map(|(pk, msg, sig)| (pk.inner(), *msg, sig.inner()))
330 .collect();
331
332 Ed25519BatchVerifier::verify_batch(&arcanum_items).map_err(|_| Error::invalid_signature())
333}
334
335#[derive(Debug, Clone)]
337pub struct BatchVerifyResult {
338 pub invalid_indices: Vec<usize>,
340}
341
342impl BatchVerifyResult {
343 pub fn all_valid(&self) -> bool {
345 self.invalid_indices.is_empty()
346 }
347}
348
349pub fn batch_verify_with_fallback(items: &[(&PublicKey, &[u8], &Sig)]) -> BatchVerifyResult {
358 if batch_verify(items).is_ok() {
360 return BatchVerifyResult {
361 invalid_indices: Vec::new(),
362 };
363 }
364
365 let invalid_indices = items
367 .iter()
368 .enumerate()
369 .filter_map(|(i, (pk, msg, sig))| {
370 if pk.verify(msg, sig).is_err() {
371 Some(i)
372 } else {
373 None
374 }
375 })
376 .collect();
377
378 BatchVerifyResult { invalid_indices }
379}
380
381impl fmt::Debug for Sig {
382 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
383 write!(f, "Sig({})", &hex::encode(&self.to_bytes()[..8]))
384 }
385}
386
387#[cfg(test)]
388mod tests {
389 use super::*;
390
391 #[test]
392 fn test_sig_bincode_roundtrip() {
393 let key = SecretKey::generate();
394 let sig = key.sign(b"test message");
395
396 let bytes = bincode::serialize(&sig).expect("serialize should work");
398 println!("Serialized sig size: {} bytes", bytes.len());
399
400 let restored: Sig = bincode::deserialize(&bytes).expect("deserialize should work");
402
403 assert_eq!(sig.to_bytes(), restored.to_bytes());
404 }
405
406 #[test]
407 fn test_pubkey_bincode_roundtrip() {
408 let key = SecretKey::generate();
409 let pk = key.public_key();
410
411 let bytes = bincode::serialize(&pk).expect("serialize should work");
413 println!("Serialized pubkey size: {} bytes", bytes.len());
414
415 let restored: PublicKey = bincode::deserialize(&bytes).expect("deserialize should work");
417
418 assert_eq!(pk.as_bytes(), restored.as_bytes());
419 }
420
421 #[test]
422 fn test_hash_basic() {
423 let h1 = hash(b"hello");
424 let h2 = hash(b"hello");
425 let h3 = hash(b"world");
426
427 assert_eq!(h1, h2);
428 assert_ne!(h1, h3);
429 assert!(!h1.is_zero());
430 assert!(Hash::ZERO.is_zero());
431 }
432
433 #[test]
434 fn test_hash_matches_blake3() {
435 let h = hash(b"hello");
437 assert_eq!(
439 h.to_hex(),
440 "ea8f163db38682925e4491c5e58d4bb3506ef8c14eb78a86e908c5624a67200f"
441 );
442 }
443
444 #[test]
445 fn test_hash_hex_roundtrip() {
446 let h = hash(b"test data");
447 let hex_str = h.to_hex();
448 let h2 = Hash::from_hex(&hex_str).unwrap();
449 assert_eq!(h, h2);
450 }
451
452 #[test]
453 fn test_hash_pair_order_matters() {
454 let a = hash(b"a");
455 let b = hash(b"b");
456
457 let ab = hash_pair(a, b);
458 let ba = hash_pair(b, a);
459
460 assert_ne!(ab, ba);
461 }
462
463 #[test]
464 fn test_sign_verify() {
465 let sk = SecretKey::generate();
466 let pk = sk.public_key();
467
468 let message = b"audit event data";
469 let sig = sk.sign(message);
470
471 assert!(pk.verify(message, &sig).is_ok());
472 assert!(pk.verify(b"wrong message", &sig).is_err());
473 }
474
475 #[test]
476 fn test_key_id_deterministic() {
477 let sk = SecretKey::generate();
478 let pk = sk.public_key();
479
480 let id1 = pk.id();
481 let id2 = pk.id();
482
483 assert_eq!(id1, id2);
484 }
485
486 #[test]
487 fn test_secret_key_roundtrip() {
488 let sk = SecretKey::generate();
489 let bytes = sk.as_bytes();
490 let restored = SecretKey::from_bytes(&bytes).unwrap();
491
492 assert_eq!(sk.public_key().as_bytes(), restored.public_key().as_bytes());
494 }
495}