wasi-crypto 0.1.15

Experimental implementation of the WASI cryptography APIs
Documentation
mod ecdsa;
mod eddsa;
mod keypair;
mod publickey;
mod rsa;
mod secretkey;
mod signature;

use std::any::Any;
use std::convert::TryFrom;

pub use keypair::*;
pub use publickey::*;
pub use secretkey::*;
pub use signature::*;

use crate::options::*;
use crate::{asymmetric_common, error::*};

#[allow(non_camel_case_types)]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum SignatureAlgorithm {
    ECDSA_P256_SHA256,
    ECDSA_K256_SHA256,
    ECDSA_P384_SHA384,
    Ed25519,
    RSA_PKCS1_2048_SHA256,
    RSA_PKCS1_2048_SHA384,
    RSA_PKCS1_2048_SHA512,
    RSA_PKCS1_3072_SHA384,
    RSA_PKCS1_3072_SHA512,
    RSA_PKCS1_4096_SHA512,
    RSA_PSS_2048_SHA256,
    RSA_PSS_2048_SHA384,
    RSA_PSS_2048_SHA512,
    RSA_PSS_3072_SHA384,
    RSA_PSS_3072_SHA512,
    RSA_PSS_4096_SHA512,
}

pub enum SignatureAlgorithmFamily {
    ECDSA,
    EdDSA,
    RSA,
}

impl SignatureAlgorithm {
    pub fn family(&self) -> SignatureAlgorithmFamily {
        match self {
            SignatureAlgorithm::ECDSA_P256_SHA256
            | SignatureAlgorithm::ECDSA_K256_SHA256
            | SignatureAlgorithm::ECDSA_P384_SHA384 => SignatureAlgorithmFamily::ECDSA,
            SignatureAlgorithm::Ed25519 => SignatureAlgorithmFamily::EdDSA,
            SignatureAlgorithm::RSA_PKCS1_2048_SHA256
            | SignatureAlgorithm::RSA_PKCS1_2048_SHA384
            | SignatureAlgorithm::RSA_PKCS1_2048_SHA512
            | SignatureAlgorithm::RSA_PKCS1_3072_SHA384
            | SignatureAlgorithm::RSA_PKCS1_3072_SHA512
            | SignatureAlgorithm::RSA_PKCS1_4096_SHA512
            | SignatureAlgorithm::RSA_PSS_2048_SHA256
            | SignatureAlgorithm::RSA_PSS_2048_SHA384
            | SignatureAlgorithm::RSA_PSS_2048_SHA512
            | SignatureAlgorithm::RSA_PSS_3072_SHA384
            | SignatureAlgorithm::RSA_PSS_3072_SHA512
            | SignatureAlgorithm::RSA_PSS_4096_SHA512 => SignatureAlgorithmFamily::RSA,
        }
    }
}

impl TryFrom<&str> for SignatureAlgorithm {
    type Error = CryptoError;

    fn try_from(alg_str: &str) -> Result<Self, CryptoError> {
        match alg_str.to_uppercase().as_str() {
            "ECDSA_P256_SHA256" => Ok(SignatureAlgorithm::ECDSA_P256_SHA256),
            "ECDSA_K256_SHA256" => Ok(SignatureAlgorithm::ECDSA_K256_SHA256),
            "ECDSA_P384_SHA384" => Ok(SignatureAlgorithm::ECDSA_P384_SHA384),

            "ED25519" => Ok(SignatureAlgorithm::Ed25519),

            "RSA_PKCS1_2048_SHA256" => Ok(SignatureAlgorithm::RSA_PKCS1_2048_SHA256),
            "RSA_PKCS1_2048_SHA384" => Ok(SignatureAlgorithm::RSA_PKCS1_2048_SHA384),
            "RSA_PKCS1_2048_SHA512" => Ok(SignatureAlgorithm::RSA_PKCS1_2048_SHA512),
            "RSA_PKCS1_3072_SHA384" => Ok(SignatureAlgorithm::RSA_PKCS1_3072_SHA384),
            "RSA_PKCS1_3072_SHA512" => Ok(SignatureAlgorithm::RSA_PKCS1_3072_SHA512),
            "RSA_PKCS1_4096_SHA512" => Ok(SignatureAlgorithm::RSA_PKCS1_4096_SHA512),

            "RSA_PSS_2048_SHA256" => Ok(SignatureAlgorithm::RSA_PSS_2048_SHA256),
            "RSA_PSS_2048_SHA384" => Ok(SignatureAlgorithm::RSA_PSS_2048_SHA384),
            "RSA_PSS_2048_SHA512" => Ok(SignatureAlgorithm::RSA_PSS_2048_SHA512),
            "RSA_PSS_3072_SHA384" => Ok(SignatureAlgorithm::RSA_PSS_3072_SHA384),
            "RSA_PSS_3072_SHA512" => Ok(SignatureAlgorithm::RSA_PSS_3072_SHA512),
            "RSA_PSS_4096_SHA512" => Ok(SignatureAlgorithm::RSA_PSS_4096_SHA512),

            _ => bail!(CryptoError::UnsupportedAlgorithm),
        }
    }
}

#[derive(Clone, Debug, Default)]
pub struct SignatureOptions {}

impl OptionsLike for SignatureOptions {
    fn as_any(&self) -> &dyn Any {
        self
    }

    fn set(&mut self, _name: &str, _value: &[u8]) -> Result<(), CryptoError> {
        bail!(CryptoError::UnsupportedOption)
    }

    fn set_u64(&mut self, _name: &str, _value: u64) -> Result<(), CryptoError> {
        bail!(CryptoError::UnsupportedOption)
    }
}

#[test]
fn test_signatures_ecdsa() {
    use crate::{AlgorithmType, CryptoCtx};

    let ctx = CryptoCtx::new();
    let alg = "ECDSA_P256_SHA256";

    let kp_handle = ctx
        .keypair_generate(AlgorithmType::Signatures, alg, None)
        .unwrap();
    let pk_handle = ctx.keypair_publickey(kp_handle).unwrap();

    let pk_serialized = ctx
        .publickey_export(pk_handle, asymmetric_common::PublicKeyEncoding::Raw)
        .unwrap();
    let mut raw = vec![0u8; ctx.array_output_len(pk_serialized).unwrap()];
    ctx.array_output_pull(pk_serialized, &mut raw).unwrap();
    let pk_handle = ctx
        .publickey_import(
            AlgorithmType::Signatures,
            alg,
            &raw,
            asymmetric_common::PublicKeyEncoding::Raw,
        )
        .unwrap();

    let kp_serialized = ctx
        .keypair_export(kp_handle, asymmetric_common::KeyPairEncoding::Raw)
        .unwrap();
    let mut raw = vec![0u8; ctx.array_output_len(kp_serialized).unwrap()];
    ctx.array_output_pull(kp_serialized, &mut raw).unwrap();
    let kp2_handle = ctx
        .keypair_import(
            AlgorithmType::Signatures,
            alg,
            &raw,
            asymmetric_common::KeyPairEncoding::Raw,
        )
        .unwrap();
    let kp_handle = kp2_handle;

    let state_handle = ctx.signature_state_open(kp_handle).unwrap();
    ctx.signature_state_update(state_handle, b"test").unwrap();
    let signature_handle = ctx.signature_state_sign(state_handle).unwrap();

    let verification_state_handle = ctx.signature_verification_state_open(pk_handle).unwrap();
    ctx.signature_verification_state_update(verification_state_handle, b"test")
        .unwrap();
    ctx.signature_verification_state_verify(verification_state_handle, signature_handle)
        .unwrap();

    ctx.signature_verification_state_close(verification_state_handle)
        .unwrap();
    ctx.signature_state_close(state_handle).unwrap();
    ctx.keypair_close(kp_handle).unwrap();
    ctx.publickey_close(pk_handle).unwrap();
    ctx.signature_close(signature_handle).unwrap();
}

#[test]
fn test_signatures_eddsa() {
    use crate::{AlgorithmType, CryptoCtx};

    let ctx = CryptoCtx::new();

    let kp_handle = ctx
        .keypair_generate(AlgorithmType::Signatures, "Ed25519", None)
        .unwrap();
    let pk_handle = ctx.keypair_publickey(kp_handle).unwrap();

    let state_handle = ctx.signature_state_open(kp_handle).unwrap();
    ctx.signature_state_update(state_handle, b"test").unwrap();
    let signature_handle = ctx.signature_state_sign(state_handle).unwrap();

    let verification_state_handle = ctx.signature_verification_state_open(pk_handle).unwrap();
    ctx.signature_verification_state_update(verification_state_handle, b"test")
        .unwrap();
    ctx.signature_verification_state_verify(verification_state_handle, signature_handle)
        .unwrap();

    ctx.signature_verification_state_close(verification_state_handle)
        .unwrap();
    ctx.signature_state_close(state_handle).unwrap();
    ctx.keypair_close(kp_handle).unwrap();
    ctx.publickey_close(pk_handle).unwrap();
    ctx.signature_close(signature_handle).unwrap();
}

#[test]
fn test_signatures_rsa() {
    use crate::{AlgorithmType, CryptoCtx};

    let alg = "RSA_PKCS1_2048_SHA256";
    let ctx = CryptoCtx::new();

    let kp_handle = ctx
        .keypair_generate(AlgorithmType::Signatures, alg, None)
        .unwrap();
    let pk_handle = ctx.keypair_publickey(kp_handle).unwrap();

    let pk_serialized = ctx
        .publickey_export(pk_handle, asymmetric_common::PublicKeyEncoding::Local)
        .unwrap();
    let mut raw = vec![0u8; ctx.array_output_len(pk_serialized).unwrap()];
    ctx.array_output_pull(pk_serialized, &mut raw).unwrap();
    let pk_handle = ctx
        .publickey_import(
            AlgorithmType::Signatures,
            alg,
            &raw,
            asymmetric_common::PublicKeyEncoding::Local,
        )
        .unwrap();

    let kp_serialized = ctx
        .keypair_export(kp_handle, asymmetric_common::KeyPairEncoding::Local)
        .unwrap();
    let mut raw = vec![0u8; ctx.array_output_len(kp_serialized).unwrap()];
    ctx.array_output_pull(kp_serialized, &mut raw).unwrap();
    let kp2_handle = ctx
        .keypair_import(
            AlgorithmType::Signatures,
            alg,
            &raw,
            asymmetric_common::KeyPairEncoding::Local,
        )
        .unwrap();
    let kp_handle = kp2_handle;

    let state_handle = ctx.signature_state_open(kp_handle).unwrap();
    ctx.signature_state_update(state_handle, b"test").unwrap();
    let signature_handle = ctx.signature_state_sign(state_handle).unwrap();

    let verification_state_handle = ctx.signature_verification_state_open(pk_handle).unwrap();
    ctx.signature_verification_state_update(verification_state_handle, b"test")
        .unwrap();
    ctx.signature_verification_state_verify(verification_state_handle, signature_handle)
        .unwrap();

    ctx.signature_verification_state_close(verification_state_handle)
        .unwrap();
    ctx.signature_state_close(state_handle).unwrap();
    ctx.keypair_close(kp_handle).unwrap();
    ctx.publickey_close(pk_handle).unwrap();
    ctx.signature_close(signature_handle).unwrap();
}