-
Notifications
You must be signed in to change notification settings - Fork 387
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
argon2: choose a steady parallelism value #3630
Conversation
Change-Id: I6006da7d7980cda88f5f08ee759612df23a8132d
pkg/encryption/password.go
Outdated
@@ -25,19 +24,19 @@ func sha256hmac(key, data []byte) ([]byte, error) { | |||
|
|||
// DeriveRootKey derives a root key for some path using the salt for the bucket and | |||
// a password from the user. See the password key derivation design doc. | |||
func DeriveRootKey(password, salt []byte, path storj.Path) (*storj.Key, error) { | |||
func DeriveRootKey(password, salt []byte, argon2Threads uint8) (*storj.Key, error) { |
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.
Removing the path changes the design (https://github.com/storj/storj/blob/master/docs/blueprints/password-key-derivation.md#design)
While it's not used, it exists to allow different root encryption keys at different paths inside of a bucket.
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.
okay nbd to bring it back. i wrongly assumed it was refactor cruft
Change-Id: Ied9039f9a9be1d0f6ff3c7d5c4839a83fc7b4b1f
Change-Id: I07288cd6cef32ba387f2f003febff5c297e50997
Change-Id: Icdbda8b709cc100a86f3859303c40edb8dff1e0f
@@ -40,6 +40,8 @@ type GatewayFlags struct { | |||
uplink.Config | |||
|
|||
Version checker.Config | |||
|
|||
PBKDFConcurrency int `help:"please see <url>. default value recommended" default:"0"` |
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.
Do we need to put an actual URL value here?
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.
yes, we also need to update the comment about which version numbers the problem applies to, once we have a version it no longer applies to. i'll submit a new pr with updates for both when that happens
* argon2: choose a steady parallelism value Change-Id: I6006da7d7980cda88f5f08ee759612df23a8132d * whoops, not cruft Change-Id: Ied9039f9a9be1d0f6ff3c7d5c4839a83fc7b4b1f * fix broken test file Change-Id: I07288cd6cef32ba387f2f003febff5c297e50997 * fix linting error Change-Id: Icdbda8b709cc100a86f3859303c40edb8dff1e0f (cherry picked from commit 031ba86)
* storj/master: (63 commits) web/satellite: token payments logic (#3581) satellite/metainfo: reduce pointerDB access for CommitObject (#3589) satellite/metainfo: Fix misspelling in comment (#3636) argon2: choose a steady parallelism value (#3630) satellitedb: add support to testplanet for cockroachdb (#3634) satellite/console/auth: return in error handle added (#3639) Make sed a little more cross platformable (#3629) web: ms edge support bug fixed (#3638) web/satellite: registration/welcome message fixed, usage-report url fixed, storj-sim fixed (#3622) web/satellite: fonts changed to Inter (#3620) storagenode/updater: read identity location from storagenode's config.yaml (#3607) cmd/segment-reaper: Implement bitmask type (#3626) storagenode/gracefulexit: improve logging (#3633) private/testplanet: add a mock referral manager server into testplanet (#3631) satellite/gracefulexit: refactor concurrency (#3624) pkg/pb/referralmanager: update to add satellite ID to Get Tokens request (#3625) satellite/metainfo: improve Loop comments (#3595) storagenode: add bandwidth metrics (#3623) satellite/console: Add security headers (#3615) satellite/payments: token deposit accept cents (#3628) ...
* argon2: choose a steady parallelism value Change-Id: I6006da7d7980cda88f5f08ee759612df23a8132d * whoops, not cruft Change-Id: Ied9039f9a9be1d0f6ff3c7d5c4839a83fc7b4b1f * fix broken test file Change-Id: I07288cd6cef32ba387f2f003febff5c297e50997 * fix linting error Change-Id: Icdbda8b709cc100a86f3859303c40edb8dff1e0f
Huge thanks to Least Authority, our security audit team, for finding and notifying us of this issue!!! This is almost certainly the cause of lots of bugs we’ve been unable to identify for some time now.
Problem
At the time of this writing, this line of code is how we turn a passphrase into a root encryption key:
https://github.com/storj/storj/blob/ee6c1ca/pkg/encryption/password.go#L40
keyData := argon2.IDKey(password, pathSalt, 1, uint32(64*memory.MiB/memory.KiB), uint8(runtime.GOMAXPROCS(-1)), 32)
The documentation for argon2’s IDKey says:
Emphasis mine. (
runtime.GOMAXPROCS(-1)
returns the number of CPUs available).It turns out, argon2 generates different keys depending on the requested parallelism!!
https://play.golang.org/p/cyuYw2cXQxI
In our defense, I think the documentation for the argon2.IDKey method is really misleading, even though we probably should have checked this.
Implications
We generate keys from passphrases whenever someone calls SaltedKeyFromPassphrase in libuplink, or whenever someone runs
uplink setup
orgateway setup
. This is the only time this matters.However, if someone runs
uplink setup
on two different devices with the same project, API key, and passphrase, but the devices have a different number of CPU cores, they will not be able to encrypt or decrypt each installation’s data.If instead, someone uses scopes/encryption accesses for sharing access, key generation is not involved, and this problem will not affect the user.
This is a broad problem that certainly affects all of our users if they ever use more than one device. A sample of Storj employees had surprisingly large variation in the number of cores people had (4, 8, 12, and 16 were all common).
Proposed solution
Uggghhhhh
Well, so it’s easy to fix for all new users going forward. We pick the argon2 parallelism statically.
For all existing users it’s hard. There is no default value that will broadly work for most people. Continuing to use CPU-specific settings means that decryption does not interoperate well.
We could give up on passphrase determinism (scopes are unaffected, and just require everyone to save their scopes), but then why have passphrases at all?
So, we have a couple of different users affected.
This change does everything but the error cleanup.
Code Review Checklist (to be filled out by reviewer)