【问题标题】:How to generate an Ethereum public key from a private key using rust-secp256k1?如何使用 rust-secp256k1 从私钥生成以太坊公钥?
【发布时间】:2021-03-15 16:14:19
【问题描述】:

我找到了rust-secp256k1,这似乎是我需要的,但文档中没有示例。

我尝试在我的代码中使用这个箱子:

extern crate secp256k1;

use secp256k1::key::SecretKey;

fn main() {
    let context = secp256k1::Secp256k1::without_caps();

    let private_key: String = String::from("d500266f7d37f0957564e4ce1a1dcc8bb3408383634774a2f4a94a35f4bc53e0");

    let secret_key = SecretKey::new(&context, &mut private_key);

    println!("{:?}", secret_key);
}

我遇到了一个错误:

error[E0277]: the trait bound `std::string::String: secp256k1::rand::Rng` is not satisfied
  --> src/main.rs:10:22
   |
10 |     let secret_key = SecretKey::new(&context, &mut private_key);
   |                      ^^^^^^^^^^^^^^ the trait `secp256k1::rand::Rng` is not implemented for `std::string::String`
   |
   = note: required by `secp256k1::key::SecretKey::new`

【问题讨论】:

  • SecretKey::new 需要一个随机数生成器(如,它实现了Rng)作为第二个参数。如果您将其他字符串设为兼容的字节片,则可以改用SecretKey::from_slice

标签: rust ecdsa


【解决方案1】:

只是添加到接受的答案:

您在最后一行打印的公钥不是未压缩公钥的正确形式。要显示它,需要在公钥上使用 secp256k1 crate 中的 serialize_uncompressed 方法,并删除前导 04 十六进制字节。

更多关于不正确格式here的信息。

【讨论】:

    【解决方案2】:

    以下代码从私钥生成公钥:

    extern crate secp256k1;
    extern crate hex;
    
    use secp256k1::key::{SecretKey, PublicKey};
    
    fn main() {
        let context = secp256k1::Secp256k1::new();
    
        let private_key: &[u8] = "d500266f7d37f0957564e4ce1a1dcc8bb3408383634774a2f4a94a35f4bc53e0".as_bytes();
    
        let secret_key = SecretKey::from_slice(&hex::decode(private_key).unwrap());
    
        let public_key = PublicKey::from_secret_key(&context, &secret_key.unwrap());
    
        println!("{:?}", public_key.unwrap()); // PublicKey(a423c05d32e3385bb2930e42ebbf104567215761e166c3ae3dd91d9c8bee0adcfc4f9e4ec43998eae8000de6b166014c5921c6d4545675f4f9205e7bc3d4401e)
    }
    

    我需要使用SecretKey::from_slice,而不是使用SecretKey::new,它需要一个随机数生成器作为第二个参数。 from_slice 接受一个 32 字节的密钥,我可以将其 parse from my string 转换为兼容的字节片。

    【讨论】:

    • 您可能希望以不同的方式使用"d500266f7d37f0957564e4ce1a1dcc8bb3408383634774a2f4a94a35f4bc53e0".as_bytes(),因为此语句会将字符串视为文本,而不是十六进制缓冲区。