I am able to create a public/private ecdsa key in Rust, how can I store the keys for further use? I can't seem to find a method that will export the key.
use p256::{ecdsa::{SigningKey, Signature, signature::Signer}};
use rand_core::OsRng; // requires 'getrandom' feature
fn main() {
// Signing
let signing_key = SigningKey::random(&mut OsRng); // Serialize with `::to_bytes()`
let message = b"ECDSA proves knowledge of a secret number in the context of a single message";
let signature = signing_key.sign(message);
// Verification
use p256::ecdsa::{VerifyingKey, signature::Verifier};
let verifying_key = VerifyingKey::from(&signing_key); // Serialize with `::to_encoded_point()`
assert!(verifying_key.verify(message, &signature).is_ok());
}
There are many different ways to represent keys. Internally, it's a byte array that can be dumped as such directly. But for compatibility, you probably want a more standardized, human readable format.
The most common one is the PEM format.
To get a PEM, you cannot construct SigningKey and VerifyingKey directly. You need to create a SecretKey and a PublicKey. They can be stored and loaded to/from the PEM format.
You can then convert the SecretKey to a SigningKey and the PublicKey to a VerifyingKey.
Be aware that you need to enable the pem feature for the p256 dependency:
p256 = { version = "0.11", features = ["pem"] }
use p256::{
ecdsa::{
signature::{Signer, Verifier},
SigningKey, VerifyingKey,
},
pkcs8::EncodePrivateKey,
PublicKey, SecretKey,
};
use rand_core::OsRng;
fn main() {
// Generate secret key
let secret_key = SecretKey::random(&mut OsRng);
// Store secret key
let secret_key_serialized = secret_key
.to_pkcs8_pem(Default::default())
.unwrap()
.to_string();
println!("Secret Key: \n{}", secret_key_serialized);
// Load secret key
let secret_key = secret_key_serialized.parse::<SecretKey>().unwrap();
// Derive public key
let public_key = secret_key.public_key();
// Store public key
let public_key_serialized = public_key.to_string();
println!("Public Key: \n{}", public_key_serialized);
// Load public key
let public_key = public_key_serialized.parse::<PublicKey>().unwrap();
// Signing
let signing_key: SigningKey = secret_key.into();
let message = b"ECDSA proves knowledge of a secret number in the context of a single message";
let signature = signing_key.sign(message);
// Verification
let verifying_key: VerifyingKey = public_key.into();
assert!(verifying_key.verify(message, &signature).is_ok());
}
Secret Key:
-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQguKslF8gIC/Fm36Yk
SK2qZ4MXbUg/ZwCJwY9OmzRzkOehRANCAAQrRw99abOvHAPdz79CkuihXfaKZqx+
ZUG6iQRDzZy0c+gw20KeevA4gXKnW0nFK8PDmOgBprCU/uHf4vpMbqgo
-----END PRIVATE KEY-----
Public Key:
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEK0cPfWmzrxwD3c+/QpLooV32imas
fmVBuokEQ82ctHPoMNtCnnrwOIFyp1tJxSvDw5joAaawlP7h3+L6TG6oKA==
-----END PUBLIC KEY-----
One possible format is the export as raw keys. The private key is 32 bytes for P-256 (aka secp256r1, prime256v1), the public key is 65 bytes (uncompressed) or 33 bytes (compressed), s. e.g. here.
signing_key can be exported as raw private key with to_bytes() and verifying_key can be exported as an uncompressed/compressed public key with to_encoded_point(false/true). false returns an uncompressed key, true a compressed one. Usually the keys are then hex or Base64 encoded, s. here (with sample data):
...
println!("{}", hex::encode(signing_key.to_bytes())); // 3ee21644150adb50dc4c20e330184fabf12e75ecbf31fe167885587e6ebf2255
println!("{}", hex::encode(verifying_key.to_encoded_point(false))); // 044e6dbeefb3ffbab80281596869352fd4e90353758c3955914be90f0849d16aed5cefb4d5d4e209efaf8eb9349eed862c816cba3f2188e07d101f6ba2e23a69e9
println!("{}", hex::encode(verifying_key.to_encoded_point(true))); // 034e6dbeefb3ffbab80281596869352fd4e90353758c3955914be90f0849d16aed
...
For completeness: The import of the private key is possible with SigningKey::from_bytes() and that of the uncompressed/compressed public key with VerifyingKey::from_encoded_point().
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With