Rust
Rust
ECDSA Sign and Verify
See more ECC Examples
Demonstrates how to create an ECDSA signature on the SHA256 hash of some data, and then verify.Chilkat Rust Downloads
// This example assumes the Chilkat API to have been previously unlocked.
// See Global Unlock Sample for sample code.
// First load an ECDSA private key to be used for signing.
let priv_key = chilkat::PrivateKey::new();
if priv_key.load_encrypted_pem_file("qa_data/ecc/secp256r1-key-pkcs8-secret.pem", "secret").is_err() {
println!("{}", priv_key.last_error_text());
return;
}
// Sign the SHA256 hash of some data.
let bd = chilkat::BinData::new();
if bd.load_file("qa_data/hamlet.xml").is_err() {
println!("Failed to load file to be hashed.");
return;
}
let crypt = chilkat::Crypt2::new();
crypt.set_hash_algorithm("sha256");
crypt.set_encoding_mode("base64");
let hash_str = crypt.hash_bd_enc(&bd).unwrap_or_default();
let ecdsa = chilkat::Ecc::new();
let prng = chilkat::Prng::new();
// Returns ASN.1 signature as a base64 string.
let sig = ecdsa.sign_hash_enc(&hash_str, "base64", &priv_key, &prng).unwrap_or_default();
println!("sig = {}", sig);
// The signature is in ASN.1 format (which may be described as the "encoded DSS signature").
// SEQUENCE (2 elem)
// INTEGER (255 bit) 4849395540832462044300553275435608522154141569743642905628579547100940...
// INTEGER (255 bit) 3680701124244788134409868118208591399799457104230118295614152238560005...
// If you wish, you can get the r and s components of the signature like this:
let asn = chilkat::Asn::new();
let _ = asn.load_encoded(&sig, "base64");
let xml = chilkat::Xml::new();
let _ = xml.load_xml(&asn.asn_to_xml().unwrap_or_default());
println!("{}", xml.get_xml().unwrap_or_default());
// We now have this:
// <?xml version="1.0" encoding="utf-8"?>
// <sequence>
// <int>6650D422D86BA4A228B5617604E59052591B9B2C32EF324C44D09EF67E5F0060</int>
// <int>0CFD9F6AC85042FC70F672C141BA6B2A4CAFBB906C3D907BCCC1BED62B28326F</int>
// </sequence>
// Get the "r" and "s" as hex strings
let r = xml.get_child_content_by_index(0).unwrap_or_default();
let s = xml.get_child_content_by_index(1).unwrap_or_default();
println!("r = {}", r);
println!("s = {}", s);
// --------------------------------------------------------------------
// Now verify against the hash of the original data.
// Get the corresponding public key.
let pub_key = chilkat::PublicKey::new();
if pub_key.load_from_file("qa_data/ecc/secp256r1-pub.pem").is_err() {
println!("{}", pub_key.last_error_text());
return;
}
// We already have the SHA256 hash of the original data (hashStr) so no need to re-do it..
let ecc2 = chilkat::Ecc::new();
let result = ecc2.verify_hash_enc(&hash_str, &sig, "base64", &pub_key);
if result != 1 {
println!("{}", ecc2.last_error_text());
return;
}
println!("Verified!");
// Note: If we have only r,s and wish to reconstruct the ASN.1 signature, we do it like this:
let xml2 = chilkat::Xml::new();
xml2.set_tag("sequence");
xml2.new_child2("int", &r);
xml2.new_child2("int", &s);
let asn2 = chilkat::Asn::new();
let _ = asn2.load_asn_xml(&xml2.get_xml().unwrap_or_default());
let encoded_sig = asn2.get_encoded_der("base64").unwrap_or_default();
println!("encoded DSS signature: {}", encoded_sig);
// You can go to https://lapo.it/asn1js/ and copy/paste the base64 encodedSig into the online tool, then press the "decode" button.
// You will see the ASN.1 such as this:
// SEQUENCE (2 elem)
// INTEGER (255 bit) 4849395540832462044300553275435608522154141569743642905628579547100940...
// INTEGER (255 bit) 3680701124244788134409868118208591399799457104230118295614152238560005...