Merge pull request #16 from apoelstra/compact-sig

add compact signature encoding
This commit is contained in:
Andrew Poelstra 2017-07-12 20:06:53 +00:00 committed by GitHub
commit e69fedb35a
3 changed files with 48 additions and 2 deletions

View File

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

View File

@ -150,6 +150,10 @@ extern "C" {
input: *const c_uchar, in_len: size_t) input: *const c_uchar, in_len: size_t)
-> c_int; -> 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, pub fn ecdsa_signature_parse_der_lax(cx: *const Context, sig: *mut Signature,
input: *const c_uchar, in_len: size_t) input: *const c_uchar, in_len: size_t)
-> c_int; -> c_int;
@ -158,6 +162,10 @@ extern "C" {
out_len: *mut size_t, sig: *const Signature) out_len: *mut size_t, sig: *const Signature)
-> c_int; -> 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, pub fn secp256k1_ecdsa_recoverable_signature_parse_compact(cx: *const Context, sig: *mut RecoverableSignature,
input64: *const c_uchar, recid: c_int) input64: *const c_uchar, recid: c_int)
-> 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 /// Converts a "lax DER"-encoded byte slice to a signature. This is basically
/// only useful for validating signatures in the Bitcoin blockchain from before /// only useful for validating signatures in the Bitcoin blockchain from before
/// 2016. It should never be used in new applications. This library does not /// 2016. It should never be used in new applications. This library does not
@ -171,6 +188,18 @@ impl Signature {
} }
ret 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 /// Creates a new signature from a FFI signature
@ -650,7 +679,7 @@ mod tests {
} }
#[test] #[test]
fn signature_der_roundtrip() { fn signature_serialize_roundtrip() {
let mut s = Secp256k1::new(); let mut s = Secp256k1::new();
s.randomize(&mut thread_rng()); s.randomize(&mut thread_rng());
@ -664,6 +693,15 @@ mod tests {
let der = sig1.serialize_der(&s); let der = sig1.serialize_der(&s);
let sig2 = Signature::from_der(&s, &der[..]).unwrap(); let sig2 = Signature::from_der(&s, &der[..]).unwrap();
assert_eq!(sig1, sig2); 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());
} }
} }