klave 0.5.0

A Rust SDK for the Klave platform.
Documentation
use serde::{Deserialize, Serialize};
use std::error::Error;
use std::fmt::Display;

use super::sdk_wrapper::CryptoImpl;
use super::sdk_wrapper::Key;
use super::sdk_wrapper::VerifySignResult;
use super::subtle::CryptoKey;
use super::subtle_idl_v1::{RsaMetadata, RsaOaepEncryptionMetadata, RsaPssSignatureMetadata};
use super::subtle_idl_v1_enums::{
    EncryptionAlgorithm, KeyAlgorithm, RsaKeyBitsize, SigningAlgorithm,
};
use super::util;

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct KeyRSA {
    key: Key,
    #[allow(dead_code)]
    modulus_length: u32,
}

impl Default for KeyRSA {
    fn default() -> Self {
        KeyRSA {
            key: Key::new(""),
            modulus_length: 2048,
        }
    }
}

impl Display for KeyRSA {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(
            f,
            "KeyRSA: name: {}, length: {}",
            self.key.name(),
            self.modulus_length
        )
    }
}

impl KeyRSA {
    pub fn new(name: &str, modulus_length: u32) -> KeyRSA {
        KeyRSA {
            key: Key::new(name),
            modulus_length,
        }
    }

    pub fn encrypt(&self, data: &[u8]) -> Result<Vec<u8>, Box<dyn Error>> {
        let rsa_oaep_encryption_metadata = RsaOaepEncryptionMetadata { label: vec![] };
        match CryptoImpl::encrypt(
            &self.key.name(),
            EncryptionAlgorithm::RsaOaep as u32,
            &serde_json::to_string(&rsa_oaep_encryption_metadata)?,
            data,
        ) {
            Ok(result) => Ok(result),
            Err(err) => Err(err),
        }
    }

    pub fn decrypt(&self, data: &[u8]) -> Result<Vec<u8>, Box<dyn Error>> {
        let rsa_oaep_encryption_metadata = RsaOaepEncryptionMetadata { label: vec![] };
        match CryptoImpl::decrypt(
            &self.key.name(),
            EncryptionAlgorithm::RsaOaep as u32,
            &serde_json::to_string(&rsa_oaep_encryption_metadata)?,
            data,
        ) {
            Ok(result) => Ok(result),
            Err(err) => Err(err),
        }
    }

    pub fn sign(&self, data: &[u8]) -> Result<Vec<u8>, Box<dyn Error>> {
        let salt_length = 32;
        let signature_metadata = RsaPssSignatureMetadata { salt_length };
        match CryptoImpl::sign(
            &self.key.name(),
            SigningAlgorithm::RsaPss as u32,
            &serde_json::to_string(&signature_metadata)?,
            data,
        ) {
            Ok(result) => Ok(result),
            Err(err) => Err(err),
        }
    }

    pub fn verify(
        &self,
        data: &[u8],
        signature: &[u8],
    ) -> Result<VerifySignResult, Box<dyn Error>> {
        let salt_length = 32;
        let signature_metadata = RsaPssSignatureMetadata { salt_length };
        match CryptoImpl::verify(
            &self.key.name(),
            SigningAlgorithm::RsaPss as u32,
            &serde_json::to_string(&signature_metadata)?,
            data,
            signature,
        ) {
            Ok(result) => Ok(result),
            Err(err) => Err(err),
        }
    }

    pub fn get_public_key(&self) -> Result<Vec<u8>, Box<dyn Error>> {
        match CryptoImpl::get_public_key(&self.key.name()) {
            Ok(result) => Ok(result),
            Err(err) => Err(err),
        }
    }
}

pub fn get_key(name: &str) -> Result<KeyRSA, Box<dyn Error>> {
    match CryptoImpl::key_exists(name) {
        Ok(_) => Ok(KeyRSA::new(name, 2048)),
        Err(err) => Err(err),
    }
}

pub fn generate_key(name: &str) -> Result<KeyRSA, Box<dyn Error>> {
    if name.is_empty() {
        return Err("Invalid key name: key name cannot be empty".into());
    }

    match CryptoImpl::key_exists(name) {
        Ok(exists) => {
            if exists {
                return Err(format!("Invalid key name: key name {name} already exists").into());
            }
        }
        Err(e) => return Err(e),
    }

    let sha_algo = String::from("sha-256");
    let sha_metadata = util::get_sha_metadata(&sha_algo)?;
    let metadata = RsaMetadata {
        modulus: RsaKeyBitsize::Rsa2048,
        public_exponent: 0,
        sha_metadata,
    };
    let key = CryptoImpl::generate_key(
        name,
        KeyAlgorithm::Rsa as u32,
        &serde_json::to_string(&metadata)?,
        true,
        &["sign", "decrypt"],
    )?;

    match CryptoImpl::save_key(name) {
        Ok(_) => (),
        Err(e) => return Err(e),
    };

    match serde_json::from_str::<CryptoKey>(&String::from_utf8(key)?) {
        Ok(_) => (),
        Err(e) => return Err(e.into()),
    };

    Ok(KeyRSA::new(name, 2048))
}