keeper_secrets_manager_core/
crypto.rs

1// -*- coding: utf-8 -*-
2//  _  __
3// | |/ /___ ___ _ __  ___ _ _ (R)
4// | ' </ -_) -_) '_ \/ -_) '_|
5// |_|\_\___\___| .__/\___|_|
6//              |_|
7//
8// Keeper Secrets Manager
9// Copyright 2024 Keeper Security Inc.
10// Contact: sm@keepersecurity.com
11//
12
13pub struct CryptoUtils;
14use std::error::Error;
15use std::vec;
16use cipher::{BlockEncrypt, BlockDecrypt};
17use crate::custom_error::KSMRError;
18use crate::utils;
19use aes::Aes256;
20use aes_gcm::aead::AeadMut;
21use aes_gcm::KeyInit;
22use aes_gcm::{self, AeadCore, Aes256Gcm};
23use base64::{engine::general_purpose::URL_SAFE_NO_PAD, prelude::BASE64_URL_SAFE, Engine as _};
24use block_padding::generic_array::GenericArray;
25use num_bigint::BigUint;
26use ecdsa::signature::Signer;
27use ecdsa::signature::Verifier;
28use p256::elliptic_curve::rand_core::OsRng;
29use p256::pkcs8::EncodePrivateKey;
30use p256::SecretKey;
31use p256::{ecdh::EphemeralSecret, EncodedPoint, PublicKey};
32use p256::{
33    ecdsa::{Signature, SigningKey, VerifyingKey},
34    pkcs8::DecodePrivateKey as _,
35};
36use rand::{Rng, RngCore};
37use sha2::Digest;
38
39// types declared here
40
41// constants are declared here
42const BLOCK_SIZE: usize = 16;
43const AES_256_KEY_SIZE: usize = 32;
44
45/// Pads the given data according to the PKCS#7 padding scheme.
46///
47/// In the PKCS#7 padding scheme, data is padded so that its length is a multiple of the specified block size.
48/// If the input data is empty, the function will pad the data to the full block size. The padding bytes are
49/// filled with the value of the number of padding bytes added.
50///
51/// # Arguments
52///
53/// * `data` - A slice of bytes that you want to pad.
54/// * `block_size_var` - The block size to which the data should be padded.
55///
56/// # Returns
57///
58/// Returns a new `Vec<u8>` containing the original data followed by the appropriate padding bytes.
59///
60/// # Examples
61///
62/// ```
63/// use keeper_secrets_manager_core::crypto::pad_data;
64/// let data = b"YELLOW SUBMARINE";
65/// let block_size = 20;
66/// let padded = pad_data(data, block_size);
67/// assert_eq!(padded, b"YELLOW SUBMARINE\x04\x04\x04\x04");
68///
69/// let empty_data: &[u8] = b"";
70/// let padded_empty = pad_data(empty_data, block_size);
71/// assert_eq!(padded_empty, vec![20; 20]); // 20 padding bytes of value 20
72/// ```
73///
74/// # Panics
75///
76/// This function does not panic, but it assumes that `block_size_var` is greater than zero.
77pub fn pad_data(data: &[u8], block_size_var: usize) -> Vec<u8> {
78    // Calculate the padding length
79    let pad_len = if data.is_empty() || (data.len() % block_size_var == 0) {
80        block_size_var
81    } else {
82        block_size_var - (data.len() % block_size_var)
83    };
84
85    let mut padded_data = Vec::with_capacity(data.len() + pad_len);
86
87    // Copy original data
88    padded_data.extend_from_slice(data);
89
90    // Add padding bytes
91    padded_data.extend(vec![pad_len as u8; pad_len]);
92
93    padded_data
94}
95/// Removes PKCS#7 padding from the given data.
96///
97/// This function checks for and removes padding bytes added to the data according to the PKCS#7 padding scheme.
98/// The last byte of the data indicates how many bytes were added as padding. The function will return an error
99/// if the padding is invalid or if the data is empty.
100///
101/// # Arguments
102///
103/// * `data` - A slice of bytes that contains the padded data.
104///
105/// # Returns
106///
107/// Returns a `Result<Vec<u8>, KSMRError>` where:
108/// - `Ok(Vec<u8>)` contains the unpadded data if the padding is valid.
109/// - `Err(KSMRError)` provides an error message if the padding is invalid or if the data is empty.
110///
111/// # Examples
112///
113/// ```
114/// use keeper_secrets_manager_core::crypto::unpad_data;
115/// let padded_data = b"YELLOW SUBMA\x04\x04\x04\x04";
116/// let unpadded = unpad_data(padded_data).unwrap();
117/// assert_eq!(unpadded, b"YELLOW SUBMA");
118///
119/// let invalid_padded_data = b"YELLOW SUBMARINE\x04\x04\x04\x05"; // Incorrect padding
120/// assert!(unpad_data(invalid_padded_data).is_err());
121///
122/// let empty_data: &[u8] = b"";
123/// assert!(unpad_data(empty_data).is_err()); // Expecting an error for empty data
124/// ```
125///
126/// # Errors
127///
128/// This function will return the following errors:
129/// - `KSMRError::CryptoError("Data is empty")`: If the input data is an empty slice.
130/// - `KSMRError::CryptoError("Invalid padding length: ...")`: If the padding length is out of the valid range.
131/// - `KSMRError::CryptoError("Invalid padding bytes")`: If the padding bytes are not consistent.
132pub fn unpad_data(data: &[u8]) -> Result<Vec<u8>, KSMRError> {
133    let data_len = data.len();
134
135    // Check for empty data
136    if data_len == 0 {
137        return Err(KSMRError::CryptoError("Data is empty".to_string()));
138    }
139
140    let pad_len = data[data_len - 1] as usize;
141
142    if !data[data_len - pad_len..]
143        .iter()
144        .all(|&b| b == pad_len as u8)
145    {
146        return Err(KSMRError::CryptoError("Invalid padding bytes".to_string()));
147    }
148
149    // Return the unpadded data
150    Ok(data[..data_len - pad_len].to_vec())
151}
152
153impl CryptoUtils {
154    /// Pads the given binary data to a multiple of the block size using the PKCS#7 padding scheme.
155    ///
156    /// This function adds padding to the input `data` so its length becomes a multiple of the `BLOCK_SIZE`.
157    /// The padding scheme specifies that each padding byte's value is the total number of padding bytes added.
158    /// If `data` is already a multiple of `BLOCK_SIZE`, an additional full block of padding is appended.
159    ///
160    /// # Arguments
161    ///
162    /// * `data` - A slice of bytes to be padded.
163    ///
164    /// # Returns
165    ///
166    /// A `Vec<u8>` containing the original data followed by the necessary padding bytes.
167    ///
168    /// # Example
169    ///
170    /// ```
171    /// use keeper_secrets_manager_core::crypto::CryptoUtils;
172    /// const BLOCK_SIZE: usize = 16;
173    ///
174    /// // Example with exact block size
175    /// let data = b"YELLOW SUBMARINE";
176    /// let padded_data = CryptoUtils::pad_binary(data);
177    /// assert_eq!(padded_data, b"YELLOW SUBMARINE\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10");
178    ///
179    /// // Example with non-exact block size
180    /// let data = b"HELLO";
181    /// let padded_data = CryptoUtils::pad_binary(data);
182    /// assert_eq!(padded_data, b"HELLO\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b");
183    /// ```
184    ///
185    /// In the first example, the input `"YELLOW SUBMARINE"` is 16 bytes, so an extra block of padding is added.
186    /// In the second, `"HELLO"` is 5 bytes, and padding is added to reach the next multiple of the block size.
187    ///
188    /// # Panics
189    ///
190    /// This function does not panic under normal usage.
191    ///
192    /// # Errors
193    ///
194    /// This function does not return errors.
195    pub fn pad_binary(data: &[u8]) -> Vec<u8> {
196        const BLOCK_SIZE: usize = 16; // Define or pass as argument as needed
197
198        let pad_len = BLOCK_SIZE - (data.len() % BLOCK_SIZE);
199        let mut padded_data = Vec::with_capacity(data.len() + pad_len);
200
201        // Add original data
202        padded_data.extend_from_slice(data);
203
204        // Add padding bytes
205        padded_data.extend(vec![pad_len as u8; pad_len]);
206
207        padded_data
208    }
209
210    /// Removes PKCS#7 padding from the given binary data.
211    ///
212    /// This function removes padding from the input `data` that was added according to the PKCS#7 padding scheme.
213    /// It checks the validity of the padding bytes and returns an error if the padding is invalid. The function assumes
214    /// that the length of the data is a multiple of the `BLOCK_SIZE`.
215    ///
216    /// # Arguments
217    ///
218    /// * `data` - A slice of padded binary data to be unpadded.
219    ///
220    /// # Returns
221    ///
222    /// * `Ok(Vec<u8>)` - The unpadded data if the padding is valid.
223    /// * `Err(&'static str)` - An error message if the padding or data length is invalid.
224    ///
225    /// # Errors
226    ///
227    /// This function returns an error in the following cases:
228    /// - The data is empty.
229    /// - The data length is not a multiple of the `BLOCK_SIZE`.
230    /// - The padding is invalid (either incorrectly formatted or out of bounds).
231    ///
232    /// # Example
233    ///
234    /// ```
235    /// use keeper_secrets_manager_core::crypto::CryptoUtils;
236    /// const BLOCK_SIZE: usize = 16;
237    ///
238    /// // Example with valid padding
239    /// let padded_data = b"YELLOW SUBMARINE\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10";
240    /// let unpadded_data = CryptoUtils::unpad_binary(padded_data).unwrap();
241    /// assert_eq!(unpadded_data, b"YELLOW SUBMARINE");
242    ///
243    /// // Example with invalid padding
244    /// let invalid_padded_data = b"YELLOW SUBMARINE\x05\x05\x05\x05\x06";
245    /// assert!(CryptoUtils::unpad_binary(invalid_padded_data).is_err());
246    /// ```
247    ///
248    /// # Panics
249    ///
250    /// This function does not panic but returns a `Result` in case of errors like invalid padding or improper length.
251    pub fn unpad_binary(data: &[u8]) -> Result<Vec<u8>, KSMRError> {
252        const BLOCK_SIZE: usize = 16; // Define or pass as argument as needed
253
254        let data_len = data.len();
255
256        // Check if the data is empty
257        if data_len == 0 {
258            return Err(KSMRError::CryptoError("Data is empty".to_string()));
259        }
260
261        // Check if the length is a multiple of the block size
262        if data_len % BLOCK_SIZE != 0 {
263            return Err(KSMRError::CryptoError("Invalid data length".to_string()));
264        }
265
266        // Get the padding length from the last byte
267        let pad_len = data[data_len - 1];
268
269        // Validate the padding length
270        if pad_len == 0 || pad_len as usize > BLOCK_SIZE || pad_len as usize > data_len {
271            return Err(KSMRError::CryptoError("Invalid padding".to_string()));
272        }
273
274        // Ensure padding bytes are correct
275        if !data[data_len - pad_len as usize..]
276            .iter()
277            .all(|&b| b == pad_len)
278        {
279            return Err(KSMRError::CryptoError("Invalid padding".to_string()));
280        }
281
282        // Return the unpadded data
283        Ok(data[..data_len - pad_len as usize].to_vec())
284    }
285
286    /// Removes padding from the given binary data.
287    ///
288    /// This function removes padding by interpreting the last byte of the input data as the number of padding bytes added.
289    /// It returns the unpadded data if the padding is valid. The function is simpler than PKCS#7, and it does not verify
290    /// the contents of the padding bytes—just their length.
291    ///
292    /// # Arguments
293    ///
294    /// * `data` - A slice of binary data to be unpadded.
295    ///
296    /// # Returns
297    ///
298    /// * `Ok(Vec<u8>)` - The unpadded data if the padding is valid.
299    /// * `Err(&'static str)` - An error message if the padding or data length is invalid.
300    ///
301    /// # Errors
302    ///
303    /// This function returns an error in the following cases:
304    /// - The data is empty.
305    /// - The padding length (extracted from the last byte) is greater than the length of the data.
306    ///
307    /// # Example
308    ///
309    /// ```
310    /// use keeper_secrets_manager_core::crypto::CryptoUtils;
311    /// let padded_data = b"HELLO WORLD\x04\x04\x04\x04";
312    /// let unpadded_data = CryptoUtils::unpad_char(padded_data).unwrap();
313    /// assert_eq!(unpadded_data, b"HELLO WORLD");
314    /// ```
315    ///
316    /// In this example, the input `padded_data` ends with four padding bytes (`\x04`), which are removed by the function.
317    /// The resulting unpadded data is `"HELLO WORLD"`.
318    ///
319    /// # Errors
320    ///
321    /// * `"Data is empty"` - If the input data is empty.
322    /// * `"Invalid padding length"` - If the padding length exceeds the length of the input data.
323    ///
324    /// # Panics
325    ///
326    /// This function does not panic but returns a `Result` in case of errors.
327    pub fn unpad_char(data: &[u8]) -> Result<Vec<u8>, KSMRError> {
328        if data.is_empty() {
329            return Err(KSMRError::CryptoError("Data is empty".to_string()));
330        }
331
332        let pad_len = data[data.len() - 1] as usize;
333
334        // Ensure padding length is not greater than data length
335        if pad_len == 0 || pad_len > data.len() {
336            return Err(KSMRError::CryptoError("Invalid padding length".to_string()));
337        }
338
339        // Optionally, you could also check that all padding bytes are equal to the padding length
340        if !data[data.len() - pad_len..]
341            .iter()
342            .all(|&b| b == pad_len as u8)
343        {
344            return Err(KSMRError::CryptoError("Invalid padding".to_string()));
345        }
346
347        // Return the unpadded data
348        Ok(data[..data.len() - pad_len].to_vec())
349    }
350
351    /// Converts a byte slice into a `BigUint` integer.
352    ///
353    /// # Parameters
354    ///
355    /// - `b`: A byte slice representing the input bytes to be converted to an integer.
356    ///
357    /// # Returns
358    ///
359    /// This function returns a `Result`:
360    /// - `Ok(BigUint)`: The converted integer on success.
361    /// - `Err(KSMRError)`: An error message if the input is invalid (e.g., empty input or exceeds 16 bytes).
362    ///
363    /// # Errors
364    ///
365    /// - Returns `"Input is empty"` if the provided byte slice is empty.
366    /// - Returns `"Input exceeds maximum length of 16 bytes"` if the input byte slice is longer than 16 bytes.
367    ///
368    /// # Example
369    ///
370    /// ```rust
371    /// use keeper_secrets_manager_core::crypto::CryptoUtils;
372    /// use std::str::FromStr;
373    /// use num_bigint::BigUint;
374    /// let bytes = &[1; 17];
375    /// let result = CryptoUtils::bytes_to_int(bytes).unwrap();
376    /// assert_eq!(result, BigUint::from_str("341616807575530379006368233343265341697").unwrap());
377    /// ```
378    pub fn bytes_to_int(b: &[u8]) -> Result<BigUint, KSMRError> {
379        if b.is_empty() {
380            return Err(KSMRError::InsufficientBytes("Input is empty".to_string()));
381        }
382        let big_number = BigUint::from_bytes_be(b);
383        Ok(big_number)
384    }
385
386    /// Converts a URL-safe Base64 encoded string to a byte vector.
387    ///
388    /// This function decodes a URL-safe Base64 encoded string into a vector of bytes. It automatically
389    /// adds the necessary padding (`=`) to the input string if it's missing, ensuring it conforms to
390    /// Base64 encoding rules. The function also includes optional checks to verify the length of the
391    /// decoded byte vector for specific use cases (e.g., UUIDs).
392    ///
393    /// # Parameters
394    ///
395    /// - `s`: A string slice representing the URL-safe Base64 encoded string to decode.
396    ///
397    /// # Returns
398    ///
399    /// This function returns a `Result`:
400    /// - `Ok(Vec<u8>)`: A vector of bytes resulting from decoding the input string on success.
401    /// - `Err(KSMRError)`: An error variant indicating an issue with decoding, such as invalid Base64 format.
402    ///
403    /// # Errors
404    ///
405    /// - `KSMRError::InvalidBase64`: If the input string fails to decode as valid Base64.
406    /// - `KSMRError::DecodedBytesTooShort`: If the decoded byte array is shorter than the required length
407    ///   (e.g., for UUID or other fixed-length conversions).
408    ///
409    /// # Example
410    ///
411    /// ```rust
412    /// use keeper_secrets_manager_core::crypto::CryptoUtils;
413    /// use keeper_secrets_manager_core::custom_error::KSMRError;
414    ///
415    /// fn main() -> Result<(), KSMRError> {
416    ///     let url_safe_base64 = "c29tZSBkYXRh"; // Example URL-safe Base64 string
417    ///
418    ///     // Convert URL-safe Base64 string to bytes
419    ///     let decoded_bytes = CryptoUtils::url_safe_str_to_bytes(url_safe_base64);
420    ///
421    ///     // Print the resulting byte vector
422    ///     println!("Decoded bytes: {:?}", decoded_bytes);
423    ///
424    ///     Ok(())
425    /// }
426    /// ```
427    ///
428    /// # Panics
429    ///
430    /// This function does not panic under normal operation. However, it will return an error if the input string is not valid Base64.
431    ///
432    /// # Notes
433    ///
434    /// - The function automatically adds padding (`=`) to the input string if necessary to conform to Base64 encoding rules.
435    /// - The decoded byte array is optionally validated for minimum length (e.g., at least 8 bytes for UUIDs).
436    pub fn url_safe_str_to_bytes(s: &str) -> Result<Vec<u8>, KSMRError> {
437        // Attempt to decode the URL-safe Base64 string
438        let text = s.replace("+", "-").replace("/", "_");
439        let decoded_bytes = URL_SAFE_NO_PAD
440            .decode(&text)
441            .map_err(|err| KSMRError::DecodeError(err.to_string()));
442        let decoded_bytes = match decoded_bytes {
443            Ok(decoded_bytes) => decoded_bytes,
444            Err(err) => {
445                if err == KSMRError::InvalidBase64 {
446                    URL_SAFE_NO_PAD
447                        .decode(s)
448                        .map_err(|err| KSMRError::DecodeError(err.to_string()))?
449                } else {
450                    return Err(err);
451                }
452            }
453        };
454
455        // Optional: Check if the decoded bytes are long enough (e.g., for UUIDs)
456        if decoded_bytes.len() < 8 {
457            return Err(KSMRError::DecodedBytesTooShort);
458        }
459
460        Ok(decoded_bytes)
461    }
462
463    pub fn url_safe_str_to_bytes_trim_padding(s: &str) -> Result<Vec<u8>, KSMRError> {
464        let mut text = s.trim_end_matches("=").to_string();
465        // Attempt to decode the URL-safe Base64 string
466        text = text.replace("+", "-").replace("/", "_");
467        let decoded_bytes = URL_SAFE_NO_PAD
468            .decode(&text)
469            .map_err(|err| KSMRError::DecodeError(err.to_string()));
470        let decoded_bytes = match decoded_bytes {
471            Ok(decoded_bytes) => decoded_bytes,
472            Err(err) => {
473                if err == KSMRError::InvalidBase64 {
474                    URL_SAFE_NO_PAD
475                        .decode(s)
476                        .map_err(|err| KSMRError::DecodeError(err.to_string()))?
477                } else {
478                    return Err(err);
479                }
480            }
481        };
482        // Optional: Check if the decoded bytes are long enough (e.g., for UUIDs)
483        if decoded_bytes.len() < 8 {
484            return Err(KSMRError::DecodedBytesTooShort);
485        }
486        Ok(decoded_bytes)
487    }
488
489    #[allow(clippy::needless_doctest_main)]
490    /// Generates a vector of random bytes of the specified length.
491    ///
492    /// # Parameters
493    ///
494    /// - `length`: The desired length of the random byte vector.
495    ///
496    /// # Returns
497    ///
498    /// This function returns a `Vec<u8>` containing `length` random bytes.
499    ///
500    /// # Example
501    ///
502    /// ```rust
503    /// use keeper_secrets_manager_core::crypto::CryptoUtils;
504    /// fn main() {
505    ///     let length = 16; // Specify the length of random bytes
506    ///     let random_bytes = CryptoUtils::generate_random_bytes(length);
507    ///
508    ///     // Print the generated random bytes
509    ///     println!("Generated random bytes: {:?}", random_bytes);
510    /// }
511    /// ```
512    ///
513    /// # Panics
514    ///
515    /// This function will panic if `length` is zero.
516    pub fn generate_random_bytes(length: usize) -> Vec<u8> {
517        let mut rng = rand::thread_rng(); // Get a random number generator
518        let mut bytes = vec![0u8; length];
519        rng.fill(&mut bytes[..]);
520        bytes // Return the random bytes
521    }
522
523    #[allow(clippy::needless_doctest_main)]
524    /// Generates a 32-byte random encryption key.
525    ///
526    /// This function is suitable for creating encryption keys for symmetric encryption algorithms,
527    /// such as AES-256, which requires a 256-bit (32-byte) key.
528    ///
529    /// # Returns
530    ///
531    /// This function returns a `Vec<u8>` containing 32 random bytes, which can be used as an encryption key.
532    ///
533    /// # Example
534    ///
535    /// ```rust
536    /// use keeper_secrets_manager_core::crypto::CryptoUtils;
537    /// fn main() {
538    ///     let encryption_key = CryptoUtils::generate_encryption_key_bytes();
539    ///
540    ///     // Print the generated encryption key
541    ///     println!("Generated encryption key: {:?}", encryption_key);
542    /// }
543    /// ```
544    ///
545    /// # Panics
546    ///
547    /// This function does not panic under normal operation since it relies on generating random bytes.
548    pub fn generate_encryption_key_bytes() -> Vec<u8> {
549        Self::generate_random_bytes(32)
550    }
551
552    #[allow(clippy::needless_doctest_main)]
553    /// Converts a byte slice to a URL-safe Base64-encoded string.
554    ///
555    /// This function encodes the given byte slice into a URL-safe Base64 string,
556    /// stripping any trailing padding characters (`=`) that are typically used
557    /// in Base64 encoding. The resulting string can be safely included in URLs.
558    ///
559    /// # Parameters
560    ///
561    /// - `b`: A byte slice that you want to encode to a URL-safe Base64 string.
562    ///
563    /// # Returns
564    ///
565    /// This function returns a `String` containing the URL-safe Base64-encoded representation
566    /// of the input byte slice.
567    ///
568    /// # Example
569    ///
570    /// ```rust
571    /// use keeper_secrets_manager_core::crypto::CryptoUtils;
572    /// fn main() {
573    ///     let data = b"Hello, World!";
574    ///     let encoded_str = CryptoUtils::bytes_to_url_safe_str(data);
575    ///
576    ///     // Print the URL-safe Base64-encoded string
577    ///     println!("Encoded URL-safe string: {}", encoded_str);
578    /// }
579    /// ```
580    ///
581    /// # Notes
582    ///
583    /// - The function uses the `BASE64_URL_SAFE` encoder, which ensures that the resulting
584    ///   string is safe for use in URLs and does not contain characters that may need
585    ///   to be escaped.
586    pub fn bytes_to_url_safe_str(b: &[u8]) -> String {
587        // Encode bytes to URL-safe Base64 and strip padding '=' characters
588        let encoded_value = BASE64_URL_SAFE.encode(b);
589        encoded_value.trim_end_matches('=').to_string()
590    }
591
592    /// Converts a URL-safe Base64-encoded string to a `BigUint` integer.
593    ///
594    /// This function first decodes the URL-safe Base64 string into a byte vector.
595    /// It then converts the resulting byte vector into a `BigUint` integer. The function
596    /// will return an error if the string cannot be decoded or if the resulting byte
597    /// vector cannot be converted to a valid integer.
598    ///
599    /// # Parameters
600    ///
601    /// - `s`: A string slice representing the URL-safe Base64-encoded data.
602    ///
603    /// # Returns
604    ///
605    /// This function returns a `Result`:
606    /// - `Ok(BigUint)`: The decoded integer value on success.
607    /// - `Err(KSMRError)`: An error variant indicating a failure in decoding or conversion.
608    ///
609    /// # Example
610    ///
611    /// ```rust
612    /// use keeper_secrets_manager_core::crypto::CryptoUtils;
613    /// use keeper_secrets_manager_core::custom_error::KSMRError;
614    /// fn main() -> Result<(), KSMRError> {
615    ///     let url_safe_str = "AQIDBAUGBwgJCgsMDQ4PEA=="; // Example URL-safe Base64 string
616    ///
617    ///     match CryptoUtils::url_safe_str_to_int(url_safe_str) {
618    ///         Ok(int_value) => println!("Decoded integer value: {}", int_value),
619    ///         Err(err) => println!("Error decoding string: {:?}", err),
620    ///     }
621    ///     Ok(())
622    /// }
623    /// ```
624    ///
625    /// # Errors
626    ///
627    /// - Returns a `KSMRError::InvalidBase64` if the input string is not valid Base64.
628    /// - Returns `KSMRError::InvalidIntegerConversion` if the decoded byte slice cannot
629    ///   be converted to a valid `BigUint` integer.
630    ///
631    /// # Notes
632    ///
633    /// - The function assumes that the input string is a valid URL-safe Base64 string.
634    /// - Any invalid Base64 characters or decoding issues will result in a `KSMRError`.
635    pub fn url_safe_str_to_int(s: &str) -> Result<BigUint, KSMRError> {
636        let bytes = Self::url_safe_str_to_bytes(s)?; // Assuming this function is also updated
637        let int_value = Self::bytes_to_int(&bytes)?; // Now returns KSMRError
638        Ok(int_value)
639    }
640
641    #[allow(clippy::needless_doctest_main)]
642    /// Generates an ECC signing key.
643    ///
644    /// This function generates a random encryption key, converts it to a URL-safe Base64 string,
645    /// then converts the string into an integer. The integer is used to populate the first 16 bytes
646    /// of a 32-byte array, with the remaining 16 bytes set to zeros. This 32-byte array is then used
647    /// to create a `SigningKey` that can be used for ECC-based signing operations.
648    ///
649    /// # Returns
650    ///
651    /// This function returns a `Result`:
652    /// - `Ok(SigningKey)`: A successfully generated `SigningKey` instance, which can be used for ECC signing operations.
653    /// - `Err(KSMRError)`: If any of the operations fail, such as key generation, conversion, or `SigningKey` creation.
654    ///
655    /// # Example
656    ///
657    /// ```rust
658    /// use keeper_secrets_manager_core::crypto::CryptoUtils; // Adjust to your actual module path
659    ///
660    /// fn main() {
661    ///     let signing_key = CryptoUtils::generate_ecc_keys().unwrap();
662    ///     println!("Generated ECC Signing Key: {:?}", signing_key);
663    /// }
664    /// ```
665    ///
666    /// # Panics
667    ///
668    /// This function may panic if:
669    /// - The conversion from URL-safe Base64 string to integer fails.
670    /// - The creation of the `SigningKey` from the byte array fails.
671    ///
672    /// # Notes
673    ///
674    /// - 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.
675    /// - The final `SigningKey` is 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.
676    /// - The generated signing key is suitable for use in ECC-based cryptographic operations.
677    pub fn generate_ecc_keys() -> Result<SigningKey, KSMRError> {
678        // Generate encryption key bytes
679        let encryption_key_bytes: Vec<u8> = Self::generate_encryption_key_bytes();
680
681        // Convert bytes to URL-safe Base64 string
682        let private_key_str = Self::bytes_to_url_safe_str(&encryption_key_bytes);
683
684        // Convert URL-safe Base64 string to integer
685        let encryption_key_int = Self::url_safe_str_to_int(&private_key_str).map_err(|_| {
686            KSMRError::CryptoError("Failed to convert URL-safe Base64 string to integer".into())
687        })?;
688
689        // Create a 32-byte array for the SigningKey
690        let mut key_bytes = [0u8; 32];
691
692        // Convert the BigUint encryption_key_int to bytes and copy it to the key_bytes array
693        let int_bytes = encryption_key_int.to_bytes_be(); // This gives 16 bytes
694        key_bytes.copy_from_slice(&int_bytes); // Copy the 16 bytes from the integer
695
696        // Create the SigningKey from the byte array
697        SigningKey::from_bytes(GenericArray::from_slice(&key_bytes))
698            .map_err(|_| KSMRError::CryptoError("Failed to create SigningKey from bytes".into()))
699    }
700
701
702    #[allow(clippy::needless_doctest_main)]
703    /// Derives the public key from a given ECC private key.
704    ///
705    /// This function takes a reference to a `SigningKey` (private key) and derives
706    /// the corresponding public key. The public key is then serialized in uncompressed
707    /// format (X9.62).
708    ///
709    /// # Parameters
710    ///
711    /// - `private_key`: A reference to a `SigningKey`, which represents the ECC private key
712    ///   from which the public key will be derived.
713    ///
714    /// # Returns
715    ///
716    /// This function returns a `Vec<u8>` containing the serialized public key in uncompressed
717    /// format.
718    ///
719    /// # Example
720    ///
721    /// ```rust
722    /// use keeper_secrets_manager_core::crypto::CryptoUtils; // Adjust to your actual module path
723    ///
724    /// fn main() {
725    ///     // Assume you have a valid SigningKey instance
726    ///     let private_key = CryptoUtils::generate_ecc_keys().unwrap();
727    ///
728    ///     // Get the corresponding public key
729    ///     let public_key = CryptoUtils::public_key_ecc(&private_key);
730    ///     
731    ///     println!("Public Key: {:?}", public_key);
732    /// }
733    /// ```
734    ///
735    /// # Notes
736    ///
737    /// - The uncompressed format of the public key allows for straightforward serialization
738    ///   and transmission. It includes the x-coordinate and the y-coordinate of the point
739    ///   on the elliptic curve.
740    /// - Ensure that the `SigningKey` provided to this function is valid and has been properly
741    ///   initialized before calling this function.
742    pub fn public_key_ecc(private_key: &SigningKey) -> Vec<u8> {
743        // Get the public key from the private key
744        let public_key: VerifyingKey = *private_key.verifying_key();
745
746        // Serialize the public key in uncompressed format (X9.62)
747        let pub_key_bytes = public_key.to_encoded_point(false).as_ref().to_vec();
748
749        pub_key_bytes
750    }
751
752
753    #[allow(clippy::needless_doctest_main)]
754    /// Generates a new ECC private key.
755    ///
756    /// This function generates a new 256-bit (32-byte) private key suitable for ECC operations,
757    /// specifically for the P256 curve. The process involves generating random bytes, converting
758    /// those bytes into a URL-safe Base64 string, and then converting that string into an integer.
759    /// The integer is then used to create the `SigningKey` which represents the ECC private key.
760    ///
761    /// # Returns
762    ///
763    /// This function returns a `Result`:
764    /// - `Ok(SigningKey)`: The successfully generated ECC private key as a `SigningKey`.
765    /// - `Err(KSMRError)`: An error if any step of the key generation process fails, including random byte generation, Base64 conversion, integer conversion, or `SigningKey` creation.
766    ///
767    /// # Example
768    ///
769    /// ```rust
770    /// use keeper_secrets_manager_core::crypto::CryptoUtils; // Adjust to your actual module path
771    ///
772    /// fn main() {
773    ///     // Generate a new ECC private key
774    ///     let private_key = CryptoUtils::generate_private_key_ecc().unwrap();
775    ///
776    ///     // Print or use the private key as needed
777    ///     println!("Generated Private Key: {:?}", private_key);
778    /// }
779    /// ```
780    ///
781    /// # Notes
782    ///
783    /// - The generated private key is a 256-bit (32-byte) key, which is compatible with the P256 curve used in ECC operations.
784    /// - 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.
785    ///
786    /// # Panics
787    ///
788    /// This function will panic if any of the following conditions occur:
789    /// - The conversion of the URL-safe Base64 string to an integer fails.
790    /// - The `SigningKey` creation from the byte array fails.
791    ///
792    /// # Implementation Details
793    ///
794    /// - The key is derived from random bytes, which are encoded into a URL-safe Base64 string, then decoded back to an integer.
795    /// - The integer is converted to bytes, and the first 16 bytes are used for the key, with the remaining bytes padded with zeros.
796    /// - The final 32-byte array is used to create the `SigningKey` using `SigningKey::from_bytes`.
797    pub fn generate_private_key_ecc() -> Result<SigningKey, KSMRError> {
798        // Generate random bytes for the encryption key
799        let encryption_key_bytes = Self::generate_random_bytes(32);
800
801        // Convert bytes to URL-safe Base64 string
802        let private_key_str = Self::bytes_to_url_safe_str(&encryption_key_bytes);
803
804        // Convert URL-safe Base64 string to integer
805        let encryption_key_int = Self::url_safe_str_to_int(&private_key_str).map_err(|e| {
806            KSMRError::CryptoError(format!(
807                "Failed to convert URL-safe Base64 string to integer: {}",
808                e
809            ))
810        })?;
811
812        // Create a byte array from the integer representation (needs 32 bytes)
813        let mut key_bytes = [0u8; 32];
814
815        // Right-align int_bytes in key_bytes
816        let int_bytes = encryption_key_int.to_bytes_be();
817        let start = 32 - int_bytes.len();
818        key_bytes[start..].copy_from_slice(&int_bytes);
819
820        // Create SigningKey from the byte array
821        SigningKey::from_bytes(GenericArray::from_slice(&key_bytes)).map_err(|e| {
822            KSMRError::CryptoError(format!("Failed to create SigningKey from bytes: {}", e))
823        })?;
824
825        // Return the generated SigningKey
826        Ok(SigningKey::from_bytes(GenericArray::from_slice(&key_bytes)).unwrap())
827    }
828
829    #[allow(clippy::needless_doctest_main)]
830    /// Generates a new ECC private key.
831    ///
832    /// This function generates a new 256-bit (32-byte) private key suitable for ECC operations,
833    /// specifically for the P256 curve. The process involves generating random bytes, converting
834    /// those bytes into a URL-safe Base64 string, and then converting that string into an integer.
835    /// The integer is then used to create the `SigningKey`, which represents the ECC private key.
836    ///
837    /// # Returns
838    ///
839    /// This function returns a `Result`:
840    /// - `Ok(SigningKey)`: The successfully generated ECC private key as a `SigningKey`.
841    /// - `Err(KSMRError)`: An error if any step of the key generation process fails, including random byte generation, Base64 conversion, integer conversion, or `SigningKey` creation.
842    ///
843    /// # Example
844    ///
845    /// ```rust
846    /// use keeper_secrets_manager_core::crypto::CryptoUtils; // Adjust to your actual module path
847    ///
848    /// fn main() {
849    ///     // Generate a new ECC private key
850    ///     let private_key = CryptoUtils::generate_private_key_ecc().unwrap();
851    ///
852    ///     // Print or use the private key as needed
853    ///     println!("Generated Private Key: {:?}", private_key);
854    /// }
855    /// ```
856    ///
857    /// # Notes
858    ///
859    /// - The generated private key is a 256-bit (32-byte) key, which is compatible with the P256 curve used in ECC operations.
860    /// - The first 16 bytes of the 32-byte private key are filled with the integer representation of the random bytes.
861    /// - The second 16 bytes are a repeat of the same integer to meet the required key length for P256.
862    /// - 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.
863    ///
864    /// # Panics
865    ///
866    /// This function will panic if any of the following conditions occur:
867    /// - The conversion of the URL-safe Base64 string to an integer fails.
868    /// - The `SigningKey` creation from the byte array fails.
869    ///
870    /// # Implementation Details
871    ///
872    /// - The key is derived from random bytes, which are encoded into a URL-safe Base64 string, then decoded back to an integer.
873    /// - The integer is converted to bytes, and the first 16 bytes are used for the key, with the remaining bytes padded with zeros.
874    /// - The final 32-byte array is used to create the `SigningKey` using `SigningKey::from_bytes`.
875    pub fn generate_private_key_der() -> Result<Vec<u8>, KSMRError> {
876        // Generate ECC signing key
877        let signing_key = Self::generate_private_key_ecc()
878            .map_err(|err| KSMRError::CryptoError(err.to_string()))
879            .unwrap();
880
881        // Export to DER format
882        match signing_key.to_pkcs8_der() {
883            Ok(private_key_der) => Ok(private_key_der.as_bytes().to_vec()), // Return the DER bytes
884            Err(e) => Err(KSMRError::CryptoError(format!(
885                "Failed to serialize to DER: {}",
886                e
887            ))),
888        }
889    }
890
891
892
893    #[allow(clippy::needless_doctest_main)]
894    /// Generates a new ephemeral ECC signing key using the SECP256R1 curve.
895    ///
896    /// This function creates a new ECC signing key that can be used for cryptographic operations such as
897    /// signing or key exchange. It utilizes a secure random number generator to ensure the key is
898    /// generated in a cryptographically secure manner.
899    ///
900    /// # Returns
901    ///
902    /// This function returns a `SigningKey`, which represents the newly generated ECC signing key.
903    ///
904    /// # Example
905    ///
906    /// ```rust
907    /// use keeper_secrets_manager_core::crypto::CryptoUtils; // Adjust to your actual module path
908    /// use p256::ecdsa::SigningKey;
909    /// fn main() {
910    ///     // Generate a new ECC signing key
911    ///     let signing_key: SigningKey = CryptoUtils::generate_new_ecc_key();
912    ///
913    ///     // Use the signing key for further cryptographic operations
914    ///     println!("Generated new ECC signing key: {:?}", signing_key);
915    /// }
916    /// ```
917    ///
918    /// # Notes
919    ///
920    /// - The generated key is ephemeral and should be used for a single session or transaction.
921    /// - Ensure that you securely manage and store the signing key if needed, as it is essential for
922    ///   cryptographic integrity.
923    pub fn generate_new_ecc_key() -> SigningKey {
924        // Create a new OS random number generator
925        let mut rng = OsRng;
926
927        // Generate an ephemeral ECC signing key for SECP256R1
928        SigningKey::random(&mut rng)
929    }
930
931    /// Encrypts data using AES-256-GCM with an optional nonce.
932    ///
933    /// This function performs authenticated encryption of the provided `data` using AES-256-GCM.
934    /// AES-256-GCM requires a 32-byte key for encryption and uses a 12-byte nonce. If a nonce is
935    /// not provided, a random 12-byte nonce will be generated.
936    ///
937    /// # Parameters
938    ///
939    /// - `data`: A byte slice representing the plaintext data to be encrypted.
940    /// - `key_bytes`: A byte slice representing the 32-byte AES key used for encryption (AES-256).
941    /// - `nonce_bytes`: An optional byte slice representing the nonce. If not provided, a random nonce will be generated.
942    ///
943    /// # Returns
944    ///
945    /// This function returns a `Result`:
946    /// - `Ok(Vec<u8>)`: The result will contain a vector with the concatenated nonce and the encrypted ciphertext on success.
947    /// - `Err(KSMRError)`: An error if encryption fails or if invalid input parameters are provided (e.g., wrong key size).
948    ///
949    /// # Errors
950    ///
951    /// - Returns `KSMRError::CryptoError("Invalid key size")` if the provided `key_bytes` slice is not exactly 32 bytes long.
952    /// - Returns `KSMRError::CryptoError("Encryption failed")` if the encryption operation fails (for example, due to invalid key or data).
953    ///
954    /// # Example
955    ///
956    /// ```rust
957    /// use keeper_secrets_manager_core::crypto::CryptoUtils;
958    /// use std::error::Error;
959    /// use hex;
960    ///
961    /// fn main() -> Result<(), Box<dyn Error>> {
962    ///     // 32-byte AES key (AES-256 requires a 32-byte key)
963    ///     let key = b"an example very very secret key."; // Must be exactly 32 bytes
964    ///
965    ///     // Example plaintext data
966    ///     let data = b"plaintext message that needs encryption";
967    ///
968    ///     // Encrypt the data with a random nonce
969    ///     let encrypted_data = CryptoUtils::encrypt_aes_gcm(data, key, None)?;
970    ///
971    ///     // Print the encrypted data in hex format for better readability
972    ///     println!("Encrypted data: {:?}", hex::encode(&encrypted_data));
973    ///
974    ///     Ok(())
975    /// }
976    /// ```
977    ///
978    /// # Panics
979    ///
980    /// 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).
981    ///
982    /// # Notes
983    ///
984    /// - 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.
985    /// - The nonce is prepended to the ciphertext before returning, allowing the recipient to extract and use it for decryption.
986    ///
987    /// # Implementation Details
988    ///
989    /// - 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.
990    /// - 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.
991    /// - The function uses the `Aes256Gcm` cipher from the `aes-gcm` crate and the `rand` crate to generate random nonces when necessary.
992    pub fn encrypt_aes_gcm(
993        data: &[u8],
994        key_bytes: &[u8],
995        nonce_bytes: Option<&[u8]>,
996    ) -> Result<Vec<u8>, KSMRError> {
997        let _ = nonce_bytes;
998
999        // Validate key size (32 bytes for AES-256)
1000        if key_bytes.len() != 32 {
1001            return Err(KSMRError::CryptoError("Invalid key size".to_string()));
1002        }
1003
1004        if key_bytes.len() != 32 {
1005            return Err(KSMRError::CryptoError("Invalid key size".to_string()));
1006        }
1007
1008        // Create the key from the provided bytes
1009        let mut cipher_obj =
1010            aes_gcm::Aes256Gcm::new(aes_gcm::Key::<Aes256Gcm>::from_slice(key_bytes));
1011        let nonce_obj = aes_gcm::Aes256Gcm::generate_nonce(&mut OsRng);
1012        let cipher_txt_obj = cipher_obj
1013            .encrypt(&nonce_obj, data)
1014            .map_err(|_| KSMRError::CryptoError("Encryption failed".to_string()))?;
1015
1016        let mut result_obj = Vec::with_capacity(nonce_obj.as_slice().len() + cipher_txt_obj.len());
1017        result_obj.extend_from_slice(nonce_obj.as_slice());
1018        result_obj.extend_from_slice(&cipher_txt_obj);
1019        Ok(result_obj)
1020    }
1021
1022    /// Decrypts data using AES-256-GCM with a 12-byte nonce.
1023    ///
1024    /// # Parameters
1025    ///
1026    /// - `data`: A byte slice containing the nonce followed by the ciphertext. The first 12 bytes represent the nonce, and the rest is the ciphertext.
1027    /// - `key_bytes`: A byte slice representing the 32-byte AES key used for decryption (AES-256).
1028    ///
1029    /// # Returns
1030    ///
1031    /// This function returns a `Result`:
1032    /// - `Ok(Vec<u8>)`: The decrypted plaintext on success.
1033    /// - `Err(Box<dyn Error>)`: An error if decryption fails or if invalid input parameters are provided (e.g., wrong key size).
1034    ///
1035    /// # Errors
1036    ///
1037    /// - Returns `"Invalid key size"` if the provided `key_bytes` slice is not exactly 32 bytes long.
1038    /// - Returns `"Data too short to contain nonce"` if the provided `data` slice is smaller than 12 bytes.
1039    /// - Returns `"Decryption failed"` if the decryption operation itself fails (for example, if the ciphertext or key is invalid).
1040    ///
1041    /// # Example
1042    ///
1043    /// ```rust
1044    /// use keeper_secrets_manager_core::crypto::CryptoUtils;
1045    /// use keeper_secrets_manager_core::custom_error::KSMRError;
1046    /// use aes_gcm::{Aes256Gcm, Key, Nonce}; // Import the AES-GCM library
1047    /// use std::error::Error;
1048    /// use hex;
1049    ///
1050    /// fn main() -> Result<(), KSMRError> {
1051    ///     // 32-byte AES key (AES-256 requires a 32-byte key)
1052    ///     let key = b"an example very very secret key."; // Should be exactly 32 bytes
1053    ///
1054    ///     // 12-byte nonce (unique for each encryption)
1055    ///     let nonce = b"unique nonce"; // Must be exactly 12 bytes
1056    ///
1057    ///     // Example ciphertext (encrypted using the same key and nonce)
1058    ///     let ciphertext = hex::decode("c5d3db06f6c3d543663a94051a7a0d65")?; // Example encrypted data
1059    ///   
1060    ///     // Concatenate nonce and ciphertext
1061    ///     let mut encrypted_data = Vec::new();
1062    ///     encrypted_data.extend_from_slice(nonce);
1063    ///     encrypted_data.extend_from_slice(&ciphertext);
1064    ///
1065    ///     // Attempt to decrypt the data
1066    ///     let result = CryptoUtils::decrypt_aes(&encrypted_data, key);
1067    ///
1068    ///     // Check if the decryption was successful
1069    ///     match result {
1070    ///         Ok(decrypted_data) => {
1071    ///             println!("Decrypted data: {:?}", decrypted_data);
1072    ///         },
1073    ///         Err(err) => {
1074    ///             println!("Error: {}", err);
1075    ///             assert_eq!(err.to_string(), "Cryptography module Error: aead::Error");
1076    ///         }
1077    ///     }
1078    ///
1079    ///     Ok(())
1080    /// }
1081    /// ```
1082    ///
1083    /// # Panics
1084    ///
1085    /// 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).
1086    ///
1087    /// # Notes
1088    ///
1089    /// - This function assumes that the first 12 bytes of `data` represent the nonce.
1090    /// - AES-256-GCM is an authenticated encryption mode, so decryption will fail if the ciphertext or key is tampered with.
1091    pub fn decrypt_aes(data: &[u8], key_bytes: &[u8]) -> Result<Vec<u8>, KSMRError> {
1092        use aes_gcm::KeyInit;
1093        // Validate key size (32 bytes for AES-256)
1094        if key_bytes.len() != 32 {
1095            return Err(KSMRError::CryptoError("Invalid key size".to_string()));
1096        }
1097
1098        if data.len() < 12 {
1099            return Err(KSMRError::CryptoError(
1100                "Data too short to contain nonce".to_string(),
1101            ));
1102        }
1103
1104        let ciphertext = &data[12..]; // The rest is the ciphertext
1105
1106        let mut key2 = aes_gcm::Aes256Gcm::new_from_slice(key_bytes)
1107            .map_err(|err| KSMRError::CryptoError(err.to_string()))?;
1108        let nonce2 = aes_gcm::Nonce::from_slice(&data[..12]);
1109
1110        // Decrypt the data
1111        let decrypted_plaintext = key2
1112            .decrypt(nonce2, ciphertext)
1113            .map_err(|err| KSMRError::CryptoError(err.to_string()))?;
1114        Ok(decrypted_plaintext)
1115    }
1116
1117    /// Encrypts data using AES-256 in CBC (Cipher Block Chaining) mode.
1118    ///
1119    /// This function encrypts the provided plaintext data using AES-256 in CBC mode with a 32-byte key.
1120    /// If an Initialization Vector (IV) is not provided, a random 16-byte IV is generated. The IV
1121    /// is then prepended to the resulting ciphertext for later use during decryption.
1122    ///
1123    /// # Parameters
1124    ///
1125    /// - `data`: A byte slice representing the plaintext data to be encrypted.
1126    /// - `key`: A 32-byte slice representing the AES-256 key used for encryption (AES-256 requires a 256-bit key).
1127    /// - `iv`: An optional 16-byte slice representing the Initialization Vector (IV). If `None` is provided,
1128    ///   a random IV will be generated.
1129    ///
1130    /// # Returns
1131    ///
1132    /// This function returns a `Result`:
1133    /// - `Ok(Vec<u8>)`: A vector containing the concatenated IV and the encrypted ciphertext on success.
1134    /// - `Err(KSMRError)`: An error if the key size is invalid (i.e., not 32 bytes).
1135    ///
1136    /// # Errors
1137    ///
1138    /// - Returns `KSMRError::CryptoError("Invalid key size")` if the provided `key` is not 32 bytes long.
1139    /// - Returns an error if encryption fails or if the padding or encryption process encounters issues.
1140    ///
1141    /// # Example
1142    ///
1143    /// ```rust
1144    /// use keeper_secrets_manager_core::crypto::CryptoUtils;
1145    /// use rand::rngs::OsRng;
1146    ///
1147    /// let plaintext = b"Sensitive data to encrypt";
1148    /// let key = b"0123456789abcdef0123456789abcdef"; // A 32-byte AES-256 key.
1149    /// let iv = b"1234567890123456"; // A 16-byte IV (optional).
1150    ///
1151    /// let encrypted_data = CryptoUtils::encrypt_aes_cbc(plaintext, key, Some(iv)).unwrap();
1152    ///
1153    /// println!("Encrypted data: {:?}", encrypted_data);
1154    /// ```
1155    ///
1156    /// # Panics
1157    ///
1158    /// This function does not panic but returns an error if input is invalid (e.g., incorrect key size or encryption failure).
1159    ///
1160    /// # Notes
1161    ///
1162    /// - AES-256 in CBC mode requires the key to be exactly 32 bytes. The IV must be 16 bytes in length.
1163    /// - 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.
1164    /// - The resulting ciphertext is returned with the IV prepended to facilitate decryption.
1165    pub fn encrypt_aes_cbc(
1166        data: &[u8],
1167        key: &[u8],
1168        iv: Option<&[u8]>,
1169    ) -> Result<Vec<u8>, KSMRError> {
1170        if key.len() != AES_256_KEY_SIZE {
1171            return Err(KSMRError::CryptoError("Invalid key size".to_string()));
1172        }
1173
1174        let iv = match iv {
1175            Some(iv) => iv.to_vec(),
1176            None => {
1177                let mut iv = vec![0u8; BLOCK_SIZE];
1178                OsRng.fill_bytes(&mut iv); // Secure random IV generation
1179                iv
1180            }
1181        };
1182
1183        match iv.len() {
1184            BLOCK_SIZE => (),
1185            _ => {
1186                return Err(KSMRError::CryptoError("Invalid IV size".to_string()));
1187            }
1188        }
1189
1190        let cipher = Aes256::new(GenericArray::from_slice(key));
1191        let padded_data = pad_data(data, BLOCK_SIZE);
1192        let mut ciphertext = Vec::with_capacity(padded_data.len());
1193        let mut previous_block = iv.clone();
1194
1195        for block in padded_data.chunks(BLOCK_SIZE) {
1196            let mut block = block.to_vec();
1197
1198            // XOR block with the previous block or IV
1199            for (i, byte) in block.iter_mut().enumerate() {
1200                *byte ^= previous_block[i];
1201            }
1202
1203            let mut block_arr = GenericArray::clone_from_slice(&block);
1204            cipher.encrypt_block(&mut block_arr);
1205
1206            ciphertext.extend_from_slice(&block_arr);
1207            previous_block = block_arr.to_vec();
1208        }
1209
1210        let mut result = iv.clone();
1211        result.extend(ciphertext);
1212        Ok(result)
1213    }
1214
1215    /// Decrypts data using AES-256 in CBC (Cipher Block Chaining) mode.
1216    ///
1217    /// This function decrypts the provided encrypted data using AES-256 in CBC mode with a 32-byte key.
1218    /// The first 16 bytes of the input data are treated as the Initialization Vector (IV), and the remaining
1219    /// bytes are treated as the ciphertext. After decryption, the padding is removed from the data to obtain the
1220    /// original plaintext.
1221    ///
1222    /// # Parameters
1223    ///
1224    /// - `data`: A byte slice representing the encrypted data. The first 16 bytes are treated as the IV, and the
1225    ///   remaining bytes are the ciphertext.
1226    /// - `key`: A 32-byte slice representing the AES-256 key used for decryption.
1227    ///
1228    /// # Returns
1229    ///
1230    /// This function returns a `Result`:
1231    /// - `Ok(Vec<u8>)`: A vector containing the decrypted and unpadded plaintext data.
1232    /// - `Err(KSMRError)`: An error if the key size is invalid, the data is too short to contain an IV, or the
1233    ///   data length is not a multiple of 16 bytes (indicating possible encoding issues).
1234    ///
1235    /// # Errors
1236    ///
1237    /// - Returns `KSMRError::CryptoError("Invalid key size")` if the provided `key` is not 32 bytes long.
1238    /// - Returns `KSMRError::CryptoError("Data too short to contain IV")` if the provided `data` is less than 16 bytes long.
1239    /// - Returns `KSMRError::CryptoError("Data is probably not encoded")` if the data length is not a multiple of 16 bytes.
1240    /// - Returns `KSMRError::CryptoError("Unpadding failed: <error message>")` if the unpadding process fails.
1241    ///
1242    /// # Example
1243    ///
1244    /// ```rust
1245    /// use keeper_secrets_manager_core::crypto::CryptoUtils;
1246    ///
1247    /// let encrypted_data = b"\x01\x02..."; // Some encrypted data with a 16-byte IV followed by ciphertext.
1248    /// let key = b"0123456789abcdef0123456789abcdef"; // A 32-byte AES-256 key.
1249    /// let data = CryptoUtils::decrypt_aes_cbc(encrypted_data, key);
1250    /// match data {
1251    ///     Ok(plaintext) => println!("Decrypted data: {:?}", plaintext),
1252    ///     Err(e) => eprintln!("Decryption error: {}", e),
1253    /// }
1254    /// ```
1255    ///
1256    /// In this example, `decrypt_aes_cbc` attempts to decrypt the `encrypted_data` using the provided AES-256 key.
1257    /// The decrypted data is returned after removing the padding.
1258    ///
1259    /// # Panics
1260    ///
1261    /// This function does not panic but returns a `Result` in case of errors.
1262    ///
1263    /// # Notes
1264    ///
1265    /// - AES-256 in CBC mode requires the key to be exactly 32 bytes. The IV must be 16 bytes in length.
1266    /// - The first 16 bytes of the input data are interpreted as the IV, while the rest is treated as the ciphertext.
1267    /// - CBC mode requires the ciphertext length to be a multiple of the AES block size (16 bytes).
1268    /// - 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.
1269    pub fn decrypt_aes_cbc(data: &[u8], key: &[u8]) -> Result<Vec<u8>, KSMRError> {
1270        // Validate key size (32 bytes for AES-256)
1271        if key.len() != 32 {
1272            return Err(KSMRError::CryptoError("Invalid key size".to_string()));
1273        }
1274        // Validate that data is large enough to contain an IV (16 bytes for AES-CBC)
1275        if data.len() < 16 {
1276            return Err(KSMRError::CryptoError(
1277                "Data too short to contain IV".to_string(),
1278            ));
1279        }
1280        // Extract the IV and ciphertext
1281        let iv = &data[..16]; // First 16 bytes are the IV
1282        let ciphertext = &data[16..]; // Remaining bytes are the encrypted data
1283        // Validate ciphertext length
1284        if ciphertext.len() % BLOCK_SIZE != 0 {
1285            return Err(KSMRError::CryptoError("Data is probably not encoded".to_string()));
1286        }
1287        let cipher = Aes256::new(GenericArray::from_slice(key));
1288        let mut plaintext = Vec::with_capacity(ciphertext.len());
1289        let mut previous_block = iv.to_vec();
1290        for block in ciphertext.chunks(BLOCK_SIZE) {
1291            let mut block_arr = GenericArray::clone_from_slice(block);
1292            cipher.decrypt_block(&mut block_arr);
1293            // XOR decrypted block with previous ciphertext block (or IV)
1294            let decrypted_block: Vec<u8> = block_arr
1295            .iter()
1296            .zip(&previous_block)
1297            .map(|(b, p)| b ^ p)
1298            .collect();
1299            plaintext.extend_from_slice(&decrypted_block);
1300            previous_block = block.to_vec();
1301        }
1302        // Remove PKCS#7 padding
1303        // let unpadded = unpad_data(&plaintext)
1304        //     .map_err(|e| KSMRError::CryptoError(format!("Unpadding failed: {}", e)))?;
1305        Ok(plaintext)
1306    }
1307
1308    /// Encrypts data using an ephemeral ECDH key exchange and AES-GCM.
1309    ///
1310    /// This function uses Elliptic Curve Diffie-Hellman (ECDH) to derive a shared secret between
1311    /// an ephemeral key generated on the fly and a server's public key provided in the input.
1312    /// The derived key is optionally concatenated with an identifier (`idz`), hashed using SHA-256
1313    /// to generate an AES encryption key, and then used to encrypt the input data with AES-GCM.
1314    ///
1315    /// # Arguments
1316    ///
1317    /// * `data` - A byte slice representing the data to be encrypted.
1318    /// * `server_public_raw_key_bytes` - A byte slice representing the server's public key in SEC1 format.
1319    /// * `idz` - An optional byte slice identifier that, if provided, is appended to the shared secret before key derivation.
1320    ///
1321    /// # Returns
1322    ///
1323    /// This function returns a `Result` containing:
1324    /// - `Ok(Vec<u8>)`: A vector of bytes containing the concatenation of the ephemeral public key and the encrypted data.
1325    /// - `Err(KSMRError)`: An error if key derivation or encryption fails.
1326    ///
1327    /// # Errors
1328    ///
1329    /// * Returns an error if the server public key is invalid or encryption fails.
1330    /// * If the `server_public_raw_key_bytes` cannot be parsed into a valid public key, it returns `"Invalid server public key!"`.
1331    /// * If encryption fails during AES-GCM, the error message will indicate the failure.
1332    ///
1333    /// # Example
1334    ///
1335    /// ```rust
1336    /// use keeper_secrets_manager_core::crypto::CryptoUtils;
1337    ///
1338    /// // Data to encrypt
1339    /// let data = b"Sensitive data to encrypt";
1340    ///
1341    /// // A raw public key as a string (this is just an example key)
1342    /// let server_public_key = "04d88c6fa31ea40af14c137b8e62f1151f1cc1e5688cad37b7f2e7";
1343    ///
1344    /// // Convert the public key from hex string to bytes
1345    /// let server_public_key_bytes = hex::decode(server_public_key).expect("Invalid hex key");
1346    ///
1347    /// // Optional IDZ
1348    /// let idz = Some("optional_identifier".as_bytes());
1349    ///
1350    /// // Encrypt the data
1351    /// match CryptoUtils::public_encrypt(data, &server_public_key_bytes, idz) {
1352    ///     Ok(encrypted_data) => println!("Encrypted data: {:?}", encrypted_data),
1353    ///     Err(e) => println!("Encryption failed: {}", e),
1354    /// }
1355    /// ```
1356    pub fn public_encrypt(
1357        data: &[u8],
1358        server_public_raw_key_bytes: &[u8],
1359        idz: Option<&[u8]>,
1360    ) -> Result<Vec<u8>, KSMRError> {
1361        // Load the server public key from raw bytes
1362        let server_public_key = PublicKey::from_sec1_bytes(server_public_raw_key_bytes)
1363            .map_err(|_| KSMRError::CryptoError("Invalid server public key!".to_string()))?;
1364
1365        // Generate a new ephemeral key
1366        let ephemeral_key = EphemeralSecret::random(&mut OsRng);
1367
1368        // Compute the shared key using ECDH (Diffie-Hellman)
1369        let shared_key = ephemeral_key.diffie_hellman(&server_public_key);
1370
1371        // If idz is provided, concatenate it with the shared secret
1372        let mut derived_key = shared_key.raw_secret_bytes().to_vec();
1373        if let Some(idz_bytes) = idz {
1374            derived_key.extend_from_slice(idz_bytes);
1375        }
1376
1377        // Hash the derived key to create a suitable AES key
1378        let mut hasher = sha2::Sha256::new();
1379        hasher.update(&derived_key);
1380        let enc_key = hasher.finalize().to_vec();
1381
1382        // Encrypt the data with AES-GCM
1383        let encrypted_data = CryptoUtils::encrypt_aes_gcm(data, &enc_key, None)
1384            .map_err(|e| KSMRError::CryptoError(format!("AES encryption failed: {}", e)))?;
1385
1386        // Get the public key bytes from the ephemeral key
1387        let eph_key_clone: p256::elliptic_curve::PublicKey<p256::NistP256> =
1388            ephemeral_key.public_key();
1389
1390        let binding_clone = EncodedPoint::from(eph_key_clone);
1391        let eph_public_key_bytes: &[u8] = binding_clone.as_bytes();
1392
1393        // Combine the ephemeral public key and the encrypted data
1394        let mut result = Vec::with_capacity(eph_public_key_bytes.len() + encrypted_data.len());
1395        result.extend_from_slice(eph_public_key_bytes.as_ref());
1396        result.extend_from_slice(&encrypted_data);
1397
1398        Ok(result)
1399    }
1400
1401    /// Computes the SHA-256 hash of a Base64-encoded string.
1402    ///
1403    /// This function takes a Base64-encoded string, decodes it into bytes,
1404    /// and computes its SHA-256 hash. The resulting hash is returned as a
1405    /// vector of bytes.
1406    ///
1407    /// # Arguments
1408    ///
1409    /// * `value` - A string slice representing the Base64-encoded input to hash.
1410    ///
1411    /// # Returns
1412    ///
1413    /// This function returns a `Result`:
1414    /// - `Ok(Vec<u8>)`: The SHA-256 hash of the decoded input as a vector of bytes.
1415    /// - `Err(KSMRError)`: An error if the input string cannot be decoded from Base64
1416    ///   or if any other error occurs during hashing.
1417    ///
1418    /// # Errors
1419    ///
1420    /// - Returns `KSMRError::CryptoError` if the input string cannot be decoded from Base64
1421    ///   or if any other error occurs during hashing.
1422    ///
1423    /// # Examples
1424    ///
1425    /// ```
1426    /// use keeper_secrets_manager_core::crypto::CryptoUtils;
1427    /// let base64_input = "SGVsbG8sIHdvcmxkIQ=="; // Base64 encoding of "Hello, world!"
1428    /// let hash = CryptoUtils::hash_of_string(base64_input);
1429    /// match hash {
1430    ///     Ok(h) => println!("SHA-256 Hash: {:?}", h),
1431    ///     Err(e) => eprintln!("Error: {}", e),
1432    /// }
1433    /// ```
1434    ///
1435    /// # Panics
1436    ///
1437    /// This function does not panic. It will return a `KSMRError` if the input is not valid Base64
1438    /// or if hashing fails.
1439    pub fn hash_of_string(value: &str) -> Result<Vec<u8>, KSMRError> {
1440        // Decode the Base64-encoded string into bytes
1441        let value_bytes = URL_SAFE_NO_PAD
1442            .decode(value)
1443            .map_err(|e| KSMRError::CryptoError(format!("Base64 decoding failed: {}", e)))?;
1444
1445        // Use sha2 crate for SHA-256 hashing
1446        let mut hasher = sha2::Sha256::new();
1447        hasher.update(&value_bytes);
1448        let hash_result = hasher.finalize();
1449
1450        Ok(hash_result.to_vec())
1451    }
1452
1453    pub fn ecies_decrypt(
1454        _server_public_key: &[u8],
1455        _ciphertext: &[u8],
1456        _priv_key_data: &[u8],
1457        _id: &[u8],
1458    ) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
1459        unimplemented!("The hashing functionality is not yet implemented.");
1460    }
1461
1462    /// Decrypts a record using the provided secret key.
1463    ///
1464    /// This function attempts to decrypt a given record. If the record is a valid UTF-8 string,
1465    /// it is first decoded from Base64. The decoded bytes are then decrypted using AES-GCM.
1466    /// If the record is not a valid UTF-8 string, it is assumed to be in bytes and is decrypted
1467    /// directly.
1468    ///
1469    /// # Arguments
1470    ///
1471    /// * `data` - A slice of bytes representing the encrypted record. This can either be a
1472    ///   Base64-encoded UTF-8 string or raw bytes.
1473    /// * `secret_key` - A slice of bytes representing the secret key used for decryption.
1474    ///
1475    /// # Returns
1476    ///
1477    /// This function returns a `Result<String, KSMRError>`. On success, it returns the
1478    /// decrypted record as a UTF-8 string. On failure, it returns an error with a description
1479    /// of the problem encountered.
1480    ///
1481    /// # Errors
1482    ///
1483    /// This function will return an error if:
1484    /// * The input data cannot be decoded from Base64, returning a `KSMRError::CryptoError` with
1485    ///   the description `"Base64 decode error: {error}"`.
1486    /// * The decryption process fails due to an incorrect key or other issues, returning a
1487    ///   `KSMRError::CryptoError` with a relevant message.
1488    /// * The resulting decrypted bytes cannot be converted to a UTF-8 string, returning a
1489    ///   `KSMRError::Utf8Error` with a description of the error.
1490    ///
1491    /// # Examples
1492    ///
1493    /// ```rust
1494    /// use keeper_secrets_manager_core::crypto::CryptoUtils;
1495    /// use base64::{engine::general_purpose::URL_SAFE_NO_PAD, Engine as _};
1496    /// let secret_key = CryptoUtils::generate_random_bytes(32); // Generate a dummy secret key
1497    /// let original_data = b"Hello, World!";
1498    /// let encrypted_data = CryptoUtils::encrypt_aes_gcm(original_data, &secret_key, None).unwrap();
1499    /// let base64_encoded = URL_SAFE_NO_PAD.encode(&encrypted_data);
1500    /// // Action
1501    /// let result = CryptoUtils::decrypt_record(base64_encoded.as_bytes(), &secret_key);
1502    /// // Assert
1503    /// assert_eq!(result.unwrap(), "Hello, World!");
1504    ///
1505    /// let result2 = CryptoUtils::decrypt_record(base64_encoded.as_bytes(), &secret_key);
1506    /// match result2 {
1507    ///     Ok(record) => println!("Decrypted record: {}", record),
1508    ///     Err(e) => eprintln!("Failed to decrypt record: {}", e),
1509    /// }
1510    /// ```
1511    ///
1512    /// # Panics
1513    ///
1514    /// This function does not panic under normal circumstances. It handles errors by returning a `KSMRError`.
1515    pub fn decrypt_record(data: &[u8], secret_key: &[u8]) -> Result<String, KSMRError> {
1516        let decrypted_data = if let Ok(s) = std::str::from_utf8(data) {
1517            // If the data is a valid UTF-8 string, decode from Base64
1518            let decoded_bytes = URL_SAFE_NO_PAD
1519                .decode(s)
1520                .map_err(|e| KSMRError::CryptoError(format!("Base64 decode error: {}", e)))?;
1521            // Decrypt the decoded bytes
1522            CryptoUtils::decrypt_aes(&decoded_bytes, secret_key)
1523                .map_err(|e| KSMRError::CryptoError(format!("AES decryption error: {}", e)))?
1524        } else {
1525            // If the data is not a valid UTF-8 string, assume it's already in bytes
1526            CryptoUtils::decrypt_aes(data, secret_key)
1527                .map_err(|e| KSMRError::CryptoError(format!("AES decryption error: {}", e)))?
1528        };
1529
1530        // Convert decrypted bytes to a UTF-8 string
1531        let record_json = String::from_utf8(decrypted_data)
1532            .map_err(|e| KSMRError::CryptoError(format!("UTF-8 conversion error: {}", e)))?;
1533        Ok(record_json)
1534    }
1535
1536    pub fn decrypt_ec(
1537        _ecc_private_key: &SecretKey,
1538        _encrypted_data_bag: &[u8],
1539    ) -> Result<Vec<u8>, Box<dyn Error>> {
1540        unimplemented!("The hashing functionality is not yet implemented.");
1541    }
1542
1543    /// Converts a Base64-encoded DER private key string to a `SecretKey`.
1544    ///
1545    /// This function takes a Base64-encoded DER representation of a private key,
1546    /// decodes it, and converts it into a `SecretKey` type suitable for cryptographic
1547    /// operations.
1548    ///
1549    /// # Arguments
1550    ///
1551    /// * `private_key_der_base64` - A string slice containing the Base64-encoded
1552    ///   DER representation of the private key.
1553    ///
1554    /// # Returns
1555    ///
1556    /// This function returns a `Result<p256::SecretKey, KSMRError>`. On success,
1557    /// it returns the corresponding `SecretKey`. On failure, it returns an error with a
1558    /// description of the problem encountered.
1559    ///
1560    /// # Errors
1561    ///
1562    /// This function will return an error if:
1563    /// * The provided Base64 string cannot be decoded. The error will be wrapped in a `KSMRError::CryptoError`.
1564    /// * The decoded bytes cannot be parsed into a `SecretKey`. The error will be wrapped in a `KSMRError::CryptoError`.
1565    ///
1566    /// # Examples
1567    ///
1568    /// ```rust
1569    /// use keeper_secrets_manager_core::crypto::CryptoUtils; // Adjust the path as necessary
1570    /// use base64::{engine::general_purpose::URL_SAFE_NO_PAD, Engine as _};
1571    /// use p256::SecretKey; // Import the SecretKey type
1572    ///
1573    /// let private_key_der_base64 = "your_base64_encoded_der_key_here"; // Replace with your Base64 DER key
1574    ///
1575    /// // Attempt to convert the Base64 DER private key to a SecretKey
1576    /// match CryptoUtils::der_base64_private_key_to_private_key(private_key_der_base64) {
1577    ///     Ok(secret_key) => println!("Successfully converted to SecretKey: {:?}", secret_key),
1578    ///     Err(e) => eprintln!("Failed to convert private key: {}", e),
1579    /// }
1580    /// ```
1581    ///
1582    /// # Panics
1583    ///
1584    /// This function does not panic under normal circumstances, but it may return an
1585    /// error if the input is invalid.
1586    pub fn der_base64_private_key_to_private_key(
1587        private_key_der_base64: &str,
1588    ) -> Result<
1589        SecretKey,
1590        // EcKey<openssl::pkey::Private> ,
1591        KSMRError,
1592    > {
1593        use p256::pkcs8::DecodePrivateKey;
1594        // Decode the Base64-encoded DER string
1595        let private_key_der_bytes = utils::base64_to_bytes(private_key_der_base64)?;
1596
1597        // Convert to SecretKey
1598        let private_key = SecretKey::from_pkcs8_der(&private_key_der_bytes).map_err(|e| {
1599            KSMRError::CryptoError(format!("Failed to convert DER to SecretKey: {}", e))
1600        })?;
1601
1602        Ok(private_key)
1603    }
1604
1605    /// Extracts the public key bytes from a Base64-encoded DER private key string.
1606    ///
1607    /// This function takes a Base64-encoded DER representation of a private key,
1608    /// decodes it, and extracts the corresponding public key bytes in uncompressed format.
1609    ///
1610    /// # Arguments
1611    ///
1612    /// * `private_key_der_base64` - A string slice containing the Base64-encoded DER private key.
1613    ///
1614    /// # Returns
1615    ///
1616    /// Returns a `Result<Vec<u8>, KSMRError>`. On success, it returns the public key bytes
1617    /// in uncompressed format. On failure, it returns a `KSMRError` with a description of the problem.
1618    ///
1619    /// # Errors
1620    ///
1621    /// This function will return an error if:
1622    /// * The provided Base64 string cannot be decoded.
1623    /// * The decoded bytes cannot be parsed into a `SecretKey`.
1624    ///
1625    /// # Examples
1626    ///
1627    /// ```
1628    /// use keeper_secrets_manager_core::crypto::CryptoUtils;
1629    /// use base64::{engine::general_purpose::URL_SAFE_NO_PAD, Engine as _};
1630    ///
1631    /// let private_key_der_base64 = "your_base64_encoded_der_key_here"; // Replace with your Base64 DER key
1632    ///
1633    /// // Attempt to extract public key bytes
1634    /// match CryptoUtils::extract_public_key_bytes(private_key_der_base64) {
1635    ///     Ok(public_key_bytes) => println!("Successfully extracted public key bytes: {:?}", public_key_bytes),
1636    ///     Err(e) => eprintln!("Failed to extract public key bytes: {}", e),
1637    /// }
1638    /// ```
1639    ///
1640    /// # Panics
1641    ///
1642    /// This function does not panic under normal circumstances, but it will return an error if
1643    /// the Base64 string is invalid or the private key cannot be parsed.
1644    pub fn extract_public_key_bytes(private_key_der_base64: &str) -> Result<Vec<u8>, KSMRError> {
1645        // Decode the Base64-encoded DER string
1646        let private_key_der_bytes = utils::base64_to_bytes(private_key_der_base64)?;
1647
1648        // Convert to SecretKey
1649        let private_key = SecretKey::from_pkcs8_der(&private_key_der_bytes)
1650            .map_err(|e| KSMRError::CryptoError(format!("Failed to load private key: {}", e)))?;
1651
1652        // Derive the public key from the private key
1653        let public_key: VerifyingKey = private_key.public_key().into();
1654
1655        // Convert public key to bytes
1656        let pub_key_bytes = public_key.to_encoded_point(false).as_ref().to_vec();
1657
1658        Ok(pub_key_bytes)
1659    }
1660
1661    /// Signs the provided data using the specified private key.
1662    ///
1663    /// This function takes a byte slice representing the data to be signed and a
1664    /// `SecretKey`. It creates a signing key from the private key and uses it
1665    /// to generate a digital signature for the data.
1666    ///
1667    /// # Arguments
1668    ///
1669    /// * `data` - A slice of bytes representing the data to be signed.
1670    /// * `private_key` - A reference to the `SecretKey` used to sign the data.
1671    ///
1672    /// # Returns
1673    ///
1674    /// This function returns a `Result<Signature, Box<dyn std::error::Error>>`. On success,
1675    /// it returns the generated `Signature`. On failure, it returns an error with a
1676    /// description of the problem encountered.
1677    ///
1678    /// # Errors
1679    ///
1680    /// This function may return an error if:
1681    /// * The signing process fails due to an invalid private key or other cryptographic issues.
1682    ///
1683    /// # Examples
1684    ///
1685    /// ```
1686    /// use keeper_secrets_manager_core::crypto::CryptoUtils; // Adjust the path as necessary
1687    /// use p256::{SecretKey, ecdsa::{SigningKey, Signature}}; // Import necessary types
1688    /// use rand::rngs::OsRng; // Use OS random number generator
1689    ///
1690    /// // Generate a dummy private key
1691    /// let private_key = SecretKey::random(&mut OsRng);
1692    /// let data = b"Hello, World!"; // Data to be signed
1693    ///
1694    /// // Attempt to sign the data
1695    /// match CryptoUtils::sign_data(data, private_key) {
1696    ///     Ok(signature) => println!("Successfully signed the data: {:?}", signature),
1697    ///     Err(e) => eprintln!("Failed to sign the data: {}", e),
1698    /// }
1699    /// ```
1700    ///
1701    /// # Panics
1702    ///
1703    /// This function does not panic under normal circumstances, but it may return an
1704    /// error if the signing process encounters issues.
1705    pub fn sign_data(
1706        data: &[u8],
1707        // private_key: EcKey<openssl::pkey::Private>
1708        private_key: SecretKey,
1709    ) -> Result<
1710        // Signature,
1711        ecdsa::der::Signature<p256::NistP256>,
1712        KSMRError,
1713    > {
1714        // Create a SigningKey from the SecretKey
1715        let signing_key: ecdsa::SigningKey<p256::NistP256> = SigningKey::from(private_key);
1716        let signature: Signature = signing_key.sign(data);
1717        Ok(signature.to_der())
1718    }
1719
1720    pub fn validate_signature(
1721        data: &[u8],             // The original data that was signed
1722        signature_bytes: &[u8],  // The signature in DER format
1723        public_key_bytes: &[u8], // The public key in uncompressed form
1724    ) -> Result<bool, KSMRError> {
1725        // Create a VerifyingKey from the public key bytes
1726        let public_key = VerifyingKey::from_sec1_bytes(public_key_bytes).map_err(|err| {
1727            KSMRError::CryptoError(format!(
1728                "Failed to load public key from sec1 bytes: {}",
1729                err
1730            ))
1731        })?;
1732
1733        // Parse the signature from bytes
1734        let signature = Signature::from_der(signature_bytes).map_err(|err| {
1735            KSMRError::CryptoError(format!(
1736                "Failed to parse signature from der while verification: {}",
1737                err
1738            ))
1739        })?;
1740
1741        // Verify the signature using the public key and data
1742        public_key.verify(data, &signature).map_err(|err| {
1743            KSMRError::CryptoError(format!("Failed to verify signature: {}", err))
1744        })?;
1745
1746        // If verification passes, return true
1747        Ok(true)
1748    }
1749}