-
Notifications
You must be signed in to change notification settings - Fork 296
Add Argon2id password hashing builtins; switch from cryptonite to crypton #6094
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
Conversation
|
@pchiusano I know we'd spoken previously about adding some more cryptographic support, though this is a little different than what we'd discussed. |
|
Some tests with 'continue-on-error: true' have failed:
Created by continue-on-error-comment |
|
Different how? |
Originally we'd discussed AES-256 |
|
I'm good with this. Argon2 seems like the gold standard these days, however I'd prefer to get the implementation from the existing cryptonite library that we already depend on rather than a new C library. Is there any reason not to use: https://hackage.haskell.org/package/cryptonite-0.30/docs/Crypto-KDF-Argon2.html Or we could switch to the fork, crypton, which is actively maintained. |
|
I think it is reasonable to go with crypton/(ite) - if we switch to crypton, do you want to convert other usages from cryptonite to crypton in the same PR? PHC The only tradeoff is we'd have to write our own PHC codec as I don't think crypton has that, but could do that. PHC is handy since embedding params in the PHC string means you can verify hashes even if you change default params later. But, we could do this in Unison (base) and that should actually keep the Haskell side lighter. |
|
Up to you. If crypton is really a drop-in replacement as advertised, no objections to upgrading to that everywhere. Also fine to do everything with cryptonite if that works fine and leave the upgrade to crypton for a later PR. |
|
@aryairani @pchiusano should be ready for review |
| - bytes | ||
| - containers | ||
| - cryptonite | ||
| - crypton |
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.
since I was curious:
While cryptonite has a obvious bug, it has not been fixed for a long time. This is because the author is now inactive in the Haskell community. In private communication with him, I was not given the upload permission of cryptonite to Hackage. He suggested me to fork cryponite and upload it as a different package.
So, I created crypton and uploaded it to Hackage with the bug fixed.
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.
Now I am retroactively curious and my curiosity is satisfied.
|
Just chiming in that yes, |
Overview
What does this change accomplish and why?
cryptonitetocrypton(its actively-maintained fork) across the codebaseHow does it change the user experience?
crypto.argon2namespaceBefore and after examples:
Hashing a password (with OWASP-recommended settings):
Verifying a password:
Implementation approach and notes
Migrated from
cryptonitetocryptonacross the codebasecryptonis the actively-maintained fork ofcryptonite(which is no longer maintained)cryptonprovides Argon2 support viaCrypto.KDF.Argon2package.yamlfiles:unison-core,unison-syntax,unison-runtime,unison-hashing-v2,unison-cliDefined ForeignFunc enum variants in
Type.hs:Crypto_Argon2_HashRawCrypto_Argon2_VerifyRawImplemented foreign functions in
Function.hs:argon2HashRawWrapper- CallsArgon2.hashwith user options/salt, returns raw hash bytesargon2VerifyRawWrapper- Re-hashes password with same parameters and does constant-time comparisonargon2ErrMsg- Maps allCryptoErrorcodes to human-readable messagesAdded 6-tuple ForeignConvention support - The hash function takes 6 arguments (4 options + password + salt), which required adding:
pattern Tup5Vpattern Tup6CdecodeTup6/encodeTup6ForeignConvention (a,b,c,d,e,f)instanceInteresting/controversial decisions
Argon2id only - Only exposed Argon2id variant (not Argon2i or Argon2d). Argon2id is the recommended hybrid approach that provides both side-channel resistance and GPU/ASIC resistance.
Individual Nat arguments vs options struct - Chose individual
Natarguments for the builtins rather than a struct. This keeps the builtins simple; wrapper functions in@unison/basecan provide a nicerArgon2Optionsstruct API.Raw bytes API - The builtins work with raw bytes rather than PHC-encoded strings. This is the lower-level API; PHC encoding can be added in
@unison/basewrapper functions if needed.Either Failure Boolean for verify -
verifyRawreturnsEither Failure Booleanrather than justBoolean. This allows callers to distinguish between:Right True- password matchesRight False- password doesn't match (not an error)Left Failure- crypto error (e.g., invalid parameters)This is important because a crypto error (like invalid salt size) is a data integrity issue worth logging, whereas a wrong password is expected behavior.
6-tuple support - Added general 6-tuple
ForeignConventionrather than using nested tuples, as it's cleaner and may benefit other future builtins.cryptonite to crypton migration - Took the opportunity to migrate the entire codebase from the unmaintained
cryptoniteto its actively-maintained forkcrypton, which has an identical API.Test coverage
Transcript test added:
unison-src/transcripts/idempotent/argon2.mdRight true)Right false)Left Failurewith descriptive message)Additional test coverage could include:
Loose ends
Argon2Optionstype, and PHC encoding can be added to@unison/basein a follow-up PR to that repoFinal checklist
unison-src/transcripts/idempotent/argon2.md