diff --git a/native/cpp/CommonCpp/CryptoTools/opaque-ke-cxx/src/lib.rs b/native/cpp/CommonCpp/CryptoTools/opaque-ke-cxx/src/lib.rs --- a/native/cpp/CommonCpp/CryptoTools/opaque-ke-cxx/src/lib.rs +++ b/native/cpp/CommonCpp/CryptoTools/opaque-ke-cxx/src/lib.rs @@ -4,15 +4,15 @@ use opaque_ke::ciphersuite::CipherSuite; use opaque_ke::errors::{InternalPakeError, ProtocolError}; use opaque_ke::hash::Hash; +use opaque_ke::keypair::Key; use opaque_ke::slow_hash::SlowHash; use opaque_ke::{ - ClientLogin, ClientLoginFinishParameters, ClientLoginFinishResult, ClientLoginStartParameters, - ClientLoginStartResult, ClientRegistration, ClientRegistrationFinishParameters, - ClientRegistrationFinishResult, ClientRegistrationStartResult, CredentialResponse, - RegistrationResponse, + ClientLogin, ClientLoginFinishParameters, ClientLoginStartParameters, ClientRegistration, + ClientRegistrationFinishParameters, CredentialFinalization, CredentialRequest, + CredentialResponse, RegistrationRequest, RegistrationResponse, RegistrationUpload, ServerLogin, + ServerLoginStartParameters, ServerRegistration, }; use rand::rngs::OsRng; -use std::ops::Deref; struct Cipher; @@ -40,16 +40,25 @@ #[cxx::bridge] mod ffi { + struct ClientRegistrationStartResult { + message: Vec, + state: Vec, + } + #[derive(Debug)] - struct MessageState { + struct ClientRegistrationFinishResult { + message: Vec, + } + + struct ClientLoginStartResult { message: Vec, state: Vec, } #[derive(Debug)] - struct MessageSession { + struct ClientLoginFinishResult { message: Vec, - session: Vec, + session_key: Vec, } struct ServerKeyPair { @@ -57,120 +66,195 @@ private: Vec, } + struct ServerRegistrationStartResult { + message: Vec, + state: Vec, + } + + struct ServerRegistrationFinishResult { + password_file: Vec, + } + + struct ServerLoginStartResult { + message: Vec, + state: Vec, + } + + struct ServerLoginFinishResult { + session_key: Vec, + } + extern "Rust" { - fn client_register_cxx(password: String) -> Result; + fn client_register_cxx(password: String) -> Result; fn client_register_finish_cxx( client_register_state: Vec, server_message: Vec, - ) -> Result>; - fn client_login_cxx(password: String) -> Result; + ) -> Result; + fn client_login_cxx(password: String) -> Result; fn client_login_finish_cxx( client_login_state: Vec, server_message: Vec, - ) -> Result; + ) -> Result; fn server_kp() -> ServerKeyPair; + fn server_register_cxx( + registration_request: Vec, + server_public_key: Vec, + ) -> Result; + fn server_register_finish_cxx( + server_register_state: Vec, + client_message: Vec, + ) -> Result; + fn server_login_cxx( + password_file: Vec, + server_private_key: Vec, + login_request: Vec, + ) -> Result; + fn server_login_finish_cxx( + server_login_state: Vec, + client_message: Vec, + ) -> Result; } } -fn client_register_cxx(password: String) -> Result { - let c = client_register(&password)?; - - let message_bytes = c.message.serialize(); - let state_bytes = c.state.serialize(); +fn client_register_cxx( + password: String, +) -> Result { + let mut client_rng = OsRng; + let c = ClientRegistration::::start(&mut client_rng, password.as_bytes())?; - Ok(ffi::MessageState { - message: message_bytes, - state: state_bytes, + Ok(ffi::ClientRegistrationStartResult { + message: c.message.serialize(), + state: c.state.serialize(), }) } fn client_register_finish_cxx( client_register_state: Vec, server_message: Vec, -) -> Result, ProtocolError> { +) -> Result { let client_register_state = ClientRegistration::::deserialize(&client_register_state)?; let server_message = RegistrationResponse::::deserialize(&server_message)?; - let c = client_register_finish(client_register_state, server_message)?; - - let message_bytes = c.message.serialize(); + let mut client_rng = OsRng; + let c = client_register_state.finish( + &mut client_rng, + server_message, + ClientRegistrationFinishParameters::default(), + )?; - Ok(message_bytes) + Ok(ffi::ClientRegistrationFinishResult { + message: c.message.serialize(), + }) } -fn client_login_cxx(password: String) -> Result { - let c = client_login(&password)?; - - let message_bytes = c.message.serialize()?; - let state_bytes = c.state.serialize()?; +fn client_login_cxx(password: String) -> Result { + let mut client_rng = OsRng; + let c = ClientLogin::::start( + &mut client_rng, + password.as_bytes(), + ClientLoginStartParameters::default(), + )?; - Ok(ffi::MessageState { - message: message_bytes, - state: state_bytes, + Ok(ffi::ClientLoginStartResult { + message: c.message.serialize()?, + state: c.state.serialize()?, }) } fn client_login_finish_cxx( client_login_state: Vec, server_message: Vec, -) -> Result { +) -> Result { let client_login_state = ClientLogin::::deserialize(&client_login_state)?; let server_message = CredentialResponse::::deserialize(&server_message)?; // An InvalidLogin will be emitted in this step in the case of an incorrect password - let c = client_login_finish(client_login_state, server_message)?; + let c = client_login_state.finish(server_message, ClientLoginFinishParameters::default())?; - let message_bytes = c.message.serialize()?; - let session_bytes = c.session_key; - - Ok(ffi::MessageSession { - message: message_bytes, - session: session_bytes, + Ok(ffi::ClientLoginFinishResult { + message: c.message.serialize()?, + session_key: c.session_key, }) } -fn client_register(password: &str) -> Result, ProtocolError> { - let mut client_rng = OsRng; - ClientRegistration::::start(&mut client_rng, password.as_bytes()) +fn server_kp() -> ffi::ServerKeyPair { + let mut rng = OsRng; + let keypair = Cipher::generate_random_keypair(&mut rng); + let public_key = keypair.public().to_vec(); + let private_key = keypair.private().to_vec(); + ffi::ServerKeyPair { + public: public_key, + private: private_key, + } } -fn client_register_finish( - client_register_state: ClientRegistration, - server_message: RegistrationResponse, -) -> Result, ProtocolError> { - let mut client_rng = OsRng; - client_register_state.finish( - &mut client_rng, - server_message, - ClientRegistrationFinishParameters::Default, - ) +fn server_register_cxx( + registration_request: Vec, + server_public_key: Vec, +) -> Result { + let registration_request = RegistrationRequest::::deserialize(®istration_request)?; + let server_public_key = Key::from_bytes(&server_public_key)?; + + let mut server_rng = OsRng; + let s = + ServerRegistration::::start(&mut server_rng, registration_request, &server_public_key)?; + + Ok(ffi::ServerRegistrationStartResult { + message: s.message.serialize(), + state: s.state.serialize(), + }) } -fn client_login(password: &str) -> Result, ProtocolError> { - let mut client_rng = OsRng; - ClientLogin::::start( - &mut client_rng, - password.as_bytes(), - ClientLoginStartParameters::default(), - ) +fn server_register_finish_cxx( + server_register_state: Vec, + client_message: Vec, +) -> Result { + let server_register_state = ServerRegistration::::deserialize(&server_register_state)?; + let client_message = RegistrationUpload::::deserialize(&client_message)?; + + let s = server_register_state.finish(client_message)?; + + Ok(ffi::ServerRegistrationFinishResult { + password_file: s.serialize(), + }) } -fn client_login_finish( - client_login_state: ClientLogin, - server_message: CredentialResponse, -) -> Result, ProtocolError> { - client_login_state.finish(server_message, ClientLoginFinishParameters::default()) +fn server_login_cxx( + password_file: Vec, + server_private_key: Vec, + login_request: Vec, +) -> Result { + let password_file = ServerRegistration::::deserialize(&password_file)?; + let server_private_key = Key::from_bytes(&server_private_key)?; + let login_request = CredentialRequest::::deserialize(&login_request)?; + + let mut server_rng = OsRng; + let s = ServerLogin::start( + &mut server_rng, + password_file, + &server_private_key, + login_request, + ServerLoginStartParameters::default(), + )?; + + Ok(ffi::ServerLoginStartResult { + message: s.message.serialize()?, + state: s.state.serialize()?, + }) } -fn server_kp() -> ffi::ServerKeyPair { - let mut rng = OsRng; - let keypair = Cipher::generate_random_keypair(&mut rng); - let public_key = keypair.public().deref().to_vec(); - let private_key = keypair.private().deref().to_vec(); - ffi::ServerKeyPair { - public: public_key, - private: private_key, - } +fn server_login_finish_cxx( + server_login_state: Vec, + client_message: Vec, +) -> Result { + let server_login_state = ServerLogin::::deserialize(&server_login_state)?; + let client_message = CredentialFinalization::::deserialize(&client_message)?; + + let s = server_login_state.finish(client_message)?; + + Ok(ffi::ServerLoginFinishResult { + session_key: s.session_key, + }) } #[cfg(test)] @@ -389,4 +473,388 @@ assert_eq!(keys.public.len(), 32); assert_eq!(keys.private.len(), 32); } + + #[test] + fn test_server_register_cxx_ok() { + let password = "hunter2"; + let mut client_rng = OsRng; + let client_registration_start_result = + ClientRegistration::::start(&mut client_rng, password.as_bytes()).unwrap(); + let mut rng = OsRng; + let server_kp = Cipher::generate_random_keypair(&mut rng); + assert!(server_register_cxx( + client_registration_start_result.message.serialize(), + server_kp.public().to_vec() + ) + .is_ok()) + } + + #[test] + fn test_server_register_cxx_err_request_deserialization_failed() { + let mut rng = OsRng; + let server_kp = Cipher::generate_random_keypair(&mut rng); + assert!(server_register_cxx(vec![], server_kp.public().to_vec()).is_err()) + } + + #[test] + fn test_server_register_cxx_err_key_deserialization_failed() { + let password = "hunter2"; + let mut client_rng = OsRng; + let client_registration_start_result = + ClientRegistration::::start(&mut client_rng, password.as_bytes()).unwrap(); + assert!( + server_register_cxx(client_registration_start_result.message.serialize(), vec![]).is_err() + ) + } + + #[test] + fn test_server_register_finish_cxx_ok() { + let mut client_rng = OsRng; + let mut server_rng = OsRng; + let client_registration_start_result = + ClientRegistration::::start(&mut client_rng, b"hunter2").unwrap(); + let server_kp = Cipher::generate_random_keypair(&mut server_rng); + let server_registration_start_result = ServerRegistration::::start( + &mut server_rng, + client_registration_start_result.message, + server_kp.public(), + ) + .unwrap(); + let client_registration_finish_result = client_registration_start_result + .state + .finish( + &mut client_rng, + server_registration_start_result.message, + ClientRegistrationFinishParameters::default(), + ) + .unwrap(); + assert!(server_register_finish_cxx( + server_registration_start_result.state.serialize(), + client_registration_finish_result.message.serialize() + ) + .is_ok()); + } + + #[test] + fn test_server_register_finish_cxx_err_state_deserialization_failed() { + let mut client_rng = OsRng; + let mut server_rng = OsRng; + let client_registration_start_result = + ClientRegistration::::start(&mut client_rng, b"hunter2").unwrap(); + let server_kp = Cipher::generate_random_keypair(&mut server_rng); + let server_registration_start_result = ServerRegistration::::start( + &mut server_rng, + client_registration_start_result.message, + server_kp.public(), + ) + .unwrap(); + let client_registration_finish_result = client_registration_start_result + .state + .finish( + &mut client_rng, + server_registration_start_result.message, + ClientRegistrationFinishParameters::default(), + ) + .unwrap(); + assert!(server_register_finish_cxx( + vec![], + client_registration_finish_result.message.serialize() + ) + .is_err()); + } + + #[test] + fn test_server_register_finish_cxx_err_message_deserialization_failed() { + let mut client_rng = OsRng; + let mut server_rng = OsRng; + let client_registration_start_result = + ClientRegistration::::start(&mut client_rng, b"hunter2").unwrap(); + let server_kp = Cipher::generate_random_keypair(&mut server_rng); + let server_registration_start_result = ServerRegistration::::start( + &mut server_rng, + client_registration_start_result.message, + server_kp.public(), + ) + .unwrap(); + assert!( + server_register_finish_cxx(server_registration_start_result.state.serialize(), vec![]) + .is_err() + ); + } + + #[test] + fn test_server_login_cxx_ok() { + let mut client_rng = OsRng; + let mut server_rng = OsRng; + let client_registration_start_result = + ClientRegistration::::start(&mut client_rng, b"hunter2").unwrap(); + let server_kp = Cipher::generate_random_keypair(&mut server_rng); + let server_registration_start_result = ServerRegistration::::start( + &mut server_rng, + client_registration_start_result.message, + server_kp.public(), + ) + .unwrap(); + let client_registration_finish_result = client_registration_start_result + .state + .finish( + &mut client_rng, + server_registration_start_result.message, + ClientRegistrationFinishParameters::default(), + ) + .unwrap(); + let p_file = server_registration_start_result + .state + .finish(client_registration_finish_result.message) + .unwrap(); + let client_login_start_result = ClientLogin::::start( + &mut client_rng, + b"hunter2", + ClientLoginStartParameters::default(), + ) + .unwrap(); + assert!(server_login_cxx( + p_file.serialize(), + server_kp.private().to_vec(), + client_login_start_result.message.serialize().unwrap() + ) + .is_ok()); + } + + #[test] + fn test_server_login_cxx_err_password_file_deserialization_failed() { + let mut client_rng = OsRng; + let mut server_rng = OsRng; + let server_kp = Cipher::generate_random_keypair(&mut server_rng); + let client_login_start_result = ClientLogin::::start( + &mut client_rng, + b"hunter2", + ClientLoginStartParameters::default(), + ) + .unwrap(); + assert!(server_login_cxx( + vec![], + server_kp.private().to_vec(), + client_login_start_result.message.serialize().unwrap() + ) + .is_err()); + } + + #[test] + fn test_server_login_cxx_err_private_key_deserialization_failed() { + let mut client_rng = OsRng; + let mut server_rng = OsRng; + let client_registration_start_result = + ClientRegistration::::start(&mut client_rng, b"hunter2").unwrap(); + let server_kp = Cipher::generate_random_keypair(&mut server_rng); + let server_registration_start_result = ServerRegistration::::start( + &mut server_rng, + client_registration_start_result.message, + server_kp.public(), + ) + .unwrap(); + let client_registration_finish_result = client_registration_start_result + .state + .finish( + &mut client_rng, + server_registration_start_result.message, + ClientRegistrationFinishParameters::default(), + ) + .unwrap(); + let p_file = server_registration_start_result + .state + .finish(client_registration_finish_result.message) + .unwrap(); + let client_login_start_result = ClientLogin::::start( + &mut client_rng, + b"hunter2", + ClientLoginStartParameters::default(), + ) + .unwrap(); + assert!(server_login_cxx( + p_file.serialize(), + vec![], + client_login_start_result.message.serialize().unwrap() + ) + .is_err()); + } + + #[test] + fn test_server_login_cxx_err_login_request_deserialization_failed() { + let mut client_rng = OsRng; + let mut server_rng = OsRng; + let client_registration_start_result = + ClientRegistration::::start(&mut client_rng, b"hunter2").unwrap(); + let server_kp = Cipher::generate_random_keypair(&mut server_rng); + let server_registration_start_result = ServerRegistration::::start( + &mut server_rng, + client_registration_start_result.message, + server_kp.public(), + ) + .unwrap(); + let client_registration_finish_result = client_registration_start_result + .state + .finish( + &mut client_rng, + server_registration_start_result.message, + ClientRegistrationFinishParameters::default(), + ) + .unwrap(); + let p_file = server_registration_start_result + .state + .finish(client_registration_finish_result.message) + .unwrap(); + assert!(server_login_cxx(p_file.serialize(), server_kp.private().to_vec(), vec![]).is_err()); + } + + #[test] + fn test_server_login_finish_cxx_ok() { + let mut client_rng = OsRng; + let mut server_rng = OsRng; + let client_registration_start_result = + ClientRegistration::::start(&mut client_rng, b"hunter2").unwrap(); + let server_kp = Cipher::generate_random_keypair(&mut server_rng); + let server_registration_start_result = ServerRegistration::::start( + &mut server_rng, + client_registration_start_result.message, + server_kp.public(), + ) + .unwrap(); + let client_registration_finish_result = client_registration_start_result + .state + .finish( + &mut client_rng, + server_registration_start_result.message, + ClientRegistrationFinishParameters::default(), + ) + .unwrap(); + let p_file = server_registration_start_result + .state + .finish(client_registration_finish_result.message) + .unwrap(); + let client_login_start_result = ClientLogin::::start( + &mut client_rng, + b"hunter2", + ClientLoginStartParameters::default(), + ) + .unwrap(); + let server_login_start_result = ServerLogin::start( + &mut server_rng, + p_file, + &server_kp.private(), + client_login_start_result.message, + ServerLoginStartParameters::default(), + ) + .unwrap(); + let client_login_finish_result = client_login_start_result + .state + .finish( + server_login_start_result.message, + ClientLoginFinishParameters::default(), + ) + .unwrap(); + assert!(server_login_finish_cxx( + server_login_start_result.state.serialize().unwrap(), + client_login_finish_result.message.serialize().unwrap() + ) + .is_ok()); + } + + #[test] + fn test_server_login_finish_cxx_err_state_deserialization_failed() { + let mut client_rng = OsRng; + let mut server_rng = OsRng; + let client_registration_start_result = + ClientRegistration::::start(&mut client_rng, b"hunter2").unwrap(); + let server_kp = Cipher::generate_random_keypair(&mut server_rng); + let server_registration_start_result = ServerRegistration::::start( + &mut server_rng, + client_registration_start_result.message, + server_kp.public(), + ) + .unwrap(); + let client_registration_finish_result = client_registration_start_result + .state + .finish( + &mut client_rng, + server_registration_start_result.message, + ClientRegistrationFinishParameters::default(), + ) + .unwrap(); + let p_file = server_registration_start_result + .state + .finish(client_registration_finish_result.message) + .unwrap(); + let client_login_start_result = ClientLogin::::start( + &mut client_rng, + b"hunter2", + ClientLoginStartParameters::default(), + ) + .unwrap(); + let server_login_start_result = ServerLogin::start( + &mut server_rng, + p_file, + &server_kp.private(), + client_login_start_result.message, + ServerLoginStartParameters::default(), + ) + .unwrap(); + let client_login_finish_result = client_login_start_result + .state + .finish( + server_login_start_result.message, + ClientLoginFinishParameters::default(), + ) + .unwrap(); + assert!(server_login_finish_cxx( + vec![], + client_login_finish_result.message.serialize().unwrap() + ) + .is_err()); + } + + #[test] + fn test_server_login_finish_cxx_err_message_deserialization_failed() { + let mut client_rng = OsRng; + let mut server_rng = OsRng; + let client_registration_start_result = + ClientRegistration::::start(&mut client_rng, b"hunter2").unwrap(); + let server_kp = Cipher::generate_random_keypair(&mut server_rng); + let server_registration_start_result = ServerRegistration::::start( + &mut server_rng, + client_registration_start_result.message, + server_kp.public(), + ) + .unwrap(); + let client_registration_finish_result = client_registration_start_result + .state + .finish( + &mut client_rng, + server_registration_start_result.message, + ClientRegistrationFinishParameters::default(), + ) + .unwrap(); + let p_file = server_registration_start_result + .state + .finish(client_registration_finish_result.message) + .unwrap(); + let client_login_start_result = ClientLogin::::start( + &mut client_rng, + b"hunter2", + ClientLoginStartParameters::default(), + ) + .unwrap(); + let server_login_start_result = ServerLogin::start( + &mut server_rng, + p_file, + &server_kp.private(), + client_login_start_result.message, + ServerLoginStartParameters::default(), + ) + .unwrap(); + assert!( + server_login_finish_cxx(server_login_start_result.state.serialize().unwrap(), vec![]) + .is_err() + ); + } }