add compact signature encoding

This commit is contained in:
Andrew Poelstra 2017-07-12 19:55:06 +00:00
parent c1951d6025
commit b6887b44a0
No known key found for this signature in database
GPG Key ID: 4FACF08041655A68
3 changed files with 48 additions and 2 deletions

View File

@ -1,7 +1,7 @@
[package]
name = "secp256k1"
version = "0.6.2"
version = "0.6.3"
authors = [ "Dawid Ciężarkiewicz <dpc@ucore.info>",
"Andrew Poelstra <apoelstra@wpsoftware.net>" ]
license = "CC0-1.0"

View File

@ -150,6 +150,10 @@ extern "C" {
input: *const c_uchar, in_len: size_t)
-> c_int;
pub fn secp256k1_ecdsa_signature_parse_compact(cx: *const Context, sig: *mut Signature,
input64: *const c_uchar)
-> c_int;
pub fn ecdsa_signature_parse_der_lax(cx: *const Context, sig: *mut Signature,
input: *const c_uchar, in_len: size_t)
-> c_int;
@ -158,6 +162,10 @@ extern "C" {
out_len: *mut size_t, sig: *const Signature)
-> c_int;
pub fn secp256k1_ecdsa_signature_serialize_compact(cx: *const Context, output64: *const c_uchar,
sig: *const Signature)
-> c_int;
pub fn secp256k1_ecdsa_recoverable_signature_parse_compact(cx: *const Context, sig: *mut RecoverableSignature,
input64: *const c_uchar, recid: c_int)
-> c_int;

View File

@ -104,6 +104,23 @@ impl Signature {
}
}
/// Converts a 64-byte compact-encoded byte slice to a signature
pub fn from_compact(secp: &Secp256k1, data: &[u8]) -> Result<Signature, Error> {
let mut ret = unsafe { ffi::Signature::blank() };
if data.len() != 64 {
return Err(Error::InvalidSignature)
}
unsafe {
if ffi::secp256k1_ecdsa_signature_parse_compact(secp.ctx, &mut ret,
data.as_ptr()) == 1 {
Ok(Signature(ret))
} else {
Err(Error::InvalidSignature)
}
}
}
/// Converts a "lax DER"-encoded byte slice to a signature. This is basically
/// only useful for validating signatures in the Bitcoin blockchain from before
/// 2016. It should never be used in new applications. This library does not
@ -171,6 +188,18 @@ impl Signature {
}
ret
}
#[inline]
/// Serializes the signature in compact format
pub fn serialize_compact(&self, secp: &Secp256k1) -> [u8; 64] {
let mut ret = [0; 64];
unsafe {
let err = ffi::secp256k1_ecdsa_signature_serialize_compact(secp.ctx, ret.as_mut_ptr(),
self.as_ptr());
debug_assert!(err == 1);
}
ret
}
}
/// Creates a new signature from a FFI signature
@ -650,7 +679,7 @@ mod tests {
}
#[test]
fn signature_der_roundtrip() {
fn signature_serialize_roundtrip() {
let mut s = Secp256k1::new();
s.randomize(&mut thread_rng());
@ -664,6 +693,15 @@ mod tests {
let der = sig1.serialize_der(&s);
let sig2 = Signature::from_der(&s, &der[..]).unwrap();
assert_eq!(sig1, sig2);
let compact = sig1.serialize_compact(&s);
let sig2 = Signature::from_compact(&s, &compact[..]).unwrap();
assert_eq!(sig1, sig2);
assert!(Signature::from_compact(&s, &der[..]).is_err());
assert!(Signature::from_compact(&s, &compact[0..4]).is_err());
assert!(Signature::from_der(&s, &compact[..]).is_err());
assert!(Signature::from_der(&s, &der[0..4]).is_err());
}
}