🦀
RustでECDSA公開鍵からBTCアドレスを生成
はじめに
2024年4月からブロックチェーン公開講座を受講しています。今までなんとなく漠然と理解していたことを知識として体系的に整理できて、とてもありがたい講座です。
第2回『ビットコインその1』ではECDSAの公開鍵からBTCアドレスを生成する方法について学びましたので、その復習のためRustで試してみました。
RustとBlockchainの学習を目的として書いたものですので、実運用では信頼できるライブラリをお使いください。
アルゴリズム
ECDSA公開鍵からBTCアドレスを生成する流れは以下になります。
- ECDSA公開鍵をSHA256でハッシュ化する
- 1をRIPEMD160でハッシュ化する
- 2の先頭にバージョン情報1バイトを付与する
- 3をSHA256で2回ハッシュ化してその先頭4バイトを3の末尾に付与する
- 4をBase58エンコードする
プロジェクトの作成
$ cargo new study
$ cd study
依存パッケージの追加
$ cargo add base-x hex_literal ripemd sha2
src/main.rsの編集
src/main.rs
use hex_literal::hex;
use ripemd::{Ripemd160, Digest};
use sha2::Sha256;
fn get_btc_address(public_key: &[u8; 65]) -> String {
// STEP-1: SHA-256
let mut hasher = Sha256::new();
hasher.update(public_key);
let hashed_sha256 = hasher.finalize();
// STEP-2: RIPEMD160
let mut hasher = Ripemd160::new();
hasher.update(&hashed_sha256);
let account_id = hasher.finalize();
// STEP-3: Payload (Starting with 0x00)
let mut payload = account_id.to_vec();
payload.insert(0, 0x0);
// STEP-4: Append checksum (sha256 x 2)
let mut hasher = Sha256::new();
hasher.update(&payload);
let hash = hasher.finalize();
let mut hasher = Sha256::new();
hasher.update(hash);
let checksum = hasher.finalize();
payload.append(&mut checksum[0..4].to_vec());
// STEP-5: Base58
const ALPHABET: &str = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
base_x::encode(ALPHABET, &payload)
}
fn main() {
// Public key
let public_key = &hex!(
"04F028892BAD7ED57D2FB57BF33081D5CFCF6F9ED3D3D7F159C2E2FFF579DC341A07CF33DA18BD734C600B96A72BBC4749D5141C90EC8AC328AE52DDFE2E505BDB"
);
// BTC Address
let btc_address = get_btc_address(public_key);
println!("BTC Address: {}", btc_address);
}
※ECDSA公開鍵(04:非圧縮; 512bit)は、ブロックチェーン公開講座の資料に記載されているものと同じ値を使用しています。
プログラムの実行
$ cargo run
Compiling study v0.1.0 (/home/toshio/workspace/rustcrypto/rust_crypto_02_btc_address)
Finished dev [unoptimized + debuginfo] target(s) in 0.23s
Running `target/debug/study`
BTC Address: 1424C2F4bC9JidNjjTUZCbUxv6Sa1Mt62x
講座の公開資料と同じBTCアドレスを取得することができました。
Discussion