activeledger 0.1.1

Rust SDK for easy connection to Activeledger networks
Documentation
/*
 * MIT License (MIT)
 * Copyright (c) 2019 Activeledger
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

//! # Exporter
//!
//! The exporter module provides the ability to export keys generated by the SDK
//! (or imported via the importer module)
//!
//! Currently RSA and EC (SECP256K1) keys can be exported
//!
//!
//! ## Examples
//! For this example we will be using an RSA key example but other
//! keys will be similar, the alternative functions are listed at the end of the example.
//! ```
//! # use activeledger::key::RSA;
//! # use activeledger::key::export;
//! let rsa = RSA::new("Key name").unwrap();
//! let path = "export/path/file.json";
//! # let path = "./testfiles/rsaexport.json";
//! // Pass a reference of the key and write path to the exporter
//! export::export_rsa(&rsa, path).unwrap();
//! // Note! The path must include the file name!
//! ```
//! The other functions for key exporting are:
//! ```
//! # use activeledger::key::EllipticCurve;
//! # use activeledger::key::export;
//! # let ec = EllipticCurve::new("").unwrap();
//! # let path = "./testfiles/ecexport.json";
//! export::export_ec(&ec, path).unwrap();
//! ```
//!
//! ## File Structure
//! The file that is exported will have the following JSON structure
//! ```JSON
//! {
//!     "name":"",
//!     "type":"",
//!     "pem": {
//!        "private": "",
//!        "public":""
//!     }
//! }
//! ```

extern crate serde_json;

use std::fs::File;
use std::io::Write;
use std::path::Path;

use super::{
    error::{KeyError, KeyResult},
    EllipticCurve, Pkcs8pem, RSA,
};

/// Export an RSA key to the specified location.Key.
///
/// The data will be stored as a JSON file.
///
/// ## Example
/// ```
/// # use activeledger::key::RSA;
/// # use activeledger::key::export;
/// let rsa = RSA::new("Key name").unwrap();
/// let path = "export/path/file.json";
/// # let path = "./testfiles/rsaexport.json";
///
/// // Pass a reference of the key and write path to the exporter
/// export::export_rsa(&rsa, path).unwrap();
/// // Note! The path must include the file name!
/// ```
///
/// ## Errors
/// If this function cannot export the given key it will return an ExportError.
pub fn export_rsa(key: &RSA, path: &str) -> KeyResult<()> {
    let pem = key.get_pem()?;

    export(&key.name, &pem, &path, "rsa")?;

    Ok(())
}

/// Export an EC key to the specified location.Key.
///
/// The data will be stored as a JSON file.
///
/// ## Example
/// ```
/// # use activeledger::key::EllipticCurve;
/// # use activeledger::key::export;
/// let ec = EllipticCurve::new("Key name").unwrap();
/// let path = "export/path/file.json";
/// # let path = "./testfiles/ecexport.json";
///
/// // Pass a reference of the key and write path to the exporter
/// export::export_ec(&ec, &path).unwrap();
/// // Note! The path must include the file name!
/// ```
///
/// ## Errors
/// If this function cannot export the given key it will return an ExportError.
pub fn export_ec(key: &EllipticCurve, path: &str) -> KeyResult<()> {
    let pem = key.get_pem()?;

    export(&key.name, &pem, &path, "ec")?;

    Ok(())
}

/// Create a JSON export using the given data
fn export(name: &str, pem: &Pkcs8pem, path: &str, key_type: &str) -> KeyResult<()> {
    // Build the structure of the file
    let key_file_data = r#"{
            "name":"",
            "type":"",
            "pem": {
                "private": "",
                "public":""
            }
        }"#;

    // Create the JSON object
    let mut json_obj: serde_json::Value = match serde_json::from_str(key_file_data) {
        Ok(json) => json,
        Err(_) => return Err(KeyError::ExportError(5000)),
    };

    json_obj["name"] = name.to_string().into();
    json_obj["type"] = key_type.into();
    json_obj["pem"]["private"] = pem.private.to_string().into();
    json_obj["pem"]["public"] = pem.public.to_string().into();

    let path = Path::new(path);

    // Create the file instance
    let mut file = match File::create(path) {
        Ok(file) => file,
        Err(_) => return Err(KeyError::ExportError(5001)),
    };

    // Write the data to the file and return
    match file.write_all(json_obj.to_string().as_bytes()) {
        Ok(_) => return Ok(()),
        Err(_) => return Err(KeyError::ExportError(5002)),
    };
}

#[cfg(test)]
mod tests {
    use crate::key::{export, EllipticCurve, RSA};

    #[test]
    fn export_rsa() {
        let key = RSA::new("Test").unwrap();

        export::export_rsa(&key, "./testfiles/rsaexport.json").unwrap();
    }

    #[test]
    fn export_ec() {
        let key = EllipticCurve::new("Test").unwrap();

        export::export_ec(&key, "./testfiles/ecexport.json").unwrap();
    }
}