Merge pull request #38 from rust-bitcoin/2018-08-serde

add feature-gated serde 1.0 support for Signature, SecretKey, PublicKey
This commit is contained in:
Andrew Poelstra 2018-07-25 23:49:27 +00:00 committed by GitHub
commit ad080da1d8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 118 additions and 0 deletions

View File

@ -10,6 +10,7 @@ script:
- cargo build --verbose --features=fuzztarget
- cargo build --verbose --features=rand
- cargo test --verbose --features=rand
- cargo test --verbose --features="rand serde"
- cargo build --verbose
- cargo test --verbose
- cargo build --release

View File

@ -27,6 +27,7 @@ fuzztarget = []
[dev-dependencies]
rand = "0.3"
serde_test = "1.0"
[dependencies]
libc = "0.2"
@ -34,3 +35,7 @@ libc = "0.2"
[dependencies.rand]
version = "0.3"
optional = true
[dependencies.serde]
version = "1.0"
optional = true

View File

@ -121,6 +121,31 @@ impl SecretKey {
}
}
#[cfg(feature = "serde")]
impl ::serde::Serialize for SecretKey {
fn serialize<S: ::serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
s.serialize_bytes(&self.0)
}
}
#[cfg(feature = "serde")]
impl<'de> ::serde::Deserialize<'de> for SecretKey {
fn deserialize<D: ::serde::Deserializer<'de>>(d: D) -> Result<SecretKey, D::Error> {
use ::serde::de::Error;
// serde can actually deserialize a 32-byte array directly rather than deserializing
// a byte slice and copying, but it has special code for byte-slices and no special
// code for byte-arrays, meaning this is actually simpler and more efficient
let mut arr = [0; 32];
let sl: &[u8] = ::serde::Deserialize::deserialize(d)?;
if sl.len() != constants::SECRET_KEY_SIZE {
return Err(D::Error::invalid_length(sl.len(), &"32"));
}
arr.copy_from_slice(sl);
Ok(SecretKey(arr))
}
}
impl PublicKey {
/// Obtains a raw pointer suitable for use with FFI functions
#[inline]
@ -254,6 +279,24 @@ impl From<ffi::PublicKey> for PublicKey {
}
}
#[cfg(feature = "serde")]
impl ::serde::Serialize for PublicKey {
fn serialize<S: ::serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
s.serialize_bytes(&self.serialize())
}
}
#[cfg(feature = "serde")]
impl<'de> ::serde::Deserialize<'de> for PublicKey {
fn deserialize<D: ::serde::Deserializer<'de>>(d: D) -> Result<PublicKey, D::Error> {
use ::serde::de::Error;
let secp = Secp256k1::without_caps();
let sl: &[u8] = ::serde::Deserialize::deserialize(d)?;
PublicKey::from_slice(&secp, sl).map_err(D::Error::custom)
}
}
#[cfg(test)]
mod test {
use super::super::{Secp256k1};
@ -529,6 +572,33 @@ mod test {
assert!(pk3 <= pk1);
assert!(pk1 >= pk3);
}
#[cfg(feature = "serde")]
#[test]
fn test_signature_serde() {
use serde_test::{Token, assert_tokens};
static SK_BYTES: [u8; 32] = [
1, 1, 1, 1, 1, 1, 1, 1,
0, 1, 2, 3, 4, 5, 6, 7,
0xff, 0xff, 0, 0, 0xff, 0xff, 0, 0,
99, 99, 99, 99, 99, 99, 99, 99
];
static PK_BYTES: [u8; 33] = [
0x02,
0x18, 0x84, 0x57, 0x81, 0xf6, 0x31, 0xc4, 0x8f,
0x1c, 0x97, 0x09, 0xe2, 0x30, 0x92, 0x06, 0x7d,
0x06, 0x83, 0x7f, 0x30, 0xaa, 0x0c, 0xd0, 0x54,
0x4a, 0xc8, 0x87, 0xfe, 0x91, 0xdd, 0xd1, 0x66,
];
let s = Secp256k1::new();
let sk = SecretKey::from_slice(&s, &SK_BYTES).unwrap();
let pk = PublicKey::from_secret_key(&s, &sk);
assert_tokens(&sk, &[Token::BorrowedBytes(&SK_BYTES[..])]);
assert_tokens(&pk, &[Token::BorrowedBytes(&PK_BYTES[..])]);
}
}

View File

@ -39,6 +39,8 @@
#![cfg_attr(all(test, feature = "unstable"), feature(test))]
#[cfg(all(test, feature = "unstable"))] extern crate test;
#[cfg(any(test, feature = "rand"))] extern crate rand;
#[cfg(feature = "serde")] extern crate serde;
#[cfg(all(test, feature = "serde"))] extern crate serde_test;
extern crate libc;
@ -305,6 +307,25 @@ impl ops::Index<ops::RangeFull> for Signature {
}
}
#[cfg(feature = "serde")]
impl ::serde::Serialize for Signature {
fn serialize<S: ::serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
let secp = Secp256k1::without_caps();
s.serialize_bytes(&self.serialize_der(&secp))
}
}
#[cfg(feature = "serde")]
impl<'de> ::serde::Deserialize<'de> for Signature {
fn deserialize<D: ::serde::Deserializer<'de>>(d: D) -> Result<Signature, D::Error> {
use ::serde::de::Error;
let secp = Secp256k1::without_caps();
let sl: &[u8] = ::serde::Deserialize::deserialize(d)?;
Signature::from_der(&secp, sl).map_err(D::Error::custom)
}
}
/// A (hashed) message input to an ECDSA signature
pub struct Message([u8; constants::MESSAGE_SIZE]);
impl_array_newtype!(Message, u8, constants::MESSAGE_SIZE);
@ -903,6 +924,27 @@ mod tests {
sig.normalize_s(&secp);
assert_eq!(secp.verify(&msg, &sig, &pk), Ok(()));
}
#[cfg(feature = "serde")]
#[test]
fn test_signature_serde() {
use serde_test::{Token, assert_tokens};
let s = Secp256k1::new();
let msg = Message::from_slice(&[1; 32]).unwrap();
let sk = SecretKey::from_slice(&s, &[2; 32]).unwrap();
let sig = s.sign(&msg, &sk);
static SIG_BYTES: [u8; 71] = [
48, 69, 2, 33, 0, 157, 11, 173, 87, 103, 25, 211, 42, 231, 107, 237,
179, 76, 119, 72, 102, 103, 60, 189, 227, 244, 225, 41, 81, 85, 92, 148,
8, 230, 206, 119, 75, 2, 32, 40, 118, 231, 16, 47, 32, 79, 107, 254,
226, 108, 150, 124, 57, 38, 206, 112, 44, 249, 125, 75, 1, 0, 98, 225,
147, 247, 99, 25, 15, 103, 118
];
assert_tokens(&sig, &[Token::BorrowedBytes(&SIG_BYTES[..])]);
}
}
#[cfg(all(test, feature = "unstable"))]