ncrypt 0.2.0

WIP rust bindings for the win32 ncrypt api
Documentation
#![cfg(target_os = "windows")]
use rand::thread_rng;
use rsa::{
    pkcs8::{EncodePublicKey, LineEnding},
    Pkcs1v15Encrypt,
};

fn real_main() -> Result<(), Box<dyn std::error::Error>> {
    println!("Opening provider");
    let provider = ncrypt::StorageProvider::open(ncrypt::ProviderName::PlatformCrypto)?;
    println!("Creating key");
    let key = match provider.create_persisted_key("Some test key", ncrypt::Algorithm::Rsa) {
        Ok(key) => key.finalize()?,
        Err(e) if e == ncrypt::Error::ObjectExists => {
            println!("Key exists already, opening");
            provider.open_key("Some test key")?
        }
        Err(e) => return Err(e.into()),
    };

    let key_length = key.key_length()?;
    println!("Key length: {} bytes, {} bits", key_length, key_length * 8);

    for k in provider.enum_keys() {
        println!("Key \"{}\" with algorithm \"{}\"", k.name, k.algorithm);
    }

    let ncrypt::RsaKeyBlob::PublicKey(pubkey) = key.export(ncrypt::ExportType::RsaPublicKey)?
    else {
        unreachable!()
    };

    println!("{}", pubkey.to_public_key_pem(LineEnding::LF)?);

    let plaintext = b"Hello world";

    let encrypted_data = pubkey.encrypt(&mut thread_rng(), Pkcs1v15Encrypt, plaintext)?;

    let decrypted = key.decrypt(&encrypted_data)?;

    if plaintext == decrypted.as_slice() {
        println!("Encryption roundtrip success");
    } else {
        println!("Encryption roundtrip failed");
    }

    assert_eq!(plaintext, decrypted.as_slice());

    Ok(())
}

fn main() {
    if let Err(e) = real_main() {
        eprintln!("Error: {e}");
        if let Some(source) = e.source() {
            eprintln!("\t{source}");
        }
    }
}