@@ -623,6 +623,64 @@ pub type EncryptableName = Encryptable<Secret<String>>;
623623/// Type alias for `Encryptable<Secret<String>>` used for `email` field
624624pub type EncryptableEmail = Encryptable < Secret < String , pii:: EmailStrategy > > ;
625625
626+ /// Triple DES (3DES) encryption using EDE3 CBC mode
627+ /// Used by connectors like Redsys for signature generation
628+ pub struct TripleDesEde3CBC {
629+ padding : common_enums:: CryptoPadding ,
630+ iv : Vec < u8 > ,
631+ }
632+
633+ impl TripleDesEde3CBC {
634+ /// Triple DES key length (24 bytes = 192 bits)
635+ pub const TRIPLE_DES_KEY_LENGTH : usize = 24 ;
636+ /// Triple DES IV length (8 bytes = 64 bits)
637+ pub const TRIPLE_DES_IV_LENGTH : usize = 8 ;
638+
639+ /// Create a new TripleDesEde3CBC instance
640+ ///
641+ /// # Arguments
642+ /// * `padding` - Optional padding scheme (defaults to PKCS7)
643+ /// * `iv` - Initialization vector (must be 8 bytes)
644+ ///
645+ /// # Errors
646+ /// Returns `CryptoError::InvalidIvLength` if IV is not 8 bytes
647+ pub fn new (
648+ padding : Option < common_enums:: CryptoPadding > ,
649+ iv : Vec < u8 > ,
650+ ) -> CustomResult < Self , errors:: CryptoError > {
651+ if iv. len ( ) != Self :: TRIPLE_DES_IV_LENGTH {
652+ Err ( errors:: CryptoError :: InvalidIvLength ) ?
653+ } ;
654+ let padding = padding. unwrap_or ( common_enums:: CryptoPadding :: PKCS7 ) ;
655+ Ok ( Self { iv, padding } )
656+ }
657+ }
658+
659+ impl EncodeMessage for TripleDesEde3CBC {
660+ fn encode_message (
661+ & self ,
662+ secret : & [ u8 ] ,
663+ msg : & [ u8 ] ,
664+ ) -> CustomResult < Vec < u8 > , errors:: CryptoError > {
665+ if secret. len ( ) != Self :: TRIPLE_DES_KEY_LENGTH {
666+ Err ( errors:: CryptoError :: InvalidKeyLength ) ?
667+ }
668+ let mut buffer = msg. to_vec ( ) ;
669+
670+ // Apply zero padding if specified
671+ if let common_enums:: CryptoPadding :: ZeroPadding = self . padding {
672+ let pad_len = Self :: TRIPLE_DES_IV_LENGTH - ( buffer. len ( ) % Self :: TRIPLE_DES_IV_LENGTH ) ;
673+ if pad_len != Self :: TRIPLE_DES_IV_LENGTH {
674+ buffer. extend ( vec ! [ 0u8 ; pad_len] ) ;
675+ }
676+ } ;
677+
678+ let cipher = openssl:: symm:: Cipher :: des_ede3_cbc ( ) ;
679+ openssl:: symm:: encrypt ( cipher, secret, Some ( & self . iv ) , & buffer)
680+ . change_context ( errors:: CryptoError :: EncodingFailed )
681+ }
682+ }
683+
626684#[ cfg( test) ]
627685mod crypto_tests {
628686 #![ allow( clippy:: expect_used) ]
0 commit comments