本文实现 Rust 随机生成私钥/读取字符串私钥、生成公钥、地址

Rust - 以太坊

Rust 作为加密世界的宠儿,有各种好用的加密库
使用多层嵌套的库,无形中增加风险,也不利于学习
使用几个比较基本的库来实现功能可以加深理解

Cargo.toml

首先展示下本次用到的库 Cargo.toml

1
2
3
4
5
[dependencies]
libsecp256k1 = { version = "0.7.0"}
rand = {version = "0.8.5"}
hex = {version = "0.4.3"}
sha3 = {version = "0.10.1"}

以太坊 - 私钥与公钥

以太坊公钥和私钥的关系:

  • 以太坊的私钥和公钥是采用 secp256k1 算法生成的,可以用随机的 32 byte 私钥来生成对应的公钥
    对于任意一串 32 byte 的私钥可以生成唯一对应的公钥

生成随机私钥 - Rust 实现

使用 Rust 的 rand 库生成随机的私钥

代码:

1
2
3
4
5
6
7
8
9
use libsecp256k1;
use hex::*;
use rand::{thread_rng};
fn main() {
let keypair = libsecp256k1::SecretKey::random(&mut thread_rng());
println!("private_key:{:?}",libsecp256k1::SecretKey::serialize(&keypair).encode_hex::<String>());
let publickey = libsecp256k1::PublicKey::from_secret_key(&keypair);
println!("publickey:{:?}", libsecp256k1::PublicKey::serialize(&publickey).encode_hex::<String>());
}

运行结果:

1

读取字符串私钥转为公钥 - Rust 实现

需要使用 hex 库处理 hex 字符串
导入私钥:

1
2627f6859715ad1dd294ddc476193931f1adb558f0939732192bd1c0fd168e4e

代码:

1
2
3
4
5
6
7
8
9
use libsecp256k1;
use hex::*;
fn main() {
let buffer_private = <[u8; 32]>::from_hex("2627f6859715ad1dd294ddc476193931f1adb558f0939732192bd1c0fd168e4e").unwrap();
let keypair =libsecp256k1::SecretKey::parse(&buffer).unwrap();
println!("private_key:{:?}",libsecp256k1::SecretKey::serialize(&keypair).encode_hex::<String>());
let publickey = libsecp256k1::PublicKey::from_secret_key(&keypair);
println!("publickey:{:?}", libsecp256k1::PublicKey::serialize(&publickey).encode_hex::<String>());
}

结果:

1
2
private_key:"2627f6859715ad1dd294ddc476193931f1adb558f0939732192bd1c0fd168e4e"
publickey:"0416c28c003cb50c5cef10829fc325d4da3a59dfe7fc17ca1634895a06b049c17b942d9ac07f0997da6a84f8c5178662d92aaca4bbeee5120233ae34038539f159"

以太坊 - 公钥与地址

  • 地址通过对公钥去掉开头的 1 个 byte (0x04)
  • 对剩余部分进行 Keccak256
  • 将得到的 hash 取后面 20 byte

就可以获得这个公钥对应的以太坊的地址

由公钥获得地址 - Rust 实现

在前面的基础上增加 Rust sha3 库 进行 hash 运算

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
use libsecp256k1;
use hex::*;
use sha3::*;
fn main() {
let buffer_private = <[u8; 32]>::from_hex("2627f6859715ad1dd294ddc476193931f1adb558f0939732192bd1c0fd168e4e").unwrap();
let keypair = libsecp256k1::SecretKey::parse(&buffer).unwrap();
let publickey = libsecp256k1::PublicKey::from_secret_key(&keypair);

let p = &libsecp256k1::PublicKey::serialize(&publickey)[1..];
let mut hasher = Keccak256::new();
hasher.update(p);
let result = hasher.finalize();
let address = (&result[12..]);

println!("hash = {:?}" , result.encode_hex::<String>());
println!("address = {:?}" , address.encode_hex::<String>());
}

结果:

1
2
hash  = "e6a7b9ca516010f43abfbeb32959e6b2d3cee1e66a21647987b80e7f998cbfcc"
address = "2959e6b2d3cee1e66a21647987b80e7f998cbfcc"