Подписание ECDSA с использованием крейта Rust P256

Я пишу небольшую программу моделирования блокчейна на 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, чтобы понять реализацию:

Как я могу экспортировать (хранить) пару ключей ecdsa в Rust?

в этой реализации используется 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 после преобразования в шестнадцатеричный?

Спасибо

Почему Python в конце концов умрет
Почему Python в конце концов умрет
Последние 20 лет были действительно хорошими для Python. Он прошел путь от "просто языка сценариев" до основного языка, используемого для написания...
0
0
112
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

После экспериментов эта функция возвращает подпись и ключ подписи, используемый для последующей проверки подписи.

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% уверен, что это лучший способ сделать это, но он работает достаточно хорошо.

Другие вопросы по теме