signature tests and tweaks
This commit is contained in:
parent
23ef558ba4
commit
238afb59a9
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue