Skip to content

Commit

Permalink
new version
Browse files Browse the repository at this point in the history
release of version 1.1.4
  • Loading branch information
mm9942 committed Apr 2, 2024
1 parent 08cd699 commit 57cf8e2
Show file tree
Hide file tree
Showing 26 changed files with 4,095 additions and 136 deletions.
5 changes: 3 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "crypt_guard"
version = "1.1.0"
version = "1.1.4"
edition = "2021"
description = "CryptGuardLib is a comprehensive Rust library designed for strong encryption and decryption, incorporating post-quantum cryptography to safeguard against quantum threats. It's geared towards developers who need to embed advanced cryptographic capabilities in their Rust applications."
license = "MIT"
Expand All @@ -22,6 +22,7 @@ chacha20 = "0.9.1"
pqcrypto-dilithium = "0.5.0"
pqcrypto-kyber = "0.8.1"
tempfile = "3.10.1"
# notify-rust = "4.10.0"

[features]
tokio = ["dep:tokio"]
tokio = ["dep:tokio"]
21 changes: 21 additions & 0 deletions LICENSE.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2024 M

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.
241 changes: 107 additions & 134 deletions README.md

Large diffs are not rendered by default.

36 changes: 36 additions & 0 deletions examples/encrypt_aes.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//use crypt_guard::KeyKyber::KeyControl;
use crypt_guard::{*, error::*};
use std::{
fs::{self, File},
marker::PhantomData,
path::{PathBuf, Path},
io::{Read, Write},

};
use tempfile::{TempDir, Builder};

fn main() -> Result<(), Box<dyn std::error::Error>> {
let message = "Hey, how are you doing?";
let passphrase = "Test Passphrase";

// Generate key pair
let (public_key, secret_key) = KeyControKyber1024::keypair().expect("Failed to generate keypair");

// Instantiate Kyber for encryption of a message with Kyber1024 and AES
// Fails when not using either of these properties since it would be the wrong type of algorithm, data, keysize or process!
let mut encryptor = Kyber::<Encryption, Kyber1024, File, AES>::new(public_key.clone(), None)?;

// Encrypt message
let (encrypt_message, cipher) = encryptor.encrypt_msg(message.clone(), passphrase.clone())?;

// Instantiate Kyber for decryption of a message with Kyber1024 and AES
// Fails when not using either of these properties since it would be the wrong type of algorithm, data, keysize or process!
let mut decryptor = Kyber::<Decryption, Kyber1024, File, AES>::new(secret_key, None)?;

// Decrypt message
let decrypt_message = decryptor.decrypt_msg(encrypt_message.clone(), passphrase.clone(), cipher)?;

let decrypted_text = String::from_utf8(decrypt_message).expect("Failed to convert decrypted message to string");
println!("{:?}", decrypted_text);
Ok(())
}
46 changes: 46 additions & 0 deletions examples/encrypt_xchacha.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
use crypt_guard::{*, error::*};
use std::{
fs::{self, File},
marker::PhantomData,
path::{PathBuf, Path},
io::{Read, Write},

};
use tempfile::{TempDir, Builder};


fn main() -> Result<(), Box<dyn std::error::Error>> {
let message = "Hey, how are you doing?";

let tmp_dir = TempDir::new().map_err(|e| CryptError::from(e))?;
let tmp_dir = Builder::new().prefix("messages").tempdir().map_err(|e| CryptError::from(e))?;

let enc_path = tmp_dir.path().clone().join("message.txt");
let dec_path = tmp_dir.path().clone().join("message.txt.enc");

fs::write(&enc_path, message.as_bytes())?;

let passphrase = "Test Passphrase";

// Generate key pair
let (public_key, secret_key) = KeyControKyber768::keypair().expect("Failed to generate keypair");

// Instantiate Kyber for encryption of a file with Kyber768 and XChaCha20
// Fails when not using either of these properties since it would be the wrong type of algorithm, data, keysize or process!
let mut encryptor = Kyber::<Encryption, Kyber768, File, XChaCha20>::new(public_key.clone(), None)?;

// Encrypt message
let (encrypt_message, cipher) = encryptor.encrypt_file(enc_path.clone(), passphrase.clone())?;

let nonce = encryptor.get_nonce();

fs::remove_file(enc_path.clone());

// Instantiate Kyber for decryption of a file with Kyber768 and XChaCha20
// Fails when not using either of these properties since it would be the wrong type of algorithm, data, keysize or process!
let mut decryptor = Kyber::<Decryption, Kyber768, File, XChaCha20>::new(secret_key, Some(nonce?.to_string()))?;

// Decrypt message
let decrypt_message = decryptor.decrypt_file(dec_path.clone(), passphrase.clone(), cipher)?;
Ok(())
}
244 changes: 244 additions & 0 deletions src/Core/cipher_aes.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,244 @@
use crate::{
*,
error::CryptError,
signature::*,
Core::{
CryptographicFunctions,
KeyControl,
KeyControKyber512,
KeyControKyber768,
KeyControKyber1024,
KyberKeyFunctions,
kyber::KyberSizeVariant,
KeyControlVariant,
}
};
use aes::{
cipher::{
BlockEncrypt,
BlockDecrypt,
generic_array::GenericArray,
KeyInit
},
Aes256
};
use std::{
path::{PathBuf, Path},
marker::PhantomData,
result::Result,
io::{Read, Write},
fs
};
use pqcrypto_traits::kem::{PublicKey as PublicKeyKem, SecretKey as SecKeyKem, SharedSecret as SharedSecretKem, Ciphertext as CiphertextKem};
use pqcrypto_kyber::kyber1024;
use pqcrypto_kyber::kyber1024::*;

/// Provides AES encryption functionality, handling cryptographic information and shared secrets.
impl CipherAES {
/// Initializes a new `CipherAES` instance with the provided cryptographic information.
///
/// # Parameters
/// - `infos`: Cryptographic information detailing the encryption or decryption process, content type, and more.
///
/// # Returns
/// A new instance of `CipherAES`.
pub fn new(infos: CryptographicInformation) -> Self {
CipherAES { infos, sharedsecret: Vec::new() }
}

/// Retrieves the current data intended for encryption or decryption.
///
/// # Returns
/// The data as a vector of bytes (`Vec<u8>`) or a `CryptError` if the content cannot be accessed.
pub fn get_data(&self) -> Result<Vec<u8>, CryptError> {
let data = &self.infos.content()?;
let mut data = data.to_vec();
Ok(data)
}

/// Sets the shared secret key used for AES encryption and decryption.
///
/// # Parameters
/// - `sharedsecret`: The shared secret as a byte vector.
///
/// # Returns
/// A mutable reference to the `CipherAES` instance, allowing for chaining of operations.
pub fn set_shared_secret(&mut self, sharedsecret: Vec<u8>) -> &Self {
self.sharedsecret = sharedsecret;
self
}

/// Retrieves the shared secret key.
///
/// # Returns
/// A reference to the shared secret as a byte vector or a `CryptError` if it cannot be accessed.
pub fn sharedsecret(&self) -> Result<&Vec<u8>, CryptError> {
Ok(&self.sharedsecret)
}

/// Retrieves the shared secret key.
///
/// # Returns
/// A reference to the shared secret as a byte vector or a `CryptError` if it cannot be accessed.
fn encryption(&mut self) -> Result<Vec<u8>, CryptError> {
let file_contained = self.infos.contains_file()?;
if file_contained && self.infos.metadata.content_type == ContentType::File {
self.infos.content = fs::read(self.infos.location()?).unwrap();
}
let encrypted_data = self.encrypt_aes()?;
println!("Encrypted Data: {:?}", encrypted_data);

let mut passphrase = self.infos.passphrase()?.to_vec();
let mut hmac = Sign::new(encrypted_data, passphrase, Operation::Sign, SignType::Sha512);
let data = hmac.hmac();
if self.infos.safe()? {
let _ = self.infos.set_data(&data)?;
let _ = self.infos.safe_file()?;
}
Ok(data)
}

/// Saves the ciphertext to a file specified within the cryptographic information's location.
///
/// # Parameters
/// - `encrypted_data`: The ciphertext to be saved.
///
/// # Returns
/// An `Ok(())` upon successful save or a `CryptError` if saving fails.
fn save_ciphertext(&self, encrypted_data: &[u8]) -> Result<(), CryptError> {
use std::{fs::File, io::Write};

if let Some(file_metadata) = &self.infos.location {
let file_path = file_metadata.parent()?;
let filename = format!("{}/ciphertext.pem", file_path.as_os_str().to_str().unwrap());
let file_path_with_enc = PathBuf::from(filename);

let mut buffer = File::create(file_path_with_enc).map_err(|_| CryptError::WriteError)?;
buffer.write_all(self.sharedsecret()?).map_err(|_| CryptError::WriteError)?;

Ok(())
} else {
Err(CryptError::PathError)
}
}

/// Encrypts the provided data with AES-256.
///
/// # Returns
/// A result containing the encrypted data as a byte vector or a `CryptError` if encryption fails.
fn encrypt_aes(&mut self) -> Result<Vec<u8>, CryptError> {
let block_size = 16;
let mut padded_data = self.get_data()?;

// Padding the data if necessary
let padding_needed = block_size - (padded_data.len() % block_size);
padded_data.extend(vec![padding_needed as u8; padding_needed]);

let mut encrypted_data = vec![0u8; padded_data.len()];
let sharedsecret = self.sharedsecret()?;
let cipher = Aes256::new(GenericArray::from_slice(sharedsecret));

for (chunk, encrypted_chunk) in padded_data.chunks(block_size).zip(encrypted_data.chunks_mut(block_size)) {
let mut block = GenericArray::clone_from_slice(chunk);
cipher.encrypt_block(&mut block);
encrypted_chunk.copy_from_slice(&block);
}

Ok(encrypted_data)
}

/// Decrypts data using AES-256.
///
/// # Returns
/// The decrypted data as a byte vector or a `CryptError` if decryption fails.
fn decryption(&mut self) -> Result<Vec<u8>, CryptError> {
let file_contained = self.infos.contains_file()?;
if file_contained && self.infos.metadata.content_type == ContentType::File {
self.infos.content = fs::read(self.infos.location()?).unwrap();

}

let encrypted_data_with_hmac = self.infos.content()?.to_vec();
let passphrase = self.infos.passphrase()?.to_vec();
println!("Data Length: {}", encrypted_data_with_hmac.len());

let mut verifier = Sign::new(encrypted_data_with_hmac, passphrase, Operation::Verify, SignType::Sha512);
let verified_data = verifier.hmac();

self.infos.set_data(&verified_data)?;
//println!("{:?}", verified_data);
let data = self.decrypt_aes()?;
if self.infos.safe()? {
let _ = self.infos.set_data(&data)?;
let _ = self.infos.safe_file()?;
}
println!("Decrypted Data: {:?}", data);
Ok(data)
}

/// Decrypts the provided data with AES-256.
///
/// # Returns
/// A result containing the decrypted data as a byte vector or a `CryptError` if decryption fails.
fn decrypt_aes(&mut self) -> Result<Vec<u8>, CryptError> {
let data = &self.infos.content()?;
let block_size = 16;

// Ensure the data length is a multiple of the block size
if data.len() % block_size != 0 {
return Err(CryptError::InvalidDataLength);
}

let mut decrypted_data = vec![0u8; data.len()];
let sharedsecret = self.sharedsecret()?;
let cipher = Aes256::new(GenericArray::from_slice(sharedsecret));

for (chunk, decrypted_chunk) in data.chunks(block_size).zip(decrypted_data.chunks_mut(block_size)) {
let mut block = GenericArray::clone_from_slice(chunk);
cipher.decrypt_block(&mut block);
decrypted_chunk.copy_from_slice(&block);
}

if let Some(&padding_length) = decrypted_data.last() {
decrypted_data.truncate(decrypted_data.len() - padding_length as usize);
}

Ok(decrypted_data)
}
}


impl CryptographicFunctions for CipherAES {
/// Performs the encryption process using a public key.
///
/// # Parameters
/// - `public_key`: The public key for encryption.
///
/// # Returns
/// A result containing the encrypted data and the ciphertext as a key, or a `CryptError`.
fn encrypt(&mut self, public_key: Vec<u8>) -> Result<(Vec<u8>, Vec<u8>), CryptError> {
let mut key = KeyControlVariant::new(self.infos.metadata.key_type()?);
let (sharedsecret, ciphertext) = key.encap(&public_key)?;
println!("Shared secret: {:?}\nLength: {}", sharedsecret, sharedsecret.len());
let _ = self.set_shared_secret(sharedsecret);

Ok((self.encryption()?, ciphertext))
}

/// Performs the decryption process using a secret key and ciphertext.
///
/// # Parameters
/// - `secret_key`: The secret key for decryption.
/// - `ciphertext`: The ciphertext to decrypt.
///
/// # Returns
/// The decrypted data as a byte vector or a `CryptError` if decryption fails.
fn decrypt(&mut self, secret_key: Vec<u8>, ciphertext: Vec<u8>) -> Result<Vec<u8>, CryptError>{
let mut key = KeyControlVariant::new(self.infos.metadata.key_type()?);
let sharedsecret = key.decap(&secret_key, &ciphertext)?;
println!("shared secret: {:?}\nLength: {}", sharedsecret, sharedsecret.len());
let _ = self.set_shared_secret(sharedsecret);

Ok(self.decryption()?)
}
}
Loading

0 comments on commit 57cf8e2

Please sign in to comment.