-
Notifications
You must be signed in to change notification settings - Fork 22
Harden OTP system: brute-force protection, memory cleanup, and key collision fix #224
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 8 commits
05fddaf
2e42714
00d8d4a
7424cb9
b35da4b
404492f
f401dfd
c4e008a
b26f90c
de2fe62
a133f76
293db6f
38f5b15
f36079e
d954d14
d5b80a1
c87ae10
143775d
b48a7fd
e373823
0c966b2
7719f81
dc1e4c9
33ec0f6
6dde14c
aa545b8
3a2a90e
316fa01
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,8 +6,8 @@ | |
| #define OTPSYSTEM_HPP | ||
|
|
||
| #include <chrono> | ||
| #include <random> | ||
| #include <mutex> | ||
| #include <random> | ||
| #include <unordered_map> | ||
|
|
||
| namespace server | ||
|
|
@@ -16,21 +16,60 @@ namespace server | |
| class OtpSystem | ||
| { | ||
| public: | ||
| struct Settings | ||
| { | ||
| std::chrono::seconds codeTtl{30}; | ||
| uint32_t maxFailedAttempts{5}; | ||
| std::chrono::seconds lockoutDuration{60}; | ||
| std::chrono::seconds purgeInterval{60}; | ||
|
|
||
| Settings() = default; | ||
| }; | ||
|
|
||
| OtpSystem(); | ||
| explicit OtpSystem(Settings settings); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should take forward-definition of |
||
|
|
||
| //! Grants a one-time code for the given key. | ||
| //! If a code already exists for this key, it is replaced. | ||
| //! @param key Identity key the code is bound to. | ||
| //! @return The generated one-time code. | ||
| uint32_t GrantCode(size_t key); | ||
|
Koaio marked this conversation as resolved.
Outdated
|
||
|
|
||
| //! Authorizes a one-time code for the given key. | ||
| //! Enforces brute-force protection: after too many failed attempts, | ||
| //! the key is temporarily locked out. | ||
|
Koaio marked this conversation as resolved.
Outdated
|
||
| //! @param key Identity key the code is bound to. | ||
| //! @param code The code to verify. | ||
| //! @param consume If true, the code is consumed (erased) on success. | ||
| //! @return True if the code is valid and the key is not locked out. | ||
|
Koaio marked this conversation as resolved.
Outdated
|
||
| bool AuthorizeCode(size_t key, uint32_t code, bool consume = true); | ||
|
Koaio marked this conversation as resolved.
Outdated
|
||
|
|
||
| //! Removes all expired codes and stale lockout entries. | ||
| //! Called automatically on a periodic basis, but can be invoked manually. | ||
| void PurgeExpired(); | ||
|
|
||
| private: | ||
| Settings _settings; | ||
|
|
||
| struct Code | ||
| { | ||
| std::chrono::steady_clock::time_point expiry{}; | ||
| uint32_t code{}; | ||
| }; | ||
|
|
||
| struct AttemptRecord | ||
| { | ||
| uint32_t failedAttempts{0}; | ||
| std::chrono::steady_clock::time_point lockoutExpiry{}; | ||
| }; | ||
|
|
||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please merge struct Code
{
//! A time point of when the code expires.
std::chrono::steady_clock::time_point expiry{};
//! A counter of authorization attempts.
size_t authorizationAttempts{};
//! A value of the code.
uint32_t code{};
};Also if you read previous comments, reference to the |
||
| std::mutex _codesMutex; | ||
| std::random_device _rd; | ||
| std::mt19937 _rng; | ||
| std::unordered_map<size_t, Code> _codes; | ||
| std::unordered_map<size_t, AttemptRecord> _attempts; | ||
| std::chrono::steady_clock::time_point _lastPurge; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not necessary. Invalidate the key/code after 5 unsuccessful attempts to use it. |
||
| }; | ||
|
|
||
| } // namespace server | ||
|
|
||
| #endif //OTPSYSTEM_HPP | ||
| #endif // OTPSYSTEM_HPP | ||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This setting struct should be defined in
Settings.hppheader. SeeAuthenticationServicefor example..