使用 Rust P256 板条箱进行 ECDSA 签名

问题描述 投票:0回答:1

我正在用 Rust 编写一个小型区块链模拟程序,并且正在努力使用 ECDSA 签名密钥,以便我可以签署添加到区块链的交易。

我在名为

crypto.rs
的文件中配置了以下密钥对:

pub struct KeyPair {
    pub name: String,
    pub public_key: String,
    private_key: String,
}

以及以下实现来生成密钥:

impl KeyPair {
    pub fn generate(name: String, key_store: &mut KeyStore) -> KeyPair {
        // private key first
        let secret = SecretKey::random(&mut OsRng);
        let private_key = hex::encode(&secret.to_bytes());
        // then public key
        let public_key = hex::encode(secret.public_key().to_sec1_bytes());
        let key_pair: KeyPair = KeyPair {
            name,
            public_key,
            private_key,
        };
        // store a clone and return the original for further operations
        key_store.append_key_pair(key_pair.clone());
        key_store.write();
        key_pair
    }
}

测试会在名为

key_store.json
的文件中生成以下内容:

{
    "keys": [
        {
            "name": "TEST",
            "public_key": "040eda3b0d1b30a78cc830ab9e69dc25a52d5448c3c8228511481a67b1f6420bc55beb4efc297a49a657cfe08b7873293e78fef553724453f55eea3656a6369d5a",
            "private_key": "ccb789f12826fd81b45f27489b73ac5650f46f9b8f0281922f459be515f018b6"
        }
    ]
}

现在要签署交易哈希,我需要从私钥(SecretKey)获取签名密钥,但我所做的一切似乎都不起作用。

我尝试使用此函数提取签名,但它出现恐慌

signature error
:

pub fn get_signature(&self, hash: &String) -> String {
    let private_key = self.get_private_key();
    let signing_key = match private_key.parse::<SigningKey>() {
        Ok(key) => key,
        Err(e) => panic!("Error parsing signing key from private key: {}", e),
    };
    let signature: Signature = signing_key.sign(&hash.as_bytes());
    signature.to_string()
}

我使用这篇 SO 文章来帮助理解实现:

如何在 Rust 中导出(存储)ecdsa 密钥对?

此实现使用

pem
但我选择使用转换为十六进制的字节字符串,因为这是存储密钥的常见方法。

此尝试会导致出现此消息的恐慌

Error parsing bytes to String: invalid utf-8 sequence of 1 bytes from index 0
:

pub fn get_signature(&self, hash: &String) -> String {

    let private_key: String = self.get_private_key();
    let decoded: Vec<u8> = match hex::decode(&private_key) {
        Ok(bytes) => bytes,
        Err(e) => panic!("Error decoding bytes: {}", e),
    };
    let str_from_bytes: String = match String::from_utf8(decoded) {
        Ok(s) => s,
        Err(e) => panic!("Error parsing bytes to String: {}", e),
    };
    let signing_key = match str_from_bytes.parse::<SigningKey>() {
        Ok(key) => key,
        Err(e) => panic!("Error parsing signing key from private key: {}", e),
    };
    let signature: Signature = signing_key.sign(&hash.as_bytes());
    signature.to_string()

}

有人知道如何从 SecretKey 转换为十六进制后获取签名密钥吗?

谢谢

rust ecdsa secp256k1
1个回答
0
投票

实验后,此函数返回签名,用于稍后验证签名的签名密钥

pub fn get_signature(&self, hash: &String) -> (Signature, SigningKey) {
    let private_key = self.get_private_key();
    let key_bytes = hex::decode(&private_key).unwrap();
    let signing_key = SigningKey::from_slice(key_bytes.as_slice()).unwrap();
    let signature: Signature = signing_key.sign(&hash.as_bytes());
    (signature, signing_key)
}

使用

from_slice
初始化 SigningKey 似乎有效:

SigningKey::from_slice(key_bytes.as_slice()).unwrap()

为了完整起见,随附的

verify
函数如下所示:

pub fn verify(&self, signature: Signature, signing_key: SigningKey, hash: String) -> bool {
    let verifying_key = VerifyingKey::from(&signing_key);
    let verified = match verifying_key.verify(&hash.as_bytes(), &signature) {
        Ok(_res) => true,
        Err(_) => false,
    };
    verified
}

非常欢迎评论和替代解决方案,因为我不是 100% 认为这是最好的方法,但这已经足够好了。

© www.soinside.com 2019 - 2024. All rights reserved.