stellar_baselib/
signing.rs1pub fn sign(data: &[u8], secret_key: &[u8]) -> [u8; 64] {
5 signing_impl::sign(data, secret_key)
6}
7pub fn verify(data: &[u8], signature: &[u8], public_key: &[u8]) -> bool {
9 signing_impl::verify(data, signature, public_key)
10}
11
12pub fn generate(secret_key: &[u8]) -> [u8; 32] {
14 signing_impl::generate(secret_key)
15}
16
17#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
18mod signing_impl {
19 pub fn generate(secret_key: &[u8]) -> [u8; 32] {
20 let secret_key_u8: &[u8; 32] = secret_key.try_into().unwrap();
21 let nacl_keys = nacl::sign::generate_keypair(secret_key_u8);
22 nacl_keys.pkey
23 }
24
25 pub fn sign(data: &[u8], secret_key: &[u8]) -> [u8; 64] {
26 let mut data_u8 = data;
27 let mut secret_key_u8 = secret_key;
28 let signed_msg = nacl::sign::signature(&mut data_u8, &mut secret_key_u8).unwrap();
29 let mut signature = [0u8; 64];
30
31 for i in 0..signed_msg.len() {
32 signature[i] = signed_msg[i];
33 }
34 signature
35 }
36
37 pub fn verify(data: &[u8], signature: &[u8], public_key: &[u8]) -> bool {
38 let data_u8 = data;
39 let signature_u8 = signature;
40 let public_key_u8 = public_key;
41 nacl::sign::verify(data_u8, signature_u8, public_key_u8).unwrap()
42 }
43}
44
45#[cfg(not(target_arch = "wasm32"))]
46mod signing_impl {
47 use libsodium_sys::crypto_sign_detached;
48 use libsodium_sys::crypto_sign_seed_keypair;
49
50 macro_rules! raw_ptr_char {
51 ($name: ident) => {
52 $name.as_mut_ptr() as *mut libc::c_uchar
53 };
54 }
55
56 macro_rules! raw_ptr_char_immut {
58 ($name: ident) => {
59 $name.as_ptr() as *const libc::c_uchar
60 };
61 }
62
63 pub fn generate(secret_key: &[u8]) -> [u8; 32] {
64 unsafe {
65 libsodium_sys::sodium_init();
66 };
67
68 unsafe {
69 let mut pk = [0u8; libsodium_sys::crypto_sign_PUBLICKEYBYTES as usize];
70 let mut sk = [0u8; libsodium_sys::crypto_sign_SECRETKEYBYTES as usize];
71
72 libsodium_sys::crypto_sign_seed_keypair(
73 raw_ptr_char!(pk),
74 raw_ptr_char!(sk),
75 raw_ptr_char_immut!(secret_key),
76 );
77
78 pk
79 }
80 }
81
82 pub fn sign(data: &[u8], secret_key: &[u8]) -> [u8; 64] {
83 unsafe {
84 unsafe {
85 let mut signature = [0u8; libsodium_sys::crypto_sign_BYTES as usize];
86
87 libsodium_sys::crypto_sign_detached(
88 raw_ptr_char!(signature),
89 std::ptr::null_mut(),
90 raw_ptr_char_immut!(data),
91 data.len() as libc::c_ulonglong,
92 secret_key.as_ptr(),
93 );
94
95 signature
96 }
97 }
98 }
99
100 pub fn verify(data: &[u8], signature: &[u8], public_key: &[u8]) -> bool {
101 unsafe {
102 let val = libsodium_sys::crypto_sign_verify_detached(
103 raw_ptr_char_immut!(signature),
104 raw_ptr_char_immut!(data),
105 data.len() as libc::c_ulonglong,
106 raw_ptr_char_immut!(public_key),
107 );
108
109 val == 0
110 }
111 }
112}
113
114#[cfg(test)]
115mod tests {
116 use super::*;
117 use hex_literal::hex;
118
119 #[test]
120 fn test_hash_string() {
121 let data = b"hello world";
122 let expected_sig = hex!(
123 "587d4b472eeef7d07aafcd0b049640b0bb3f39784118c2e2b73a04fa2f64c9c538b4b2d0f5335e968a480021fdc23e98c0ddf424cb15d8131df8cb6c4bb58309"
124 );
125 let actual_sig = sign(data, &hex!(
126 "1123740522f11bfef6b3671f51e159ccf589ccf8965262dd5f97d1721d383dd4ffbdd7ef9933fe7249dc5ca1e7120b6d7b7b99a7a367e1a2fc6cb062fe420437"
127 ));
128 assert_eq!(expected_sig, actual_sig);
129 }
130 #[test]
131 fn test_verify_string() {
132 let data = "hello world".as_bytes();
133 let sig = hex!(
134 "587d4b472eeef7d07aafcd0b049640b0bb3f39784118c2e2b73a04fa2f64c9c538b4b2d0f5335e968a480021fdc23e98c0ddf424cb15d8131df8cb6c4bb58309"
135 );
136 let bad_sig = hex!(
137 "687d4b472eeef7d07aafcd0b049640b0bb3f39784118c2e2b73a04fa2f64c9c538b4b2d0f5335e968a480021fdc23e98c0ddf424cb15d8131df8cb6c4bb58309"
138 );
139 let public_key = hex!("ffbdd7ef9933fe7249dc5ca1e7120b6d7b7b99a7a367e1a2fc6cb062fe420437");
140
141 assert!(verify(data, &sig, &public_key));
142 assert!(!verify(b"corrupted", &sig, &public_key));
143 assert!(!verify(data, &bad_sig, &public_key));
144 }
145}