pub struct CryptoUtils;Implementations§
Source§impl CryptoUtils
impl CryptoUtils
Sourcepub fn pad_binary(data: &[u8]) -> Vec<u8> ⓘ
pub fn pad_binary(data: &[u8]) -> Vec<u8> ⓘ
Pads the given binary data to a multiple of the block size using the PKCS#7 padding scheme.
This function adds padding to the input data so its length becomes a multiple of the BLOCK_SIZE.
The padding scheme specifies that each padding byte’s value is the total number of padding bytes added.
If data is already a multiple of BLOCK_SIZE, an additional full block of padding is appended.
§Arguments
data- A slice of bytes to be padded.
§Returns
A Vec<u8> containing the original data followed by the necessary padding bytes.
§Example
use keeper_secrets_manager_core::crypto::CryptoUtils;
const BLOCK_SIZE: usize = 16;
// Example with exact block size
let data = b"YELLOW SUBMARINE";
let padded_data = CryptoUtils::pad_binary(data);
assert_eq!(padded_data, b"YELLOW SUBMARINE\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10");
// Example with non-exact block size
let data = b"HELLO";
let padded_data = CryptoUtils::pad_binary(data);
assert_eq!(padded_data, b"HELLO\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b");In the first example, the input "YELLOW SUBMARINE" is 16 bytes, so an extra block of padding is added.
In the second, "HELLO" is 5 bytes, and padding is added to reach the next multiple of the block size.
§Panics
This function does not panic under normal usage.
§Errors
This function does not return errors.
Sourcepub fn unpad_binary(data: &[u8]) -> Result<Vec<u8>, KSMRError>
pub fn unpad_binary(data: &[u8]) -> Result<Vec<u8>, KSMRError>
Removes PKCS#7 padding from the given binary data.
This function removes padding from the input data that was added according to the PKCS#7 padding scheme.
It checks the validity of the padding bytes and returns an error if the padding is invalid. The function assumes
that the length of the data is a multiple of the BLOCK_SIZE.
§Arguments
data- A slice of padded binary data to be unpadded.
§Returns
Ok(Vec<u8>)- The unpadded data if the padding is valid.Err(&'static str)- An error message if the padding or data length is invalid.
§Errors
This function returns an error in the following cases:
- The data is empty.
- The data length is not a multiple of the
BLOCK_SIZE. - The padding is invalid (either incorrectly formatted or out of bounds).
§Example
use keeper_secrets_manager_core::crypto::CryptoUtils;
const BLOCK_SIZE: usize = 16;
// Example with valid padding
let padded_data = b"YELLOW SUBMARINE\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10";
let unpadded_data = CryptoUtils::unpad_binary(padded_data).unwrap();
assert_eq!(unpadded_data, b"YELLOW SUBMARINE");
// Example with invalid padding
let invalid_padded_data = b"YELLOW SUBMARINE\x05\x05\x05\x05\x06";
assert!(CryptoUtils::unpad_binary(invalid_padded_data).is_err());§Panics
This function does not panic but returns a Result in case of errors like invalid padding or improper length.
Sourcepub fn unpad_char(data: &[u8]) -> Result<Vec<u8>, KSMRError>
pub fn unpad_char(data: &[u8]) -> Result<Vec<u8>, KSMRError>
Removes padding from the given binary data.
This function removes padding by interpreting the last byte of the input data as the number of padding bytes added. It returns the unpadded data if the padding is valid. The function is simpler than PKCS#7, and it does not verify the contents of the padding bytes—just their length.
§Arguments
data- A slice of binary data to be unpadded.
§Returns
Ok(Vec<u8>)- The unpadded data if the padding is valid.Err(&'static str)- An error message if the padding or data length is invalid.
§Errors
This function returns an error in the following cases:
- The data is empty.
- The padding length (extracted from the last byte) is greater than the length of the data.
§Example
use keeper_secrets_manager_core::crypto::CryptoUtils;
let padded_data = b"HELLO WORLD\x04\x04\x04\x04";
let unpadded_data = CryptoUtils::unpad_char(padded_data).unwrap();
assert_eq!(unpadded_data, b"HELLO WORLD");In this example, the input padded_data ends with four padding bytes (\x04), which are removed by the function.
The resulting unpadded data is "HELLO WORLD".
§Errors
"Data is empty"- If the input data is empty."Invalid padding length"- If the padding length exceeds the length of the input data.
§Panics
This function does not panic but returns a Result in case of errors.
Sourcepub fn bytes_to_int(b: &[u8]) -> Result<BigUint, KSMRError>
pub fn bytes_to_int(b: &[u8]) -> Result<BigUint, KSMRError>
Converts a byte slice into a BigUint integer.
§Parameters
b: A byte slice representing the input bytes to be converted to an integer.
§Returns
This function returns a Result:
Ok(BigUint): The converted integer on success.Err(KSMRError): An error message if the input is invalid (e.g., empty input or exceeds 16 bytes).
§Errors
- Returns
"Input is empty"if the provided byte slice is empty. - Returns
"Input exceeds maximum length of 16 bytes"if the input byte slice is longer than 16 bytes.
§Example
use keeper_secrets_manager_core::crypto::CryptoUtils;
use std::str::FromStr;
use num_bigint::BigUint;
let bytes = &[1; 17];
let result = CryptoUtils::bytes_to_int(bytes).unwrap();
assert_eq!(result, BigUint::from_str("341616807575530379006368233343265341697").unwrap());Sourcepub fn url_safe_str_to_bytes(s: &str) -> Result<Vec<u8>, KSMRError>
pub fn url_safe_str_to_bytes(s: &str) -> Result<Vec<u8>, KSMRError>
Converts a URL-safe Base64 encoded string to a byte vector.
This function decodes a URL-safe Base64 encoded string into a vector of bytes. It automatically
adds the necessary padding (=) to the input string if it’s missing, ensuring it conforms to
Base64 encoding rules. The function also includes optional checks to verify the length of the
decoded byte vector for specific use cases (e.g., UUIDs).
§Parameters
s: A string slice representing the URL-safe Base64 encoded string to decode.
§Returns
This function returns a Result:
Ok(Vec<u8>): A vector of bytes resulting from decoding the input string on success.Err(KSMRError): An error variant indicating an issue with decoding, such as invalid Base64 format.
§Errors
KSMRError::InvalidBase64: If the input string fails to decode as valid Base64.KSMRError::DecodedBytesTooShort: If the decoded byte array is shorter than the required length (e.g., for UUID or other fixed-length conversions).
§Example
use keeper_secrets_manager_core::crypto::CryptoUtils;
use keeper_secrets_manager_core::custom_error::KSMRError;
fn main() -> Result<(), KSMRError> {
let url_safe_base64 = "c29tZSBkYXRh"; // Example URL-safe Base64 string
// Convert URL-safe Base64 string to bytes
let decoded_bytes = CryptoUtils::url_safe_str_to_bytes(url_safe_base64);
// Print the resulting byte vector
println!("Decoded bytes: {:?}", decoded_bytes);
Ok(())
}§Panics
This function does not panic under normal operation. However, it will return an error if the input string is not valid Base64.
§Notes
- The function automatically adds padding (
=) to the input string if necessary to conform to Base64 encoding rules. - The decoded byte array is optionally validated for minimum length (e.g., at least 8 bytes for UUIDs).
pub fn url_safe_str_to_bytes_trim_padding(s: &str) -> Result<Vec<u8>, KSMRError>
Sourcepub fn generate_random_bytes(length: usize) -> Vec<u8> ⓘ
pub fn generate_random_bytes(length: usize) -> Vec<u8> ⓘ
Generates a vector of random bytes of the specified length.
§Parameters
length: The desired length of the random byte vector.
§Returns
This function returns a Vec<u8> containing length random bytes.
§Example
use keeper_secrets_manager_core::crypto::CryptoUtils;
fn main() {
let length = 16; // Specify the length of random bytes
let random_bytes = CryptoUtils::generate_random_bytes(length);
// Print the generated random bytes
println!("Generated random bytes: {:?}", random_bytes);
}§Panics
This function will panic if length is zero.
Sourcepub fn generate_encryption_key_bytes() -> Vec<u8> ⓘ
pub fn generate_encryption_key_bytes() -> Vec<u8> ⓘ
Generates a 32-byte random encryption key.
This function is suitable for creating encryption keys for symmetric encryption algorithms, such as AES-256, which requires a 256-bit (32-byte) key.
§Returns
This function returns a Vec<u8> containing 32 random bytes, which can be used as an encryption key.
§Example
use keeper_secrets_manager_core::crypto::CryptoUtils;
fn main() {
let encryption_key = CryptoUtils::generate_encryption_key_bytes();
// Print the generated encryption key
println!("Generated encryption key: {:?}", encryption_key);
}§Panics
This function does not panic under normal operation since it relies on generating random bytes.
Sourcepub fn bytes_to_url_safe_str(b: &[u8]) -> String
pub fn bytes_to_url_safe_str(b: &[u8]) -> String
Converts a byte slice to a URL-safe Base64-encoded string.
This function encodes the given byte slice into a URL-safe Base64 string,
stripping any trailing padding characters (=) that are typically used
in Base64 encoding. The resulting string can be safely included in URLs.
§Parameters
b: A byte slice that you want to encode to a URL-safe Base64 string.
§Returns
This function returns a String containing the URL-safe Base64-encoded representation
of the input byte slice.
§Example
use keeper_secrets_manager_core::crypto::CryptoUtils;
fn main() {
let data = b"Hello, World!";
let encoded_str = CryptoUtils::bytes_to_url_safe_str(data);
// Print the URL-safe Base64-encoded string
println!("Encoded URL-safe string: {}", encoded_str);
}§Notes
- The function uses the
BASE64_URL_SAFEencoder, which ensures that the resulting string is safe for use in URLs and does not contain characters that may need to be escaped.
Sourcepub fn url_safe_str_to_int(s: &str) -> Result<BigUint, KSMRError>
pub fn url_safe_str_to_int(s: &str) -> Result<BigUint, KSMRError>
Converts a URL-safe Base64-encoded string to a BigUint integer.
This function first decodes the URL-safe Base64 string into a byte vector.
It then converts the resulting byte vector into a BigUint integer. The function
will return an error if the string cannot be decoded or if the resulting byte
vector cannot be converted to a valid integer.
§Parameters
s: A string slice representing the URL-safe Base64-encoded data.
§Returns
This function returns a Result:
Ok(BigUint): The decoded integer value on success.Err(KSMRError): An error variant indicating a failure in decoding or conversion.
§Example
use keeper_secrets_manager_core::crypto::CryptoUtils;
use keeper_secrets_manager_core::custom_error::KSMRError;
fn main() -> Result<(), KSMRError> {
let url_safe_str = "AQIDBAUGBwgJCgsMDQ4PEA=="; // Example URL-safe Base64 string
match CryptoUtils::url_safe_str_to_int(url_safe_str) {
Ok(int_value) => println!("Decoded integer value: {}", int_value),
Err(err) => println!("Error decoding string: {:?}", err),
}
Ok(())
}§Errors
- Returns a
KSMRError::InvalidBase64if the input string is not valid Base64. - Returns
KSMRError::InvalidIntegerConversionif the decoded byte slice cannot be converted to a validBigUintinteger.
§Notes
- The function assumes that the input string is a valid URL-safe Base64 string.
- Any invalid Base64 characters or decoding issues will result in a
KSMRError.
Sourcepub fn generate_ecc_keys() -> Result<SigningKey, KSMRError>
pub fn generate_ecc_keys() -> Result<SigningKey, KSMRError>
Generates an ECC signing key.
This function generates a random encryption key, converts it to a URL-safe Base64 string,
then converts the string into an integer. The integer is used to populate the first 16 bytes
of a 32-byte array, with the remaining 16 bytes set to zeros. This 32-byte array is then used
to create a SigningKey that can be used for ECC-based signing operations.
§Returns
This function returns a Result:
Ok(SigningKey): A successfully generatedSigningKeyinstance, which can be used for ECC signing operations.Err(KSMRError): If any of the operations fail, such as key generation, conversion, orSigningKeycreation.
§Example
use keeper_secrets_manager_core::crypto::CryptoUtils; // Adjust to your actual module path
fn main() {
let signing_key = CryptoUtils::generate_ecc_keys().unwrap();
println!("Generated ECC Signing Key: {:?}", signing_key);
}§Panics
This function may panic if:
- The conversion from URL-safe Base64 string to integer fails.
- The creation of the
SigningKeyfrom the byte array fails.
§Notes
- The encryption key used to generate the signing key is created randomly for each call to the function, ensuring that the signing key is unique each time.
- The final
SigningKeyis based on a 32-byte array, where the first 16 bytes come from the converted integer, and the remaining 16 bytes are filled with zeros. - The generated signing key is suitable for use in ECC-based cryptographic operations.
Sourcepub fn public_key_ecc(private_key: &SigningKey) -> Vec<u8> ⓘ
pub fn public_key_ecc(private_key: &SigningKey) -> Vec<u8> ⓘ
Derives the public key from a given ECC private key.
This function takes a reference to a SigningKey (private key) and derives
the corresponding public key. The public key is then serialized in uncompressed
format (X9.62).
§Parameters
private_key: A reference to aSigningKey, which represents the ECC private key from which the public key will be derived.
§Returns
This function returns a Vec<u8> containing the serialized public key in uncompressed
format.
§Example
use keeper_secrets_manager_core::crypto::CryptoUtils; // Adjust to your actual module path
fn main() {
// Assume you have a valid SigningKey instance
let private_key = CryptoUtils::generate_ecc_keys().unwrap();
// Get the corresponding public key
let public_key = CryptoUtils::public_key_ecc(&private_key);
println!("Public Key: {:?}", public_key);
}§Notes
- The uncompressed format of the public key allows for straightforward serialization and transmission. It includes the x-coordinate and the y-coordinate of the point on the elliptic curve.
- Ensure that the
SigningKeyprovided to this function is valid and has been properly initialized before calling this function.
Sourcepub fn generate_private_key_ecc() -> Result<SigningKey, KSMRError>
pub fn generate_private_key_ecc() -> Result<SigningKey, KSMRError>
Generates a new ECC private key.
This function generates a new 256-bit (32-byte) private key suitable for ECC operations,
specifically for the P256 curve. The process involves generating random bytes, converting
those bytes into a URL-safe Base64 string, and then converting that string into an integer.
The integer is then used to create the SigningKey which represents the ECC private key.
§Returns
This function returns a Result:
Ok(SigningKey): The successfully generated ECC private key as aSigningKey.Err(KSMRError): An error if any step of the key generation process fails, including random byte generation, Base64 conversion, integer conversion, orSigningKeycreation.
§Example
use keeper_secrets_manager_core::crypto::CryptoUtils; // Adjust to your actual module path
fn main() {
// Generate a new ECC private key
let private_key = CryptoUtils::generate_private_key_ecc().unwrap();
// Print or use the private key as needed
println!("Generated Private Key: {:?}", private_key);
}§Notes
- The generated private key is a 256-bit (32-byte) key, which is compatible with the P256 curve used in ECC operations.
- Ensure that the random bytes are securely generated, as this key will be used in cryptographic operations. The private key should be kept confidential at all times.
§Panics
This function will panic if any of the following conditions occur:
- The conversion of the URL-safe Base64 string to an integer fails.
- The
SigningKeycreation from the byte array fails.
§Implementation Details
- The key is derived from random bytes, which are encoded into a URL-safe Base64 string, then decoded back to an integer.
- The integer is converted to bytes, and the first 16 bytes are used for the key, with the remaining bytes padded with zeros.
- The final 32-byte array is used to create the
SigningKeyusingSigningKey::from_bytes.
Sourcepub fn generate_private_key_der() -> Result<Vec<u8>, KSMRError>
pub fn generate_private_key_der() -> Result<Vec<u8>, KSMRError>
Generates a new ECC private key.
This function generates a new 256-bit (32-byte) private key suitable for ECC operations,
specifically for the P256 curve. The process involves generating random bytes, converting
those bytes into a URL-safe Base64 string, and then converting that string into an integer.
The integer is then used to create the SigningKey, which represents the ECC private key.
§Returns
This function returns a Result:
Ok(SigningKey): The successfully generated ECC private key as aSigningKey.Err(KSMRError): An error if any step of the key generation process fails, including random byte generation, Base64 conversion, integer conversion, orSigningKeycreation.
§Example
use keeper_secrets_manager_core::crypto::CryptoUtils; // Adjust to your actual module path
fn main() {
// Generate a new ECC private key
let private_key = CryptoUtils::generate_private_key_ecc().unwrap();
// Print or use the private key as needed
println!("Generated Private Key: {:?}", private_key);
}§Notes
- The generated private key is a 256-bit (32-byte) key, which is compatible with the P256 curve used in ECC operations.
- The first 16 bytes of the 32-byte private key are filled with the integer representation of the random bytes.
- The second 16 bytes are a repeat of the same integer to meet the required key length for P256.
- Ensure that the random bytes are securely generated, as this key will be used in cryptographic operations. The private key should be kept confidential at all times.
§Panics
This function will panic if any of the following conditions occur:
- The conversion of the URL-safe Base64 string to an integer fails.
- The
SigningKeycreation from the byte array fails.
§Implementation Details
- The key is derived from random bytes, which are encoded into a URL-safe Base64 string, then decoded back to an integer.
- The integer is converted to bytes, and the first 16 bytes are used for the key, with the remaining bytes padded with zeros.
- The final 32-byte array is used to create the
SigningKeyusingSigningKey::from_bytes.
Sourcepub fn generate_new_ecc_key() -> SigningKey
pub fn generate_new_ecc_key() -> SigningKey
Generates a new ephemeral ECC signing key using the SECP256R1 curve.
This function creates a new ECC signing key that can be used for cryptographic operations such as signing or key exchange. It utilizes a secure random number generator to ensure the key is generated in a cryptographically secure manner.
§Returns
This function returns a SigningKey, which represents the newly generated ECC signing key.
§Example
use keeper_secrets_manager_core::crypto::CryptoUtils; // Adjust to your actual module path
use p256::ecdsa::SigningKey;
fn main() {
// Generate a new ECC signing key
let signing_key: SigningKey = CryptoUtils::generate_new_ecc_key();
// Use the signing key for further cryptographic operations
println!("Generated new ECC signing key: {:?}", signing_key);
}§Notes
- The generated key is ephemeral and should be used for a single session or transaction.
- Ensure that you securely manage and store the signing key if needed, as it is essential for cryptographic integrity.
Sourcepub fn encrypt_aes_gcm(
data: &[u8],
key_bytes: &[u8],
nonce_bytes: Option<&[u8]>,
) -> Result<Vec<u8>, KSMRError>
pub fn encrypt_aes_gcm( data: &[u8], key_bytes: &[u8], nonce_bytes: Option<&[u8]>, ) -> Result<Vec<u8>, KSMRError>
Encrypts data using AES-256-GCM with an optional nonce.
This function performs authenticated encryption of the provided data using AES-256-GCM.
AES-256-GCM requires a 32-byte key for encryption and uses a 12-byte nonce. If a nonce is
not provided, a random 12-byte nonce will be generated.
§Parameters
data: A byte slice representing the plaintext data to be encrypted.key_bytes: A byte slice representing the 32-byte AES key used for encryption (AES-256).nonce_bytes: An optional byte slice representing the nonce. If not provided, a random nonce will be generated.
§Returns
This function returns a Result:
Ok(Vec<u8>): The result will contain a vector with the concatenated nonce and the encrypted ciphertext on success.Err(KSMRError): An error if encryption fails or if invalid input parameters are provided (e.g., wrong key size).
§Errors
- Returns
KSMRError::CryptoError("Invalid key size")if the providedkey_bytesslice is not exactly 32 bytes long. - Returns
KSMRError::CryptoError("Encryption failed")if the encryption operation fails (for example, due to invalid key or data).
§Example
use keeper_secrets_manager_core::crypto::CryptoUtils;
use std::error::Error;
use hex;
fn main() -> Result<(), Box<dyn Error>> {
// 32-byte AES key (AES-256 requires a 32-byte key)
let key = b"an example very very secret key."; // Must be exactly 32 bytes
// Example plaintext data
let data = b"plaintext message that needs encryption";
// Encrypt the data with a random nonce
let encrypted_data = CryptoUtils::encrypt_aes_gcm(data, key, None)?;
// Print the encrypted data in hex format for better readability
println!("Encrypted data: {:?}", hex::encode(&encrypted_data));
Ok(())
}§Panics
This function does not panic under normal operation. However, it will return an error if input is invalid (e.g., wrong key size or if encryption fails).
§Notes
- AES-256-GCM is an authenticated encryption mode, which provides both confidentiality and integrity. The nonce should be unique for each encryption operation with the same key to maintain security.
- The nonce is prepended to the ciphertext before returning, allowing the recipient to extract and use it for decryption.
§Implementation Details
- AES-256-GCM requires a 32-byte key, and the nonce used must be 12 bytes in length. If a nonce is not provided, a random 12-byte nonce will be generated for each encryption operation.
- The AES-GCM encryption process uses the provided key and nonce to encrypt the
data. The resulting ciphertext is then concatenated with the nonce before being returned. - The function uses the
Aes256Gcmcipher from theaes-gcmcrate and therandcrate to generate random nonces when necessary.
Sourcepub fn decrypt_aes(data: &[u8], key_bytes: &[u8]) -> Result<Vec<u8>, KSMRError>
pub fn decrypt_aes(data: &[u8], key_bytes: &[u8]) -> Result<Vec<u8>, KSMRError>
Decrypts data using AES-256-GCM with a 12-byte nonce.
§Parameters
data: A byte slice containing the nonce followed by the ciphertext. The first 12 bytes represent the nonce, and the rest is the ciphertext.key_bytes: A byte slice representing the 32-byte AES key used for decryption (AES-256).
§Returns
This function returns a Result:
Ok(Vec<u8>): The decrypted plaintext on success.Err(Box<dyn Error>): An error if decryption fails or if invalid input parameters are provided (e.g., wrong key size).
§Errors
- Returns
"Invalid key size"if the providedkey_bytesslice is not exactly 32 bytes long. - Returns
"Data too short to contain nonce"if the provideddataslice is smaller than 12 bytes. - Returns
"Decryption failed"if the decryption operation itself fails (for example, if the ciphertext or key is invalid).
§Example
use keeper_secrets_manager_core::crypto::CryptoUtils;
use keeper_secrets_manager_core::custom_error::KSMRError;
use aes_gcm::{Aes256Gcm, Key, Nonce}; // Import the AES-GCM library
use std::error::Error;
use hex;
fn main() -> Result<(), KSMRError> {
// 32-byte AES key (AES-256 requires a 32-byte key)
let key = b"an example very very secret key."; // Should be exactly 32 bytes
// 12-byte nonce (unique for each encryption)
let nonce = b"unique nonce"; // Must be exactly 12 bytes
// Example ciphertext (encrypted using the same key and nonce)
let ciphertext = hex::decode("c5d3db06f6c3d543663a94051a7a0d65")?; // Example encrypted data
// Concatenate nonce and ciphertext
let mut encrypted_data = Vec::new();
encrypted_data.extend_from_slice(nonce);
encrypted_data.extend_from_slice(&ciphertext);
// Attempt to decrypt the data
let result = CryptoUtils::decrypt_aes(&encrypted_data, key);
// Check if the decryption was successful
match result {
Ok(decrypted_data) => {
println!("Decrypted data: {:?}", decrypted_data);
},
Err(err) => {
println!("Error: {}", err);
assert_eq!(err.to_string(), "Cryptography module Error: aead::Error");
}
}
Ok(())
}§Panics
This function does not panic under normal operation. However, it will return an error if input is invalid (e.g., wrong key size or if decryption fails).
§Notes
- This function assumes that the first 12 bytes of
datarepresent the nonce. - AES-256-GCM is an authenticated encryption mode, so decryption will fail if the ciphertext or key is tampered with.
Sourcepub fn encrypt_aes_cbc(
data: &[u8],
key: &[u8],
iv: Option<&[u8]>,
) -> Result<Vec<u8>, KSMRError>
pub fn encrypt_aes_cbc( data: &[u8], key: &[u8], iv: Option<&[u8]>, ) -> Result<Vec<u8>, KSMRError>
Encrypts data using AES-256 in CBC (Cipher Block Chaining) mode.
This function encrypts the provided plaintext data using AES-256 in CBC mode with a 32-byte key. If an Initialization Vector (IV) is not provided, a random 16-byte IV is generated. The IV is then prepended to the resulting ciphertext for later use during decryption.
§Parameters
data: A byte slice representing the plaintext data to be encrypted.key: A 32-byte slice representing the AES-256 key used for encryption (AES-256 requires a 256-bit key).iv: An optional 16-byte slice representing the Initialization Vector (IV). IfNoneis provided, a random IV will be generated.
§Returns
This function returns a Result:
Ok(Vec<u8>): A vector containing the concatenated IV and the encrypted ciphertext on success.Err(KSMRError): An error if the key size is invalid (i.e., not 32 bytes).
§Errors
- Returns
KSMRError::CryptoError("Invalid key size")if the providedkeyis not 32 bytes long. - Returns an error if encryption fails or if the padding or encryption process encounters issues.
§Example
use keeper_secrets_manager_core::crypto::CryptoUtils;
use rand::rngs::OsRng;
let plaintext = b"Sensitive data to encrypt";
let key = b"0123456789abcdef0123456789abcdef"; // A 32-byte AES-256 key.
let iv = b"1234567890123456"; // A 16-byte IV (optional).
let encrypted_data = CryptoUtils::encrypt_aes_cbc(plaintext, key, Some(iv)).unwrap();
println!("Encrypted data: {:?}", encrypted_data);§Panics
This function does not panic but returns an error if input is invalid (e.g., incorrect key size or encryption failure).
§Notes
- AES-256 in CBC mode requires the key to be exactly 32 bytes. The IV must be 16 bytes in length.
- CBC mode requires padding to ensure the data is a multiple of the block size (16 bytes for AES). This function uses a padding scheme (assumed to be implemented in
pad_data) to handle this. - The resulting ciphertext is returned with the IV prepended to facilitate decryption.
Sourcepub fn decrypt_aes_cbc(data: &[u8], key: &[u8]) -> Result<Vec<u8>, KSMRError>
pub fn decrypt_aes_cbc(data: &[u8], key: &[u8]) -> Result<Vec<u8>, KSMRError>
Decrypts data using AES-256 in CBC (Cipher Block Chaining) mode.
This function decrypts the provided encrypted data using AES-256 in CBC mode with a 32-byte key. The first 16 bytes of the input data are treated as the Initialization Vector (IV), and the remaining bytes are treated as the ciphertext. After decryption, the padding is removed from the data to obtain the original plaintext.
§Parameters
data: A byte slice representing the encrypted data. The first 16 bytes are treated as the IV, and the remaining bytes are the ciphertext.key: A 32-byte slice representing the AES-256 key used for decryption.
§Returns
This function returns a Result:
Ok(Vec<u8>): A vector containing the decrypted and unpadded plaintext data.Err(KSMRError): An error if the key size is invalid, the data is too short to contain an IV, or the data length is not a multiple of 16 bytes (indicating possible encoding issues).
§Errors
- Returns
KSMRError::CryptoError("Invalid key size")if the providedkeyis not 32 bytes long. - Returns
KSMRError::CryptoError("Data too short to contain IV")if the provideddatais less than 16 bytes long. - Returns
KSMRError::CryptoError("Data is probably not encoded")if the data length is not a multiple of 16 bytes. - Returns
KSMRError::CryptoError("Unpadding failed: <error message>")if the unpadding process fails.
§Example
use keeper_secrets_manager_core::crypto::CryptoUtils;
let encrypted_data = b"\x01\x02..."; // Some encrypted data with a 16-byte IV followed by ciphertext.
let key = b"0123456789abcdef0123456789abcdef"; // A 32-byte AES-256 key.
let data = CryptoUtils::decrypt_aes_cbc(encrypted_data, key);
match data {
Ok(plaintext) => println!("Decrypted data: {:?}", plaintext),
Err(e) => eprintln!("Decryption error: {}", e),
}In this example, decrypt_aes_cbc attempts to decrypt the encrypted_data using the provided AES-256 key.
The decrypted data is returned after removing the padding.
§Panics
This function does not panic but returns a Result in case of errors.
§Notes
- AES-256 in CBC mode requires the key to be exactly 32 bytes. The IV must be 16 bytes in length.
- The first 16 bytes of the input data are interpreted as the IV, while the rest is treated as the ciphertext.
- CBC mode requires the ciphertext length to be a multiple of the AES block size (16 bytes).
- The padding is removed from the decrypted data using a custom unpadding function (
unpad_data), which will return an error if the padding is incorrect.
Sourcepub fn public_encrypt(
data: &[u8],
server_public_raw_key_bytes: &[u8],
idz: Option<&[u8]>,
) -> Result<Vec<u8>, KSMRError>
pub fn public_encrypt( data: &[u8], server_public_raw_key_bytes: &[u8], idz: Option<&[u8]>, ) -> Result<Vec<u8>, KSMRError>
Encrypts data using an ephemeral ECDH key exchange and AES-GCM.
This function uses Elliptic Curve Diffie-Hellman (ECDH) to derive a shared secret between
an ephemeral key generated on the fly and a server’s public key provided in the input.
The derived key is optionally concatenated with an identifier (idz), hashed using SHA-256
to generate an AES encryption key, and then used to encrypt the input data with AES-GCM.
§Arguments
data- A byte slice representing the data to be encrypted.server_public_raw_key_bytes- A byte slice representing the server’s public key in SEC1 format.idz- An optional byte slice identifier that, if provided, is appended to the shared secret before key derivation.
§Returns
This function returns a Result containing:
Ok(Vec<u8>): A vector of bytes containing the concatenation of the ephemeral public key and the encrypted data.Err(KSMRError): An error if key derivation or encryption fails.
§Errors
- Returns an error if the server public key is invalid or encryption fails.
- If the
server_public_raw_key_bytescannot be parsed into a valid public key, it returns"Invalid server public key!". - If encryption fails during AES-GCM, the error message will indicate the failure.
§Example
use keeper_secrets_manager_core::crypto::CryptoUtils;
// Data to encrypt
let data = b"Sensitive data to encrypt";
// A raw public key as a string (this is just an example key)
let server_public_key = "04d88c6fa31ea40af14c137b8e62f1151f1cc1e5688cad37b7f2e7";
// Convert the public key from hex string to bytes
let server_public_key_bytes = hex::decode(server_public_key).expect("Invalid hex key");
// Optional IDZ
let idz = Some("optional_identifier".as_bytes());
// Encrypt the data
match CryptoUtils::public_encrypt(data, &server_public_key_bytes, idz) {
Ok(encrypted_data) => println!("Encrypted data: {:?}", encrypted_data),
Err(e) => println!("Encryption failed: {}", e),
}Sourcepub fn hash_of_string(value: &str) -> Result<Vec<u8>, KSMRError>
pub fn hash_of_string(value: &str) -> Result<Vec<u8>, KSMRError>
Computes the SHA-256 hash of a Base64-encoded string.
This function takes a Base64-encoded string, decodes it into bytes, and computes its SHA-256 hash. The resulting hash is returned as a vector of bytes.
§Arguments
value- A string slice representing the Base64-encoded input to hash.
§Returns
This function returns a Result:
Ok(Vec<u8>): The SHA-256 hash of the decoded input as a vector of bytes.Err(KSMRError): An error if the input string cannot be decoded from Base64 or if any other error occurs during hashing.
§Errors
- Returns
KSMRError::CryptoErrorif the input string cannot be decoded from Base64 or if any other error occurs during hashing.
§Examples
use keeper_secrets_manager_core::crypto::CryptoUtils;
let base64_input = "SGVsbG8sIHdvcmxkIQ=="; // Base64 encoding of "Hello, world!"
let hash = CryptoUtils::hash_of_string(base64_input);
match hash {
Ok(h) => println!("SHA-256 Hash: {:?}", h),
Err(e) => eprintln!("Error: {}", e),
}§Panics
This function does not panic. It will return a KSMRError if the input is not valid Base64
or if hashing fails.
pub fn ecies_decrypt( _server_public_key: &[u8], _ciphertext: &[u8], _priv_key_data: &[u8], _id: &[u8], ) -> Result<Vec<u8>, Box<dyn Error>>
Sourcepub fn decrypt_record(
data: &[u8],
secret_key: &[u8],
) -> Result<String, KSMRError>
pub fn decrypt_record( data: &[u8], secret_key: &[u8], ) -> Result<String, KSMRError>
Decrypts a record using the provided secret key.
This function attempts to decrypt a given record. If the record is a valid UTF-8 string, it is first decoded from Base64. The decoded bytes are then decrypted using AES-GCM. If the record is not a valid UTF-8 string, it is assumed to be in bytes and is decrypted directly.
§Arguments
data- A slice of bytes representing the encrypted record. This can either be a Base64-encoded UTF-8 string or raw bytes.secret_key- A slice of bytes representing the secret key used for decryption.
§Returns
This function returns a Result<String, KSMRError>. On success, it returns the
decrypted record as a UTF-8 string. On failure, it returns an error with a description
of the problem encountered.
§Errors
This function will return an error if:
- The input data cannot be decoded from Base64, returning a
KSMRError::CryptoErrorwith the description"Base64 decode error: {error}". - The decryption process fails due to an incorrect key or other issues, returning a
KSMRError::CryptoErrorwith a relevant message. - The resulting decrypted bytes cannot be converted to a UTF-8 string, returning a
KSMRError::Utf8Errorwith a description of the error.
§Examples
use keeper_secrets_manager_core::crypto::CryptoUtils;
use base64::{engine::general_purpose::URL_SAFE_NO_PAD, Engine as _};
let secret_key = CryptoUtils::generate_random_bytes(32); // Generate a dummy secret key
let original_data = b"Hello, World!";
let encrypted_data = CryptoUtils::encrypt_aes_gcm(original_data, &secret_key, None).unwrap();
let base64_encoded = URL_SAFE_NO_PAD.encode(&encrypted_data);
// Action
let result = CryptoUtils::decrypt_record(base64_encoded.as_bytes(), &secret_key);
// Assert
assert_eq!(result.unwrap(), "Hello, World!");
let result2 = CryptoUtils::decrypt_record(base64_encoded.as_bytes(), &secret_key);
match result2 {
Ok(record) => println!("Decrypted record: {}", record),
Err(e) => eprintln!("Failed to decrypt record: {}", e),
}§Panics
This function does not panic under normal circumstances. It handles errors by returning a KSMRError.
pub fn decrypt_ec( _ecc_private_key: &SecretKey, _encrypted_data_bag: &[u8], ) -> Result<Vec<u8>, Box<dyn Error>>
Sourcepub fn der_base64_private_key_to_private_key(
private_key_der_base64: &str,
) -> Result<SecretKey, KSMRError>
pub fn der_base64_private_key_to_private_key( private_key_der_base64: &str, ) -> Result<SecretKey, KSMRError>
Converts a Base64-encoded DER private key string to a SecretKey.
This function takes a Base64-encoded DER representation of a private key,
decodes it, and converts it into a SecretKey type suitable for cryptographic
operations.
§Arguments
private_key_der_base64- A string slice containing the Base64-encoded DER representation of the private key.
§Returns
This function returns a Result<p256::SecretKey, KSMRError>. On success,
it returns the corresponding SecretKey. On failure, it returns an error with a
description of the problem encountered.
§Errors
This function will return an error if:
- The provided Base64 string cannot be decoded. The error will be wrapped in a
KSMRError::CryptoError. - The decoded bytes cannot be parsed into a
SecretKey. The error will be wrapped in aKSMRError::CryptoError.
§Examples
use keeper_secrets_manager_core::crypto::CryptoUtils; // Adjust the path as necessary
use base64::{engine::general_purpose::URL_SAFE_NO_PAD, Engine as _};
use p256::SecretKey; // Import the SecretKey type
let private_key_der_base64 = "your_base64_encoded_der_key_here"; // Replace with your Base64 DER key
// Attempt to convert the Base64 DER private key to a SecretKey
match CryptoUtils::der_base64_private_key_to_private_key(private_key_der_base64) {
Ok(secret_key) => println!("Successfully converted to SecretKey: {:?}", secret_key),
Err(e) => eprintln!("Failed to convert private key: {}", e),
}§Panics
This function does not panic under normal circumstances, but it may return an error if the input is invalid.
Sourcepub fn extract_public_key_bytes(
private_key_der_base64: &str,
) -> Result<Vec<u8>, KSMRError>
pub fn extract_public_key_bytes( private_key_der_base64: &str, ) -> Result<Vec<u8>, KSMRError>
Extracts the public key bytes from a Base64-encoded DER private key string.
This function takes a Base64-encoded DER representation of a private key, decodes it, and extracts the corresponding public key bytes in uncompressed format.
§Arguments
private_key_der_base64- A string slice containing the Base64-encoded DER private key.
§Returns
Returns a Result<Vec<u8>, KSMRError>. On success, it returns the public key bytes
in uncompressed format. On failure, it returns a KSMRError with a description of the problem.
§Errors
This function will return an error if:
- The provided Base64 string cannot be decoded.
- The decoded bytes cannot be parsed into a
SecretKey.
§Examples
use keeper_secrets_manager_core::crypto::CryptoUtils;
use base64::{engine::general_purpose::URL_SAFE_NO_PAD, Engine as _};
let private_key_der_base64 = "your_base64_encoded_der_key_here"; // Replace with your Base64 DER key
// Attempt to extract public key bytes
match CryptoUtils::extract_public_key_bytes(private_key_der_base64) {
Ok(public_key_bytes) => println!("Successfully extracted public key bytes: {:?}", public_key_bytes),
Err(e) => eprintln!("Failed to extract public key bytes: {}", e),
}§Panics
This function does not panic under normal circumstances, but it will return an error if the Base64 string is invalid or the private key cannot be parsed.
Sourcepub fn sign_data(
data: &[u8],
private_key: SecretKey,
) -> Result<Signature<NistP256>, KSMRError>
pub fn sign_data( data: &[u8], private_key: SecretKey, ) -> Result<Signature<NistP256>, KSMRError>
Signs the provided data using the specified private key.
This function takes a byte slice representing the data to be signed and a
SecretKey. It creates a signing key from the private key and uses it
to generate a digital signature for the data.
§Arguments
data- A slice of bytes representing the data to be signed.private_key- A reference to theSecretKeyused to sign the data.
§Returns
This function returns a Result<Signature, Box<dyn std::error::Error>>. On success,
it returns the generated Signature. On failure, it returns an error with a
description of the problem encountered.
§Errors
This function may return an error if:
- The signing process fails due to an invalid private key or other cryptographic issues.
§Examples
use keeper_secrets_manager_core::crypto::CryptoUtils; // Adjust the path as necessary
use p256::{SecretKey, ecdsa::{SigningKey, Signature}}; // Import necessary types
use rand::rngs::OsRng; // Use OS random number generator
// Generate a dummy private key
let private_key = SecretKey::random(&mut OsRng);
let data = b"Hello, World!"; // Data to be signed
// Attempt to sign the data
match CryptoUtils::sign_data(data, private_key) {
Ok(signature) => println!("Successfully signed the data: {:?}", signature),
Err(e) => eprintln!("Failed to sign the data: {}", e),
}§Panics
This function does not panic under normal circumstances, but it may return an error if the signing process encounters issues.