Expose ability to tweak secret keys for contract hash
This commit is contained in:
parent
fdc854edd9
commit
8defba2fb3
|
@ -1,7 +1,7 @@
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "bitcoin"
|
name = "bitcoin"
|
||||||
version = "0.3.5"
|
version = "0.3.6"
|
||||||
authors = ["Andrew Poelstra <apoelstra@wpsoftware.net>"]
|
authors = ["Andrew Poelstra <apoelstra@wpsoftware.net>"]
|
||||||
license = "CC0-1.0"
|
license = "CC0-1.0"
|
||||||
homepage = "https://github.com/apoelstra/rust-bitcoin/"
|
homepage = "https://github.com/apoelstra/rust-bitcoin/"
|
||||||
|
|
|
@ -112,6 +112,23 @@ pub fn tweak_keys(secp: &Secp256k1, keys: &[PublicKey], contract: &[u8]) -> Resu
|
||||||
Ok(ret)
|
Ok(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Tweak a secret key using some arbitrary data
|
||||||
|
pub fn tweak_secret_key(secp: &Secp256k1, key: &SecretKey, contract: &[u8]) -> Result<SecretKey, Error> {
|
||||||
|
// Compute public key
|
||||||
|
let pk = try!(PublicKey::from_secret_key(secp, &key).map_err(Error::Secp));
|
||||||
|
// Compute HMAC tweak
|
||||||
|
let mut hmac_raw = [0; 32];
|
||||||
|
let mut hmac = hmac::Hmac::new(sha2::Sha256::new(), &pk.serialize_vec(&secp, true));
|
||||||
|
hmac.input(contract);
|
||||||
|
hmac.raw_result(&mut hmac_raw);
|
||||||
|
let hmac_sk = try!(SecretKey::from_slice(&secp, &hmac_raw).map_err(Error::BadTweak));
|
||||||
|
// Execute the tweak
|
||||||
|
let mut key = key.clone();
|
||||||
|
try!(key.add_assign(&secp, &hmac_sk).map_err(Error::Secp));
|
||||||
|
// Return
|
||||||
|
Ok(key)
|
||||||
|
}
|
||||||
|
|
||||||
/// Takes a contract, template and key set and runs through all the steps
|
/// Takes a contract, template and key set and runs through all the steps
|
||||||
pub fn create_address(secp: &Secp256k1,
|
pub fn create_address(secp: &Secp256k1,
|
||||||
network: Network,
|
network: Network,
|
||||||
|
@ -201,6 +218,7 @@ mod tests {
|
||||||
use secp256k1::Secp256k1;
|
use secp256k1::Secp256k1;
|
||||||
use secp256k1::key::PublicKey;
|
use secp256k1::key::PublicKey;
|
||||||
use serialize::hex::FromHex;
|
use serialize::hex::FromHex;
|
||||||
|
use rand::thread_rng;
|
||||||
|
|
||||||
use blockdata::script::Script;
|
use blockdata::script::Script;
|
||||||
use network::constants::Network;
|
use network::constants::Network;
|
||||||
|
@ -244,6 +262,28 @@ mod tests {
|
||||||
assert_eq!(keys, alpha_keys);
|
assert_eq!(keys, alpha_keys);
|
||||||
assert_eq!(template, alpha_template);
|
assert_eq!(template, alpha_template);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn tweak_secret() {
|
||||||
|
let secp = Secp256k1::new();
|
||||||
|
let (sk1, pk1) = secp.generate_keypair(&mut thread_rng()).unwrap();
|
||||||
|
let (sk2, pk2) = secp.generate_keypair(&mut thread_rng()).unwrap();
|
||||||
|
let (sk3, pk3) = secp.generate_keypair(&mut thread_rng()).unwrap();
|
||||||
|
|
||||||
|
let pks = [pk1, pk2, pk3];
|
||||||
|
let contract = b"if bottle mt dont remembr drink wont pay";
|
||||||
|
|
||||||
|
// Directly compute tweaks on pubkeys
|
||||||
|
let tweaked_pks = tweak_keys(&secp, &pks, &contract[..]).unwrap();
|
||||||
|
// Compute tweaks on secret keys
|
||||||
|
let tweaked_pk1 = PublicKey::from_secret_key(&secp, &tweak_secret_key(&secp, &sk1, &contract[..]).unwrap()).unwrap();
|
||||||
|
let tweaked_pk2 = PublicKey::from_secret_key(&secp, &tweak_secret_key(&secp, &sk2, &contract[..]).unwrap()).unwrap();
|
||||||
|
let tweaked_pk3 = PublicKey::from_secret_key(&secp, &tweak_secret_key(&secp, &sk3, &contract[..]).unwrap()).unwrap();
|
||||||
|
// Check equality
|
||||||
|
assert_eq!(tweaked_pks[0], tweaked_pk1);
|
||||||
|
assert_eq!(tweaked_pks[1], tweaked_pk2);
|
||||||
|
assert_eq!(tweaked_pks[2], tweaked_pk3);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue