mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-27 19:46:48 +08:00
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:
@ -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" }
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
Reference in New Issue
Block a user