Exploring Bitcoin with Rust code – Part 1
Let’s get started with this ‘crate’ : bitcoin
*version = “0.31.0” at time of writing
The aim is to learn more Rust, and what better way to learn about cryptography than experimenting with Bitcoin ?
In addition we’ll look at serializing and printing bytes in hex and binary format.
Note: One of the crate's dependencies is secp256k1 a Rust "wrapper library" for Pieter Wuille's `libsecp256k1` which implements ECDSA and BIP 340 signatures for the SECG elliptic curve group secp256k1 and related utilities.
More about the Rust “Bitcoin” crate:
This is a library that supports the Bitcoin network protocol and associated primitives. It is designed for Rust programs built to work with the Bitcoin network.
Except for its dependency on libsecp256k1 (and optionally libbitcoinconsensus), this library is written entirely in Rust. It illustrates the benefits of strong type safety, including ownership and lifetime, for financial and/or cryptographic software.
Official Documentation
Webdock – Fast Cloud VPS Linux Hosting
Enough of the intro, let’s get our hands dirtier than SBF’s ex :
1. Create a new Rust binary project
cargo new bitcoin
❯ tree -L 2
.
├── Cargo.lock
├── Cargo.toml
├── src
│ └── main.rs
└── target
├── CACHEDIR.TAG
└── debug
3 directories, 4 files
cargo add bitcoin
view Cargo.toml
[package]
name = "btc"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
rand = "0.8.5"
bitcoin = { version = "0.31.0", features = ["rand-std"] }
~
2. Edit ‘main.rs’
cd src
vim main.rs
# and remove the "hello world" shizz and add the code shown below:
#![allow(unused)]
use bitcoin::secp256k1::{rand, Secp256k1};
use bitcoin::PublicKey;
use bitcoin::{Address, Network};
/// The different types of addresses.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[non_exhaustive]
pub enum AddressType {
/// Pay to pubkey hash.
P2pkh,
/// Pay to script hash.
P2sh,
/// Pay to witness pubkey hash.
P2wpkh,
/// Pay to witness script hash.
P2wsh,
/// Pay to taproot.
P2tr,
}
3. Add code for Creating Public / Private Key Pairs
Asymmetric cryptography is a branch of cryptography where a secret key can be divided into two parts, a public key and a private key.
The public key can be given to anyone, trusted or not, while the private key must be kept secret (just like the key in symmetric cryptography).
Let’s create some key pairs and view the respective public keys
fn main() {
//// Generate random key pair.
let s = Secp256k1::new();
let (secret_key, public_key) = s.generate_keypair(&mut rand::thread_rng());
println!("\n---\n");
// Print the hexadecimal representation of the public key
println!("Public Key:");
for byte in public_key.serialize_uncompressed().iter() {
print!("{:02x} ", byte);
}
// The {:02x} format specifier prints each byte as a two-digit hexadecimal number.
println!("\n---\n");
// Print the hexadecimal representation of the compressed public key
println!("Compressed Public Key:");
for byte in public_key.serialize().iter() {
print!("{:02x} ", byte);
}
// print in binary!
println!("\n---\n");
println!("Binary representation of the Compressed Public Key:");
for byte in public_key.serialize().iter() {
print!("{:b} ", byte);
}
}
Secp256k1::new()
: This line creates a new instance of theSecp256k1
object, which is a cryptographic library often used for handling operations related to the Bitcoin protocol.s.generate_keypair(&mut rand::thread_rng())
: This line generates a random key pair (consisting of a secret key and a corresponding public key) using thegenerate_keypair
function from theSecp256k1
instance (s
). It utilizes a random number generator from therand
crate (rand::thread_rng()
).- The code then proceeds to print the public key in different representations:
public_key.serialize_uncompressed()
: This section prints the public key in its uncompressed form in hexadecimal format using{:02x}
format specifier.public_key.serialize()
: This part prints the public key in its compressed form in hexadecimal format.- Lastly, the code attempts to print the public key in binary format by using
print!("{:b} ", byte)
for each byte in the serialized public key.
Output
Video:
Screenshot:
Note we only ever want to display the public key in our output code (cos: security)