keypair generation in progress

This commit is contained in:
debris 2016-08-18 12:56:18 +02:00
parent d7f650db51
commit e39f37fac7
9 changed files with 159 additions and 27 deletions

View File

@ -1,19 +0,0 @@
//! A Bitcoin address, or simply address, is an identifier of 26-35 alphanumeric characters, beginning with the number 1
//! or 3, that represents a possible destination for a bitcoin payment.
//!
//! https://en.bitcoin.it/wiki/Address
/// There are two address formats currently in use.
/// https://bitcoin.org/en/developer-reference#address-conversion
pub enum Format {
/// Pay to PubKey Hash
/// Common P2PKH which begin with the number 1, eg: 1BvBMSEYstWetqTFn5Au4m4GFg7xJaNVN2.
/// https://bitcoin.org/en/glossary/p2pkh-address
P2PKH,
/// Pay to Script Hash
/// Newer P2SH type starting with the number 3, eg: 3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy.
/// https://bitcoin.org/en/glossary/p2sh-address
P2SH,
}

71
src/keys/address.rs Normal file
View File

@ -0,0 +1,71 @@
//! A Bitcoin address, or simply address, is an identifier of 26-35 alphanumeric characters, beginning with the number 1
//! or 3, that represents a possible destination for a bitcoin payment.
//!
//! https://en.bitcoin.it/wiki/Address
use std::fmt;
use std::ops::Deref;
use base58::ToBase58;
use network::Network;
use hash::H160;
use keys::{DisplayLayout, checksum};
/// There are two address formats currently in use.
/// https://bitcoin.org/en/developer-reference#address-conversion
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum Type {
/// Pay to PubKey Hash
/// Common P2PKH which begin with the number 1, eg: 1BvBMSEYstWetqTFn5Au4m4GFg7xJaNVN2.
/// https://bitcoin.org/en/glossary/p2pkh-address
P2PKH,
/// Pay to Script Hash
/// Newer P2SH type starting with the number 3, eg: 3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy.
/// https://bitcoin.org/en/glossary/p2sh-address
P2SH,
}
#[derive(Debug, PartialEq)]
pub struct Address {
/// The type of the address.
pub kind: Type,
/// The network of the address.
pub network: Network,
/// Public key hash.
pub hash: H160,
}
pub struct AddressDisplayLayout([u8; 25]);
impl Deref for AddressDisplayLayout {
type Target = [u8];
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DisplayLayout for Address {
type Target = AddressDisplayLayout;
fn layout(&self) -> Self::Target {
let mut result = [0u8; 25];
result[0] = match (self.network, self.kind) {
(Network::Mainnet, Type::P2PKH) => 0,
(Network::Mainnet, Type::P2SH) => 5,
(Network::Testnet, Type::P2PKH) => 111,
(Network::Testnet, Type::P2SH) => 196,
};
result[1..21].copy_from_slice(&self.hash);
let cs = checksum(&result[0..21]);
result[21..25].copy_from_slice(&cs);
AddressDisplayLayout(result)
}
}
impl fmt::Display for Address {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.layout().to_base58().fmt(f)
}
}

9
src/keys/checksum.rs Normal file
View File

@ -0,0 +1,9 @@
use crypto::dhash;
/// Data checksum
pub fn checksum(data: &[u8]) -> [u8; 4] {
let mut result = [0u8; 4];
// TODO: check if this checksum is valid
result.copy_from_slice(&dhash(data)[28..]);
result
}

7
src/keys/display.rs Normal file
View File

@ -0,0 +1,7 @@
use std::ops::Deref;
pub trait DisplayLayout {
type Target: Deref<Target = [u8]>;
fn layout(&self) -> Self::Target;
}

View File

@ -1,10 +1,21 @@
//! Bitcoin KeyPair
//!
//! Fields:
//! - secret - 32 bytes
//! - public - 65 bytes
//! - private - secret with additional network identifier (and compressed flag?)
//! - address_hash - 20 bytes derived from public
//! - address - address_hash with network identifier and format type
use std::fmt;
use rustc_serialize::hex::ToHex;
use rcrypto::sha2::Sha256;
use rcrypto::ripemd160::Ripemd160;
use rcrypto::digest::Digest;
use secp256k1::key;
use keys::{Secret, Public, Error, SECP256K1, Address};
use hash::H160;
use network::Network;
use keys::{Secret, Public, Error, SECP256K1, Address, Type};
pub struct KeyPair {
secret: Secret,
@ -51,7 +62,7 @@ impl KeyPair {
}
}
pub fn address(&self) -> Address {
pub fn address_hash(&self) -> H160 {
let mut tmp = [0u8; 32];
let mut result = [0u8; 20];
let mut sha2 = Sha256::new();
@ -62,12 +73,20 @@ impl KeyPair {
rmd.result(&mut result);
result
}
pub fn address(&self, network: Network) -> Address {
Address {
kind: Type::P2PKH,
network: network,
hash: self.address_hash(),
}
}
}
#[cfg(test)]
mod tests {
use super::KeyPair;
use base58::{ToBase58, FromBase58};
use base58::{FromBase58};
#[test]
fn test_generating_address() {
@ -78,6 +97,6 @@ mod tests {
let mut address = [0u8; 20];
address.copy_from_slice(&"16meyfSoQV6twkAAxPe51RtMVz7PGRmWna".from_base58().unwrap()[1..21]);
let kp = KeyPair::from_secret(secret).unwrap();
assert_eq!(kp.address(), address);
assert_eq!(kp.address_hash(), address);
}
}

View File

@ -1,13 +1,20 @@
mod address;
mod checksum;
pub mod display;
pub mod generator;
pub mod keypair;
mod error;
mod private;
use secp256k1;
use hash::{H160, H256, H520};
use hash::{H256, H520};
pub use self::address::{Type, Address};
pub use self::checksum::checksum;
pub use self::display::DisplayLayout;
pub use self::keypair::KeyPair;
pub use self::error::Error;
pub use self::private::Private;
pub type Address = H160;
pub type Secret = H256;
pub type Public = H520;

39
src/keys/private.rs Normal file
View File

@ -0,0 +1,39 @@
use std::fmt;
use base58::ToBase58;
use network::Network;
use keys::{Secret, DisplayLayout};
#[derive(Debug, PartialEq)]
pub struct Private {
/// The network on which this key should be used.
pub network: Network,
/// ECDSA key.
pub secret: Secret,
/// True if this private key represents a compressed address.
pub compressed: bool,
}
impl DisplayLayout for Private {
type Target = Vec<u8>;
fn layout(&self) -> Self::Target {
let mut result = vec![];
let network_byte = match self.network {
Network::Mainnet => 128,
Network::Testnet => 239,
};
result.push(network_byte);
result.extend(&self.secret);
if self.compressed {
result.push(1);
}
result
}
}
impl fmt::Display for Private {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.layout().to_base58().fmt(f)
}
}

View File

@ -10,7 +10,6 @@ extern crate secp256k1;
extern crate base58;
pub mod keys;
pub mod address;
pub mod block;
pub mod block_header;
pub mod compact_integer;

View File

@ -5,7 +5,7 @@ const MAGIC_TESTNET: u32 = 0x0709110B;
/// Bitcoin network
/// https://bitcoin.org/en/glossary/mainnet
#[derive(Debug, PartialEq)]
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum Network {
/// The original and main network for Bitcoin transactions, where satoshis have real economic value.
Mainnet,