[dependencies]p256 = { version = "=0.14.0", features = ["ecdsa", "pem"] } use std::io::Write;use std::os::unix::fs::OpenOptionsExt; use p256::ecdsa::SigningKey;use p256::elliptic_curve::Generate;use p256::pkcs8::{EncodePrivateKey, EncodePublicKey, LineEnding}; fn main() -> Result<(), Box<dyn std::error::Error>> { // OS randomness (getrandom); SigningKey::random(&mut rng) is deprecated since ecdsa 0.17 let signing_key = SigningKey::generate(); let private_pem = signing_key.to_pkcs8_pem(LineEnding::LF)?; // Zeroizing<String>, wiped on drop let public_pem = signing_key.verifying_key().to_public_key_pem(LineEnding::LF)?; // create_new refuses to overwrite a key; mode 0o600 keeps it owner-only (Unix) std::fs::OpenOptions::new() .write(true) .create_new(true) .mode(0o600) .open("key.pem")? .write_all(private_pem.as_bytes())?; std::fs::write("pub.pem", &public_pem)?; print!("{public_pem}"); Ok(())} How it works
SigningKey::generate()comes from theGeneratetrait (re-exported asp256::elliptic_curve::Generate) and usesgetrandom, i.e. the OS CSPRNG;generate_from_rngaccepts an explicit RNG for special cases.to_pkcs8_pemwritesBEGIN PRIVATE KEYand returnsZeroizing<String>, which wipes the key text from memory when it goes out of scope.verifying_key().to_public_key_pemwrites the SPKIBEGIN PUBLIC KEYblock; both functions take an explicitLineEnding.OpenOptionswithcreate_new(true)andmode(0o600)creates the private key file atomically with owner-only permissions; the run confirms the mode and that OpenSSL derives the same public key.
Gotchas
SigningKey::random(&mut OsRng)from older tutorials no longer fits:randomis deprecated since ecdsa 0.17 in favour of theGeneratetrait, andrand_core0.10 has noOsRng(the OS generator is nowgetrandom::SysRng). Keep all RustCrypto crates on the same release line — types from p256 0.13 and 0.14 do not mix.genis a reserved keyword in Rust 2024, solet gen = SigningKey::generate();does not compile. Pick another variable name.std::os::unix::fs::OpenOptionsExtexists only on Unix; on Windows drop.mode()and protect the file with ACLs.- For secp256k1, use the sibling crate
k256with the same API —p256keys cannot be converted to another curve.