From 8e984c5912bbf36450e769ddf731a37ee08ef340 Mon Sep 17 00:00:00 2001 From: Andrew Poelstra Date: Mon, 26 Oct 2015 12:59:40 -0500 Subject: [PATCH] Add "lax DER" support; bump major version number for recent build system changes --- Cargo.toml | 2 +- build.rs | 36 +++++++++++++++++------------- depend/secp256k1/src/laxder_shim.c | 21 +++++++++++++++++ src/ffi.rs | 4 ++++ src/lib.rs | 27 ++++++++++++++++++++++ 5 files changed, 73 insertions(+), 17 deletions(-) create mode 100644 depend/secp256k1/src/laxder_shim.c diff --git a/Cargo.toml b/Cargo.toml index eb031f3..a29ea76 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "secp256k1" -version = "0.3.3" +version = "0.4.0" authors = [ "Dawid Ciężarkiewicz ", "Andrew Poelstra " ] license = "CC0-1.0" diff --git a/build.rs b/build.rs index fc6da49..4b49ebb 100644 --- a/build.rs +++ b/build.rs @@ -24,21 +24,25 @@ extern crate gcc; fn main() { - gcc::Config::new() - .file("depend/secp256k1/src/secp256k1.c") - .include("depend/secp256k1/") - .include("depend/secp256k1/src") - // TODO these three should be changed to use libgmp, at least until secp PR 290 is merged - .define("USE_NUM_NONE", Some("1")) - .define("USE_FIELD_INV_BUILTIN", Some("1")) - .define("USE_SCALAR_INV_BUILTIN", Some("1")) - // TODO these should use 64-bit variants on 64-bit systems - .define("USE_FIELD_10X26", Some("1")) - .define("USE_SCALAR_8X32", Some("1")) - .define("USE_ENDOMORPHISM", Some("1")) - // These all are OK. - .define("ENABLE_MODULE_ECDH", Some("1")) - .define("ENABLE_MODULE_RECOVERY", Some("1")) - .compile("libsecp256k1.a"); + let mut base_config = gcc::Config::new(); + base_config.include("depend/secp256k1/") + .include("depend/secp256k1/src") + .flag("-g") + // TODO these three should be changed to use libgmp, at least until secp PR 290 is merged + .define("USE_NUM_NONE", Some("1")) + .define("USE_FIELD_INV_BUILTIN", Some("1")) + .define("USE_SCALAR_INV_BUILTIN", Some("1")) + // TODO these should use 64-bit variants on 64-bit systems + .define("USE_FIELD_10X26", Some("1")) + .define("USE_SCALAR_8X32", Some("1")) + .define("USE_ENDOMORPHISM", Some("1")) + // These all are OK. + .define("ENABLE_MODULE_ECDH", Some("1")) + .define("ENABLE_MODULE_RECOVERY", Some("1")); + + // secp256k1 + base_config.file("depend/secp256k1/src/laxder_shim.c") + .file("depend/secp256k1/src/secp256k1.c") + .compile("libsecp256k1.a"); } diff --git a/depend/secp256k1/src/laxder_shim.c b/depend/secp256k1/src/laxder_shim.c new file mode 100644 index 0000000..a6c4cc9 --- /dev/null +++ b/depend/secp256k1/src/laxder_shim.c @@ -0,0 +1,21 @@ +/* Bitcoin secp256k1 bindings + * Written in 2015 by + * Andrew Poelstra + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to + * the public domain worldwide. This software is distributed without + * any warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication + * along with this software. + * If not, see . + */ + +#include "contrib/lax_der_parsing.h" + +int secp256k1_ecdsa_signature_parse_der_lax_(const secp256k1_context* ctx, secp256k1_ecdsa_signature* sig, const unsigned char *input, size_t inputlen) { + return secp256k1_ecdsa_signature_parse_der_lax(ctx, sig, input, inputlen); +} + + diff --git a/src/ffi.rs b/src/ffi.rs index 4016342..9be4e64 100644 --- a/src/ffi.rs +++ b/src/ffi.rs @@ -154,6 +154,10 @@ extern "C" { input: *const c_uchar, in_len: size_t) -> c_int; + pub fn secp256k1_ecdsa_signature_parse_der_lax_(cx: Context, sig: *mut Signature, + input: *const c_uchar, in_len: size_t) + -> c_int; + pub fn secp256k1_ecdsa_signature_serialize_der(cx: Context, output: *const c_uchar, out_len: *const size_t, sig: *const Signature) -> c_int; diff --git a/src/lib.rs b/src/lib.rs index a197fb5..9623215 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -99,6 +99,22 @@ impl Signature { } } + /// 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 + /// support serializing to this "format" + pub fn from_der_lax(secp: &Secp256k1, data: &[u8]) -> Result { + unsafe { + let mut ret = ffi::Signature::blank(); + if ffi::secp256k1_ecdsa_signature_parse_der_lax_(secp.ctx, &mut ret, + data.as_ptr(), data.len() as libc::size_t) == 1 { + Ok(Signature(ret)) + } else { + Err(Error::InvalidSignature) + } + } + } + /// Obtains a raw pointer suitable for use with FFI functions #[inline] pub fn as_ptr(&self) -> *const ffi::Signature { @@ -484,6 +500,7 @@ impl Secp256k1 { mod tests { use rand::{Rng, thread_rng}; use std::ptr; + use serialize::hex::FromHex; use key::{SecretKey, PublicKey}; use super::constants; @@ -491,6 +508,8 @@ mod tests { use super::Error::{InvalidMessage, InvalidPublicKey, IncorrectSignature, InvalidSignature, IncapableContext}; + macro_rules! hex (($hex:expr) => ($hex.from_hex().unwrap())); + #[test] fn capabilities() { let none = Secp256k1::with_caps(ContextFlag::None); @@ -610,6 +629,14 @@ mod tests { } } + #[test] + fn signature_lax_der() { + let secp = Secp256k1::without_caps(); + let sig = hex!("304402204c2dd8a9b6f8d425fcd8ee9a20ac73b619906a6367eac6cb93e70375225ec0160220356878eff111ff3663d7e6bf08947f94443845e0dcc54961664d922f7660b80c01"); + assert!(Signature::from_der(&secp, &sig[..]).is_err()); + assert!(Signature::from_der_lax(&secp, &sig[..]).is_ok()); + } + #[test] fn sign_and_verify() { let mut s = Secp256k1::new();