diff --git a/common/Crypto.cc b/common/Crypto.cc index 439d85f..89afdc9 100644 --- a/common/Crypto.cc +++ b/common/Crypto.cc @@ -79,24 +79,8 @@ std::string hashPassword(const std::string &password) bool verifyPassword(const std::string &password, const std::string &hash) { - constexpr std::string_view legacyPrefix = "sha256$"; constexpr std::string_view pbkdf2Prefix = "pbkdf2_sha256$"; - if (hash.starts_with(legacyPrefix)) - { - const auto saltStart = legacyPrefix.size(); - const auto hashStart = hash.find('$', saltStart); - if (hashStart == std::string::npos) - { - return false; - } - - const auto salt = hash.substr(saltStart, hashStart - saltStart); - const auto expected = - "sha256$" + salt + "$" + sha256(salt + ":" + password); - return expected == hash; - } - if (!hash.starts_with(pbkdf2Prefix)) { return false; diff --git a/docs/MILESTONE_01.md b/docs/MILESTONE_01.md index 87e230e..f4e2ed1 100644 --- a/docs/MILESTONE_01.md +++ b/docs/MILESTONE_01.md @@ -10,7 +10,7 @@ - Focused regression tests for technical endpoints and core validation helpers. - Local admin seed: `admin@visione.local` / `ChangeMe123!`, with forced password change flag. - Multipart report photo upload endpoint storing files under `uploads/reports/`. -- PBKDF2-HMAC-SHA256 password hashes for new credentials, with legacy SHA-256 verification kept for existing local rows. +- PBKDF2-HMAC-SHA256 password hashes for credentials. Legacy SHA-256 hashes are intentionally rejected. ## To do next - Consider Argon2id/bcrypt and password reset flows before production hardening. diff --git a/migrations/001_initial_schema.sql b/migrations/001_initial_schema.sql index 315caf1..2d45646 100644 --- a/migrations/001_initial_schema.sql +++ b/migrations/001_initial_schema.sql @@ -232,7 +232,7 @@ INSERT IGNORE INTO users ( 'System', 'Admin', 'admin@visione.local', - 'sha256$local-dev-salt$3a85ed70535399cc6c9b41aa26f464f650b52b36c3c62850146d1c7aca26862b', + 'pbkdf2_sha256$210000$local-dev-admin-salt$A4683BDB63C1598400B6B196F53C830F8434BA645C4A4A70AB311B278223E698', 'ADMINVISIONE0000', '+390000000000', TRUE @@ -241,4 +241,3 @@ INSERT IGNORE INTO users ( INSERT IGNORE INTO user_roles (user_id, role_id) SELECT u.id, r.id FROM users u JOIN roles r WHERE u.email = 'admin@visione.local' AND r.name = 'admin'; - diff --git a/migrations/002_seed_admin_password.sql b/migrations/002_seed_admin_password.sql index 57164b4..5163f2e 100644 --- a/migrations/002_seed_admin_password.sql +++ b/migrations/002_seed_admin_password.sql @@ -1,4 +1,4 @@ UPDATE users -SET password_hash = 'sha256$local-dev-salt$CD4FF6AC8C9685D08E55AF693970F15F9BFCD4C0DC9F4D3001D202C9DB00291F', +SET password_hash = 'pbkdf2_sha256$210000$local-dev-admin-salt$A4683BDB63C1598400B6B196F53C830F8434BA645C4A4A70AB311B278223E698', must_change_password = TRUE WHERE email = 'admin@visione.local'; diff --git a/test/test_main.cc b/test/test_main.cc index 6885426..68ad530 100644 --- a/test/test_main.cc +++ b/test/test_main.cc @@ -86,7 +86,7 @@ DROGON_TEST(GeoJsonMatchesPointInsidePolygon) CHECK(!visione::geojson::pointInPolygon(43.0, 12.5, polygon)); } -DROGON_TEST(PasswordHashSupportsPbkdf2AndLegacy) +DROGON_TEST(PasswordHashSupportsPbkdf2Only) { const auto hash = visione::crypto::hashPassword("CorrectHorse123!"); CHECK(hash.rfind("pbkdf2_sha256$", 0) == 0); @@ -95,7 +95,7 @@ DROGON_TEST(PasswordHashSupportsPbkdf2AndLegacy) const std::string legacy = "sha256$local-dev-salt$CD4FF6AC8C9685D08E55AF693970F15F9BFCD4C0DC9F4D3001D202C9DB00291F"; - CHECK(visione::crypto::verifyPassword("ChangeMe123!", legacy)); + CHECK(!visione::crypto::verifyPassword("ChangeMe123!", legacy)); } int main(int argc, char **argv)