rust-bitcoin-unsafe-fast/src/util/key.rs

486 lines
16 KiB
Rust
Raw Normal View History

2018-03-14 03:53:03 +00:00
// Rust Bitcoin Library
// Written in 2014 by
// Andrew Poelstra <apoelstra@wpsoftware.net>
// 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 <http://creativecommons.org/publicdomain/zero/1.0/>.
//
//! Bitcoin Keys
//!
//! Keys used in Bitcoin that can be roundtrip (de)serialized.
2018-03-14 03:53:03 +00:00
//!
2018-10-10 10:12:33 +00:00
use std::fmt::{self, Write};
2019-09-09 09:53:50 +00:00
use std::{io, ops, error};
2018-03-14 03:53:03 +00:00
use std::str::FromStr;
2019-03-19 14:49:27 +00:00
2018-07-27 20:15:48 +00:00
use secp256k1::{self, Secp256k1};
2018-03-14 03:53:03 +00:00
use network::constants::Network;
use hashes::{Hash, hash160};
use hash_types::{PubkeyHash, WPubkeyHash};
2018-03-14 03:53:03 +00:00
use util::base58;
2019-09-09 09:53:50 +00:00
/// A key-related error.
#[derive(Debug)]
pub enum Error {
/// Base58 encoding error
Base58(base58::Error),
/// secp256k1-related error
Secp256k1(secp256k1::Error),
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Error::Base58(ref e) => write!(f, "base58 error: {}", e),
Error::Secp256k1(ref e) => write!(f, "secp256k1 error: {}", e),
}
}
}
impl error::Error for Error {
2020-09-14 14:55:42 +00:00
fn cause(&self) -> Option<&dyn error::Error> {
2019-09-09 09:53:50 +00:00
match *self {
Error::Base58(ref e) => Some(e),
Error::Secp256k1(ref e) => Some(e),
}
}
}
#[doc(hidden)]
impl From<base58::Error> for Error {
fn from(e: base58::Error) -> Error {
Error::Base58(e)
}
}
#[doc(hidden)]
impl From<secp256k1::Error> for Error {
fn from(e: secp256k1::Error) -> Error {
Error::Secp256k1(e)
}
}
/// A Bitcoin ECDSA public key
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct PublicKey {
2019-01-21 17:59:53 +00:00
/// Whether this public key should be serialized as compressed
pub compressed: bool,
/// The actual ECDSA key
pub key: secp256k1::PublicKey,
}
impl PublicKey {
/// Returns bitcoin 160-bit hash of the public key
pub fn pubkey_hash(&self) -> PubkeyHash {
if self.compressed {
PubkeyHash::hash(&self.key.serialize())
} else {
PubkeyHash::hash(&self.key.serialize_uncompressed())
}
}
/// Returns bitcoin 160-bit hash of the public key for witness program
pub fn wpubkey_hash(&self) -> Option<WPubkeyHash> {
if self.compressed {
Some(WPubkeyHash::from_inner(
hash160::Hash::hash(&self.key.serialize()).into_inner()
))
} else {
// We can't create witness pubkey hashes for an uncompressed
// public keys
None
}
}
/// Write the public key into a writer
2019-02-27 01:56:38 +00:00
pub fn write_into<W: io::Write>(&self, mut writer: W) {
let write_res: io::Result<()> = if self.compressed {
writer.write_all(&self.key.serialize())
} else {
writer.write_all(&self.key.serialize_uncompressed())
};
debug_assert!(write_res.is_ok());
}
/// Serialize the public key to bytes
pub fn to_bytes(&self) -> Vec<u8> {
let mut buf = Vec::new();
self.write_into(&mut buf);
buf
}
/// Deserialize a public key from a slice
2019-09-09 09:53:50 +00:00
pub fn from_slice(data: &[u8]) -> Result<PublicKey, Error> {
let compressed: bool = match data.len() {
33 => true,
65 => false,
len => { return Err(base58::Error::InvalidLength(len).into()); },
};
Ok(PublicKey {
compressed: compressed,
key: secp256k1::PublicKey::from_slice(data)?,
})
}
/// Computes the public key as supposed to be used with this secret
pub fn from_private_key<C: secp256k1::Signing>(secp: &Secp256k1<C>, sk: &PrivateKey) -> PublicKey {
sk.public_key(secp)
}
}
impl fmt::Display for PublicKey {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.compressed {
for ch in &self.key.serialize()[..] {
write!(f, "{:02x}", ch)?;
}
} else {
for ch in &self.key.serialize_uncompressed()[..] {
write!(f, "{:02x}", ch)?;
}
}
Ok(())
}
}
impl FromStr for PublicKey {
2019-09-09 09:53:50 +00:00
type Err = Error;
fn from_str(s: &str) -> Result<PublicKey, Error> {
let key = secp256k1::PublicKey::from_str(s)?;
Ok(PublicKey {
key: key,
compressed: s.len() == 66
})
}
}
2019-02-27 01:56:38 +00:00
#[derive(Copy, Clone, PartialEq, Eq)]
2018-03-14 03:53:03 +00:00
/// A Bitcoin ECDSA private key
pub struct PrivateKey {
2019-01-21 17:59:53 +00:00
/// Whether this private key should be serialized as compressed
2018-03-14 03:53:03 +00:00
pub compressed: bool,
/// The network on which this key should be used
pub network: Network,
/// The actual ECDSA key
pub key: secp256k1::SecretKey,
2018-03-14 03:53:03 +00:00
}
impl PrivateKey {
2019-01-21 17:59:53 +00:00
/// Creates a public key from this private key
pub fn public_key<C: secp256k1::Signing>(&self, secp: &Secp256k1<C>) -> PublicKey {
PublicKey {
compressed: self.compressed,
key: secp256k1::PublicKey::from_secret_key(secp, &self.key)
}
2018-03-14 03:53:03 +00:00
}
/// Serialize the private key to bytes
pub fn to_bytes(&self) -> Vec<u8> {
self.key[..].to_vec()
}
2018-10-10 10:12:33 +00:00
/// Format the private key to WIF format.
2020-09-14 14:55:42 +00:00
pub fn fmt_wif(&self, fmt: &mut dyn fmt::Write) -> fmt::Result {
2018-03-14 03:53:03 +00:00
let mut ret = [0; 34];
ret[0] = match self.network {
Network::Bitcoin => 128,
Network::Testnet | Network::Regtest => 239,
2018-03-14 03:53:03 +00:00
};
ret[1..33].copy_from_slice(&self.key[..]);
let privkey = if self.compressed {
2018-03-14 03:53:03 +00:00
ret[33] = 1;
base58::check_encode_slice(&ret[..])
} else {
base58::check_encode_slice(&ret[..33])
};
fmt.write_str(&privkey)
2018-03-14 03:53:03 +00:00
}
2018-10-10 10:12:33 +00:00
/// Get WIF encoding of this private key.
pub fn to_wif(&self) -> String {
let mut buf = String::new();
buf.write_fmt(format_args!("{}", self)).unwrap();
buf.shrink_to_fit();
buf
}
2018-03-14 03:53:03 +00:00
2018-10-10 10:12:33 +00:00
/// Parse WIF encoded private key.
2019-09-09 09:53:50 +00:00
pub fn from_wif(wif: &str) -> Result<PrivateKey, Error> {
2018-10-10 10:12:33 +00:00
let data = base58::from_check(wif)?;
2018-03-14 03:53:03 +00:00
let compressed = match data.len() {
33 => false,
34 => true,
2019-09-09 09:53:50 +00:00
_ => { return Err(Error::Base58(base58::Error::InvalidLength(data.len()))); }
2018-03-14 03:53:03 +00:00
};
let network = match data[0] {
128 => Network::Bitcoin,
239 => Network::Testnet,
2019-09-09 09:53:50 +00:00
x => { return Err(Error::Base58(base58::Error::InvalidVersion(vec![x]))); }
2018-03-14 03:53:03 +00:00
};
Ok(PrivateKey {
2018-03-14 03:53:03 +00:00
compressed: compressed,
network: network,
key: secp256k1::SecretKey::from_slice(&data[1..33])?,
2018-03-14 03:53:03 +00:00
})
}
}
impl fmt::Display for PrivateKey {
2018-10-10 10:12:33 +00:00
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.fmt_wif(f)
}
}
impl fmt::Debug for PrivateKey {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "[private key data]")
}
}
impl FromStr for PrivateKey {
2019-09-09 09:53:50 +00:00
type Err = Error;
fn from_str(s: &str) -> Result<PrivateKey, Error> {
PrivateKey::from_wif(s)
2018-10-10 10:12:33 +00:00
}
}
2019-02-27 01:56:38 +00:00
impl ops::Index<ops::RangeFull> for PrivateKey {
type Output = [u8];
fn index(&self, _: ops::RangeFull) -> &[u8] {
&self.key[..]
}
}
2019-03-19 14:49:27 +00:00
#[cfg(feature = "serde")]
impl ::serde::Serialize for PrivateKey {
fn serialize<S: ::serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
s.collect_str(self)
}
}
#[cfg(feature = "serde")]
impl<'de> ::serde::Deserialize<'de> for PrivateKey {
fn deserialize<D: ::serde::Deserializer<'de>>(d: D) -> Result<PrivateKey, D::Error> {
struct WifVisitor;
impl<'de> ::serde::de::Visitor<'de> for WifVisitor {
type Value = PrivateKey;
fn expecting(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
formatter.write_str("an ASCII WIF string")
}
fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
where
E: ::serde::de::Error,
{
if let Ok(s) = ::std::str::from_utf8(v) {
PrivateKey::from_str(s).map_err(E::custom)
} else {
Err(E::invalid_value(::serde::de::Unexpected::Bytes(v), &self))
}
}
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: ::serde::de::Error,
{
PrivateKey::from_str(v).map_err(E::custom)
}
}
d.deserialize_str(WifVisitor)
}
}
#[cfg(feature = "serde")]
impl ::serde::Serialize for PublicKey {
fn serialize<S: ::serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
if s.is_human_readable() {
s.collect_str(self)
} else {
if self.compressed {
s.serialize_bytes(&self.key.serialize()[..])
} else {
s.serialize_bytes(&self.key.serialize_uncompressed()[..])
}
}
}
}
#[cfg(feature = "serde")]
impl<'de> ::serde::Deserialize<'de> for PublicKey {
fn deserialize<D: ::serde::Deserializer<'de>>(d: D) -> Result<PublicKey, D::Error> {
if d.is_human_readable() {
struct HexVisitor;
impl<'de> ::serde::de::Visitor<'de> for HexVisitor {
type Value = PublicKey;
fn expecting(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
formatter.write_str("an ASCII hex string")
}
fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
where
E: ::serde::de::Error,
{
if let Ok(hex) = ::std::str::from_utf8(v) {
PublicKey::from_str(hex).map_err(E::custom)
} else {
Err(E::invalid_value(::serde::de::Unexpected::Bytes(v), &self))
}
}
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: ::serde::de::Error,
{
PublicKey::from_str(v).map_err(E::custom)
}
}
d.deserialize_str(HexVisitor)
} else {
struct BytesVisitor;
impl<'de> ::serde::de::Visitor<'de> for BytesVisitor {
type Value = PublicKey;
fn expecting(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
formatter.write_str("a bytestring")
}
fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
where
E: ::serde::de::Error,
{
PublicKey::from_slice(v).map_err(E::custom)
}
}
d.deserialize_bytes(BytesVisitor)
}
}
}
2018-03-14 03:53:03 +00:00
#[cfg(test)]
mod tests {
use super::{PrivateKey, PublicKey};
2018-03-14 03:53:03 +00:00
use secp256k1::Secp256k1;
use std::str::FromStr;
use hashes::hex::ToHex;
2018-03-14 03:53:03 +00:00
use network::constants::Network::Testnet;
use network::constants::Network::Bitcoin;
use util::address::Address;
2018-03-14 03:53:03 +00:00
#[test]
fn test_key_derivation() {
// testnet compressed
let sk = PrivateKey::from_wif("cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy").unwrap();
assert_eq!(sk.network, Testnet);
assert_eq!(sk.compressed, true);
2018-10-10 10:12:33 +00:00
assert_eq!(&sk.to_wif(), "cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy");
2018-03-14 03:53:03 +00:00
let secp = Secp256k1::new();
let pk = Address::p2pkh(&sk.public_key(&secp), sk.network);
2018-03-14 03:53:03 +00:00
assert_eq!(&pk.to_string(), "mqwpxxvfv3QbM8PU8uBx2jaNt9btQqvQNx");
2018-10-10 10:12:33 +00:00
// test string conversion
assert_eq!(&sk.to_string(), "cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy");
let sk_str =
PrivateKey::from_str("cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy").unwrap();
2018-10-10 10:12:33 +00:00
assert_eq!(&sk.to_wif(), &sk_str.to_wif());
2018-03-14 03:53:03 +00:00
// mainnet uncompressed
let sk = PrivateKey::from_wif("5JYkZjmN7PVMjJUfJWfRFwtuXTGB439XV6faajeHPAM9Z2PT2R3").unwrap();
assert_eq!(sk.network, Bitcoin);
assert_eq!(sk.compressed, false);
2018-10-10 10:12:33 +00:00
assert_eq!(&sk.to_wif(), "5JYkZjmN7PVMjJUfJWfRFwtuXTGB439XV6faajeHPAM9Z2PT2R3");
2018-03-14 03:53:03 +00:00
let secp = Secp256k1::new();
let mut pk = sk.public_key(&secp);
assert_eq!(pk.compressed, false);
assert_eq!(&pk.to_string(), "042e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af191923a2964c177f5b5923ae500fca49e99492d534aa3759d6b25a8bc971b133");
assert_eq!(pk, PublicKey::from_str("042e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af191923a2964c177f5b5923ae500fca49e99492d534aa3759d6b25a8bc971b133").unwrap());
let addr = Address::p2pkh(&pk, sk.network);
assert_eq!(&addr.to_string(), "1GhQvF6dL8xa6wBxLnWmHcQsurx9RxiMc8");
pk.compressed = true;
assert_eq!(&pk.to_string(), "032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af");
assert_eq!(pk, PublicKey::from_str("032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af").unwrap());
2018-03-14 03:53:03 +00:00
}
2019-03-19 14:49:27 +00:00
#[test]
fn test_pubkey_hash() {
let pk = PublicKey::from_str("032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af").unwrap();
let upk = PublicKey::from_str("042e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af191923a2964c177f5b5923ae500fca49e99492d534aa3759d6b25a8bc971b133").unwrap();
assert_eq!(pk.pubkey_hash().to_hex(), "9511aa27ef39bbfa4e4f3dd15f4d66ea57f475b4");
assert_eq!(upk.pubkey_hash().to_hex(), "ac2e7daf42d2c97418fd9f78af2de552bb9c6a7a");
}
#[test]
fn test_wpubkey_hash() {
let pk = PublicKey::from_str("032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af").unwrap();
let upk = PublicKey::from_str("042e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af191923a2964c177f5b5923ae500fca49e99492d534aa3759d6b25a8bc971b133").unwrap();
assert_eq!(pk.wpubkey_hash().unwrap().to_hex(), "9511aa27ef39bbfa4e4f3dd15f4d66ea57f475b4");
assert_eq!(upk.wpubkey_hash(), None);
}
2019-03-19 14:49:27 +00:00
#[cfg(feature = "serde")]
#[test]
fn test_key_serde() {
use serde_test::{Configure, Token, assert_tokens};
static KEY_WIF: &'static str = "cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy";
static PK_STR: &'static str = "039b6347398505f5ec93826dc61c19f47c66c0283ee9be980e29ce325a0f4679ef";
static PK_STR_U: &'static str = "\
04\
9b6347398505f5ec93826dc61c19f47c66c0283ee9be980e29ce325a0f4679ef\
87288ed73ce47fc4f5c79d19ebfa57da7cff3aff6e819e4ee971d86b5e61875d\
";
static PK_BYTES: [u8; 33] = [
0x03,
0x9b, 0x63, 0x47, 0x39, 0x85, 0x05, 0xf5, 0xec,
0x93, 0x82, 0x6d, 0xc6, 0x1c, 0x19, 0xf4, 0x7c,
0x66, 0xc0, 0x28, 0x3e, 0xe9, 0xbe, 0x98, 0x0e,
0x29, 0xce, 0x32, 0x5a, 0x0f, 0x46, 0x79, 0xef,
];
static PK_BYTES_U: [u8; 65] = [
0x04,
0x9b, 0x63, 0x47, 0x39, 0x85, 0x05, 0xf5, 0xec,
0x93, 0x82, 0x6d, 0xc6, 0x1c, 0x19, 0xf4, 0x7c,
0x66, 0xc0, 0x28, 0x3e, 0xe9, 0xbe, 0x98, 0x0e,
0x29, 0xce, 0x32, 0x5a, 0x0f, 0x46, 0x79, 0xef,
0x87, 0x28, 0x8e, 0xd7, 0x3c, 0xe4, 0x7f, 0xc4,
0xf5, 0xc7, 0x9d, 0x19, 0xeb, 0xfa, 0x57, 0xda,
0x7c, 0xff, 0x3a, 0xff, 0x6e, 0x81, 0x9e, 0x4e,
0xe9, 0x71, 0xd8, 0x6b, 0x5e, 0x61, 0x87, 0x5d,
];
let s = Secp256k1::new();
let sk = PrivateKey::from_str(&KEY_WIF).unwrap();
let pk = PublicKey::from_private_key(&s, &sk);
let pk_u = PublicKey {
key: pk.key,
compressed: false,
};
assert_tokens(&sk, &[Token::BorrowedStr(KEY_WIF)]);
assert_tokens(&pk.compact(), &[Token::BorrowedBytes(&PK_BYTES[..])]);
assert_tokens(&pk.readable(), &[Token::BorrowedStr(PK_STR)]);
assert_tokens(&pk_u.compact(), &[Token::BorrowedBytes(&PK_BYTES_U[..])]);
assert_tokens(&pk_u.readable(), &[Token::BorrowedStr(PK_STR_U)]);
}
}