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::keys::PublicKey;
use super::sdk_wrapper::{CryptoImpl, Key, VerifySignResult};
use super::subtle::CryptoKey;
use super::subtle_idl_v1::{EcdsaSignatureMetadata, SecpR1Metadata, ShaMetadata};
use super::subtle_idl_v1_enums::{
    KeyAlgorithm, SecpR1KeyBitsize, ShaAlgorithm, ShaDigestBitsize, SigningAlgorithm,
};

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct KeyECC {
    key: Key,
    #[allow(dead_code)]
    named_curve: String,
}

impl Default for KeyECC {
    fn default() -> Self {
        KeyECC {
            key: Key::new(""),
            named_curve: String::from("P-256"),
        }
    }
}

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

impl KeyECC {
    pub fn new(name: &str, named_curve: &str) -> KeyECC {
        KeyECC {
            key: Key::new(name),
            named_curve: named_curve.to_string(),
        }
    }

    pub fn sign(&self, data: &[u8]) -> Result<Vec<u8>, Box<dyn Error>> {
        let hash_algo = ShaMetadata {
            algo_id: ShaAlgorithm::Sha2,
            length: ShaDigestBitsize::Sha256,
        };
        let signature_metadata = EcdsaSignatureMetadata {
            sha_metadata: hash_algo,
        };
        match CryptoImpl::sign(
            &self.key.name(),
            SigningAlgorithm::Ecdsa 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 hash_algo = ShaMetadata {
            algo_id: ShaAlgorithm::Sha2,
            length: ShaDigestBitsize::Sha256,
        };
        let signature_metadata = EcdsaSignatureMetadata {
            sha_metadata: hash_algo,
        };
        match CryptoImpl::verify(
            &self.key.name(),
            SigningAlgorithm::Ecdsa 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<PublicKey, Box<dyn Error>> {
        match CryptoImpl::get_public_key(&self.key.name()) {
            Ok(result) => Ok(PublicKey::new(&result)),
            Err(err) => Err(err),
        }
    }
}

pub fn get_key(name: &str) -> Result<KeyECC, Box<dyn Error>> {
    match CryptoImpl::key_exists(name) {
        Ok(_) => Ok(KeyECC::new(name, &String::from("P-256"))),
        Err(err) => Err(err),
    }
}

pub fn generate_key(name: &str) -> Result<KeyECC, 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 metadata = serde_json::to_string(&SecpR1Metadata {
        length: SecpR1KeyBitsize::SecpR1256,
    })?;
    let key: Vec<u8> = CryptoImpl::generate_key(
        name,
        KeyAlgorithm::SecpR1 as u32,
        &metadata,
        true,
        &["sign"],
    )?;

    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(KeyECC::new(name, "P-256"))
}