diff --git a/crates/common_utils/src/crypto.rs b/crates/common_utils/src/crypto.rs index cc9c0778d6..a0f365dd40 100644 --- a/crates/common_utils/src/crypto.rs +++ b/crates/common_utils/src/crypto.rs @@ -623,24 +623,34 @@ mod crypto_tests { #[test] fn test_gcm_aes_256_decode_message() { + // Inputs taken from AES GCM test vectors provided by NIST + // https://github.com/briansmith/ring/blob/95948b3977013aed16db92ae32e6b8384496a740/tests/aead_aes_256_gcm_tests.txt#L447-L452 + let right_secret = - hex::decode("000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f") + hex::decode("feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308") .expect("Secret decoding"); let wrong_secret = - hex::decode("000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0e") + hex::decode("feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308309") .expect("Secret decoding"); let message = - hex::decode("0A3471C72D9BE49A8520F79C66BBD9A12FF9").expect("Message decoding"); + // The three parts of the message are the nonce, ciphertext and tag from the test vector + hex::decode( + "cafebabefacedbaddecaf888\ + 522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015ad\ + b094dac5d93471bdec1a502270e3cc6c" + ).expect("Message decoding"); - let algorithm = super::GcmAes256 { - // nonce: nonce.to_vec(), - }; + let algorithm = super::GcmAes256; let decoded = algorithm .decode_message(&right_secret, message.clone().into()) .expect("Decoded message"); - assert_eq!(decoded, r#"{"type":"PAYMENT"}"#.as_bytes()); + assert_eq!( + decoded, + hex::decode("d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255") + .expect("Decoded plaintext message") + ); let err_decoded = algorithm.decode_message(&wrong_secret, message.into()); diff --git a/crates/redis_interface/src/lib.rs b/crates/redis_interface/src/lib.rs index ee00229a6c..b06cc6c274 100644 --- a/crates/redis_interface/src/lib.rs +++ b/crates/redis_interface/src/lib.rs @@ -6,12 +6,11 @@ //! //! # Examples //! ``` -//! pub mod types; -//! use self::types; +//! use redis_interface::{types::RedisSettings, RedisConnectionPool}; //! //! #[tokio::main] -//! fn main() -> Result<(), Box> { -//! let redis_conn = RedisConnectionPool::new(types::RedisSettings::default()).await; +//! async fn main() { +//! let redis_conn = RedisConnectionPool::new(&RedisSettings::default()).await; //! // ... redis_conn ready to use //! } //! ``` diff --git a/crates/router/src/core/payment_methods/transformers.rs b/crates/router/src/core/payment_methods/transformers.rs index f5a7babf2a..6e4b43593a 100644 --- a/crates/router/src/core/payment_methods/transformers.rs +++ b/crates/router/src/core/payment_methods/transformers.rs @@ -173,14 +173,14 @@ pub async fn get_decrypted_response_payload( jwe_body: encryption::JweBody, ) -> CustomResult { #[cfg(feature = "kms")] - let public_key = jwekey.jwekey.peek().vault_encryption_key.clone(); + let public_key = jwekey.jwekey.peek().vault_encryption_key.as_bytes(); #[cfg(feature = "kms")] - let private_key = jwekey.jwekey.peek().vault_private_key.clone(); + let private_key = jwekey.jwekey.peek().vault_private_key.as_bytes(); #[cfg(not(feature = "kms"))] - let public_key = jwekey.vault_encryption_key.to_owned(); + let public_key = jwekey.vault_encryption_key.as_bytes(); #[cfg(not(feature = "kms"))] - let private_key = jwekey.vault_private_key.to_owned(); + let private_key = jwekey.vault_private_key.as_bytes(); let jwt = get_dotted_jwe(jwe_body); let alg = jwe::RSA_OAEP; @@ -200,7 +200,7 @@ pub async fn get_decrypted_response_payload( .change_context(errors::VaultError::ResponseDeserializationFailed)?; let jws_body = get_dotted_jws(jws); - encryption::verify_sign(jws_body, &public_key) + encryption::verify_sign(jws_body, public_key) .change_context(errors::VaultError::SaveCardFailed) .attach_printable("Jws Decryption failed for JwsBody for vault") } @@ -226,10 +226,10 @@ pub async fn mk_basilisk_req( .change_context(errors::VaultError::SaveCardFailed)?; #[cfg(feature = "kms")] - let public_key = jwekey.jwekey.peek().vault_encryption_key.clone(); + let public_key = jwekey.jwekey.peek().vault_encryption_key.as_bytes(); #[cfg(not(feature = "kms"))] - let public_key = jwekey.vault_encryption_key.to_owned(); + let public_key = jwekey.vault_encryption_key.as_bytes(); let jwe_encrypted = encryption::encrypt_jwe(&payload, public_key) .await @@ -281,10 +281,10 @@ pub async fn mk_add_card_request_hs( .change_context(errors::VaultError::RequestEncodingFailed)?; #[cfg(feature = "kms")] - let private_key = jwekey.jwekey.peek().vault_private_key.clone(); + let private_key = jwekey.jwekey.peek().vault_private_key.as_bytes(); #[cfg(not(feature = "kms"))] - let private_key = jwekey.vault_private_key.to_owned(); + let private_key = jwekey.vault_private_key.as_bytes(); let jws = encryption::jws_sign_payload(&payload, &locker.locker_signing_key_id, private_key) .await @@ -427,10 +427,10 @@ pub async fn mk_get_card_request_hs( .change_context(errors::VaultError::RequestEncodingFailed)?; #[cfg(feature = "kms")] - let private_key = jwekey.jwekey.peek().vault_private_key.clone(); + let private_key = jwekey.jwekey.peek().vault_private_key.as_bytes(); #[cfg(not(feature = "kms"))] - let private_key = jwekey.vault_private_key.to_owned(); + let private_key = jwekey.vault_private_key.as_bytes(); let jws = encryption::jws_sign_payload(&payload, &locker.locker_signing_key_id, private_key) .await @@ -507,10 +507,10 @@ pub async fn mk_delete_card_request_hs( .change_context(errors::VaultError::RequestEncodingFailed)?; #[cfg(feature = "kms")] - let private_key = jwekey.jwekey.peek().vault_private_key.clone(); + let private_key = jwekey.jwekey.peek().vault_private_key.as_bytes(); #[cfg(not(feature = "kms"))] - let private_key = jwekey.vault_private_key.to_owned(); + let private_key = jwekey.vault_private_key.as_bytes(); let jws = encryption::jws_sign_payload(&payload, &locker.locker_signing_key_id, private_key) .await diff --git a/crates/router/src/core/payments/helpers.rs b/crates/router/src/core/payments/helpers.rs index 2323056991..319b970207 100644 --- a/crates/router/src/core/payments/helpers.rs +++ b/crates/router/src/core/payments/helpers.rs @@ -2114,10 +2114,15 @@ pub async fn get_merchant_connector_account( )?; #[cfg(feature = "kms")] - let private_key = state.kms_secrets.jwekey.peek().tunnel_private_key.clone(); + let private_key = state + .kms_secrets + .jwekey + .peek() + .tunnel_private_key + .as_bytes(); #[cfg(not(feature = "kms"))] - let private_key = state.conf.jwekey.tunnel_private_key.to_owned(); + let private_key = state.conf.jwekey.tunnel_private_key.as_bytes(); let decrypted_mca = services::decrypt_jwe(mca_config.config.as_str(), services::KeyIdCheck::SkipKeyIdCheck, private_key, jwe::RSA_OAEP_256) .await diff --git a/crates/router/src/db/merchant_connector_account.rs b/crates/router/src/db/merchant_connector_account.rs index 5f25d43c92..18358ae955 100644 --- a/crates/router/src/db/merchant_connector_account.rs +++ b/crates/router/src/db/merchant_connector_account.rs @@ -582,6 +582,7 @@ mod merchant_connector_account_cache_tests { #[allow(clippy::unwrap_used)] #[tokio::test] + #[ignore = "blocked on MockDb implementation of merchant key store"] async fn test_connector_label_cache() { let db = MockDb::new(&Default::default()).await; diff --git a/crates/router/src/services/encryption.rs b/crates/router/src/services/encryption.rs index 9079afceac..acea96f866 100644 --- a/crates/router/src/services/encryption.rs +++ b/crates/router/src/services/encryption.rs @@ -119,7 +119,7 @@ pub fn decrypt(mut data: Vec, key: &[u8]) -> CustomResult, ) -> CustomResult { let alg = jwe::RSA_OAEP_256; let enc = "A256GCM"; @@ -146,7 +146,7 @@ pub enum KeyIdCheck<'a> { pub async fn decrypt_jwe( jwt: &str, key_ids: KeyIdCheck<'_>, - private_key: String, + private_key: impl AsRef<[u8]>, alg: jwe::alg::rsaes::RsaesJweAlgorithm, ) -> CustomResult { if let KeyIdCheck::RequestResponseKeyId((req_key_id, resp_key_id)) = key_ids { @@ -176,7 +176,7 @@ pub async fn decrypt_jwe( pub async fn jws_sign_payload( payload: &[u8], kid: &str, - private_key: String, + private_key: impl AsRef<[u8]>, ) -> CustomResult { let alg = jws::RS256; let mut src_header = jws::JwsHeader::new(); @@ -195,7 +195,7 @@ pub async fn jws_sign_payload( pub fn verify_sign( jws_body: String, - key: &String, + key: impl AsRef<[u8]>, ) -> CustomResult { let alg = jws::RS256; let input = jws_body.as_bytes(); @@ -220,10 +220,93 @@ mod tests { #![allow(clippy::unwrap_used, clippy::expect_used)] use super::*; - use crate::{ - configs::settings, - utils::{self, ValueExt}, - }; + use crate::utils::{self, ValueExt}; + + // Keys used for tests + // Can be generated using the following commands: + // `openssl genrsa -out private_key.pem 2048` + // `openssl rsa -in private_key.pem -pubout -out public_key.pem` + const ENCRYPTION_KEY: &str = "\ +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwa6siKaSYqD1o4J3AbHq +Km8oVTvep7GoN/C45qY60C7DO72H1O7Ujt6ZsSiK83EyI0CaUg3ORPS3ayobFNmu +zR366ckK8GIf3BG7sVI6u/9751z4OvBHZMM9JFWa7Bx/RCPQ8aeM+iJoqf9auuQm +3NCTlfaZJif45pShswR+xuZTR/bqnsOSP/MFROI9ch0NE7KRogy0tvrZe21lP24i +Ro2LJJG+bYshxBddhxQf2ryJ85+/Trxdu16PunodGzCl6EMT3bvb4ZC41i15omqU +aXXV1Z1wYUhlsO0jyd1bVvjyuE/KE1TbBS0gfR/RkacODmmE2zEdZ0EyyiXwqkmc +oQIDAQAB +-----END PUBLIC KEY----- +"; + const DECRYPTION_KEY: &str = "\ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAwa6siKaSYqD1o4J3AbHqKm8oVTvep7GoN/C45qY60C7DO72H +1O7Ujt6ZsSiK83EyI0CaUg3ORPS3ayobFNmuzR366ckK8GIf3BG7sVI6u/9751z4 +OvBHZMM9JFWa7Bx/RCPQ8aeM+iJoqf9auuQm3NCTlfaZJif45pShswR+xuZTR/bq +nsOSP/MFROI9ch0NE7KRogy0tvrZe21lP24iRo2LJJG+bYshxBddhxQf2ryJ85+/ +Trxdu16PunodGzCl6EMT3bvb4ZC41i15omqUaXXV1Z1wYUhlsO0jyd1bVvjyuE/K +E1TbBS0gfR/RkacODmmE2zEdZ0EyyiXwqkmcoQIDAQABAoIBAEavZwxgLmCMedl4 +zdHyipF+C+w/c10kO05fLjwPQrujtWDiJOaTW0Pg/ZpoP33lO/UdqLR1kWgdH6ue +rE+Jun/lhyM3WiSsyw/X8PYgGotuDFw90+I+uu+NSY0vKOEu7UuC/siS66KGWEhi +h0xZ480G2jYKz43bXL1aVUEuTM5tsjtt0a/zm08DEluYwrmxaaTvHW2+8FOn3z8g +UMClV2mN9X3rwlRhKAI1RVlymV95LmkTgzA4wW/M4j0kk108ouY8bo9vowoqidpo +0zKGfnqbQCIZP1QY6Xj8f3fqMY7IrFDdFHCEBXs29DnRz4oS8gYCAUXDx5iEVa1R +KVxic5kCgYEA4vGWOANuv+RoxSnNQNnZjqHKjhd+9lXARnK6qVVXcJGTps72ILGJ +CNrS/L6ndBePQGhtLtVyrvtS3ZvYhsAzJeMeeFUSZhQ2SOP5SCFWRnLJIBObJ5/x +fFwrCbp38qsEBlqJXue4JQCOxqO4P6YYUmeE8fxLPmdVNWq5fNe2YtsCgYEA2nrl +iMfttvNfQGX4pB3yEh/eWwqq4InFQdmWVDYPKJFG4TtUKJ48vzQXJqKfCBZ2q387 +bH4KaKNWD7rYz4NBfE6z6lUc8We9w1tjVaqs5omBKUuovz8/8miUtxf2W5T2ta1/ +zl9NyQ57duO423PeaCgPKKz3ftaxlz8G1CKYMTMCgYEAqkR7YhchNpOWD6cnOeq4 +kYzNvgHe3c7EbZaSeY1wByMR1mscura4i44yEjKwzCcI8Vfn4uV+H86sA1xz/dWi +CmD2cW3SWgf8GoAAfZ+VbVGdmJVdKUOVGKrGF4xxhf3NDT9MJYpQ3GIovNwE1qw1 +P04vrqaNhYpdobAq7oGhc1UCgYAkimNzcgTHEYM/0Q453KxM7bmRvoH/1esA7XRg +Fz6HyWxyZSrZNEXysLKiipZQkvk8C6aTqazx/Ud6kASNCGXedYdPzPZvRauOTe2a +OVZ7pEnO71GE0v5N+8HLsZ1JieuNTTxP9s6aruplYwba5VEwWGrYob0vIJdJNYhd +2H9d0wKBgFzqGPvG8u1lVOLYDU9BjhA/3l00C97WHIG0Aal70PVyhFhm5ILNSHU1 +Sau7H1Bhzy5G7rwt05LNpU6nFcAGVaZtzl4/+FYfYIulubYjuSEh72yuBHHyvi1/ +4Zql8DXhF5kkKx75cMcIxZ/ceiRiQyjzYv3LoTTADHHjzsiBEiQY +-----END RSA PRIVATE KEY----- +"; + + const SIGNATURE_VERIFICATION_KEY: &str = "\ +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5Z/K0JWds8iHhWCa+rj0 +rhOQX1nVs/ArQ1D0vh3UlSPR2vZUTrkdP7i3amv4d2XDC+3+5/YWExTkpxqnfl1T +9J37leN2guAARed6oYoTDEP/OoKtnUrKK2xk/+V5DNOWcRiSpcCrJOOIEoACOlPI +rXQSg16KDZQb0QTMntnsiPIJDbsOGcdKytRAcNaokiKLnia1v13N3bk6dSplrj1Y +zawslZfgqD0eov4FjzBMoA19yNtlVLLf6kOkLcFQjTKXJLP1tLflLUBPTg8fm9wg +APK2BjMQ2AMkUxx0ubbtw/9CeJ+bFWrqGnEhlvfDMlyAV77sAiIdQ4mXs3TLcLb/ +AQIDAQAB +-----END PUBLIC KEY----- +"; + const SIGNING_KEY: &str = "\ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEA5Z/K0JWds8iHhWCa+rj0rhOQX1nVs/ArQ1D0vh3UlSPR2vZU +TrkdP7i3amv4d2XDC+3+5/YWExTkpxqnfl1T9J37leN2guAARed6oYoTDEP/OoKt +nUrKK2xk/+V5DNOWcRiSpcCrJOOIEoACOlPIrXQSg16KDZQb0QTMntnsiPIJDbsO +GcdKytRAcNaokiKLnia1v13N3bk6dSplrj1YzawslZfgqD0eov4FjzBMoA19yNtl +VLLf6kOkLcFQjTKXJLP1tLflLUBPTg8fm9wgAPK2BjMQ2AMkUxx0ubbtw/9CeJ+b +FWrqGnEhlvfDMlyAV77sAiIdQ4mXs3TLcLb/AQIDAQABAoIBAGNekD1N0e5AZG1S +zh6cNb6zVrH8xV9WGtLJ0PAJJrrXwnQYT4m10DOIM0+Jo/+/ePXLq5kkRI9DZmPu +Q/eKWc+tInfN9LZUS6n0r3wCrZWMQ4JFlO5RtEWwZdDbtFPZqOwObz/treKL2JHw +9YXaRijR50UUf3e61YLRqd9AfX0RNuuG8H+WgU3Gwuh5TwRnljM3JGaDPHsf7HLS +tNkqJuByp26FEbOLTokZDbHN0sy7/6hufxnIS9AK4vp8y9mZAjghG26Rbg/H71mp +Z+Q6P1y7xdgAKbhq7usG3/o4Y1e9wnghHvFS7DPwGekHQH2+LsYNEYOir1iRjXxH +GUXOhfUCgYEA+cR9jONQFco8Zp6z0wdGlBeYoUHVMjThQWEblWL2j4RG/qQd/y0j +uhVeU0/PmkYK2mgcjrh/pgDTtPymc+QuxBi+lexs89ppuJIAgMvLUiJT67SBHguP +l4+oL9U78KGh7PfJpMKH+Pk5yc1xucAevk0wWmr5Tz2vKRDavFTPV+MCgYEA61qg +Y7yN0cDtxtqlZdMC8BJPFCQ1+s3uB0wetAY3BEKjfYc2O/4sMbixXzt5PkZqZy96 +QBUBxhcM/rIolpM3nrgN7h1nmJdk9ljCTjWoTJ6fDk8BUh8+0GrVhTbe7xZ+bFUN +UioIqvfapr/q/k7Ah2mCBE04wTZFry9fndrH2ssCgYEAh1T2Cj6oiAX6UEgxe2h3 +z4oxgz6efAO3AavSPFFQ81Zi+VqHflpA/3TQlSerfxXwj4LV5mcFkzbjfy9eKXE7 +/bjCm41tQ3vWyNEjQKYr1qcO/aniRBtThHWsVa6eObX6fOGN+p4E+txfeX693j3A +6q/8QSGxUERGAmRFgMIbTq0CgYAmuTeQkXKII4U75be3BDwEgg6u0rJq/L0ASF74 +4djlg41g1wFuZ4if+bJ9Z8ywGWfiaGZl6s7q59oEgg25kKljHQd1uTLVYXuEKOB3 +e86gJK0o7ojaGTf9lMZi779IeVv9uRTDAxWAA93e987TXuPAo/R3frkq2SIoC9Rg +paGidwKBgBqYd/iOJWsUZ8cWEhSE1Huu5rDEpjra8JPXHqQdILirxt1iCA5aEQou +BdDGaDr8sepJbGtjwTyiG8gEaX1DD+KsF2+dQRQdQfcYC40n8fKkvpFwrKjDj1ac +VuY3OeNxi+dC2r7HppP3O/MJ4gX/RJJfSrcaGP8/Ke1W5+jE97Qy +-----END RSA PRIVATE KEY----- +"; fn generate_key() -> [u8; 32] { let key: [u8; 32] = rand::random(); @@ -241,35 +324,23 @@ mod tests { } #[actix_rt::test] - #[ignore] async fn test_jwe() { - let conf = settings::Settings::new().unwrap(); - let jwt = encrypt_jwe( - "request_payload".as_bytes(), - conf.jwekey.locker_encryption_key1.to_owned(), - ) - .await - .unwrap(); + let jwt = encrypt_jwe("request_payload".as_bytes(), ENCRYPTION_KEY) + .await + .unwrap(); let alg = jwe::RSA_OAEP_256; - let payload = decrypt_jwe( - &jwt, - KeyIdCheck::SkipKeyIdCheck, - conf.jwekey.locker_decryption_key1.to_owned(), - alg, - ) - .await - .unwrap(); + let payload = decrypt_jwe(&jwt, KeyIdCheck::SkipKeyIdCheck, DECRYPTION_KEY, alg) + .await + .unwrap(); assert_eq!("request_payload".to_string(), payload) } #[actix_rt::test] - #[ignore] async fn test_jws() { - let conf = settings::Settings::new().unwrap(); - let jwt = jws_sign_payload("jws payload".as_bytes(), "1", conf.jwekey.vault_private_key) + let jwt = jws_sign_payload("jws payload".as_bytes(), "1", SIGNING_KEY) .await .unwrap(); - let payload = verify_sign(jwt, &conf.jwekey.vault_encryption_key).unwrap(); + let payload = verify_sign(jwt, SIGNATURE_VERIFICATION_KEY).unwrap(); assert_eq!("jws payload".to_string(), payload) } }