Repository navigation
Add Nokia SR OS $2y$ bcrypt password support - #6
Merged
Merged
Conversation
…SR OS implementations
# Conflicts: # CHANGELOG.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds Nokia SR OS local user passwords as an eighth format, in the Python package, the CLI and the website.
SR OS stores local user passwords as bcrypt, written in config as
$2y$10$<22-char salt><31-char digest>. It is a one-way hash, so it follows the contract Cisco type 8 and type 9 established:encrypthashes,checkverifies a candidate password,decryptraises. On the site it gets Hash and Verify tabs and a One-way badge, and joins the existing Nokia vendor menu.Known-answer vector, pinned in both test suites:
Two behaviours worth knowing
$2a$,$2b$and$2y$all verify. They are the same algorithm with different historical markers, so accepting all three is not guesswork. Hashing always emits$2y$, which is what SR OS writes. The recomputed value incheck's return tuple preserves whichever prefix you passed in.The cost is bounded to 4-16, and that bound is load-bearing. bcrypt's cost is an exponent read from the value being checked, so an unbounded cost lets a pasted hash force arbitrarily expensive work. Measured: cost 10 is 0.11s, cost 14 is 1.9s, cost 16 is 8.5s, cost 31 is roughly 583 hours. Without the bound, pasting a
$2y$31$hash into the website would freeze the browser tab indefinitely. This mirrors howjuniper8bounds its iteration count for the same reason. The web implementation also usesbcryptjs's asynchronous API, so the converter's "Working" state can actually paint.A malformed cost field is rejected rather than silently treated as a mismatch. bcrypt always writes the cost zero-padded to two digits, so
$2y$4$...is not a low-cost hash, it is invalid input; reporting "no match" for it would tell the user their password was wrong when it was their input that was malformed.Dependencies
Two new ones, both necessary: Python 3.13 removed the stdlib
cryptmodule and Web Crypto has no bcrypt, sobcrypt>=4.0andbcryptjs. Hand-rolling bcrypt would mean implementing Blowfish's key schedule in security-sensitive code, which is not a trade worth making.Verification
Python 178 tests, web 168 tests,
npm run checkclean,npm run buildsucceeds. Both implementations were checked against each other directly: same vector, all three prefixes, byte-identical error messages for every malformed input, and immediate rejection of an out-of-range cost without hashing. The site was verified by hand in a browser, including that a cost-31 hash errors instantly instead of hanging the tab.