1use std::cell::RefCell;
4
5use bytes::Bytes;
6use ndn_packet::encode::{DataBuilder, InterestBuilder};
7
8use crate::{Signer, TrustError};
9
10pub trait SignWith: Sized {
31 fn sign_with_sync(self, signer: &dyn Signer) -> Result<Bytes, TrustError>;
37}
38
39impl SignWith for DataBuilder {
40 fn sign_with_sync(self, signer: &dyn Signer) -> Result<Bytes, TrustError> {
41 let sig_type = signer.sig_type();
42 let key_name = signer.key_name().clone();
43 let captured_err: RefCell<Option<TrustError>> = RefCell::new(None);
44 let wire = self.sign_sync(sig_type, Some(&key_name), |region| {
45 match signer.sign_sync(region) {
46 Ok(sig) => sig,
47 Err(e) => {
48 *captured_err.borrow_mut() = Some(e);
49 Bytes::new()
50 }
51 }
52 });
53 if let Some(e) = captured_err.into_inner() {
54 Err(e)
55 } else {
56 Ok(wire)
57 }
58 }
59}
60
61impl SignWith for InterestBuilder {
62 fn sign_with_sync(self, signer: &dyn Signer) -> Result<Bytes, TrustError> {
63 let sig_type = signer.sig_type();
64 let key_name = signer.key_name().clone();
65 let captured_err: RefCell<Option<TrustError>> = RefCell::new(None);
66 let wire = self.sign_sync(sig_type, Some(&key_name), |region| {
67 match signer.sign_sync(region) {
68 Ok(sig) => sig,
69 Err(e) => {
70 *captured_err.borrow_mut() = Some(e);
71 Bytes::new()
72 }
73 }
74 });
75 if let Some(e) = captured_err.into_inner() {
76 Err(e)
77 } else {
78 Ok(wire)
79 }
80 }
81}
82
83#[cfg(test)]
84mod tests {
85 use super::*;
86 use crate::{KeyChain, signer::Ed25519Signer};
87 use ndn_packet::encode::DataBuilder;
88
89 #[test]
90 fn data_sign_with_sync_roundtrip() {
91 let kc = KeyChain::ephemeral("/test/producer").unwrap();
92 let signer = kc.signer().unwrap();
93
94 let wire = DataBuilder::new("/test/producer/data", b"payload")
95 .sign_with_sync(&*signer)
96 .unwrap();
97
98 let data = ndn_packet::Data::decode(wire).unwrap();
100 assert_eq!(data.name.to_string(), "/test/producer/data");
101
102 let si = data.sig_info().unwrap();
104 let kl = si.key_locator.as_ref().unwrap();
105 assert_eq!(kl.to_string(), signer.key_name().to_string());
106 }
107
108 #[test]
109 fn interest_sign_with_sync_roundtrip() {
110 let seed = [42u8; 32];
111 let key_name: ndn_packet::Name = "/test/key".parse().unwrap();
112 let signer = Ed25519Signer::from_seed(&seed, key_name);
113
114 let wire = InterestBuilder::new("/test/prefix")
115 .sign_with_sync(&signer)
116 .unwrap();
117
118 let _interest = ndn_packet::Interest::decode(wire).unwrap();
120 }
121}