chore: merging back release v0.3.0 back to main (#636) (#655)

Co-authored-by: Sangamesh Kulkarni <59434228+Sangamesh26@users.noreply.github.com>
Co-authored-by: ItsMeShashank <shashank.attarde@juspay.in>
Co-authored-by: Abhishek <abhishek.marrivagu@juspay.in>
Co-authored-by: Jagan <jaganelavarasan@gmail.com>
Co-authored-by: SamraatBansal <55536657+SamraatBansal@users.noreply.github.com>
Co-authored-by: Sampras Lopes <lsampras@protonmail.com>
This commit is contained in:
Arun Raj M
2023-02-26 13:55:17 +05:30
committed by GitHub
parent 7792de55ef
commit f3224cc4df
74 changed files with 5979 additions and 355 deletions

View File

@ -26,6 +26,7 @@ signal-hook = "0.3.14"
tokio = { version = "1.25.0", features = ["macros", "rt-multi-thread"] }
thiserror = "1.0.38"
time = { version = "0.3.17", features = ["serde", "serde-well-known", "std"] }
md5 = "0.7.0"
# First party crates
masking = { version = "0.1.0", path = "../masking" }

View File

@ -1,5 +1,6 @@
//! Utilities for cryptographic algorithms
use error_stack::{IntoReport, ResultExt};
use md5;
use ring::{aead, hmac};
use crate::errors::{self, CustomResult};
@ -219,6 +220,10 @@ impl DecodeMessage for GcmAes256 {
#[derive(Debug)]
pub struct Sha512;
/// Secure Hash Algorithm 256
#[derive(Debug)]
pub struct Sha256;
/// Trait for generating a digest for SHA
pub trait GenerateDigest {
/// takes a message and creates a digest for it
@ -231,6 +236,37 @@ impl GenerateDigest for Sha512 {
Ok(digest.as_ref().to_vec())
}
}
/// MD5 hash function
#[derive(Debug)]
pub struct Md5;
impl GenerateDigest for Md5 {
fn generate_digest(&self, message: &[u8]) -> CustomResult<Vec<u8>, errors::CryptoError> {
let digest = md5::compute(message);
Ok(digest.as_ref().to_vec())
}
}
impl VerifySignature for Md5 {
fn verify_signature(
&self,
_secret: &[u8],
signature: &[u8],
msg: &[u8],
) -> CustomResult<bool, errors::CryptoError> {
let hashed_digest = Self
.generate_digest(msg)
.change_context(errors::CryptoError::SignatureVerificationFailed)?;
Ok(hashed_digest == signature)
}
}
impl GenerateDigest for Sha256 {
fn generate_digest(&self, message: &[u8]) -> CustomResult<Vec<u8>, errors::CryptoError> {
let digest = ring::digest::digest(&ring::digest::SHA256, message);
Ok(digest.as_ref().to_vec())
}
}
/// Generate a random string using a cryptographically secure pseudo-random number generator
/// (CSPRNG). Typically used for generating (readable) keys and passwords.
@ -256,6 +292,7 @@ pub fn generate_cryptographically_secure_random_bytes<const N: usize>() -> [u8;
mod crypto_tests {
#![allow(clippy::expect_used)]
use super::{DecodeMessage, EncodeMessage, SignMessage, VerifySignature};
use crate::crypto::GenerateDigest;
#[test]
fn test_hmac_sha256_sign_message() {
@ -387,4 +424,39 @@ mod crypto_tests {
assert!(err_decoded.is_err());
}
#[test]
fn test_md5_digest() {
let message = "abcdefghijklmnopqrstuvwxyz".as_bytes();
assert_eq!(
format!(
"{}",
hex::encode(super::Md5.generate_digest(message).expect("Digest"))
),
"c3fcd3d76192e4007dfb496cca67e13b"
);
}
#[test]
fn test_md5_verify_signature() {
let right_signature =
hex::decode("c3fcd3d76192e4007dfb496cca67e13b").expect("signature decoding");
let wrong_signature =
hex::decode("d5550730377011948f12cc28889bee590d2a5434d6f54b87562f2dbc2657823f")
.expect("Wrong signature decoding");
let secret = "".as_bytes();
let data = "abcdefghijklmnopqrstuvwxyz".as_bytes();
let right_verified = super::Md5
.verify_signature(secret, &right_signature, data)
.expect("Right signature verification result");
assert!(right_verified);
let wrong_verified = super::Md5
.verify_signature(secret, &wrong_signature, data)
.expect("Wrong signature verification result");
assert!(!wrong_verified);
}
}

View File

@ -49,6 +49,28 @@ pub mod date_time {
(result, start.elapsed().as_seconds_f64() * 1000f64)
}
/// Prefix the date field with zero if it has single digit Eg: 1 -> 01
fn prefix_zero(input: u8) -> String {
if input < 10 {
return "0".to_owned() + input.to_string().as_str();
}
input.to_string()
}
/// Return the current date and time in UTC with the format YYYYMMDDHHmmss Eg: 20191105081132
pub fn date_as_yyyymmddhhmmss() -> String {
let now = OffsetDateTime::now_utc();
format!(
"{}{}{}{}{}{}",
now.year(),
prefix_zero(u8::from(now.month())),
prefix_zero(now.day()),
prefix_zero(now.hour()),
prefix_zero(now.minute()),
prefix_zero(now.second())
)
}
/// Return the current date and time in UTC with the format [year]-[month]-[day]T[hour]:[minute]:[second].mmmZ Eg: 2023-02-15T13:33:18.898Z
pub fn date_as_yyyymmddthhmmssmmmz() -> Result<String, time::error::Format> {
const ISO_CONFIG: EncodedConfig = Config::DEFAULT