Skip to content

Commit

Permalink
Added a new struct for the DER serialized signature
Browse files Browse the repository at this point in the history
  • Loading branch information
elichai committed Apr 11, 2019
1 parent 9427070 commit 0e0d8df
Showing 1 changed file with 79 additions and 55 deletions.
134 changes: 79 additions & 55 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ pub mod key;
pub use key::SecretKey;
pub use key::PublicKey;
use core::marker::PhantomData;
use core::ops::Deref;

/// A tag used for recovering the public key from a compact signature
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
Expand All @@ -165,6 +166,13 @@ pub struct RecoveryId(i32);
#[derive(Copy, Clone, PartialEq, Eq)]
pub struct Signature(ffi::Signature);

/// A DER serialized Signature
#[derive(Copy, Clone)]
pub struct SerSignature {
data: [u8; 72],
len: usize,
}

impl fmt::Debug for Signature {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(self, f)
Expand Down Expand Up @@ -231,6 +239,40 @@ pub fn to_i32(self) -> i32 {
}
}

impl SerSignature {
/// Get a pointer to the underlying data with the specified capacity.
pub fn get_data_mut_ptr(&mut self) -> *mut u8 {
self.data.as_mut_ptr()
}

/// Get the capacity of the underlying data buffer.
pub fn capacity(&self) -> usize {
self.data.len()
}

/// Get the len of the used data.
pub fn len(&self) -> usize {
self.len
}

/// Set the length of the object.
pub(crate) fn set_len(&mut self, len: usize) {
self.len = len;
}

/// Convert the serialized signature into the Signature struct.
/// (This basically DER deserialize it)
pub fn to_signature(&self) -> Result<Signature, Error> {
Signature::from_der(&self)
}

/// Create a SerSignature from a Signature.
/// (this basically DER serialize it)
pub fn from_signature(sig: &Signature) -> SerSignature {
sig.serialize_der()
}
}

impl Signature {
#[inline]
/// Converts a DER-encoded byte slice to a signature
Expand Down Expand Up @@ -335,44 +377,24 @@ impl Signature {
&mut self.0 as *mut _
}

#[cfg(feature = "std")]
#[inline]
/// Serializes the signature in DER format
pub fn serialize_der(&self) -> Vec<u8>{
let mut ret = Vec::with_capacity(72);
let mut len: usize = ret.capacity() as usize;
pub fn serialize_der(&self) -> SerSignature {
let mut ret = SerSignature::default();
let mut len: usize = ret.capacity();
unsafe {
let err = ffi::secp256k1_ecdsa_signature_serialize_der(
ffi::secp256k1_context_no_precomp,
ret.as_mut_ptr(),
ret.get_data_mut_ptr(),
&mut len,
self.as_ptr(),
);
debug_assert!(err == 1);
ret.set_len(len as usize);
ret.set_len(len);
}
ret
}

#[inline]
/// Serializes the signature in DER format without allocating memory
/// The signature can be anywhere from 8 bytes to 72 bytes
/// So the function needs a buffer that is equal or larger than 72 bytes
/// It will write into that buffer and return a slice containing only the signature
pub fn serialize_der_no_alloc<'a>(&self, buf: &'a mut [u8]) -> &'a [u8] {
let mut len: usize = buf.len();
unsafe {
let err = ffi::secp256k1_ecdsa_signature_serialize_der(
ffi::secp256k1_context_no_precomp,
buf.as_mut_ptr(),
&mut len,
self.as_ptr(),
);
debug_assert!(err == 1);
}
&buf[..len]
}

#[inline]
/// Serializes the signature in compact format
pub fn serialize_compact(&self) -> [u8; 64] {
Expand Down Expand Up @@ -474,8 +496,7 @@ impl From<ffi::RecoverableSignature> for RecoverableSignature {
#[cfg(feature = "serde")]
impl ::serde::Serialize for Signature {
fn serialize<S: ::serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
let mut buf = [0u8; 72];
s.serialize_bytes(&self.serialize_der_no_alloc(&mut buf))
s.serialize_bytes(&self.serialize_der())
}
}

Expand Down Expand Up @@ -611,6 +632,37 @@ impl<C> PartialEq for Secp256k1<C> {
fn eq(&self, _other: &Secp256k1<C>) -> bool { true }
}

impl Default for SerSignature {
fn default() -> SerSignature {
SerSignature {
data: [0u8; 72],
len: 0,
}
}
}

impl PartialEq for SerSignature {
fn eq(&self, other: &SerSignature) -> bool {
&self.data[..] == &other.data[..] &&
self.len == other.len
}
}

impl AsRef<[u8]> for SerSignature {
fn as_ref(&self) -> &[u8] {
&self.data[..self.len]
}
}

impl Deref for SerSignature {
type Target = [u8];
fn deref(&self) -> &[u8] {
&self.data[..self.len]
}
}

impl Eq for SerSignature {}

impl<C> Eq for Secp256k1<C> { }

impl<C> Drop for Secp256k1<C> {
Expand Down Expand Up @@ -932,34 +984,6 @@ mod tests {
}
}

#[test]
fn signature_serialize_no_alloc_roundtrip() {
let mut s = Secp256k1::new();
s.randomize(&mut thread_rng());

let mut msg = [0; 32];
for _ in 0..100 {
thread_rng().fill_bytes(&mut msg);
let msg = Message::from_slice(&msg).unwrap();

let (sk, _) = s.generate_keypair(&mut thread_rng());
let sig1 = s.sign(&msg, &sk);
let mut buf = vec![0u8; 172];
let der = sig1.serialize_der_no_alloc(&mut buf);
let sig2 = Signature::from_der(&der[..]).unwrap();
assert_eq!(sig1, sig2);

let compact = sig1.serialize_compact();
let sig2 = Signature::from_compact(&compact[..]).unwrap();
assert_eq!(sig1, sig2);

assert!(Signature::from_compact(&der[..]).is_err());
assert!(Signature::from_compact(&compact[0..4]).is_err());
assert!(Signature::from_der(&compact[..]).is_err());
assert!(Signature::from_der(&der[0..4]).is_err());
}
}

#[test]
fn signature_display() {
let hex_str = "3046022100839c1fbc5304de944f697c9f4b1d01d1faeba32d751c0f7acb21ac8a0f436a72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab45";
Expand Down

0 comments on commit 0e0d8df

Please sign in to comment.