Skip to content

Commit

Permalink
Put signing behind feature flag (#33)
Browse files Browse the repository at this point in the history
Enables usage of the maths features crate without using the signing.
  • Loading branch information
dvdplm authored Jan 29, 2020
1 parent fcbcd94 commit 4c3eeec
Show file tree
Hide file tree
Showing 3 changed files with 155 additions and 140 deletions.
9 changes: 5 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ name = "secp256k1"

[dependencies]
rand = { version = "0.7", default-features = false }
hmac-drbg = "0.2"
sha2 = { version = "0.8", default-features = false }
hmac-drbg = { version = "0.2", optional = true }
sha2 = { version = "0.8", optional = true, default-features = false }
digest = "0.8"
typenum = "1.11"
typenum = { version = "1.11", optional = true }
arrayref = "0.3"
subtle = { version = "2.2", default-features = false }
crunchy = "0.2"
Expand All @@ -27,8 +27,9 @@ clear_on_drop = "0.2"
rand-test = { package = "rand", version = "0.4" }

[features]
default = ["std"]
default = ["std", "hmac"]
std = ["subtle/std", "rand/std", "sha2/std"]
hmac = ["hmac-drbg", "sha2", "typenum"]

[workspace]
members = [
Expand Down
4 changes: 4 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,11 @@ mod der;
extern crate alloc;

use core::convert::TryFrom;
#[cfg(feature = "hmac")]
use hmac_drbg::HmacDRBG;
#[cfg(feature = "hmac")]
use sha2::Sha256;
#[cfg(feature = "hmac")]
use typenum::U32;
use arrayref::{array_ref, array_mut_ref};
use rand::Rng;
Expand Down Expand Up @@ -617,6 +620,7 @@ pub fn recover(message: &Message, signature: &Signature, recovery_id: &RecoveryI
}

/// Sign a message using the secret key.
#[cfg(feature = "hmac")]
pub fn sign(message: &Message, seckey: &SecretKey) -> (Signature, RecoveryId) {
let seckey_b32 = seckey.0.b32();
let message_b32 = message.0.b32();
Expand Down
282 changes: 146 additions & 136 deletions tests/verify.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,153 @@
use rand_test::thread_rng;
use secp256k1::*;
use secp256k1::curve::*;
use secp256k1_test::{Secp256k1, Error as SecpError, Message as SecpMessage, RecoverableSignature as SecpRecoverableSignature, RecoveryId as SecpRecoveryId, Signature as SecpSignature};
use secp256k1_test::ecdh::{SharedSecret as SecpSharedSecret};
use secp256k1_test::{Secp256k1, Error as SecpError, Message as SecpMessage, Signature as SecpSignature};
use secp256k1_test::key;
use sha2::Sha256;

#[cfg(feature = "hmac")]
mod signatures {
use crate::{Message, PublicKey, SecretKey, SharedSecret, Signature, sign, verify, recover};
use rand_test::thread_rng;
use secp256k1_test::{Secp256k1, Message as SecpMessage, RecoverableSignature as SecpRecoverableSignature, RecoveryId as SecpRecoveryId, Signature as SecpSignature};
use secp256k1_test::ecdh::{SharedSecret as SecpSharedSecret};
use secp256k1_test::key;
use sha2::Sha256;


fn genkey(secp256k1: &Secp256k1) -> (key::PublicKey, key::SecretKey, PublicKey, SecretKey) {
let (secp_privkey, secp_pubkey) = secp256k1.generate_keypair(&mut thread_rng()).unwrap();
let pubkey_arr = secp_pubkey.serialize_vec(&secp256k1, false);
assert_eq!(pubkey_arr.len(), 65);
let mut pubkey_a = [0u8; 65];
for i in 0..65 {
pubkey_a[i] = pubkey_arr[i];
}
let pubkey = PublicKey::parse(&pubkey_a).unwrap();
let mut seckey_a = [0u8; 32];
for i in 0..32 {
seckey_a[i] = secp_privkey[i];
}
let seckey = SecretKey::parse(&seckey_a).unwrap();

(secp_pubkey, secp_privkey, pubkey, seckey)
}

#[test]
fn test_signature_der() {
let secp256k1 = Secp256k1::new();

let message_arr = [5u8; 32];
let (privkey, _) = secp256k1.generate_keypair(&mut thread_rng()).unwrap();

assert!(privkey[..].len() == 32);
let mut privkey_a = [0u8; 32];
for i in 0..32 {
privkey_a[i] = privkey[i];
}

let ctx_privkey = SecretKey::parse(&privkey_a).unwrap();
let ctx_message = Message::parse(&message_arr);

let (signature, _) = sign(&ctx_message, &ctx_privkey);
let reconstructed = Signature::parse_der(signature.serialize_der().as_ref()).unwrap();
assert_eq!(signature, reconstructed);
}

#[test]
fn test_sign_verify() {
let secp256k1 = Secp256k1::new();

let message_arr = [6u8; 32];
let (secp_privkey, secp_pubkey) = secp256k1.generate_keypair(&mut thread_rng()).unwrap();

let secp_message = SecpMessage::from_slice(&message_arr).unwrap();
let pubkey_arr = secp_pubkey.serialize_vec(&secp256k1, false);
assert_eq!(pubkey_arr.len(), 65);
let mut pubkey_a = [0u8; 65];
for i in 0..65 {
pubkey_a[i] = pubkey_arr[i];
}
let pubkey = PublicKey::parse(&pubkey_a).unwrap();
let mut seckey_a = [0u8; 32];
for i in 0..32 {
seckey_a[i] = secp_privkey[i];
}
let seckey = SecretKey::parse(&seckey_a).unwrap();
let message = Message::parse(&message_arr);

let (sig, recid) = sign(&message, &seckey);

// Self verify
assert!(verify(&message, &sig, &pubkey));

// Self recover
let recovered_pubkey = recover(&message, &sig, &recid).unwrap();
let rpa = recovered_pubkey.serialize();
let opa = pubkey.serialize();
let rpr: &[u8] = &rpa;
let opr: &[u8] = &opa;
assert_eq!(rpr, opr);

let signature_a = sig.serialize();
let secp_recid = SecpRecoveryId::from_i32(recid.into()).unwrap();
let secp_rec_signature = SecpRecoverableSignature::from_compact(&secp256k1, &signature_a, secp_recid).unwrap();
let secp_signature = SecpSignature::from_compact(&secp256k1, &signature_a).unwrap();

// External verify
secp256k1.verify(&secp_message, &secp_signature, &secp_pubkey).unwrap();

// External recover
let recovered_pubkey = secp256k1.recover(&secp_message, &secp_rec_signature).unwrap();
let rpa = recovered_pubkey.serialize_vec(&secp256k1, false);
let rpr: &[u8] = &rpa;
assert_eq!(rpr, opr);
}

#[test]
fn test_failing_sign_verify() {
let seckey_a: [u8; 32] = [169, 195, 92, 103, 2, 159, 75, 46, 158, 79, 249, 49, 208, 28, 48, 210, 5, 47, 136, 77, 21, 51, 224, 54, 213, 165, 90, 122, 233, 199, 0, 248];
let seckey = SecretKey::parse(&seckey_a).unwrap();
let pubkey = PublicKey::from_secret_key(&seckey);
let message_arr = [6u8; 32];
let message = Message::parse(&message_arr);

let (sig, recid) = sign(&message, &seckey);
let tmp: u8 = recid.into();
assert_eq!(tmp, 1u8);

let recovered_pubkey = recover(&message, &sig, &recid).unwrap();
let rpa = recovered_pubkey.serialize();
let opa = pubkey.serialize();
let rpr: &[u8] = &rpa;
let opr: &[u8] = &opa;
assert_eq!(rpr, opr);
}

#[test]
fn test_shared_secret() {
let secp256k1 = Secp256k1::new();

let (spub1, ssec1, pub1, sec1) = genkey(&secp256k1);
let (spub2, ssec2, pub2, sec2) = genkey(&secp256k1);

let shared1 = SharedSecret::<Sha256>::new(&pub1, &sec2).unwrap();
let shared2 = SharedSecret::<Sha256>::new(&pub2, &sec1).unwrap();

let secp_shared1 = SecpSharedSecret::new(&secp256k1, &spub1, &ssec2);
let secp_shared2 = SecpSharedSecret::new(&secp256k1, &spub2, &ssec1);

assert_eq!(shared1.as_ref(), shared2.as_ref());

for i in 0..32 {
assert_eq!(shared1.as_ref()[i], secp_shared1[i]);
}

for i in 0..32 {
assert_eq!(shared2.as_ref()[i], secp_shared2[i]);
}
}

}

#[test]
fn test_verify() {
Expand Down Expand Up @@ -88,27 +231,6 @@ fn test_recover() {
assert_eq!(sps, gps);
}

#[test]
fn test_signature_der() {
let secp256k1 = Secp256k1::new();

let message_arr = [5u8; 32];
let (privkey, _) = secp256k1.generate_keypair(&mut thread_rng()).unwrap();

assert!(privkey[..].len() == 32);
let mut privkey_a = [0u8; 32];
for i in 0..32 {
privkey_a[i] = privkey[i];
}

let ctx_privkey = SecretKey::parse(&privkey_a).unwrap();
let ctx_message = Message::parse(&message_arr);

let (signature, _) = sign(&ctx_message, &ctx_privkey);
let reconstructed = Signature::parse_der(signature.serialize_der().as_ref()).unwrap();
assert_eq!(signature, reconstructed);
}

fn from_hex(hex: &str, target: &mut [u8]) -> Result<usize, ()> {
if hex.len() % 2 == 1 || hex.len() > target.len() * 2 {
return Err(());
Expand Down Expand Up @@ -264,118 +386,6 @@ fn test_convert_anykey() {
assert_eq!(secp_pubkey_compressed_r, pubkey_compressed_r);
}

#[test]
fn test_sign_verify() {
let secp256k1 = Secp256k1::new();

let message_arr = [6u8; 32];
let (secp_privkey, secp_pubkey) = secp256k1.generate_keypair(&mut thread_rng()).unwrap();

let secp_message = SecpMessage::from_slice(&message_arr).unwrap();
let pubkey_arr = secp_pubkey.serialize_vec(&secp256k1, false);
assert_eq!(pubkey_arr.len(), 65);
let mut pubkey_a = [0u8; 65];
for i in 0..65 {
pubkey_a[i] = pubkey_arr[i];
}
let pubkey = PublicKey::parse(&pubkey_a).unwrap();
let mut seckey_a = [0u8; 32];
for i in 0..32 {
seckey_a[i] = secp_privkey[i];
}
let seckey = SecretKey::parse(&seckey_a).unwrap();
let message = Message::parse(&message_arr);

let (sig, recid) = sign(&message, &seckey);

// Self verify
assert!(verify(&message, &sig, &pubkey));

// Self recover
let recovered_pubkey = recover(&message, &sig, &recid).unwrap();
let rpa = recovered_pubkey.serialize();
let opa = pubkey.serialize();
let rpr: &[u8] = &rpa;
let opr: &[u8] = &opa;
assert_eq!(rpr, opr);

let signature_a = sig.serialize();
let secp_recid = SecpRecoveryId::from_i32(recid.into()).unwrap();
let secp_rec_signature = SecpRecoverableSignature::from_compact(&secp256k1, &signature_a, secp_recid).unwrap();
let secp_signature = SecpSignature::from_compact(&secp256k1, &signature_a).unwrap();

// External verify
secp256k1.verify(&secp_message, &secp_signature, &secp_pubkey).unwrap();

// External recover
let recovered_pubkey = secp256k1.recover(&secp_message, &secp_rec_signature).unwrap();
let rpa = recovered_pubkey.serialize_vec(&secp256k1, false);
let rpr: &[u8] = &rpa;
assert_eq!(rpr, opr);
}

#[test]
fn test_failing_sign_verify() {
let seckey_a: [u8; 32] = [169, 195, 92, 103, 2, 159, 75, 46, 158, 79, 249, 49, 208, 28, 48, 210, 5, 47, 136, 77, 21, 51, 224, 54, 213, 165, 90, 122, 233, 199, 0, 248];
let seckey = SecretKey::parse(&seckey_a).unwrap();
let pubkey = PublicKey::from_secret_key(&seckey);
let message_arr = [6u8; 32];
let message = Message::parse(&message_arr);

let (sig, recid) = sign(&message, &seckey);
let tmp: u8 = recid.into();
assert_eq!(tmp, 1u8);

let recovered_pubkey = recover(&message, &sig, &recid).unwrap();
let rpa = recovered_pubkey.serialize();
let opa = pubkey.serialize();
let rpr: &[u8] = &rpa;
let opr: &[u8] = &opa;
assert_eq!(rpr, opr);
}

fn genkey(secp256k1: &Secp256k1) -> (key::PublicKey, key::SecretKey, PublicKey, SecretKey) {
let (secp_privkey, secp_pubkey) = secp256k1.generate_keypair(&mut thread_rng()).unwrap();
let pubkey_arr = secp_pubkey.serialize_vec(&secp256k1, false);
assert_eq!(pubkey_arr.len(), 65);
let mut pubkey_a = [0u8; 65];
for i in 0..65 {
pubkey_a[i] = pubkey_arr[i];
}
let pubkey = PublicKey::parse(&pubkey_a).unwrap();
let mut seckey_a = [0u8; 32];
for i in 0..32 {
seckey_a[i] = secp_privkey[i];
}
let seckey = SecretKey::parse(&seckey_a).unwrap();

(secp_pubkey, secp_privkey, pubkey, seckey)
}

#[test]
fn test_shared_secret() {
let secp256k1 = Secp256k1::new();

let (spub1, ssec1, pub1, sec1) = genkey(&secp256k1);
let (spub2, ssec2, pub2, sec2) = genkey(&secp256k1);

let shared1 = SharedSecret::<Sha256>::new(&pub1, &sec2).unwrap();
let shared2 = SharedSecret::<Sha256>::new(&pub2, &sec1).unwrap();

let secp_shared1 = SecpSharedSecret::new(&secp256k1, &spub1, &ssec2);
let secp_shared2 = SecpSharedSecret::new(&secp256k1, &spub2, &ssec1);

assert_eq!(shared1.as_ref(), shared2.as_ref());

for i in 0..32 {
assert_eq!(shared1.as_ref()[i], secp_shared1[i]);
}

for i in 0..32 {
assert_eq!(shared2.as_ref()[i], secp_shared2[i]);
}
}

#[test]
fn test_pubkey_combine() {
let pk1 = PublicKey::parse(&[4, 126, 60, 36, 91, 73, 177, 194, 111, 11, 3, 99, 246, 204, 86, 122, 109, 85, 28, 43, 169, 243, 35, 76, 152, 90, 76, 241, 17, 108, 232, 215, 115, 15, 19, 23, 164, 151, 43, 28, 44, 59, 141, 167, 134, 112, 105, 251, 15, 193, 183, 224, 238, 154, 204, 230, 163, 216, 235, 112, 77, 239, 98, 135, 132]).unwrap();
Expand Down

0 comments on commit 4c3eeec

Please sign in to comment.