#![allow(non_camel_case_types)]
use openssl::base64;
use openssl::error::ErrorStack;
use openssl::rand::rand_bytes;
use openssl::symm::Mode;
use serde::{Deserialize, Serialize};
use std::str::Utf8Error;
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
pub enum FileKeyVersion {
#[serde(rename = "A")]
RSA2048_AES256GCM,
#[serde(rename = "RSA-4096/AES-256-GCM")]
RSA4096_AES256GCM,
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
pub enum PlainFileKeyVersion {
#[serde(rename = "AES-256-GCM")]
AES256CM,
}
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
pub enum UserKeyPairVersion {
#[serde(rename = "A")]
RSA2048,
#[serde(rename = "RSA-4096")]
RSA4096,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct FileKey {
pub key: String,
pub iv: String,
pub version: FileKeyVersion,
pub tag: Option<String>,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct PlainFileKey {
pub key: String,
pub iv: String,
pub version: PlainFileKeyVersion,
pub tag: Option<String>,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(rename_all = "camelCase")]
pub struct PublicKeyContainer {
pub version: UserKeyPairVersion,
pub public_key: String,
pub created_at: Option<String>,
pub expire_at: Option<String>,
pub created_by: Option<u64>,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(rename_all = "camelCase")]
pub struct PrivateKeyContainer {
pub version: UserKeyPairVersion,
pub private_key: String,
pub created_at: Option<String>,
pub expire_at: Option<String>,
pub created_by: Option<u64>,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(rename_all = "camelCase")]
pub struct UserKeyPairContainer {
pub private_key_container: PrivateKeyContainer,
pub public_key_container: PublicKeyContainer,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(rename_all = "camelCase")]
pub struct PlainUserKeyPairContainer {
pub private_key_container: PrivateKeyContainer,
pub public_key_container: PublicKeyContainer,
}
impl PrivateKeyContainer {
pub fn new(private_key_pem: String, version: UserKeyPairVersion) -> Self {
Self {
private_key: private_key_pem,
version,
created_at: None,
expire_at: None,
created_by: None,
}
}
}
impl PublicKeyContainer {
pub fn new(public_key_pem: String, version: UserKeyPairVersion) -> Self {
Self {
public_key: public_key_pem,
version,
created_at: None,
expire_at: None,
created_by: None,
}
}
}
impl PlainUserKeyPairContainer {
pub fn new(
private_key_pem: String,
public_key_pem: String,
version: UserKeyPairVersion,
) -> Self {
let public_key_container = PublicKeyContainer::new(public_key_pem, version.clone());
let private_key_container = PrivateKeyContainer::new(private_key_pem, version);
Self {
private_key_container,
public_key_container,
}
}
pub fn new_from_keypair(
enc_keypair: UserKeyPairContainer,
plain_private_key_pem: &str,
) -> Self {
let version = enc_keypair.private_key_container.version;
let private_key_container =
PrivateKeyContainer::new(plain_private_key_pem.to_string(), version);
Self {
private_key_container,
public_key_container: enc_keypair.public_key_container,
}
}
}
impl UserKeyPairContainer {
pub fn new_from_plain_keypair(
plain_keypair: PlainUserKeyPairContainer,
enc_private_key_pem: &str,
) -> Self {
let version = plain_keypair.private_key_container.version;
let private_key_container =
PrivateKeyContainer::new(enc_private_key_pem.to_string(), version);
Self {
private_key_container,
public_key_container: plain_keypair.public_key_container,
}
}
}
impl FileKey {
pub fn new_from_plain_key(
plain_file_key: PlainFileKey,
enc_key: &str,
version: FileKeyVersion,
) -> Self {
Self {
key: enc_key.to_string(),
iv: plain_file_key.iv,
tag: plain_file_key.tag,
version,
}
}
}
impl PlainFileKey {
pub fn new_from_file_key(enc_file_key: FileKey, plain_file_key: &str) -> Self {
Self {
key: plain_file_key.to_string(),
iv: enc_file_key.iv,
tag: enc_file_key.tag,
version: PlainFileKeyVersion::AES256CM,
}
}
pub fn try_new_for_encryption() -> Result<Self, DracoonCryptoError> {
let mut key: [u8; 32] = [0; 32];
rand_bytes(&mut key)?;
let mut iv: [u8; 12] = [0; 12];
rand_bytes(&mut iv)?;
let key = base64::encode_block(&key);
let iv = base64::encode_block(&iv);
let plain_file_key = PlainFileKey {
key,
iv,
tag: None,
version: PlainFileKeyVersion::AES256CM,
};
Ok(plain_file_key)
}
pub fn set_tag(&mut self, tag: String) {
self.tag = Some(tag);
}
}
#[derive(Serialize, Debug, Clone, PartialEq)]
pub enum KeyState {
#[serde(rename = "none")]
None,
#[serde(rename = "available")]
Available,
#[serde(rename = "pending")]
Pending,
}
#[derive(Serialize, Debug, Clone, PartialEq)]
pub struct EncryptionInfo {
user_key_state: KeyState,
room_key_state: KeyState,
dataspace_key_state: KeyState,
}
#[derive(Debug, Clone, PartialEq)]
pub enum DracoonCryptoError {
RsaOperationFailed,
RsaImportFailed,
ByteParseError,
CrypterOperationFailed(String),
InvalidKeypairVersion,
BadData,
InvalidFileKeyFormat(String),
InvalidTag,
Unknown,
}
impl From<ErrorStack> for DracoonCryptoError {
fn from(_: ErrorStack) -> Self {
Self::RsaOperationFailed
}
}
impl From<Utf8Error> for DracoonCryptoError {
fn from(_: Utf8Error) -> Self {
Self::ByteParseError
}
}
pub type EncryptionResult = (Vec<u8>, PlainFileKey);
pub type ChunkedEncryptionResult = (Vec<u8>, Option<PlainFileKey>);
pub trait PublicKey {
fn get_public_key(&self) -> &PublicKeyContainer;
}
pub trait PrivateKey {
fn get_private_key(&self) -> &PrivateKeyContainer;
}
impl PublicKey for PlainUserKeyPairContainer {
fn get_public_key(&self) -> &PublicKeyContainer {
&self.public_key_container
}
}
impl PublicKey for PublicKeyContainer {
fn get_public_key(&self) -> &PublicKeyContainer {
self
}
}
impl PrivateKey for PlainUserKeyPairContainer {
fn get_private_key(&self) -> &PrivateKeyContainer {
&self.private_key_container
}
}
impl PrivateKey for PrivateKeyContainer {
fn get_private_key(&self) -> &PrivateKeyContainer {
self
}
}
pub trait DracoonRSACrypto {
fn create_plain_user_keypair(
version: UserKeyPairVersion,
) -> Result<PlainUserKeyPairContainer, DracoonCryptoError>;
fn encrypt_private_key(
secret: &str,
plain_keypair: PlainUserKeyPairContainer,
) -> Result<UserKeyPairContainer, DracoonCryptoError>;
fn decrypt_keypair(
secret: &str,
keypair: UserKeyPairContainer,
) -> Result<PlainUserKeyPairContainer, DracoonCryptoError>;
fn decrypt_private_key(
secret: &str,
plain_private_key: &PrivateKeyContainer,
) -> Result<PrivateKeyContainer, DracoonCryptoError>;
fn encrypt_file_key(
plain_file_key: PlainFileKey,
public_key: impl PublicKey,
) -> Result<FileKey, DracoonCryptoError>;
fn decrypt_file_key(
file_key: FileKey,
keypair: impl PrivateKey,
) -> Result<PlainFileKey, DracoonCryptoError>;
}
pub trait Encrypt {
fn encrypt(data: impl AsRef<[u8]>) -> Result<EncryptionResult, DracoonCryptoError>;
}
pub trait Decrypt {
fn decrypt(
data: &impl AsRef<[u8]>,
plain_file_key: PlainFileKey,
) -> Result<Vec<u8>, DracoonCryptoError>;
}
pub struct Open;
pub struct Finalized;
pub struct Crypter<'b, C, State = Open> {
pub crypter: C,
pub buffer: &'b mut Vec<u8>,
pub count: usize,
pub plain_file_key: PlainFileKey,
pub mode: Mode,
pub state: std::marker::PhantomData<State>,
}
pub trait Encrypter<C> {
fn encrypter(buffer: &mut Vec<u8>) -> Result<Crypter<C>, DracoonCryptoError>;
}
pub trait Decrypter<C> {
fn decrypter(
plain_file_key: PlainFileKey,
buffer: &mut Vec<u8>,
) -> Result<Crypter<C>, DracoonCryptoError>;
}
pub trait ChunkedEncryption<'b, C> {
fn finalize(&mut self) -> Result<usize, DracoonCryptoError>;
fn get_message(&mut self) -> &Vec<u8>;
fn get_plain_file_key(&self) -> PlainFileKey;
fn set_tag(&mut self, tag: &[u8]) -> Result<(), DracoonCryptoError>;
fn try_new_for_decryption(
plain_file_key: PlainFileKey,
buffer: &'b mut Vec<u8>,
) -> Result<Crypter<C>, DracoonCryptoError>;
fn try_new_for_encryption(buffer: &'b mut Vec<u8>) -> Result<Crypter<C>, DracoonCryptoError>;
fn update(&mut self, data: &[u8]) -> Result<usize, DracoonCryptoError>;
}