-
Notifications
You must be signed in to change notification settings - Fork 65
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
feat: Support sha256 and sha512 oaep algorithms #240
Conversation
We want to check that the async onDecrypt function returns a promise that rejects. We were trying to use chai-as-promised's rejectedWith matcher for this, but within an `async` function. It looks like mocha isn't clever enough to wait for the promise to reject and run the assertion unless we return the promise from the function. It prints a warning about the uncaught promise rejection instead. Once we fix the test to return the promise it fails, because the promise is not actually being rejected, so I'm excluding it while I work on a fix.
This test was excluded because the precondition wasn't hit when calling `keyring.onDecrypt` (I think due to another precondition somewhere else). It might be a bit sneaky to call the "private" method (`_unwrapKey`) in the tests, but it hits the precondition we're trying to test more directly.
This is particularly useful because CloudFront's Field Level Encryption uses RSA_OAEP_SHA256_MGF1, which this library doesn't support yet. Support for oaepHash was added in node 12.9 (nodejs/node#28335), so this won't work for older node versions. It's still a backwards compatible change because by default `oaepHash` will be undefined, as before. I've updated the tests to cover use of the new parameter, but they're not very strict because they both encrypt and decrypt using the same parameter. This means if node silently ignores the oaepHash parameter (as it will in versions < 12.9) the tests will still pass, which isn't great. On the other hand, I think this project may still be being tested on an older version of node, so perhaps the fact the tests won't break is an unexpected blessing. I've also tested this manually against AWS CloudFront's Field Level Encryption and it seems to work. Resolves aws#198
This is most excellent. Thank you. This will also need to be updated. |
Judging from the types in the test, this is supported by other libraries, and it looks like it also works in node.
I haven't been able to run these tests myself to confirm they work because there's a fair bit of setup I don't know how to do. I'd expect the tests to fail on versions of node < 12.9, which may be a problem for CI.
👍 thanks! I had a go at adding support in the integration tests. I haven't been able to run them myself because I don't fully understand the setup (they seem to want to connect to KMS, which I'm not going to let them do). Hopefully CI should run them for me, but if it's using a node version older than 12.9 they'll probably fail, at which point I might need some help - we'll see how we go :) |
I guess the failing build is due to < 12.9 node version in the integration tests, but I can't see the output. Over to you @seebees. |
You are right. The issues is v10 vs v12. We are going to need 3 things.
OpenSSL will take, and Node.js will pass, any hash as a valid hash. But the ESDK only supports SHA-1 and SHA-2 :) . Also it will pass through the hash even if you select
I suppose the best way is just to try it in the initialization. Ugly but practical. To run the integration tests, all that is needed is AWS credentials.
Thanks again! |
Thanks - sounds good. On the precondition, I can't think of a nice way of feature detecting support for the oaepHash parameter. I think the options are:
I guess that by "I suppose the best way is just to try it in the initialization" you mean you'd prefer the first option? |
I did some work on this, I do think that actually testing it is, unfortunately, the way to go here. |
It is important to be perscriptive in what options will work. Node.js versions that do not support `oaepHash` will silently encrypt data. This means that the encrypted data key would not have the security properties requested. So, `oaep_hash_supported.ts` will attempt to encrypt and report the success. This will happen only once, on initializaion. Both the tests, and the integration tests have been updated honor `oaepHashSupported` values
@richardTowers Turns out I don't have access to push to your fork :( |
Ah yes - I've just invited you to collaborate on the fork, so hopefully you should be able to push now. Your code looks good to me - it's true that the feature detection is a bit confusingly backwards, but it seems robust. Shame there's no runtime types or reflection in JS, but you work with what you've got I suppose. |
Pushed. |
Agree completely, yeah. I'm happy with the commit you pushed, so as far as I'm concerned this PR is good to go. That said, I haven't run the integration tests against node v12, and I'm guessing CI hasn't either. It looks like you've already got an issue to test against a matrix of node versions (#206), but perhaps a manual run would be enough for this PR. |
Also note, if this lands, AWS should update this documentation to call out support in newer node versions: https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/javascript.html#javascript-language-compatibility (edit: I had the wrong link) |
Thanks. I have run this agains v12 locally. |
Issue #, if available: #198
Description of changes:
AWS CloudFront Field Level Encryption uses the
RSA_OAEP_SHA256_MGF1
suite of algorithms. Because this library's raw RSA code only supports OAEP_SHA1, it can't be used to decrypt CloudFront fields.Support for oaepHash was added in node's crypto library in node 12.9 (nodejs/node#28335), so it's possible to expose this functionality through this library now.
I've tested this manually against AWS CloudFront with Field Level Encryption set, and it seems to work nicely.
I also spotted some async test warnings, so I've done my best to clean those up. See the individual commits for more detail.
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
Check any applicable: