From 3ad1d1c0cf87c7092a9ca688c621fc0f0106ed40 Mon Sep 17 00:00:00 2001 From: Ruben Perez Date: Mon, 9 Dec 2024 16:34:21 +0100 Subject: [PATCH 1/3] Code changes --- .../boost/mysql/impl/internal/auth/auth.ipp | 66 +++++++++++-------- 1 file changed, 37 insertions(+), 29 deletions(-) diff --git a/include/boost/mysql/impl/internal/auth/auth.ipp b/include/boost/mysql/impl/internal/auth/auth.ipp index 2ac250b79..b03474dc0 100644 --- a/include/boost/mysql/impl/internal/auth/auth.ipp +++ b/include/boost/mysql/impl/internal/auth/auth.ipp @@ -18,10 +18,11 @@ #include #include +#include +#include #include #include -#include namespace boost { namespace mysql { @@ -39,21 +40,26 @@ BOOST_INLINE_CONSTEXPR std::size_t mnp_response_length = 20; // SHA1( password ) XOR SHA1( "20-bytes random data from server" SHA1( SHA1( password ) ) ) inline void mnp_compute_auth_string(string_view password, const void* challenge, void* output) { - // SHA1 (password) - using sha1_buffer = unsigned char[SHA_DIGEST_LENGTH]; - sha1_buffer password_sha1; - SHA1(reinterpret_cast(password.data()), password.size(), password_sha1); - - // Add server challenge (salt) - unsigned char salted_buffer[mnp_challenge_length + SHA_DIGEST_LENGTH]; - memcpy(salted_buffer, challenge, mnp_challenge_length); - SHA1(password_sha1, sizeof(password_sha1), salted_buffer + 20); - sha1_buffer salted_sha1; - SHA1(salted_buffer, sizeof(salted_buffer), salted_sha1); + // Algorithm: SHA1(password) XOR SHA1(challenge | SHA1(SHA1(password))) + // SHA1(password) + hash2::sha1_160 hasher1; + hasher1.update(password.data(), password.size()); + auto password_sha1 = hasher1.result(); + + // SHA1(SHA1(password)) + hash2::sha1_160 hasher2; + hasher2.update(password_sha1.data(), password_sha1.size()); + auto result2 = hasher2.result(); + + // SHA1(challenge | SHA1(SHA1(password))) + hash2::sha1_160 hasher3; + hasher3.update(challenge, mnp_challenge_length); + hasher3.update(result2.data(), result2.size()); + auto salted_sha1 = hasher3.result(); // XOR - static_assert(mnp_response_length == SHA_DIGEST_LENGTH, "Buffer size mismatch"); - for (std::size_t i = 0; i < SHA_DIGEST_LENGTH; ++i) + static_assert(mnp_response_length == hash2::sha1_160::result_type().size(), "Buffer size mismatch"); + for (std::size_t i = 0; i < salted_sha1.size(); ++i) { static_cast(output)[i] = password_sha1[i] ^ salted_sha1[i]; } @@ -96,27 +102,29 @@ BOOST_INLINE_CONSTEXPR std::size_t csha2p_response_length = 32; // output must point to response_length bytes of data inline void csha2p_compute_auth_string(string_view password, const void* challenge, void* output) { - static_assert(csha2p_response_length == SHA256_DIGEST_LENGTH, "Buffer size mismatch"); + static_assert(csha2p_response_length == hash2::sha2_256::result_type().size(), "Buffer size mismatch"); - // SHA(SHA(password_sha) concat challenge) XOR password_sha - // hash1 = SHA(pass) - using sha_buffer = std::uint8_t[csha2p_response_length]; - sha_buffer password_sha; - SHA256(reinterpret_cast(password.data()), password.size(), password_sha); + // Algorithm: SHA2(SHA2(SHA2(password)) | challenge) XOR SHA2(password) + // SHA2(password) + hash2::sha2_256 hasher1; + hasher1.update(password.data(), password.size()); + auto password_hash = hasher1.result(); - // SHA(password_sha) concat challenge = buffer - std::uint8_t buffer[csha2p_response_length + csha2p_challenge_length]; - SHA256(password_sha, csha2p_response_length, buffer); - std::memcpy(buffer + csha2p_response_length, challenge, csha2p_challenge_length); + // SHA2(SHA2(password)) + hash2::sha2_256 hasher2; + hasher2.update(password_hash.data(), password_hash.size()); + auto password_double_hash = hasher2.result(); - // SHA(SHA(password_sha) concat challenge) = SHA(buffer) = salted_password - sha_buffer salted_password; - SHA256(buffer, sizeof(buffer), salted_password); + // SHA2(SHA2(SHA2(password)) | challenge) + hash2::sha2_256 hasher3; + hasher3.update(password_double_hash.data(), password_double_hash.size()); + hasher3.update(challenge, csha2p_challenge_length); + auto salted_password = hasher3.result(); - // salted_password XOR password_sha + // XOR for (unsigned i = 0; i < csha2p_response_length; ++i) { - static_cast(output)[i] = salted_password[i] ^ password_sha[i]; + static_cast(output)[i] = salted_password[i] ^ password_hash[i]; } } From 9bbef339dd2561768f6cd66af8ee802f748204f1 Mon Sep 17 00:00:00 2001 From: Ruben Perez Date: Mon, 9 Dec 2024 16:34:27 +0100 Subject: [PATCH 2/3] CMake --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4c9243091..4c166ea96 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -45,6 +45,7 @@ target_link_libraries( Boost::system Boost::throw_exception Boost::variant2 + Boost::hash2 Threads::Threads OpenSSL::Crypto OpenSSL::SSL From 713ab907b932958acaf14c19b606bc755f643824 Mon Sep 17 00:00:00 2001 From: Ruben Perez Date: Mon, 9 Dec 2024 16:46:56 +0100 Subject: [PATCH 3/3] CI changes --- tools/ci/ci_util/install_boost.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/ci/ci_util/install_boost.py b/tools/ci/ci_util/install_boost.py index 4401f419a..4993fedf1 100644 --- a/tools/ci/ci_util/install_boost.py +++ b/tools/ci/ci_util/install_boost.py @@ -70,6 +70,9 @@ def install_boost( run(["git", "config", "submodule.fetchJobs", "8"]) run(["git", "submodule", "update", "-q", "--init"] + submodules) + # Manually install the proposed Boost.Hash2 + run(["git", "clone", "-b", "master", "https://github.com/pdimov/hash2.git", "libs/hash2"]) + if docs_install: run(['python', 'tools/boostdep/depinst/depinst.py', '../tools/quickbook']) else: