signature tests and tweaks

This commit is contained in:
debris 2016-08-21 14:58:35 +02:00
parent 23ef558ba4
commit 238afb59a9
4 changed files with 120 additions and 55 deletions

View File

@ -94,8 +94,7 @@ impl KeyPair {
#[cfg(test)]
mod tests {
use keys::Message;
use crypto::hash;
use crypto::dhash;
use super::KeyPair;
/// Tests from:
@ -111,6 +110,11 @@ mod tests {
const ADDRESS_1C: &'static str = "1NoJrossxPBKfCHuJXT4HadJrXRE9Fxiqs";
const ADDRESS_2C: &'static str = "1CRj2HyM1CXWzHAXLQtiGLyggNT9WQqsDs";
const SIGN_1: &'static str = "304402205dbbddda71772d95ce91cd2d14b592cfbc1dd0aabd6a394b6c2d377bbe59d31d022014ddda21494a4e221f0824f0b8b924c43fa43c0ad57dccdaa11f81a6bd4582f6";
const SIGN_2: &'static str = "3044022052d8a32079c11e79db95af63bb9600c5b04f21a9ca33dc129c2bfa8ac9dc1cd5022061d8ae5e0f6c1a16bde3719c64c2fd70e404b6428ab9a69566962e8771b5944d";
const SIGN_COMPACT_1: &'static str = "1c5dbbddda71772d95ce91cd2d14b592cfbc1dd0aabd6a394b6c2d377bbe59d31d14ddda21494a4e221f0824f0b8b924c43fa43c0ad57dccdaa11f81a6bd4582f6";
const SIGN_COMPACT_1C: &'static str = "205dbbddda71772d95ce91cd2d14b592cfbc1dd0aabd6a394b6c2d377bbe59d31d14ddda21494a4e221f0824f0b8b924c43fa43c0ad57dccdaa11f81a6bd4582f6";
const SIGN_COMPACT_2: &'static str = "1c52d8a32079c11e79db95af63bb9600c5b04f21a9ca33dc129c2bfa8ac9dc1cd561d8ae5e0f6c1a16bde3719c64c2fd70e404b6428ab9a69566962e8771b5944d";
const SIGN_COMPACT_2C: &'static str = "2052d8a32079c11e79db95af63bb9600c5b04f21a9ca33dc129c2bfa8ac9dc1cd561d8ae5e0f6c1a16bde3719c64c2fd70e404b6428ab9a69566962e8771b5944d";
fn check_addresses(secret: &'static str, address: &'static str) -> bool {
let kp = KeyPair::from_private(secret.into()).unwrap();
@ -122,6 +126,18 @@ mod tests {
kp.private().compressed == compressed
}
fn check_sign(secret: &'static str, raw_message: &[u8], signature: &'static str) -> bool {
let message = dhash(raw_message);
let kp = KeyPair::from_private(secret.into()).unwrap();
kp.private().sign(&message).unwrap() == signature.into()
}
fn check_sign_compact(secret: &'static str, raw_message: &[u8], signature: &'static str) -> bool {
let message = dhash(raw_message);
let kp = KeyPair::from_private(secret.into()).unwrap();
kp.private().sign_compact(&message).unwrap() == signature.into()
}
#[test]
fn test_keypair_address() {
assert!(check_addresses(SECRET_0, ADDRESS_0));
@ -140,15 +156,21 @@ mod tests {
assert!(check_compressed(SECRET_2C, true));
}
// TODO: fix
#[test]
#[ignore]
fn test_sign() {
use hex::ToHex;
let message = hash(b"Very deterministic message");
println!("message: {}", message.to_hex());
let kp = KeyPair::from_private(SECRET_1.into()).unwrap();
let signature = kp.private().sign(&message).unwrap();
assert_eq!(signature, SIGN_1.into());
let message = b"Very deterministic message";
assert!(check_sign(SECRET_1, message, SIGN_1));
assert!(check_sign(SECRET_1C, message, SIGN_1));
assert!(check_sign(SECRET_2, message, SIGN_2));
assert!(check_sign(SECRET_2C, message, SIGN_2));
}
#[test]
fn test_sign_compact() {
let message = b"Very deterministic message";
assert!(check_sign_compact(SECRET_1, message, SIGN_COMPACT_1));
assert!(check_sign_compact(SECRET_1C, message, SIGN_COMPACT_1C));
assert!(check_sign_compact(SECRET_2, message, SIGN_COMPACT_2));
assert!(check_sign_compact(SECRET_2C, message, SIGN_COMPACT_2C));
}
}

View File

@ -23,7 +23,7 @@ pub use self::keypair::KeyPair;
pub use self::error::Error;
pub use self::private::Private;
pub use self::public::Public;
pub use self::signature::Signature;
pub use self::signature::{Signature, CompactSignature};
use hash::{H160, H256};
pub type AddressHash = H160;

View File

@ -5,7 +5,7 @@ use secp256k1::Message as SecpMessage;
use hex::ToHex;
use base58::{ToBase58, FromBase58};
use network::Network;
use keys::{Secret, DisplayLayout, checksum, Error, Message, Signature, SECP256K1};
use keys::{Secret, DisplayLayout, checksum, Error, Message, Signature, CompactSignature, SECP256K1};
#[derive(PartialEq)]
pub struct Private {
@ -24,10 +24,10 @@ impl Private {
let message = try!(SecpMessage::from_slice(message));
let signature = try!(context.sign(&message, &secret));
let data = signature.serialize_der(context);
Ok(Signature::DER(data))
Ok(data.into())
}
pub fn sign_compact(&self, message: &Message) -> Result<Signature, Error> {
pub fn sign_compact(&self, message: &Message) -> Result<CompactSignature, Error> {
let context = &SECP256K1;
let secret = try!(key::SecretKey::from_slice(context, &self.secret));
let message = try!(SecpMessage::from_slice(message));
@ -40,7 +40,7 @@ impl Private {
true => 27 + recovery_id + 4,
false => 27 + recovery_id,
};
Ok(Signature::Compact(signature))
Ok(signature.into())
}
}

View File

@ -1,3 +1,7 @@
//! Bitcoin signatures.
//!
//! http://bitcoin.stackexchange.com/q/12554/40688
use std::fmt;
use std::cmp::PartialEq;
use std::ops::Deref;
@ -6,43 +10,26 @@ use hex::{ToHex, FromHex};
use hash::H520;
use keys::Error;
/// http://bitcoin.stackexchange.com/q/12554/40688
pub enum Signature {
DER(Vec<u8>),
Compact(H520),
#[derive(PartialEq)]
pub struct Signature(Vec<u8>);
impl fmt::Debug for Signature {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.0.to_hex().fmt(f)
}
}
impl fmt::Display for Signature {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.0.to_hex().fmt(f)
}
}
impl Deref for Signature {
type Target = [u8];
fn deref(&self) -> &Self::Target {
match *self {
Signature::DER(ref hash) => hash,
Signature::Compact(ref hash) => hash,
}
}
}
impl PartialEq for Signature {
fn eq(&self, other: &Signature) -> bool {
let s_slice: &[u8] = self;
let o_slice: &[u8] = other;
s_slice == o_slice
}
}
impl fmt::Debug for Signature {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Signature::DER(ref hash) => writeln!(f, "normal: {}", hash.to_hex()),
Signature::Compact(ref hash) => writeln!(f, "compact: {}", hash.to_hex()),
}
}
}
impl fmt::Display for Signature {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.to_hex().fmt(f)
&self.0
}
}
@ -51,15 +38,7 @@ impl FromStr for Signature {
fn from_str(s: &str) -> Result<Self, Error> {
let vec = try!(s.from_hex().map_err(|_| Error::InvalidSignature));
let signature = match vec.len() {
65 => {
let mut compact = [0u8; 65];
compact.copy_from_slice(&vec);
Signature::Compact(compact)
},
_ => Signature::DER(vec),
};
Ok(signature)
Ok(Signature(vec))
}
}
@ -68,3 +47,67 @@ impl From<&'static str> for Signature {
s.parse().unwrap()
}
}
impl From<Vec<u8>> for Signature {
fn from(v: Vec<u8>) -> Self {
Signature(v)
}
}
pub struct CompactSignature(H520);
impl fmt::Debug for CompactSignature {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.0.to_hex().fmt(f)
}
}
impl fmt::Display for CompactSignature {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.0.to_hex().fmt(f)
}
}
impl Deref for CompactSignature {
type Target = [u8];
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl PartialEq for CompactSignature {
fn eq(&self, other: &Self) -> bool {
let s_slice: &[u8] = self;
let o_slice: &[u8] = other;
s_slice == o_slice
}
}
impl FromStr for CompactSignature {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Error> {
let vec = try!(s.from_hex().map_err(|_| Error::InvalidSignature));
match vec.len() {
65 => {
let mut compact = [0u8; 65];
compact.copy_from_slice(&vec);
Ok(CompactSignature(compact))
},
_ => Err(Error::InvalidSignature)
}
}
}
impl From<&'static str> for CompactSignature {
fn from(s: &'static str) -> Self {
s.parse().unwrap()
}
}
impl From<H520> for CompactSignature {
fn from(h: H520) -> Self {
CompactSignature(h)
}
}