helium-crypto 0.10.0

Helium Blockchain cryptography library
use crate::nova_tz::keyblob;
use crate::nova_tz::Error;
use crate::nova_tz::Result;
use rsa::RSAPublicKey;
use std::fs;
use std::path::Path;
use uuid::Uuid;

pub struct TzRsaKeyInfo {
    key_name: String,
    rsa_key: RSAPublicKey,
}

impl TzRsaKeyInfo {
    const NOVA_RSA_KEYS_PATH: &'static str = "/sys/nova-rsa/keys/";
    const NOVA_RSA_ADD_PATH: &'static str = "/sys/nova-rsa/add";
    const NOVA_RSA_REMOVE_PATH: &'static str = "/sys/nova-rsa/remove";

    pub fn from_path(key_path: &Path) -> Result<Self> {
        if !key_path.exists() {
            return Err(Error::BadKeyPath(
                key_path.to_string_lossy().to_string(),
                "file doesn't exist".to_string(),
            )
            .into());
        }

        let key_blob_data = fs::read(key_path).map_err(|e| {
            Error::BadKeyPath(key_path.to_string_lossy().to_string(), e.to_string())
        })?;

        TzRsaKeyInfo::from_key_blob_data(key_blob_data.as_slice())
    }

    pub fn from_key_blob_data(key_blob_data: &[u8]) -> Result<Self> {
        let key_name = Uuid::new_v4().to_string();
        let rsa_key = keyblob::parse_key_blob(key_blob_data).map_err(Error::KeyBlobError)?;

        fs::write(TzRsaKeyInfo::NOVA_RSA_ADD_PATH, &key_name).map_err(Error::QseecomError)?;
        fs::write(
            format!("{}{}{}", TzRsaKeyInfo::NOVA_RSA_KEYS_PATH, key_name, "/key"),
            key_blob_data,
        )
        .map_err(Error::QseecomError)?;

        Ok(TzRsaKeyInfo { key_name, rsa_key })
    }

    pub fn public_key(&self) -> Result<RSAPublicKey> {
        Ok(self.rsa_key.clone())
    }

    pub fn sign(&self, msg: &[u8]) -> Result<Vec<u8>> {
        let sign_path = format!(
            "{}{}{}",
            TzRsaKeyInfo::NOVA_RSA_KEYS_PATH,
            self.key_name,
            "/sign"
        );

        fs::write(&sign_path, msg).map_err(Error::QseecomError)?;
        let signed = fs::read(&sign_path).map_err(Error::QseecomError)?;
        Ok(signed)
    }

    fn remove_key(&self) -> Result {
        fs::write(TzRsaKeyInfo::NOVA_RSA_REMOVE_PATH, &self.key_name)
            .map_err(Error::QseecomError)?;
        Ok(())
    }
}

impl Drop for TzRsaKeyInfo {
    fn drop(&mut self) {
        self.remove_key().expect("Failed to remove key");
    }
}