Skip to content

Commit

Permalink
digest authentication attempt (not working)
Browse files Browse the repository at this point in the history
  • Loading branch information
catink123 committed Jan 27, 2024
1 parent 1d03e79 commit 03b6285
Show file tree
Hide file tree
Showing 7 changed files with 310 additions and 52 deletions.
9 changes: 9 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,13 @@ CPMAddPackage(
"BUILD_TESTS OFF"
)

CPMAddPackage(
NAME cryptopp
VERSION 8.9.0
GITHUB_REPOSITORY "abdes/cryptopp-cmake"
GIT_TAG "CRYPTOPP_8_9_0"
OPTIONS
"BUILD_TESTS OFF"
)

add_subdirectory(${PROJECT_SOURCE_DIR}/src)
11 changes: 6 additions & 5 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,19 @@ target_link_libraries(
${PROJECT_NAME}
Boost::beast
nlohmann_json::nlohmann_json
bcrypt
# bcrypt
cryptopp::cryptopp
)

# password-hash generator
add_executable(password_hasher hash_generator.cpp)
set_property(TARGET password_hasher PROPERTY CXX_STANDARD 20)
target_link_libraries(password_hasher bcrypt)
# add_executable(password_hasher hash_generator.cpp)
# set_property(TARGET password_hasher PROPERTY CXX_STANDARD 20)
# target_link_libraries(password_hasher bcrypt)

# install the server binary and the password hasher to bin

install(
TARGETS ${PROJECT_NAME} password_hasher
TARGETS ${PROJECT_NAME} # password_hasher
RUNTIME DESTINATION bin
)

Expand Down
171 changes: 171 additions & 0 deletions src/auth.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,175 @@ open_auth_table_from_file(fs::path file_path) {
file.close();

return auth_table;
}

void digest_auth::set_field(
std::string_view key,
std::string_view value
) {
if (key == "username") username = value;
if (key == "response") response = value;
if (key == "nonce") nonce = value;
if (key == "realm") realm = value;
if (key == "uri") uri = value;
if (key == "nc") nc = value;
if (key == "cnonce") cnonce = value;
if (key == "opaque") opaque = value;
if (key == "qop") qop = value;
}

bool digest_auth::is_valid() const {
if (
username.size() != 0 &&
response.size() != 0 &&
nonce.size() != 0 &&
realm.size() != 0 &&
uri.size() != 0
) {
if (qop) {
return cnonce && nc;
}
return !cnonce && !nc;
}
return false;
}

std::string to_hex(const std::string& input, bool uppercase) {
std::string output;

CryptoPP::StringSource(input, true,
new CryptoPP::HexEncoder(
new CryptoPP::StringSink(output),
uppercase
)
);

return output;
}

std::string md5_hash(const std::string& input) {
std::string output;

CryptoPP::Weak::MD5 hash;

CryptoPP::StringSource(input, true,
new CryptoPP::HashFilter(hash,
new CryptoPP::HexEncoder(
new CryptoPP::StringSink(output),
false
)
)
);

return output;

// CryptoPP::Weak::MD5 hash;

// hash.Update(
// reinterpret_cast<const CryptoPP::byte*>(
// input.data()
//),
// input.size()
// );

// unsigned int size = hash.DigestSize();
// std::vector<char> hashed_value(size, '\0');
// char* hashed_value_c_str = &hashed_value[0];

// hash.Final(
// reinterpret_cast<CryptoPP::byte*>(hashed_value_c_str)
// );

// return std::string(hashed_value_c_str, size);
}

std::string http_method_to_str(const http::verb& method) {
if (method == http::verb::get) return "GET";
if (method == http::verb::put) return "PUT";
if (method == http::verb::delete_) return "DELETE";
if (method == http::verb::head) return "HEAD";
if (method == http::verb::options) return "OPTIONS";
if (method == http::verb::connect) return "CONNECT";
return "unknown";
}

bool digest_auth::check_password(
std::string_view password,
std::string_view method,
std::string_view nonce,
const auth_table_t& auth_table
) const {
if (auth_table.find(username) == auth_table.end()) {
return false;
}

const auto& data = auth_table.at(username);

std::string A1 =
username + ':' + realm + ':' + std::string(password);
std::string A1_hash = md5_hash(A1);

std::string A2 = std::string(method) + ':' + uri;
std::string A2_hash = md5_hash(A2);

std::string A1_nonce_A2 = A1_hash + ':' + std::string(nonce) + ':' + A2_hash;
std::string KD = md5_hash(A1_nonce_A2);

return response == KD;
}

std::optional<digest_auth> parse_digest_auth_field(
const std::string& field_value
) {
// make sure the field_value starts with the word Digest
if (!field_value.starts_with("Digest")) {
return std::nullopt;
}

digest_auth params;

auto it = std::sregex_iterator(
field_value.begin(),
field_value.end(),
key_value_regex
);

for (; it != std::sregex_iterator(); it++) {
auto smatch = *it;

// make sure there are 3 submatches for the whole match,
// the key and the value
if (std::distance(smatch.begin(), smatch.end()) != 3) {
return std::nullopt;
}

auto key = smatch[1].str();
auto value = smatch[2].str();

if (value[0] == '"' && value[value.size() - 1] == '"') {
value = value.substr(1, value.size() - 2);
}

params.set_field(key, value);
}

if (params.is_valid()) {
return params;
}
else {
return std::nullopt;
}
}

std::string generate_nonce() {
std::string output;

CryptoPP::AutoSeededRandomPool rng;
CryptoPP::RandomNumberSource(rng, NONCE_SIZE, true,
new CryptoPP::Base64URLEncoder(
new CryptoPP::StringSink(output)
)
);

return output;
}

0 comments on commit 03b6285

Please sign in to comment.