Bug: Use `subtle` crate for constant-time comparison



Usual comparison is not safe in cryptography as is lazy (fail-fast) and makes the code potentially vulnerable to timing attacks: https://www.chosenplaintext.ca/articles/beginners-guide-constant-time-cryptography.html.
Use crates like `subtle` for constant-time comparison of secret values: https://docs.rs/subtle.

https://github.com/juspay/orca/blob/dff8b22489e36058326bee36b2c91014cdb4c9f2/crates/masking/src/strong_secret.rs#L54-L62


diff --git a/Cargo.lock b/Cargo.lock
index 9e107e0a17d..9efade25962 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1808,6 +1808,7 @@ dependencies = [
  "diesel",
  "serde",
  "serde_json",
+ "subtle",
  "zeroize",
 ]
 
@@ -3053,6 +3054,12 @@ dependencies = [
  "syn",
 ]
 
+[[package]]
+name = "subtle"
+version = "2.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
+
 [[package]]
 name = "supports-color"
 version = "1.3.1"
diff --git a/crates/common_utils/src/pii.rs b/crates/common_utils/src/pii.rs
index c6e7800ace0..97b395b26d7 100644
--- a/crates/common_utils/src/pii.rs
+++ b/crates/common_utils/src/pii.rs
@@ -21,11 +21,7 @@ where
             return WithType::fmt(val, f);
         }
 
-        f.write_str(&format!(
-            "{}{}",
-            &val_str[..6],
-            "*".repeat(val_str.len() - 6)
-        ))
+        write!(f, "{}{}", &val_str[..6], "*".repeat(val_str.len() - 6))
     }
 }
 
@@ -45,12 +41,13 @@ where
             return WithType::fmt(val, f);
         }
 
-        f.write_str(&format!(
+        write!(
+            f,
             "{}{}{}",
             &val_str[..2],
             "*".repeat(val_str.len() - 5),
             &val_str[(val_str.len() - 3)..]
-        ))
+        )
     }
 }
 */
@@ -71,12 +68,11 @@ where
             return WithType::fmt(val, f);
         }
 
-        let parts: Vec<&str> = val_str.split('@').collect();
-        if parts.len() != 2 {
-            return WithType::fmt(val, f);
+        if let Some((a, b)) = val_str.split_once('@') {
+            write!(f, "{}@{}", "*".repeat(a.len()), b)
+        } else {
+            WithType::fmt(val, f)
         }
-
-        f.write_str(&format!("{}@{}", "*".repeat(parts[0].len()), parts[1]))
     }
 }
 
@@ -102,7 +98,7 @@ where
             }
         }
 
-        f.write_str(&format!("{}.**.**.**", segments[0]))
+        write!(f, "{}.**.**.**", segments[0])
     }
 }
 
@@ -115,62 +111,62 @@ mod pii_masking_strategy_tests {
     #[test]
     fn test_valid_card_number_masking() {
         let secret: Secret<String, CardNumber> = Secret::new("1234567890987654".to_string());
-        assert_eq!("123456**********", &format!("{:?}", secret));
+        assert_eq!("123456**********", format!("{:?}", secret));
     }
 
     #[test]
     fn test_invalid_card_number_masking() {
         let secret: Secret<String, CardNumber> = Secret::new("1234567890".to_string());
-        assert_eq!("123456****", &format!("{:?}", secret));
+        assert_eq!("123456****", format!("{:?}", secret));
     }
 
     /*
     #[test]
     fn test_valid_phone_number_masking() {
         let secret: Secret<String, PhoneNumber> = Secret::new("9922992299".to_string());
-        assert_eq!("99*****299", &format!("{}", secret));
+        assert_eq!("99*****299", format!("{}", secret));
     }
 
     #[test]
     fn test_invalid_phone_number_masking() {
         let secret: Secret<String, PhoneNumber> = Secret::new("99229922".to_string());
-        assert_eq!("*** alloc::string::String ***", &format!("{}", secret));
+        assert_eq!("*** alloc::string::String ***", format!("{}", secret));
 
         let secret: Secret<String, PhoneNumber> = Secret::new("9922992299229922".to_string());
-        assert_eq!("*** alloc::string::String ***", &format!("{}", secret));
+        assert_eq!("*** alloc::string::String ***", format!("{}", secret));
     }
     */
 
     #[test]
     fn test_valid_email_masking() {
         let secret: Secret<String, Email> = Secret::new("myemail@gmail.com".to_string());
-        assert_eq!("*******@gmail.com", &format!("{:?}", secret));
+        assert_eq!("*******@gmail.com", format!("{:?}", secret));
     }
 
     #[test]
     fn test_invalid_email_masking() {
         let secret: Secret<String, Email> = Secret::new("myemailgmail.com".to_string());
-        assert_eq!("*** alloc::string::String ***", &format!("{:?}", secret));
+        assert_eq!("*** alloc::string::String ***", format!("{:?}", secret));
 
         let secret: Secret<String, Email> = Secret::new("myemail@gmail@com".to_string());
-        assert_eq!("*** alloc::string::String ***", &format!("{:?}", secret));
+        assert_eq!("*** alloc::string::String ***", format!("{:?}", secret));
     }
 
     #[test]
     fn test_valid_ip_addr_masking() {
         let secret: Secret<String, IpAddress> = Secret::new("123.23.1.78".to_string());
-        assert_eq!("123.**.**.**", &format!("{:?}", secret));
+        assert_eq!("123.**.**.**", format!("{:?}", secret));
     }
 
     #[test]
     fn test_invalid_ip_addr_masking() {
         let secret: Secret<String, IpAddress> = Secret::new("123.4.56".to_string());
-        assert_eq!("*** alloc::string::String ***", &format!("{:?}", secret));
+        assert_eq!("*** alloc::string::String ***", format!("{:?}", secret));
 
         let secret: Secret<String, IpAddress> = Secret::new("123.4567.12.4".to_string());
-        assert_eq!("*** alloc::string::String ***", &format!("{:?}", secret));
+        assert_eq!("*** alloc::string::String ***", format!("{:?}", secret));
 
         let secret: Secret<String, IpAddress> = Secret::new("123..4.56".to_string());
-        assert_eq!("*** alloc::string::String ***", &format!("{:?}", secret));
+        assert_eq!("*** alloc::string::String ***", format!("{:?}", secret));
     }
 }
diff --git a/crates/masking/Cargo.toml b/crates/masking/Cargo.toml
index 7a4bcc089ab..f20ed96ce2e 100644
--- a/crates/masking/Cargo.toml
+++ b/crates/masking/Cargo.toml
@@ -16,6 +16,7 @@ all-features = true
 rustdoc-args = ["--cfg", "docsrs"]
 
 [dependencies]
+subtle = "2.4.1"
 bytes = { version = "1", optional = true }
 diesel = { git = "https://github.com/juspay/diesel", features = ["postgres", "serde_json", "time"], optional = true, rev = "22f3f59f1db8a3f61623e4d6b375d64cd7bd3d02" }
 serde = { version = "1", features = ["derive"], optional = true }
diff --git a/crates/masking/README.md b/crates/masking/README.md
index e17a0b5443a..c2f2a249113 100644
--- a/crates/masking/README.md
+++ b/crates/masking/README.md
@@ -4,6 +4,12 @@ Personal Identifiable Information protection.
 Wrapper types and traits for secret management which help ensure they aren't accidentally copied, logged, or otherwise exposed (as much as possible), and also ensure secrets are securely wiped from memory when dropped.
 Secret-keeping library inspired by `secrecy`.
 
+This solution has such advantages over alternatives:
+- alternatives have not implemented several traits from the box which are needed
+- alternatives do not have WeakSecret and Secret differentiation
+- alternatives do not support masking strategies
+- alternatives had several minor problems
+
 ## How to use
 
 To convert non-secret variable into secret use `new()`. Sample:
@@ -19,13 +25,13 @@ To get value from secret use `expose()`. Sample:
 last4_digits: Some(card_number.expose())
 ```
 
-Most fields are under `Option`. To simplify dealing with `Option`, use `expose_cloning()`. Sample:
+Most fields are under `Option`. To simplify dealing with `Option`, use `expose_option()`. Sample:
 
 ```rust,ignore
     card_info.push_str(
         &card_detail
             .card_holder_name
-            .expose_cloning()
+            .expose_option()
             .unwrap_or_default(),
     );
 ```
@@ -38,7 +44,6 @@ Most fields are under `Option`. To simplify dealing with `Option`, use `expose_c
 <!-- ```text
 
 ├── src                        : source code
-│   ├── bachstd                : utilities
 └── tests                      : unit and integration tests
 
 ``` -->
diff --git a/crates/masking/src/abs.rs b/crates/masking/src/abs.rs
index 36789508976..e0830aa85fc 100644
--- a/crates/masking/src/abs.rs
+++ b/crates/masking/src/abs.rs
@@ -10,10 +10,10 @@ pub trait PeekInterface<S> {
     fn peek(&self) -> &S;
 }
 
-/// Interface to expose a clone of secret
-pub trait PeekOptionInterface<S> {
+/// Interface that consumes a option secret and returns the value.
+pub trait ExposeOptionInterface<S> {
     /// Expose option.
-    fn peek_cloning(&self) -> S;
+    fn expose_option(self) -> S;
 }
 
 /// Interface that consumes a secret and returns the inner value.
@@ -22,23 +22,13 @@ pub trait ExposeInterface<S> {
     fn expose(self) -> S;
 }
 
-impl<S, I> PeekOptionInterface<Option<S>> for Option<Secret<S, I>>
+impl<S, I> ExposeOptionInterface<Option<S>> for Option<Secret<S, I>>
 where
     S: Clone,
     I: crate::Strategy<S>,
 {
-    fn peek_cloning(&self) -> Option<S> {
-        self.as_ref().map(|val| val.peek().clone())
-    }
-}
-
-impl<S, I> PeekOptionInterface<S> for Secret<S, I>
-where
-    S: Clone,
-    I: crate::Strategy<S>,
-{
-    fn peek_cloning(&self) -> S {
-        self.peek().clone()
+    fn expose_option(self) -> Option<S> {
+        self.map(ExposeInterface::expose)
     }
 }
 
diff --git a/crates/masking/src/bytes.rs b/crates/masking/src/bytes.rs
index cc28b92f210..e828f8a78e0 100644
--- a/crates/masking/src/bytes.rs
+++ b/crates/masking/src/bytes.rs
@@ -14,13 +14,13 @@ use super::{PeekInterface, ZeroizableSecret};
 /// Because of the nature of how the `BytesMut` type works, it needs some special
 /// care in order to have a proper zeroizing drop handler.
 #[derive(Clone)]
-#[cfg_attr(docsrs, doc(cfg(feature = "bytes")))]
+#[cfg_attr(docsrs, cfg(feature = "bytes"))]
 pub struct SecretBytesMut(BytesMut);
 
 impl SecretBytesMut {
     /// Wrap bytes in `SecretBytesMut`
-    pub fn new(bytes: impl Into<BytesMut>) -> SecretBytesMut {
-        SecretBytesMut(bytes.into())
+    pub fn new(bytes: impl Into<BytesMut>) -> Self {
+        Self(bytes.into())
     }
 }
 
@@ -37,8 +37,8 @@ impl fmt::Debug for SecretBytesMut {
 }
 
 impl From<BytesMut> for SecretBytesMut {
-    fn from(bytes: BytesMut) -> SecretBytesMut {
-        SecretBytesMut::new(bytes)
+    fn from(bytes: BytesMut) -> Self {
+        Self::new(bytes)
     }
 }
 
diff --git a/crates/masking/src/lib.rs b/crates/masking/src/lib.rs
index 8b37a13ec3d..f9675727662 100644
--- a/crates/masking/src/lib.rs
+++ b/crates/masking/src/lib.rs
@@ -1,4 +1,5 @@
-#![cfg_attr(docsrs, feature(doc_cfg))]
+#![cfg_attr(docsrs, feature(doc_auto_cfg, doc_cfg_hide))]
+#![cfg_attr(docsrs, doc(cfg_hide(doc)))]
 #![forbid(unsafe_code)]
 #![warn(
     missing_docs,
@@ -11,7 +12,8 @@
     clippy::panicking_unwrap,
     clippy::unreachable,
     clippy::unwrap_in_result,
-    clippy::unwrap_used
+    clippy::unwrap_used,
+    clippy::use_self
 )]
 
 //!
@@ -27,7 +29,7 @@ mod strategy;
 
 pub use strategy::{Strategy, WithType, WithoutType};
 mod abs;
-pub use abs::{ExposeInterface, PeekInterface, PeekOptionInterface};
+pub use abs::{ExposeInterface, ExposeOptionInterface, PeekInterface};
 
 mod secret;
 mod strong_secret;
@@ -60,7 +62,7 @@ pub use crate::serde::{Deserialize, SerializableSecret, Serialize};
 /// `use masking::prelude::*;`
 ///
 pub mod prelude {
-    pub use super::{ExposeInterface, PeekInterface, PeekOptionInterface};
+    pub use super::{ExposeInterface, ExposeOptionInterface, PeekInterface};
 }
 
 #[cfg(feature = "diesel")]
diff --git a/crates/masking/src/secret.rs b/crates/masking/src/secret.rs
index 07e861a0e39..a5ab4103f52 100644
--- a/crates/masking/src/secret.rs
+++ b/crates/masking/src/secret.rs
@@ -31,9 +31,7 @@ use crate::{strategy::Strategy, PeekInterface};
 ///     T: fmt::Display
 /// {
 ///     fn fmt(val: &T, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-///         f.write_str(
-///             &format!("{}", val).to_ascii_lowercase()
-///         )
+///         write!(f, "{}", val.to_string().to_ascii_lowercase())
 ///     }
 /// }
 ///
@@ -42,93 +40,93 @@ use crate::{strategy::Strategy, PeekInterface};
 /// assert_eq!("hello", &format!("{:?}", my_secret));
 /// ```
 ///
-pub struct Secret<S, I = crate::WithType>
+pub struct Secret<Secret, MaskingStrategy = crate::WithType>
 where
-    I: Strategy<S>,
+    MaskingStrategy: Strategy<Secret>,
 {
-    /// Inner secret value
-    pub(crate) inner_secret: S,
-    pub(crate) marker: PhantomData<I>,
+    pub(crate) inner_secret: Secret,
+    pub(crate) masking_strategy: PhantomData<MaskingStrategy>,
 }
 
-impl<S, I> Secret<S, I>
+impl<SecretValue, MaskingStrategy> Secret<SecretValue, MaskingStrategy>
 where
-    I: Strategy<S>,
+    MaskingStrategy: Strategy<SecretValue>,
 {
     /// Take ownership of a secret value
-    pub fn new(secret: S) -> Self {
-        Secret {
+    pub fn new(secret: SecretValue) -> Self {
+        Self {
             inner_secret: secret,
-            marker: PhantomData,
+            masking_strategy: PhantomData,
         }
     }
 }
 
-impl<S, I> PeekInterface<S> for Secret<S, I>
+impl<SecretValue, MaskingStrategy> PeekInterface<SecretValue>
+    for Secret<SecretValue, MaskingStrategy>
 where
-    I: Strategy<S>,
+    MaskingStrategy: Strategy<SecretValue>,
 {
-    fn peek(&self) -> &S {
+    fn peek(&self) -> &SecretValue {
         &self.inner_secret
     }
 }
 
-impl<S, I> From<S> for Secret<S, I>
+impl<SecretValue, MaskingStrategy> From<SecretValue> for Secret<SecretValue, MaskingStrategy>
 where
-    I: Strategy<S>,
+    MaskingStrategy: Strategy<SecretValue>,
 {
-    fn from(secret: S) -> Secret<S, I> {
+    fn from(secret: SecretValue) -> Self {
         Self::new(secret)
     }
 }
 
-impl<S, I> Clone for Secret<S, I>
+impl<SecretValue, MaskingStrategy> Clone for Secret<SecretValue, MaskingStrategy>
 where
-    S: Clone,
-    I: Strategy<S>,
+    SecretValue: Clone,
+    MaskingStrategy: Strategy<SecretValue>,
 {
     fn clone(&self) -> Self {
-        Secret {
+        Self {
             inner_secret: self.inner_secret.clone(),
-            marker: PhantomData,
+            masking_strategy: PhantomData,
         }
     }
 }
 
-impl<S, I> PartialEq for Secret<S, I>
+impl<SecretValue, MaskingStrategy> PartialEq for Secret<SecretValue, MaskingStrategy>
 where
-    Self: PeekInterface<S>,
-    S: PartialEq,
-    I: Strategy<S>,
+    Self: PeekInterface<SecretValue>,
+    SecretValue: PartialEq,
+    MaskingStrategy: Strategy<SecretValue>,
 {
     fn eq(&self, other: &Self) -> bool {
         self.peek().eq(other.peek())
     }
 }
 
-impl<S, I> Eq for Secret<S, I>
+impl<SecretValue, MaskingStrategy> Eq for Secret<SecretValue, MaskingStrategy>
 where
-    Self: PeekInterface<S>,
-    S: Eq,
-    I: Strategy<S>,
+    Self: PeekInterface<SecretValue>,
+    SecretValue: Eq,
+    MaskingStrategy: Strategy<SecretValue>,
 {
 }
 
-impl<S, I> fmt::Debug for Secret<S, I>
+impl<SecretValue, MaskingStrategy> fmt::Debug for Secret<SecretValue, MaskingStrategy>
 where
-    I: Strategy<S>,
+    MaskingStrategy: Strategy<SecretValue>,
 {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        I::fmt(&self.inner_secret, f)
+        MaskingStrategy::fmt(&self.inner_secret, f)
     }
 }
 
-impl<S, I> Default for Secret<S, I>
+impl<SecretValue, MaskingStrategy> Default for Secret<SecretValue, MaskingStrategy>
 where
-    S: Default,
-    I: Strategy<S>,
+    SecretValue: Default,
+    MaskingStrategy: Strategy<SecretValue>,
 {
     fn default() -> Self {
-        S::default().into()
+        SecretValue::default().into()
     }
 }
diff --git a/crates/masking/src/serde.rs b/crates/masking/src/serde.rs
index 8903ca45160..b0f300f0879 100644
--- a/crates/masking/src/serde.rs
+++ b/crates/masking/src/serde.rs
@@ -17,7 +17,7 @@ use crate::{PeekInterface, Secret, Strategy, StrongSecret, ZeroizableSecret};
 /// via `serde` serialization.
 ///
 
-#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
+#[cfg_attr(docsrs, cfg(feature = "serde"))]
 pub trait SerializableSecret: Serialize {}
 // #[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
 // pub trait NonSerializableSecret: Serialize {}
@@ -33,7 +33,7 @@ where
     where
         D: de::Deserializer<'de>,
     {
-        T::deserialize(deserializer).map(Secret::new)
+        T::deserialize(deserializer).map(Self::new)
     }
 }
 
@@ -59,7 +59,7 @@ where
     where
         D: serde::Deserializer<'de>,
     {
-        T::deserialize(deserializer).map(StrongSecret::new)
+        T::deserialize(deserializer).map(Self::new)
     }
 }
 
diff --git a/crates/masking/src/strategy.rs b/crates/masking/src/strategy.rs
index 3d981675e75..f744ee1f4b5 100644
--- a/crates/masking/src/strategy.rs
+++ b/crates/masking/src/strategy.rs
@@ -3,14 +3,14 @@ use core::fmt;
 /// Debugging trait which is specialized for handling secret values
 pub trait Strategy<T> {
     /// Format information about the secret's type.
-    fn fmt(value: &T, fmt: &mut fmt::Formatter<'_>) -> std::fmt::Result;
+    fn fmt(value: &T, fmt: &mut fmt::Formatter<'_>) -> fmt::Result;
 }
 
 /// Debug with type
 pub struct WithType;
 
 impl<T> Strategy<T> for WithType {
-    fn fmt(_: &T, fmt: &mut fmt::Formatter<'_>) -> std::fmt::Result {
+    fn fmt(_: &T, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
         fmt.write_str("*** ")?;
         fmt.write_str(std::any::type_name::<T>())?;
         fmt.write_str(" ***")
@@ -21,18 +21,7 @@ impl<T> Strategy<T> for WithType {
 pub struct WithoutType;
 
 impl<T> Strategy<T> for WithoutType {
-    fn fmt(_: &T, fmt: &mut fmt::Formatter<'_>) -> std::fmt::Result {
+    fn fmt(_: &T, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
         fmt.write_str("*** ***")
     }
 }
-
-pub struct NoMasking;
-
-impl<T> Strategy<T> for NoMasking
-where
-    T: fmt::Display,
-{
-    fn fmt(val: &T, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fmt::Display::fmt(val, f)
-    }
-}
diff --git a/crates/masking/src/string.rs b/crates/masking/src/string.rs
index 6746ba5a832..2638fbd282e 100644
--- a/crates/masking/src/string.rs
+++ b/crates/masking/src/string.rs
@@ -23,7 +23,7 @@ where
     type Err = core::convert::Infallible;
 
     fn from_str(src: &str) -> Result<Self, Self::Err> {
-        Ok(Secret::<String, I>::new(src.to_string()))
+        Ok(Self::new(src.to_string()))
     }
 }
 
@@ -34,6 +34,6 @@ where
     type Err = core::convert::Infallible;
 
     fn from_str(src: &str) -> Result<Self, Self::Err> {
-        Ok(StrongSecret::<String, I>::new(src.to_string()))
+        Ok(Self::new(src.to_string()))
     }
 }
diff --git a/crates/masking/src/strong_secret.rs b/crates/masking/src/strong_secret.rs
index d5d6ffe639d..fd1335f6993 100644
--- a/crates/masking/src/strong_secret.rs
+++ b/crates/masking/src/strong_secret.rs
@@ -4,6 +4,7 @@
 
 use std::{fmt, marker::PhantomData};
 
+use subtle::ConstantTimeEq;
 use zeroize::{self, Zeroize as ZeroizableSecret};
 
 use crate::{strategy::Strategy, PeekInterface};
@@ -13,84 +14,106 @@ use crate::{strategy::Strategy, PeekInterface};
 ///
 /// To get access to value use method `expose()` of trait [`crate::ExposeInterface`].
 ///
-
-pub struct StrongSecret<S: ZeroizableSecret, I = crate::WithType> {
+pub struct StrongSecret<Secret: ZeroizableSecret, MaskingStrategy = crate::WithType> {
     /// Inner secret value
-    pub(crate) inner_secret: S,
-    pub(crate) marker: PhantomData<I>,
+    pub(crate) inner_secret: Secret,
+    pub(crate) masking_strategy: PhantomData<MaskingStrategy>,
 }
 
-impl<S: ZeroizableSecret, I> StrongSecret<S, I> {
+impl<Secret: ZeroizableSecret, MaskingStrategy> StrongSecret<Secret, MaskingStrategy> {
     /// Take ownership of a secret value
-    pub fn new(secret: S) -> Self {
-        StrongSecret {
+    pub fn new(secret: Secret) -> Self {
+        Self {
             inner_secret: secret,
-            marker: PhantomData,
+            masking_strategy: PhantomData,
         }
     }
 }
 
-impl<S: ZeroizableSecret, I> PeekInterface<S> for StrongSecret<S, I> {
-    fn peek(&self) -> &S {
+impl<Secret: ZeroizableSecret, MaskingStrategy> PeekInterface<Secret>
+    for StrongSecret<Secret, MaskingStrategy>
+{
+    fn peek(&self) -> &Secret {
         &self.inner_secret
     }
 }
 
-impl<S: ZeroizableSecret, I> From<S> for StrongSecret<S, I> {
-    fn from(secret: S) -> StrongSecret<S, I> {
+impl<Secret: ZeroizableSecret, MaskingStrategy> From<Secret>
+    for StrongSecret<Secret, MaskingStrategy>
+{
+    fn from(secret: Secret) -> Self {
         Self::new(secret)
     }
 }
 
-impl<S: Clone + ZeroizableSecret, I> Clone for StrongSecret<S, I> {
+impl<Secret: Clone + ZeroizableSecret, MaskingStrategy> Clone
+    for StrongSecret<Secret, MaskingStrategy>
+{
     fn clone(&self) -> Self {
-        StrongSecret {
+        Self {
             inner_secret: self.inner_secret.clone(),
-            marker: PhantomData,
+            masking_strategy: PhantomData,
         }
     }
 }
 
-impl<S: ZeroizableSecret, I> PartialEq for StrongSecret<S, I>
+impl<Secret, MaskingStrategy> PartialEq for StrongSecret<Secret, MaskingStrategy>
 where
-    Self: PeekInterface<S>,
-    S: PartialEq,
+    Self: PeekInterface<Secret>,
+    Secret: ZeroizableSecret + StrongEq,
 {
     fn eq(&self, other: &Self) -> bool {
-        self.peek().eq(other.peek())
+        StrongEq::strong_eq(self.peek(), other.peek())
     }
 }
 
-impl<S: ZeroizableSecret, I> Eq for StrongSecret<S, I>
+impl<Secret, MaskingStrategy> Eq for StrongSecret<Secret, MaskingStrategy>
 where
-    Self: PeekInterface<S>,
-    S: Eq,
+    Self: PeekInterface<Secret>,
+    Secret: ZeroizableSecret + StrongEq,
 {
 }
 
-impl<S: ZeroizableSecret, I: Strategy<S>> fmt::Debug for StrongSecret<S, I> {
+impl<Secret: ZeroizableSecret, MaskingStrategy: Strategy<Secret>> fmt::Debug
+    for StrongSecret<Secret, MaskingStrategy>
+{
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        I::fmt(&self.inner_secret, f)
+        MaskingStrategy::fmt(&self.inner_secret, f)
     }
 }
 
-impl<S: ZeroizableSecret, I: Strategy<S>> fmt::Display for StrongSecret<S, I> {
+impl<Secret: ZeroizableSecret, MaskingStrategy: Strategy<Secret>> fmt::Display
+    for StrongSecret<Secret, MaskingStrategy>
+{
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        I::fmt(&self.inner_secret, f)
+        MaskingStrategy::fmt(&self.inner_secret, f)
     }
 }
 
-impl<S: ZeroizableSecret, I> Default for StrongSecret<S, I>
+impl<Secret: ZeroizableSecret, MaskingStrategy> Default for StrongSecret<Secret, MaskingStrategy>
 where
-    S: ZeroizableSecret + Default,
+    Secret: ZeroizableSecret + Default,
 {
     fn default() -> Self {
-        S::default().into()
+        Secret::default().into()
     }
 }
 
-impl<T: ZeroizableSecret, S> Drop for StrongSecret<T, S> {
+impl<Secret: ZeroizableSecret, MaskingStrategy> Drop for StrongSecret<Secret, MaskingStrategy> {
     fn drop(&mut self) {
         self.inner_secret.zeroize();
     }
 }
+
+trait StrongEq {
+    fn strong_eq(&self, other: &Self) -> bool;
+}
+
+impl StrongEq for String {
+    fn strong_eq(&self, other: &Self) -> bool {
+        let lhs = self.as_bytes();
+        let rhs = other.as_bytes();
+
+        bool::from(lhs.ct_eq(rhs))
+    }
+}
diff --git a/crates/router/src/connector/stripe/transformers.rs b/crates/router/src/connector/stripe/transformers.rs
index 5c02f4a31b3..55b8c4dcfb4 100644
--- a/crates/router/src/connector/stripe/transformers.rs
+++ b/crates/router/src/connector/stripe/transformers.rs
@@ -8,7 +8,7 @@ use uuid::Uuid;
 
 use crate::{
     core::errors,
-    pii::{self, PeekOptionInterface, Secret},
+    pii::{self, ExposeOptionInterface, Secret},
     services,
     types::{self, api, storage::enums},
 };
@@ -174,8 +174,8 @@ impl TryFrom<&types::PaymentsAuthorizeRouterData> for PaymentIntentRequest {
                 name: shipping.address.as_mut().map(|a| {
                     format!(
                         "{} {}",
-                        a.first_name.peek_cloning().unwrap_or_default(),
-                        a.last_name.peek_cloning().unwrap_or_default()
+                        a.first_name.clone().expose_option().unwrap_or_default(),
+                        a.last_name.clone().expose_option().unwrap_or_default()
                     )
                     .into()
                 }),
@@ -183,7 +183,7 @@ impl TryFrom<&types::PaymentsAuthorizeRouterData> for PaymentIntentRequest {
                     format!(
                         "{}{}",
                         p.country_code.unwrap_or_default(),
-                        p.number.peek_cloning().unwrap_or_default()
+                        p.number.expose_option().unwrap_or_default()
                     )
                     .into()
                 }),
diff --git a/crates/router/src/core/payment_methods/cards.rs b/crates/router/src/core/payment_methods/cards.rs
index e8a41aabeb4..8f7f0f1a58c 100644
--- a/crates/router/src/core/payment_methods/cards.rs
+++ b/crates/router/src/core/payment_methods/cards.rs
@@ -490,17 +490,24 @@ impl BasiliskCardSupport {
     ) -> RouterResult<api::CardDetailFromLocker> {
         let card_number = card
             .card_number
-            .peek_cloning()
+            .clone()
+            .expose_option()
             .get_required_value("card_number")?;
         let card_exp_month = card
             .expiry_month
-            .peek_cloning()
+            .clone()
+            .expose_option()
             .get_required_value("expiry_month")?;
         let card_exp_year = card
             .expiry_year
-            .peek_cloning()
+            .clone()
+            .expose_option()
             .get_required_value("expiry_year")?;
-        let card_holder_name = card.card_holder_name.peek_cloning().unwrap_or_default();
+        let card_holder_name = card
+            .card_holder_name
+            .clone()
+            .expose_option()
+            .unwrap_or_default();
         let card_detail = api::CardDetail {
             card_number: card_number.into(),
             card_exp_month: card_exp_month.into(),
@@ -526,20 +533,28 @@ impl BasiliskCardSupport {
     ) -> RouterResult<api::CardDetailFromLocker> {
         let card_number = card
             .card_number
-            .peek_cloning()
+            .clone()
+            .expose_option()
             .get_required_value("card_number")?;
         let card_exp_month = card
             .expiry_month
-            .peek_cloning()
+            .clone()
+            .expose_option()
             .get_required_value("expiry_month")?;
         let card_exp_year = card
             .expiry_year
-            .peek_cloning()
+            .clone()
+            .expose_option()
             .get_required_value("expiry_year")?;
-        let card_holder_name = card.card_holder_name.peek_cloning().unwrap_or_default();
+        let card_holder_name = card
+            .card_holder_name
+            .clone()
+            .expose_option()
+            .unwrap_or_default();
         let card_fingerprint = card
             .card_fingerprint
-            .peek_cloning()
+            .clone()
+            .expose_option()
             .get_required_value("card_fingerprint")?;
         let value1 = payment_methods::mk_card_value1(
             card_number,
diff --git a/crates/router/src/core/payments/helpers.rs b/crates/router/src/core/payments/helpers.rs
index 9493626bbc5..2d23653f048 100644
--- a/crates/router/src/core/payments/helpers.rs
+++ b/crates/router/src/core/payments/helpers.rs
@@ -2,7 +2,7 @@ use std::borrow::Cow;
 
 // TODO : Evaluate all the helper functions ()
 use error_stack::{report, IntoReport, ResultExt};
-use masking::{PeekInterface, PeekOptionInterface};
+use masking::{ExposeOptionInterface, PeekInterface};
 use router_env::{instrument, tracing};
 use uuid::Uuid;
 
@@ -525,7 +525,7 @@ pub async fn create_customer_if_not_exist<'a, F: Clone, R>(
                     db.insert_customer(api::CreateCustomerRequest {
                         customer_id: customer_id.to_string(),
                         merchant_id: merchant_id.to_string(),
-                        name: req.name.peek_cloning(),
+                        name: req.name.expose_option(),
                         email: req.email.clone(),
                         phone: req.phone.clone(),
                         phone_country_code: req.phone_country_code.clone(),
@@ -610,17 +610,17 @@ impl Vault {
         let card = resp.card;
         let card_number = card
             .card_number
-            .peek_cloning()
+            .expose_option()
             .get_required_value("card_number")?;
         let card_exp_month = card
             .card_exp_month
-            .peek_cloning()
+            .expose_option()
             .get_required_value("expiry_month")?;
         let card_exp_year = card
             .card_exp_year
-            .peek_cloning()
+            .expose_option()
             .get_required_value("expiry_year")?;
-        let card_holder_name = card.name_on_card.peek_cloning().unwrap_or_default();
+        let card_holder_name = card.name_on_card.expose_option().unwrap_or_default();
         let card = api::PaymentMethod::Card(api::CCard {
             card_number: card_number.into(),
             card_exp_month: card_exp_month.into(),
diff --git a/crates/router/src/services/api.rs b/crates/router/src/services/api.rs
index 626b5037e82..7a5486c098e 100644
--- a/crates/router/src/services/api.rs
+++ b/crates/router/src/services/api.rs
@@ -6,7 +6,7 @@ use std::{collections::HashMap, fmt::Debug, future::Future, str, time::Instant};
 use actix_web::{body, HttpRequest, HttpResponse, Responder};
 use bytes::Bytes;
 use error_stack::{report, IntoReport, Report, ResultExt};
-use masking::PeekOptionInterface;
+use masking::ExposeOptionInterface;
 use router_env::{
     tracing::{self, instrument},
     Tag,
@@ -219,7 +219,7 @@ async fn send_request(
                     client.body(url_encoded_payload).send()
                 }
                 None => client
-                    .body(request.payload.peek_cloning().unwrap_or_default())
+                    .body(request.payload.expose_option().unwrap_or_default())
                     .send(),
             }
             .await

## Type of Change
- [x] Refactoring

## Motivation and Context
Apply suggestions from code review #65 
Closes #107 

## Checklist
- [x] I formatted the code `cargo +nightly fmt`
- [x] I addressed lints thrown by `cargo clippy`
- [x] I reviewed submitted code
