|
15 | 15 | //! Support for shared secret computations.
|
16 | 16 | //!
|
17 | 17 |
|
18 |
| -use core::ptr; |
| 18 | +use core::{ptr, str}; |
19 | 19 | use core::borrow::Borrow;
|
20 | 20 |
|
| 21 | +use {Error, from_hex}; |
21 | 22 | use key::{SecretKey, PublicKey};
|
22 | 23 | use ffi::{self, CPtr};
|
23 | 24 | use secp256k1_sys::types::{c_int, c_uchar, c_void};
|
@@ -72,10 +73,35 @@ impl SharedSecret {
|
72 | 73 | self.0
|
73 | 74 | }
|
74 | 75 |
|
75 |
| - /// Creates a shared secret from a byte serialization. |
| 76 | + /// Creates a shared secret from `bytes` array. |
| 77 | + #[inline] |
76 | 78 | pub fn from_bytes(bytes: [u8; SHARED_SECRET_SIZE]) -> SharedSecret {
|
77 | 79 | SharedSecret(bytes)
|
78 | 80 | }
|
| 81 | + |
| 82 | + /// Creates a shared secret from `bytes` slice. |
| 83 | + #[inline] |
| 84 | + pub fn from_slice(bytes: &[u8]) -> Result<SharedSecret, Error> { |
| 85 | + match bytes.len() { |
| 86 | + SHARED_SECRET_SIZE => { |
| 87 | + let mut ret = [0u8; SHARED_SECRET_SIZE]; |
| 88 | + ret[..].copy_from_slice(bytes); |
| 89 | + Ok(SharedSecret(ret)) |
| 90 | + } |
| 91 | + _ => Err(Error::InvalidSharedSecret) |
| 92 | + } |
| 93 | + } |
| 94 | +} |
| 95 | + |
| 96 | +impl str::FromStr for SharedSecret { |
| 97 | + type Err = Error; |
| 98 | + fn from_str(s: &str) -> Result<SharedSecret, Error> { |
| 99 | + let mut res = [0u8; SHARED_SECRET_SIZE]; |
| 100 | + match from_hex(s, &mut res) { |
| 101 | + Ok(SHARED_SECRET_SIZE) => Ok(SharedSecret::from_bytes(res)), |
| 102 | + _ => Err(Error::InvalidSharedSecret) |
| 103 | + } |
| 104 | + } |
79 | 105 | }
|
80 | 106 |
|
81 | 107 | impl Borrow<[u8]> for SharedSecret {
|
@@ -145,6 +171,36 @@ unsafe extern "C" fn c_callback(output: *mut c_uchar, x: *const c_uchar, y: *con
|
145 | 171 | 1
|
146 | 172 | }
|
147 | 173 |
|
| 174 | +#[cfg(feature = "serde")] |
| 175 | +#[cfg_attr(docsrs, doc(cfg(feature = "serde")))] |
| 176 | +impl ::serde::Serialize for SharedSecret { |
| 177 | + fn serialize<S: ::serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> { |
| 178 | + if s.is_human_readable() { |
| 179 | + let mut buf = [0u8; SHARED_SECRET_SIZE * 2]; |
| 180 | + s.serialize_str(::to_hex(&self.0, &mut buf).expect("fixed-size hex serialization")) |
| 181 | + } else { |
| 182 | + s.serialize_bytes(&self.as_ref()[..]) |
| 183 | + } |
| 184 | + } |
| 185 | +} |
| 186 | + |
| 187 | +#[cfg(feature = "serde")] |
| 188 | +#[cfg_attr(docsrs, doc(cfg(feature = "serde")))] |
| 189 | +impl<'de> ::serde::Deserialize<'de> for SharedSecret { |
| 190 | + fn deserialize<D: ::serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> { |
| 191 | + if d.is_human_readable() { |
| 192 | + d.deserialize_str(super::serde_util::FromStrVisitor::new( |
| 193 | + "a hex string representing 32 byte SharedSecret" |
| 194 | + )) |
| 195 | + } else { |
| 196 | + d.deserialize_bytes(super::serde_util::BytesVisitor::new( |
| 197 | + "raw 32 bytes SharedSecret", |
| 198 | + SharedSecret::from_slice |
| 199 | + )) |
| 200 | + } |
| 201 | + } |
| 202 | +} |
| 203 | + |
148 | 204 | #[cfg(test)]
|
149 | 205 | #[allow(unused_imports)]
|
150 | 206 | mod tests {
|
@@ -207,6 +263,31 @@ mod tests {
|
207 | 263 |
|
208 | 264 | assert_eq!(secret_bh.as_inner(), secret_sys.as_ref());
|
209 | 265 | }
|
| 266 | + |
| 267 | + #[test] |
| 268 | + #[cfg(all(feature = "serde", any(feature = "alloc", feature = "std")))] |
| 269 | + fn serde() { |
| 270 | + use serde_test::{Configure, Token, assert_tokens}; |
| 271 | + static BYTES: [u8; 32] = [ |
| 272 | + 1, 1, 1, 1, 1, 1, 1, 1, |
| 273 | + 0, 1, 2, 3, 4, 5, 6, 7, |
| 274 | + 0xff, 0xff, 0, 0, 0xff, 0xff, 0, 0, |
| 275 | + 99, 99, 99, 99, 99, 99, 99, 99 |
| 276 | + ]; |
| 277 | + static STR: &'static str = "\ |
| 278 | + 01010101010101010001020304050607ffff0000ffff00006363636363636363\ |
| 279 | + "; |
| 280 | + |
| 281 | + let secret = SharedSecret::from_slice(&BYTES).unwrap(); |
| 282 | + |
| 283 | + assert_tokens(&secret.compact(), &[Token::BorrowedBytes(&BYTES[..])]); |
| 284 | + assert_tokens(&secret.compact(), &[Token::Bytes(&BYTES)]); |
| 285 | + assert_tokens(&secret.compact(), &[Token::ByteBuf(&BYTES)]); |
| 286 | + |
| 287 | + assert_tokens(&secret.readable(), &[Token::BorrowedStr(STR)]); |
| 288 | + assert_tokens(&secret.readable(), &[Token::Str(STR)]); |
| 289 | + assert_tokens(&secret.readable(), &[Token::String(STR)]); |
| 290 | + } |
210 | 291 | }
|
211 | 292 |
|
212 | 293 | #[cfg(all(test, feature = "unstable"))]
|
|
0 commit comments