Remove legacy hashes
This commit is contained in:
@@ -79,24 +79,8 @@ std::string hashPassword(const std::string &password)
|
|||||||
|
|
||||||
bool verifyPassword(const std::string &password, const std::string &hash)
|
bool verifyPassword(const std::string &password, const std::string &hash)
|
||||||
{
|
{
|
||||||
constexpr std::string_view legacyPrefix = "sha256$";
|
|
||||||
constexpr std::string_view pbkdf2Prefix = "pbkdf2_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))
|
if (!hash.starts_with(pbkdf2Prefix))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
- Focused regression tests for technical endpoints and core validation helpers.
|
- Focused regression tests for technical endpoints and core validation helpers.
|
||||||
- Local admin seed: `[email protected]` / `ChangeMe123!`, with forced password change flag.
|
- Local admin seed: `[email protected]` / `ChangeMe123!`, with forced password change flag.
|
||||||
- Multipart report photo upload endpoint storing files under `uploads/reports/`.
|
- 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
|
## To do next
|
||||||
- Consider Argon2id/bcrypt and password reset flows before production hardening.
|
- Consider Argon2id/bcrypt and password reset flows before production hardening.
|
||||||
|
|||||||
@@ -232,7 +232,7 @@ INSERT IGNORE INTO users (
|
|||||||
'System',
|
'System',
|
||||||
'Admin',
|
'Admin',
|
||||||
'[email protected]',
|
'[email protected]',
|
||||||
'sha256$local-dev-salt$3a85ed70535399cc6c9b41aa26f464f650b52b36c3c62850146d1c7aca26862b',
|
'pbkdf2_sha256$210000$local-dev-admin-salt$A4683BDB63C1598400B6B196F53C830F8434BA645C4A4A70AB311B278223E698',
|
||||||
'ADMINVISIONE0000',
|
'ADMINVISIONE0000',
|
||||||
'+390000000000',
|
'+390000000000',
|
||||||
TRUE
|
TRUE
|
||||||
@@ -241,4 +241,3 @@ INSERT IGNORE INTO users (
|
|||||||
INSERT IGNORE INTO user_roles (user_id, role_id)
|
INSERT IGNORE INTO user_roles (user_id, role_id)
|
||||||
SELECT u.id, r.id FROM users u JOIN roles r
|
SELECT u.id, r.id FROM users u JOIN roles r
|
||||||
WHERE u.email = '[email protected]' AND r.name = 'admin';
|
WHERE u.email = '[email protected]' AND r.name = 'admin';
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
UPDATE users
|
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
|
must_change_password = TRUE
|
||||||
WHERE email = '[email protected]';
|
WHERE email = '[email protected]';
|
||||||
|
|||||||
+2
-2
@@ -86,7 +86,7 @@ DROGON_TEST(GeoJsonMatchesPointInsidePolygon)
|
|||||||
CHECK(!visione::geojson::pointInPolygon(43.0, 12.5, polygon));
|
CHECK(!visione::geojson::pointInPolygon(43.0, 12.5, polygon));
|
||||||
}
|
}
|
||||||
|
|
||||||
DROGON_TEST(PasswordHashSupportsPbkdf2AndLegacy)
|
DROGON_TEST(PasswordHashSupportsPbkdf2Only)
|
||||||
{
|
{
|
||||||
const auto hash = visione::crypto::hashPassword("CorrectHorse123!");
|
const auto hash = visione::crypto::hashPassword("CorrectHorse123!");
|
||||||
CHECK(hash.rfind("pbkdf2_sha256$", 0) == 0);
|
CHECK(hash.rfind("pbkdf2_sha256$", 0) == 0);
|
||||||
@@ -95,7 +95,7 @@ DROGON_TEST(PasswordHashSupportsPbkdf2AndLegacy)
|
|||||||
|
|
||||||
const std::string legacy =
|
const std::string legacy =
|
||||||
"sha256$local-dev-salt$CD4FF6AC8C9685D08E55AF693970F15F9BFCD4C0DC9F4D3001D202C9DB00291F";
|
"sha256$local-dev-salt$CD4FF6AC8C9685D08E55AF693970F15F9BFCD4C0DC9F4D3001D202C9DB00291F";
|
||||||
CHECK(visione::crypto::verifyPassword("ChangeMe123!", legacy));
|
CHECK(!visione::crypto::verifyPassword("ChangeMe123!", legacy));
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
|
|||||||
Reference in New Issue
Block a user