-
Notifications
You must be signed in to change notification settings - Fork 258
Fix insecure use of AES-256-CTR cipher (#296) #299
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
Using the same IV twice with a counter mode cipher breaks the security of the cipher. Switch to AES-256-CBC. I made the cipher nonconfigurable because it seems more likely than not that people will get it wrong otherwise. This commit also drops the dependency on the secure-keys module, which appears to be unmaintained and didn't really live up to its name.
| "config-key-name": { | ||
| "alg": "aes-256-ctr", // cipher used | ||
| "alg": "aes-256-cbc", // cipher used | ||
| "value": "af07fbcf" // encrypted contents |
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.
Caveat emptor: CBC mode pads up to the block size so the value doesn't really look like this, it'll be longer.
|
Forgot to add, this PR uses a CBC cipher with a fixed IV. I wrote it that way to keep code that is already using aes-256-cbc from breaking but ideally a unique IV is used every time (more details). |
|
@bnoordhuis thanks for the PR! Given that this will go into nconf 1.x, my thought is that we have a chance to do "crypto" properly. Since that forcing the CBC cipher is already a breaking change, I would recommend that we force users to either pass in a key + iv that they've derived, or at least allow a password + salt and run that through Thoughts? |
This PR respects existing Of course fixing it properly is best but I figured this could go into a v0.x release and fix the immediate issue. For v1.0, I'd recommend switching to aes-256-gcm: that provides encryption and integrity, not just encryption.
Ouch, we say that in our crypto docs, don't we? Yeah, so that's not quite correct in this case: it's okay to key-stretch the secret to fit the cipher's passphrase size but the IV should be unique every time, otherwise identical plaintexts encrypt to identical ciphertexts. The logic would look something like this: // ...
var passphrase = crypto.pbkdf2Sync(secret, salt, 1e5, 32, 'sha256');
var iv = crypto.randomBytes(16);
var ciphertext = encrypt(passphrase, iv, data);
var value = iv.toString('hex') + ciphertext.toString('hex');
// ...I'll open a nodejs/node issue to get the documentation updated. |
|
Ping. It's been five months. |
|
@bnoordhuis Thanks for the reminder. I was a bit out of commission shortly after you opened this PR, so apologies for the delay. I want to get this merged ASAP. Will try to do some testing on my own just to ensure backwards compatibility, but would be good if you can include a test to that effect as well. Additionally, a PR fixing this "the right way" for v1.x would be greatly appreciated as well, if you get the time/opportunity. :-) |
The previous commit changed the cipher from AES-256-CTR to AES-256-CBC. This commit tests that stores predating that change still work. Note that AES-256-CTR is accepted as input but never written as output.
@mhamann Done. I don't know if I'll have time to write a proper fix anytime soon. |
|
Thanks @bnoordhuis. I figured you stay pretty busy ;-) I'll see if I can get my security hat on long enough to work something up and then maybe send a review request your way. |
|
This has been resolved via #322 due to some other changes that occurred upstream. Thanks for providing the building blocks for getting this fixed! |
Using the same IV twice with a counter mode cipher breaks the security
of the cipher. Switch to AES-256-CBC.
I made the cipher nonconfigurable because it seems more likely than not
that people will get it wrong otherwise.
This commit also drops the dependency on the secure-keys module, which
appears to be unmaintained and didn't really live up to its name.