use crate::base::*;
use crate::error::EzNaclError;
use crate::CryptoString;
use sodiumoxide::crypto;
pub fn get_supported_asymmetric_algorithms() -> Vec<String> {
vec![String::from("CURVE25519")]
}
#[derive(Debug, Clone, PartialEq, PartialOrd)]
#[cfg_attr(feature = "use_serde", derive(serde::Serialize, serde::Deserialize))]
pub struct EncryptionPair {
pubkey: CryptoString,
privkey: CryptoString,
}
impl EncryptionPair {
pub fn from(
pubkey: &CryptoString,
privkey: &CryptoString,
) -> Result<EncryptionPair, EzNaclError> {
if pubkey.prefix() != privkey.prefix() {
return Err(EzNaclError::KeyError);
}
if !is_supported_algorithm(pubkey.prefix()) {
return Err(EzNaclError::UnsupportedAlgorithm);
}
Ok(EncryptionPair {
pubkey: pubkey.clone(),
privkey: privkey.clone(),
})
}
pub fn from_strings(pubstr: &str, privstr: &str) -> Result<EncryptionPair, EzNaclError> {
let pubcs = match CryptoString::from(pubstr) {
Some(cs) => cs,
None => return Err(EzNaclError::KeyError),
};
let privcs = match CryptoString::from(privstr) {
Some(cs) => cs,
None => return Err(EzNaclError::KeyError),
};
EncryptionPair::from(&pubcs, &privcs)
}
pub fn generate(algorithm: &str) -> Result<EncryptionPair, EzNaclError> {
if algorithm != "CURVE25519" {
return Err(EzNaclError::UnsupportedAlgorithm);
}
let (raw_ekey, raw_dkey) = crypto::box_::gen_keypair();
let pubkey = match CryptoString::from_bytes("CURVE25519", &raw_ekey[..]) {
Some(cs) => cs,
None => return Err(EzNaclError::KeyError),
};
let privkey = match CryptoString::from_bytes("CURVE25519", &raw_dkey[..]) {
Some(cs) => cs,
None => return Err(EzNaclError::KeyError),
};
Ok(EncryptionPair { pubkey, privkey })
}
}
impl CryptoInfo for EncryptionPair {
fn get_usage(&self) -> KeyUsage {
KeyUsage::EncryptDecrypt
}
fn get_algorithm(&self) -> String {
String::from("CURVE25519")
}
}
impl PublicKey for EncryptionPair {
fn get_public_key(&self) -> CryptoString {
self.pubkey.clone()
}
fn get_public_str(&self) -> String {
String::from(self.pubkey.as_str())
}
fn get_public_bytes(&self) -> Vec<u8> {
Vec::from(self.pubkey.as_bytes())
}
}
impl PrivateKey for EncryptionPair {
fn get_private_key(&self) -> CryptoString {
self.privkey.clone()
}
fn get_private_str(&self) -> String {
String::from(self.privkey.as_str())
}
fn get_private_bytes(&self) -> Vec<u8> {
Vec::from(self.privkey.as_bytes())
}
}
impl Encryptor for EncryptionPair {
fn encrypt(&self, data: &[u8]) -> Result<CryptoString, EzNaclError> {
let rawkey = match crypto::box_::PublicKey::from_slice(&self.pubkey.as_raw()) {
Some(v) => v,
None => return Err(EzNaclError::KeyError),
};
let ciphertext = crypto::sealedbox::seal(data, &rawkey);
match CryptoString::from_bytes("CURVE25519", &ciphertext) {
Some(v) => Ok(v),
None => Err(EzNaclError::EncodingError),
}
}
}
impl Decryptor for EncryptionPair {
fn decrypt(&self, encdata: &CryptoString) -> Result<Vec<u8>, crate::EzNaclError> {
let ciphertext = encdata.as_raw();
let rpubkey = match crypto::box_::PublicKey::from_slice(&self.pubkey.as_raw()) {
Some(v) => v,
None => return Err(EzNaclError::KeyError),
};
let rprivkey = match crypto::box_::SecretKey::from_slice(&self.privkey.as_raw()) {
Some(v) => v,
None => return Err(EzNaclError::KeyError),
};
match crypto::sealedbox::open(&ciphertext, &rpubkey, &rprivkey) {
Ok(v) => Ok(v),
_ => Err(EzNaclError::DecryptionError),
}
}
}
#[derive(Debug, Clone, PartialEq, PartialOrd)]
#[cfg_attr(feature = "use_serde", derive(serde::Serialize, serde::Deserialize))]
pub struct EncryptionKey {
pubkey: CryptoString,
}
impl EncryptionKey {
pub fn from(pubkey: &CryptoString) -> Result<EncryptionKey, EzNaclError> {
if !is_supported_algorithm(pubkey.prefix()) {
return Err(EzNaclError::UnsupportedAlgorithm);
}
Ok(EncryptionKey {
pubkey: pubkey.clone(),
})
}
pub fn from_string(pubstr: &str) -> Result<EncryptionKey, EzNaclError> {
let pubcs = match CryptoString::from(pubstr) {
Some(cs) => cs,
None => return Err(EzNaclError::KeyError),
};
EncryptionKey::from(&pubcs)
}
}
impl CryptoInfo for EncryptionKey {
fn get_usage(&self) -> KeyUsage {
KeyUsage::Encrypt
}
fn get_algorithm(&self) -> String {
String::from("CURVE25519")
}
}
impl PublicKey for EncryptionKey {
fn get_public_key(&self) -> CryptoString {
self.pubkey.clone()
}
fn get_public_str(&self) -> String {
String::from(self.pubkey.as_str())
}
fn get_public_bytes(&self) -> Vec<u8> {
Vec::from(self.pubkey.as_bytes())
}
}
impl Encryptor for EncryptionKey {
fn encrypt(&self, data: &[u8]) -> Result<CryptoString, EzNaclError> {
let rawkey = match crypto::box_::PublicKey::from_slice(&self.pubkey.as_raw()) {
Some(v) => v,
None => return Err(EzNaclError::KeyError),
};
let ciphertext = crypto::sealedbox::seal(data, &rawkey);
match CryptoString::from_bytes("CURVE25519", &ciphertext) {
Some(v) => Ok(v),
None => Err(EzNaclError::EncodingError),
}
}
}
#[cfg(test)]
mod tests {
use crate::*;
#[test]
fn encrypt_decrypt_test() {
let keypair = match crate::EncryptionPair::from_strings(
"CURVE25519:(B2XX5|<+lOSR>_0mQ=KX4o<aOvXe6M`Z5ldINd`",
"CURVE25519:(Rj5)mmd1|YqlLCUP0vE;YZ#o;tJxtlAIzmPD7b&",
) {
Ok(kp) => kp,
Err(_) => panic!("encrypt_decrypt_test failed to create keypair"),
};
let testdata = "This is some encryption test data";
let encdata = match keypair.encrypt(testdata.as_bytes()) {
Ok(cs) => cs,
Err(_) => panic!("encrypt_decrypt_test encryption failure"),
};
let decdata = match keypair.decrypt(&encdata) {
Ok(cs) => cs,
Err(_) => panic!("encrypt_decrypt_test decryption failure"),
};
let decstring = match String::from_utf8(decdata) {
Ok(s) => s,
Err(_) => panic!("encrypt_decrypt_test failure decoding decrypted data"),
};
assert_eq!(testdata, decstring);
}
}