Skip to content

Instantly share code, notes, and snippets.

@dravenk
Last active January 10, 2024 14:36
Show Gist options
  • Save dravenk/c30e7e6c5d81fcb15dc0278d0aeeed8b to your computer and use it in GitHub Desktop.
Save dravenk/c30e7e6c5d81fcb15dc0278d0aeeed8b to your computer and use it in GitHub Desktop.
Light协议实现: 使用确定性私钥获得确定性公钥,并使用DH协议得到共享密钥
///
/// [dependencies]
/// bip32 = {version="0.5.1", features = ["alloc"]}
/// rand_core = {version="0.6.4",features = ['getrandom']}
/// x25519-dalek = {version = "2.0.0", features = ["static_secrets"]}
///
use bip32::{Mnemonic, Seed};
use rand_core::OsRng;
use x25519_dalek::{x25519,PublicKey, StaticSecret};
fn main() {
// 分别两个不同私钥种子 seed1 和 seed2,代表由不同的两个人持有
let seed1 = get_seed();
let seed2 = get_seed();
// 断言 seed1 不同于 seed2
assert_ne!(seed1.as_bytes(), seed2.as_bytes());
// 持有人 seed1 根据持有的私钥seed1 创建对应的公钥 pub1
let s1_key = seed1.as_bytes()[0..32].try_into().unwrap();
let (sec1, pub1) = sedd_to_dh_key(s1_key);
println!("sec1: {:?}", sec1.to_bytes());
println!("pub1: {:?}", pub1.to_bytes());
// 持有人 seed2 根据持有的私钥 seed2 创建对应的公钥 pub2
let s2_key = seed2.as_bytes()[0..32].try_into().unwrap();
let (sec2, pub2) = sedd_to_dh_key(s2_key);
println!("sec2: {:?}", sec2.to_bytes());
println!("pub2: {:?}", pub2.to_bytes());
// 断言 私钥1 不同于 私钥2
assert_ne!(sec1.to_bytes(), sec2.to_bytes());
// 断言 公钥1 不同于 公钥2
assert_ne!(pub1.to_bytes(), pub2.to_bytes());
// 经过DH协议交换后,seed1得到的共享密钥
let shard1 = x25519(sec1.to_bytes(), pub2.to_bytes());
// 经过DH协议交换后,seed2得到的共享密钥
let shard2 = x25519(sec2.to_bytes(), pub1.to_bytes());
println!("shard1: {:?}", shard1);
println!("shard2: {:?}", shard2);
// 断言 seed1 持有人 和 seed2 持有人经过 DH 协议,得到的共享密钥
assert_eq!(shard1, shard2);
}
pub fn get_seed() -> Seed {
let phrase = get_mnemonic();
// Derive a BIP39 seed value using the given password
let seed = phrase.to_seed("");
seed
}
pub fn get_mnemonic() -> Mnemonic {
// Generate random Mnemonic using the default language (English)
let language = Default::default();
let mnemonic = Mnemonic::random(&mut OsRng, language);
let phrase = Mnemonic::new(mnemonic.phrase(), language);
phrase.unwrap()
}
pub fn sedd_to_dh_key(seed: [u8; 32]) -> (StaticSecret, PublicKey) {
let secret_key = StaticSecret::from(seed);
let public_key = PublicKey::from(&secret_key);
(secret_key, public_key)
}
@dravenk
Copy link
Author

dravenk commented Jan 10, 2024

持有人可以通过私钥派生出子私钥,并且用子私钥与另外的私钥持有人进行DH协议交互,得到子私钥的共享密钥:

pub fn seed_to_key(seed:Seed, child_path:&str) -> (StaticSecret, PublicKey) {
    let child_xprv = XPrv::derive_from_path(&seed, &child_path.parse().unwrap()).unwrap();
    let xprv = child_xprv.to_bytes();
    let child_priv_key: [u8; 32] = xprv[0..32].try_into().unwrap();

    let secret_key = StaticSecret::from(child_priv_key);
    let public_key = PublicKey::from(&secret_key);
    (secret_key, public_key)
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment