With ECDSA (Elliptic Curve Digital Signature Algorithm) we use a private key to sign data, and then the public key can prove it. In this case we will use the sepc256k1 curve (and which is used in Bitcoin) and implement in Rust. For this we will sign a message with a private key, and the produce a verifying key to prove the signature. The private key is the signing key, and the public key is the verifying key. The curve used is \(y^2 = x^3+7\) and the prime number is \(p = 2^{256} - 2^{32} - 977\).
ECDSA Signatures in Rust using sepc256k1 |
Code
First we create the project with:
cargo new ecdsa
We then go into the ecdsa folder, and add the following to the cargo.toml file:
[package] name = "ed" version = "1.0.0" authors = ["Bill"] [dependencies] k256="0.9.6" hex="0.4.3" rand_core="0.6.3"
In this case we will use the Ring crate, and which supports a range of cryptographic methods. For this we will use sepc256k1 for the signature:
use k256::{ecdsa::{SigningKey, Signature, signature::Signer, VerifyingKey, signature::Verifier}}; use rand_core::OsRng; use std::env; fn main() { let mut message = String::from("Hello world!"); let args: Vec= env::args().collect(); if args.len() >1 { message = args[1].clone(); } println!("Message: {}",message); let mut msg=message.as_bytes(); // Signing let signing_key = SigningKey::random(&mut OsRng); let sk=signing_key.to_bytes(); println!("\nSigning key: {:x?}",hex::encode(sk)); let signature: Signature = signing_key.sign(msg); println!("\nSignature key: {:x?}",hex::encode(signature)); let verify_key = VerifyingKey::from(&signing_key); // Serialize with `::to_encoded_point()` let vk=verify_key.to_bytes(); println!("\nVerifying key: {:x?}",hex::encode(vk)); let rtn=verify_key.verify(msg, &signature).is_ok(); if rtn==true { println!("\nMessage '{0}' signature correct", message); } else { println!("\nMessage '{0}' signature incorrect",message);} msg="hello".as_bytes(); let rtn=verify_key.verify(msg, &signature).is_ok(); if rtn==true { println!("\nWith 'hello', message signature correct"); } else { println!("\nWith 'hello', message signature incorrect");} }
Finally we simply build with:
cargo build
A sample run is:
Message: Hello World! Signing key: "157d439b88b35d856bd665633910710999c6725c7c5e05dac24c4ddf15de9e86" Verifying key: "034546a2a9c2ed9e02b5e2f08f7f78429ddef52d8e13603bac5b8d36a8c2c1aa53" Signature: "5883b02624ce43f3d0c52196d8fdc8f89b4dc4a2528130a8aaff30f7de1ad43317bac337c18a87592532d767e23770bd1efd0d6ca23a5fd90c680d3372b7d5d8" Message 'Hello World!' signature correct With 'hello', message signature incorrect