-
Notifications
You must be signed in to change notification settings - Fork 30k
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
crypto: add sign/verify support for RSASSA-PSS #11705
Conversation
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.
Thanks for picking this up!
/cc @nodejs/crypto
doc/api/crypto.md
Outdated
The optional `options` argument is an object which specifies additional | ||
cryptographic parameters. Currently, the following options are supported: | ||
|
||
* `padding` : {String} - RSA padding, either `'pkcs1'` for RSASSA-PKCS1-v1_5 |
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.
Could you use lowercase string
here and drop the space before the :
?
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.
Sure, but note that the rest of the document seems to use the uppercase variant and has a space before the colon.
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.
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 that an options object is introduced, it seems the current positional parameter, output_format
, should be possible to express as an option. encoding
would be the more common name for it, I think.
doc/api/crypto.md
Outdated
(default) or `'pss'` for RSASSA-PSS | ||
* `saltLength` : {number} - salt length for RSASSA-PSS. If this is set to `-1`, | ||
the salt length will be set to the digest size. If this is set to `-2` | ||
(default), the salt length will be set to the maximum permissible value. |
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.
It might be nice to have these two values exposed as named constants on crypto.constants
… what do you think?
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.
Great, will do so! What is the best way to define a constant which is not #define
d? I have only seen people using NODE_DEFINE_CONSTANT
with existing defs. Should I just #define RSA_PKCS1_PSS_MAX_SALT_LENGTH -2
and then use NODE_DEFINE_CONSTANT
?
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.
Should I just
#define RSA_PKCS1_PSS_MAX_SALT_LENGTH -2
and then useNODE_DEFINE_CONSTANT
?
I don’t see any problem with that. :) It’s quite possible that somebody else here comes up with a better suggestion, but for the time being, I’d recommend just doing it the way you just described.
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.
Latest OpenSSL (1.1.1-dev) changes its definitions as digest
, max
and auto
(only in verification). https://github.com/openssl/openssl/blob/master/doc/man1/pkeyutl.pod#rsa-algorithm
I guess that auto
can be implemented even in openssl-1.0.2. I think it is better to follow it.
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.
named constants would be better, or perhaps strings ('digest'
, 'max'
, and 'auto'
), or perhaps both (named constants with the values being strings, not magic negative numbers)
src/node_crypto.cc
Outdated
int SignBase::GetRSAOptions(Environment *env, v8::Local<v8::Object> options, | ||
int *padding, int *saltlen) { | ||
Local<Value> key = String::NewFromUtf8(env->isolate(), "padding"); | ||
MaybeLocal<Value> maybePadding = options->Get(key); |
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.
You might want to add this to the PER_ISOLATE_STRING_PROPERTIES
table in env.h
and then simply use options->Get(env->padding_string())
instead
src/node_crypto.cc
Outdated
int *padding, int *saltlen) { | ||
Local<Value> key = String::NewFromUtf8(env->isolate(), "padding"); | ||
MaybeLocal<Value> maybePadding = options->Get(key); | ||
if (!maybePadding.IsEmpty()) { |
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.
If maybePadding
is empty you can just return 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.
Considering that I return 0
after throwing an exception (so 0 <=> error
), I should probably return 1
here as it should be optional to specify the padding. Apart from that, I agree.
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.
Considering that I
return 0
after throwing an exception (so0 <=> error
), I should probablyreturn 1
here as it should be optional to specify the padding.
In the case where maybePadding
is empty you can safely assume that an exception is pending (e.g. if the getter for "padding"
threw an error – which is obviously mostly hypothetical, but since it’s an object passed in from userland, it’s possible). So, returning 0
and returning back to JS as quickly as possible should be the right thing to do.
If the property is missing, you’ll get an Undefined
value, not an empty MaybeLocal
.
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.
If the property is missing, you’ll get an
Undefined
value, not an emptyMaybeLocal
.
Oh, that makes it clear. I did not know that, sorry!
src/node_crypto.cc
Outdated
Local<Value> paddingValue = maybePadding.ToLocalChecked(); | ||
if (paddingValue->IsString()) { | ||
v8::String::Utf8Value paddingUtf8(paddingValue); | ||
const char *paddingName = *paddingUtf8; |
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.
style nit: const char*
(I know we’re not being consistent in the code base 😄)
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.
Actually… crypto.constants.RSA_PKCS1_PSS_PADDING
and crypto.constants.RSA_PKCS1_PADDING
already exist and are accessible from userland. Maybe we could use these constants instead of a string?
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.
Nice, must have missed those when I skimmed through the constants. I just noticed that the asymmetric encrypt/decrypt API allows to specify padding
as part of the first argument (where key
, passphrase
and padding
are properties of the object). Should I remove the additional options
object and add the properties to the first argument for sign()
/ verify()
as well in order to keep it consistent?
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.
@sam-github @addaleax @bnoordhuis Thoughts on this? I have no problem keeping it as it is, with options
as an additional parameter, but you might prefer to keep it consistent with publicEncrypt
etc.
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, it should be like publicEncrypt, etc, with .padding
part of the first argument.
src/node_crypto.cc
Outdated
if (*padding == RSA_PKCS1_PSS_PADDING) { | ||
key = String::NewFromUtf8(env->isolate(), "saltLength"); | ||
MaybeLocal<Value> maybeSaltlen = options->Get(key); | ||
if (!maybeSaltlen.IsEmpty()) { |
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.
ditto, if (maybeSaltlen.IsEmpty()) return 0;
src/node_crypto.cc
Outdated
else if (strcmp(paddingName, "pss") == 0) { | ||
*padding = RSA_PKCS1_PSS_PADDING; | ||
} | ||
else { |
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.
style nit: } else {
on one line
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.
ditto.
src/node_crypto.cc:3971: An else should appear on the same line as the preceding } [whitespace/newline] [4]
src/node_crypto.cc:3971: If an else has a brace on one side, it should have it on both [readability/braces] [5]
src/node_crypto.cc
Outdated
goto err; | ||
|
||
if (mdctx->digest->flags & EVP_MD_FLAG_PKEY_METHOD_SIGNATURE) { | ||
size_t sltmp = (size_t)EVP_PKEY_size(pkey); |
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.
style nit: static_cast<size_t>
instead of (size_t)
(assuming that works 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.
This causes s cross initialization error during build. Move its definition before goto.
../src/node_crypto.cc: In function ‘int node::crypto::Node_SignFinal(EVP_MD_CTX*, unsigned char*, unsigned int*, EVP_PKEY*, int, int)’:
../src/node_crypto.cc:4109:4: error: jump to label ‘err’ [-fpermissive]
err:
^
../src/node_crypto.cc:4086:10: note: from here
goto err;
^
../src/node_crypto.cc:4089:12: note: crosses initialization of ‘size_t sltmp’
size_t sltmp = (size_t)EVP_PKEY_size(pkey);
^
src/node_crypto.cc
Outdated
goto err; | ||
if (padding == RSA_PKCS1_PSS_PADDING) | ||
if (EVP_PKEY_CTX_set_rsa_pss_saltlen(pkctx, saltlen) <= 0) | ||
goto err; |
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.
style nit: can you add {}
if the body of an if
spans more than a single line?
src/node_crypto.cc
Outdated
@@ -4357,8 +4477,15 @@ void Verify::VerifyFinal(const FunctionCallbackInfo<Value>& args) { | |||
hbuf = Buffer::Data(args[1]); | |||
} | |||
|
|||
int padding = RSA_PKCS1_PADDING; | |||
int saltlen = -2; | |||
if (args.Length() >= 4 && args[3]->IsObject()) { |
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.
Fwiw you don’t need the args.Length()
part of the check, if args[3]
is out of bounds it will just be undefined
. I don’t mind keeping it if you think that helps with readability, though.
src/node_crypto.cc
Outdated
int padding = RSA_PKCS1_PADDING; | ||
int saltlen = -2; | ||
if (args.Length() >= 4 && args[3]->IsObject()) { | ||
verify->GetRSAOptions(env, args[3]->ToObject(), &padding, &saltlen); |
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.
Forgot to comment … can you check the return value here and return from the function if there was an error?
lib/crypto.js
Outdated
var key = options.key || options; | ||
var passphrase = options.passphrase || null; | ||
var ret = this._handle.sign(toBuf(key), null, passphrase); | ||
if (typeof encoding == 'object' && !options) { |
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.
I think ===
is better than ==
.
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.
I guess it does not make a difference when using typeof
, but I can surely change it.
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, doesn't make a difference, but node style is currently to always use ===
, unless using ==
is necessary (mostly for comparisons against unsigned
and null
in a single operation)
lib/crypto.js
Outdated
Verify.prototype.verify = function verify(object, signature, sigEncoding) { | ||
Verify.prototype.verify = function verify(object, signature, sigEncoding, | ||
options) { | ||
if (typeof sigEncoding == 'object' && !options) { |
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.
same here
src/node_crypto.cc
Outdated
goto err; | ||
|
||
if (mdctx->digest->flags & EVP_MD_FLAG_PKEY_METHOD_SIGNATURE) { | ||
size_t sltmp = (size_t)EVP_PKEY_size(pkey); |
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.
This causes s cross initialization error during build. Move its definition before goto.
../src/node_crypto.cc: In function ‘int node::crypto::Node_SignFinal(EVP_MD_CTX*, unsigned char*, unsigned int*, EVP_PKEY*, int, int)’:
../src/node_crypto.cc:4109:4: error: jump to label ‘err’ [-fpermissive]
err:
^
../src/node_crypto.cc:4086:10: note: from here
goto err;
^
../src/node_crypto.cc:4089:12: note: crosses initialization of ‘size_t sltmp’
size_t sltmp = (size_t)EVP_PKEY_size(pkey);
^
src/node_crypto.cc
Outdated
if (strcmp(paddingName, "pkcs1") == 0) { | ||
*padding = RSA_PKCS1_PADDING; | ||
} | ||
else if (strcmp(paddingName, "pss") == 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.
Lint error.
src/node_crypto.cc:3968: An else should appear on the same line as the preceding } [whitespace/newline] [4]
src/node_crypto.cc:3968: If an else has a brace on one side, it should have it on both [readability/braces] [5]
src/node_crypto.cc
Outdated
else if (strcmp(paddingName, "pss") == 0) { | ||
*padding = RSA_PKCS1_PSS_PADDING; | ||
} | ||
else { |
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.
ditto.
src/node_crypto.cc:3971: An else should appear on the same line as the preceding } [whitespace/newline] [4]
src/node_crypto.cc:3971: If an else has a brace on one side, it should have it on both [readability/braces] [5]
doc/api/crypto.md
Outdated
(default) or `'pss'` for RSASSA-PSS | ||
* `saltLength` : {number} - salt length for RSASSA-PSS. If this is set to `-1`, | ||
the salt length will be set to the digest size. If this is set to `-2` | ||
(default), the salt length will be set to the maximum permissible value. |
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.
Latest OpenSSL (1.1.1-dev) changes its definitions as digest
, max
and auto
(only in verification). https://github.com/openssl/openssl/blob/master/doc/man1/pkeyutl.pod#rsa-algorithm
I guess that auto
can be implemented even in openssl-1.0.2. I think it is better to follow it.
doc/api/crypto.md
Outdated
* `saltLength` : {number} - salt length for RSASSA-PSS. If this is set to `-1`, | ||
the salt length will be set to the digest size. If this is set to `-2` | ||
(default), the salt length will be set to the maximum permissible value. | ||
|
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.
There are no descriptions for mgf1 and its hash. The default behavior is that the mgf1 hash is the same as the sign/verify hash. I think it needs to not to add an additional option parameter for mgf1 but its spec should be described in the doc.
}); | ||
}); | ||
} | ||
|
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.
There are test vectors for RSA-PSS in the link of https://www.emc.com/emc-plus/rsa-labs/standards-initiatives/pkcs-rsa-cryptography-standard.htm . We can make verify tests by using this test vectors.
If you cannot get the test vector file, it is in https://github.com/shigeki/ohtsu_rsa_pss_js/blob/master/tests/vectors/pss-vect.txt. Please refer related test vectors of RSA-PSS(example1 for RSA1024bits, and example10 for RSA2048bits) in JavaScript are in https://github.com/shigeki/ohtsu_rsa_pss_js/tree/master/tests/ .
Unfortunately, openssl cannot accept explicit salt. So we can make sign tests for RSA-PSS by writing signature data to files and verifying its signature by using openssl dgst
command with -signopt rsa_padding_mode:pss
.
doc/api/crypto.md
Outdated
@@ -1039,6 +1048,16 @@ the `signature_format` which can be `'latin1'`, `'hex'` or `'base64'`. | |||
If a `signature_format` is specified, the `signature` is expected to be a | |||
string; otherwise `signature` is expected to be a [`Buffer`][]. | |||
|
|||
The optional `options` argument is an object which specifies additional |
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.
as for sign, signature_format
should be possible to pass as encoding
in the options
unrelated, but
If a
signature_format
is specified, thesignature
is expected to be a
string; otherwisesignature
is expected to be a [Buffer
][].
is a bizarre restriction, I wonder if it is even accurate? I will investigate.
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.
needs more tests for the various argument pemutations (with options, without options, options in the various argument positions)
lib/crypto.js
Outdated
var key = options.key || options; | ||
var passphrase = options.passphrase || null; | ||
var ret = this._handle.sign(toBuf(key), null, passphrase); | ||
if (typeof encoding == 'object' && !options) { |
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.
if typeof encoding == object, && there are also options, that should be an error
lib/crypto.js
Outdated
} | ||
|
||
var key = privateKey.key || privateKey; | ||
var passphrase = privateKey.passphrase || null; |
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.
what about when privateKey is passed in options
? It would not make sense that .passPhrase
is supported when the options object is first argument, but not supported when it is second or third argument
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.
Is this still relevant when changing the options
object to be the first argument, such that the first argument is either the privateKey
itself or an options
object with properties key
and optionally passphrase
, padding
and/or saltLength
?
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.
no, it would not be, if there is only one options object, there can be no inconsistency between the options allowed in the various options objects
lib/crypto.js
Outdated
var key = options.key || options; | ||
var passphrase = options.passphrase || null; | ||
var ret = this._handle.sign(toBuf(key), null, passphrase); | ||
if (typeof encoding == 'object' && !options) { |
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, doesn't make a difference, but node style is currently to always use ===
, unless using ==
is necessary (mostly for comparisons against unsigned
and null
in a single operation)
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.
The code mostly looks good to me, I’ll just refrain from approving the PR because I don’t understand the subject matter well enough
doc/api/crypto.md
Outdated
* `passphrase`: {string} - passphrase for the private key | ||
* `padding`: {String} - RSA padding, either `RSA_PKCS1_PADDING` (default) or | ||
`RSA_PKCS1_PSS_PADDING` | ||
* `saltLength`: {number} - salt length for RSASSA-PSS. The special value |
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.
padding
and saltLength
should both be integer
, right? (Or at least number
. But integer
seems to be what’s coming out of the discussion @ #11697)
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.
This is weird, I thought I had already fixed the documentation regarding the use of integer constants. Seems like I messed that up when committing. Fixed in the latest commit :)
doc/api/crypto.md
Outdated
* `key`: {string} - PEM encoded private key (required) | ||
* `padding`: {string} - RSA padding, either `'pkcs1'` for RSASSA-PKCS1-v1_5 | ||
(default) or `'pss'` for RSASSA-PSS | ||
* `saltLength`: {number} - salt length for RSASSA-PSS. If this is set to `-1`, |
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.
ditto
doc/api/crypto.md
Outdated
* `padding`: {string} - RSA padding, either `'pkcs1'` for RSASSA-PKCS1-v1_5 | ||
(default) or `'pss'` for RSASSA-PSS | ||
* `saltLength`: {number} - salt length for RSASSA-PSS. If this is set to `-1`, | ||
the salt length will be set to the digest size. A value of `-2` (default) |
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.
Can you use the constant name instead of -2
for specifying the default? Ideally, users won’t have to care what particular value the constant has
src/node_crypto.cc
Outdated
*padding = paddingValue->Int32Value(); | ||
break; | ||
default: | ||
env->ThrowError("Padding must be RSA_PKCS1_PADDING or " |
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.
nit: lowercase padding
(or generally whatever it corresponds to in the documentation)
src/node_constants.cc
Outdated
|
||
#ifndef RSA_PSS_SALTLEN_AUTO | ||
#define RSA_PSS_SALTLEN_AUTO -2 | ||
#endif |
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.
It would be nice if you could #define
these constants in a header and then include it in the source files that rely on the specific value. node_constants.h
probably works for that, or maybe node_crypto.h
.
src/node_crypto.cc
Outdated
EVP_PKEY_CTX *pkctx = nullptr; | ||
|
||
*s = 0; | ||
if (!EVP_DigestFinal_ex(mdctx, &(m[0]), &m_len)) |
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.
I’d personally prefer just m
instead of &(m[0])
here
@addaleax I noticed, thought I had changed both occurrences to |
src/node_crypto.cc
Outdated
@@ -4132,6 +4212,14 @@ void Sign::SignFinal(const FunctionCallbackInfo<Value>& args) { | |||
size_t buf_len = Buffer::Length(args[0]); | |||
char* buf = Buffer::Data(args[0]); | |||
|
|||
int padding = RSA_PKCS1_PADDING; | |||
int saltlen = -2; |
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.
Mh, sorry if I wasn’t clear, but my idea was that you could add #include "node_constants.h"
at the top of this file and then use the constants here where you currently use the magic numbers directly
doc/api/crypto.md
Outdated
* `passphrase`: {string} - passphrase for the private key | ||
* `padding`: {integer} - RSA padding, either `RSA_PKCS1_PADDING` (default) or | ||
`RSA_PKCS1_PSS_PADDING` | ||
* `saltLength`: {integer} - salt length for RSASSA-PSS. The special value |
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.
replace RSASSA-PSS with "when padding is RSA_PKCS1_PSS_PADDING
"
doc/api/crypto.md
Outdated
one an RSA public key, a DSA public key, or an X.509 certificate. | ||
The `object` argument can be either a string containing a PEM encoded object, | ||
which can be one an RSA public key, a DSA public key, or an X.509 certificate, | ||
or an object with some of the following properties: |
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.
I like the way the first argument is described here much better than how it is described for sign. It would be nice to align them, though the inconsistency is pre-existing, and if you don't have the time that's OK.
doc/api/crypto.md
Outdated
* `key`: {string} - PEM encoded private key (required) | ||
* `padding`: {integer} - RSA padding, either `RSA_PKCS1_PADDING` (default) or | ||
`RSA_PKCS1_PSS_PADDING` | ||
* `saltLength`: {integer} - salt length for RSASSA-PSS. The special value |
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.
"for when padding is RSA_PKCS1_PSS_PADDING
" - because people may not know the relationship between RSA_PKCS1_PSS_PADDING and RSASSA-PSS
doc/api/crypto.md
Outdated
@@ -1966,6 +1981,18 @@ the `crypto`, `tls`, and `https` modules and are generally specific to OpenSSL. | |||
<td></td> | |||
</tr> | |||
<tr> | |||
<td><code>RSA_PSS_SALTLEN_DIGEST</code></td> | |||
<td></td> |
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.
I think a little bit of docs are useful here, because the constants are asymetrical. DIGEST can be used with sign and verify, MAX_SIGN only with sign, and _AUTO only with verify. It surprised me when I saw the last two constants had the same value, and I had to go back to the docs and compare the sign and verify docs to realize that some of the PSS constants were method specific, and some weren't.
src/node_crypto.cc
Outdated
Local<Value> paddingValue = maybePadding.ToLocalChecked(); | ||
if (paddingValue->IsNumber()) { | ||
switch (paddingValue->Int32Value()) { | ||
case RSA_PKCS1_PADDING: |
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.
node is a bit irregular on this, but every case
statement in node_crypto.cc is indented 2 spaces more than the switch
, best to be consistent
src/node_crypto.cc
Outdated
unsigned int *sig_len) { | ||
unsigned int *sig_len, | ||
int padding, | ||
int saltlen) { |
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.
sig_len
, therefor salt_len
src/node_crypto.cc
Outdated
if (EVP_PKEY_CTX_set_signature_md(pkctx, mdctx_.digest) <= 0) | ||
goto err; | ||
r = EVP_PKEY_verify(pkctx, | ||
reinterpret_cast<const unsigned char*>(sig), |
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.
node_crypto.cc is a bit schismatic, but style is either to have all the args aligned four spaces from start of line, or to align
them with the column after the (
src/node_crypto.cc
Outdated
bool verify_result; | ||
Error err = verify->VerifyFinal(kbuf, klen, hbuf, hlen, &verify_result); | ||
Error err = verify->VerifyFinal(kbuf, klen, hbuf, hlen, padding, saltlen, |
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.
verify_result
, therefor salt_len
src/node_crypto.h
Outdated
@@ -556,6 +556,8 @@ class SignBase : public BaseObject { | |||
|
|||
protected: | |||
void CheckThrow(Error error); | |||
int GetRSAOptions(Environment *env, v8::Local<v8::Object> options, | |||
int *padding, int *saltlen); |
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.
salt_len
@@ -71,6 +71,54 @@ const keyPem = fs.readFileSync(common.fixturesDir + '/test_key.pem', 'ascii'); | |||
assert.strictEqual(verified, true, 'sign and verify (stream)'); | |||
} | |||
|
|||
{ | |||
[ 'RSA-SHA1', 'RSA-SHA256' ].forEach((algo) => { |
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.
['RSA...SHA256']
, and below
coming along well, I like the new method calling convention |
@tniessen Looks like this needs to be rebased against |
@addaleax That should do it, hope I did not mess anything up. |
Thanks! |
CI is green except for a weird OS X failure @ https://ci.nodejs.org/job/node-test-commit-osx/8287/nodes=osx1010/console @nodejs/build Another attempt to be sure it’s unrelated: https://ci.nodejs.org/job/node-test-commit/8353/ |
doc/api/crypto.md
Outdated
@@ -935,10 +935,16 @@ Calculates the signature on all the data passed through using either | |||
|
|||
The `private_key` argument can be an object or a string. If `private_key` is a | |||
string, it is treated as a raw key with no passphrase. If `private_key` is an | |||
object, it is interpreted as a hash containing two properties: | |||
object, it is interpreted as a hash containing some of these properties: |
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.
"one or more of the following" sounds a bit better to my ears.
Tangential aside: 'hash' is a somewhat unfortunate choice of words here, seeing how we describe hash functions a few lines up.
doc/api/crypto.md
Outdated
* `saltLength`: {integer} - salt length for when padding is | ||
`RSA_PKCS1_PSS_PADDING`. The special value `RSA_PSS_SALTLEN_DIGEST` sets the | ||
salt length to the digest size, `RSA_PSS_SALTLEN_MAX_SIGN` (default) sets it | ||
to the maximum permissible value. |
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.
This needs to be clearer on the fact that you obtain the constants from crypto.constants
. Likewise verifier.update()
.
src/node_crypto.cc
Outdated
@@ -3952,6 +3954,37 @@ void SignBase::CheckThrow(SignBase::Error error) { | |||
} | |||
} | |||
|
|||
int SignBase::GetRSAOptions(Environment* env, v8::Local<v8::Object> options, |
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.
Please change the return type to bool. Better yet, I'd do the validation in lib/crypto.js, not 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.
But doesn't that imply passing the padding etc. from JavaScript to the binding as additional arguments instead of an options
object? I considered that as well, but assuming that RSASSA-PSS is not the last addition to sign()
/verify()
, it decided it could become pretty clumsy to pass all options as positional parameters.
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.
Positional arguments are easier and more efficient than wrangling objects in C++ land.
As well, it would get rid of the ThrowError(). Validation code that throws JS exceptions as a side effect tends to be pretty brittle. Callers need to be very careful not to re-enter the VM on return but that is easy to get wrong.
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.
@bnoordhuis fwiw, I’m good with the current approach. It’s readable (imho) and microperformance probably isn’t too relevant when compared against the cost of the crypto operations itself.
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.
@bnoordhuis I can fix this by adding more positional arguments if you think that is the reasonable way. I do not know enough about node internals to fully evaluate the effects. I guess I should move default values to JS as well, such that the native code does not need to handle undefined values.
I am still a little concerned considering that it might be necessary to add more options in the future and all of these are optional, meaning that we might end up passing useless arguments most of the time.
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.
I guess I should move default values to JS as well, such that the native code does not need to handle undefined values.
Yes, that's a good idea.
it might be necessary to add more options in the future and all of these are optional, meaning that we might end up passing useless arguments most of the time.
Efficiency-wise a few extra parameters won't break the bank (they're just stack slots) and like Anna says, the cost of crypto itself probably dwarfs the overhead.
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.
I guess I should move default values to JS as well, such that the native code does not need to handle undefined values.
Yes, that's a good idea.
But what if args[3]->IsInt32()
etc. returns false/fails? Should I just skip these tests, throw an exception, return silently...? (Or just keep "additional" default values in the native code).
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.
You can CHECK(args[3]->IsInt32())
, it's a bug when it asserts.
src/node_crypto.cc
Outdated
@@ -3952,6 +3954,37 @@ void SignBase::CheckThrow(SignBase::Error error) { | |||
} | |||
} | |||
|
|||
int SignBase::GetRSAOptions(Environment* env, v8::Local<v8::Object> options, | |||
int* padding, int* saltlen) { | |||
MaybeLocal<Value> maybePadding = options->Get(env->padding_string()); |
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.
Style: use snake_case (i.e., maybe_padding
) for locals.
Substance: can you use options->Get(env->context(), env->padding_string())
here? You're currently using the overload that returns a Local<Value>
which is then implicitly converted to MaybeLocal<Value>
.
src/node_crypto.cc
Outdated
|
||
Local<Value> paddingValue = maybePadding.ToLocalChecked(); | ||
if (paddingValue->IsNumber()) { | ||
*padding = paddingValue->Int32Value(); |
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.
Checking IsNumber() then coercing to int32_t is debatable, not every number is an int32_t.
Can you use the overload that takes a v8::Context
?
src/node_crypto.cc
Outdated
if (mdctx->digest->flags & EVP_MD_FLAG_PKEY_METHOD_SIGNATURE) { | ||
size_t sltmp = static_cast<size_t>(EVP_PKEY_size(pkey)); | ||
pkctx = EVP_PKEY_CTX_new(pkey, nullptr); | ||
if (!pkctx) |
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.
Please use pkctx == nullptr
.
src/node_crypto.cc
Outdated
return rv; | ||
} | ||
|
||
if (!mdctx->digest->sign) { |
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.
Please use mdctx->digest->sign == nullptr
.
src/node_crypto.cc
Outdated
} | ||
|
||
return (mdctx->digest->sign(mdctx->digest->type, m, m_len, md, sig_len, | ||
pkey->pkey.ptr)); |
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.
You can drop the extra parens and please line up the arguments.
src/node_crypto.cc
Outdated
int padding = RSA_PKCS1_PADDING; | ||
int salt_len = RSA_PSS_SALTLEN_MAX_SIGN; | ||
if (args[3]->IsObject()) { | ||
Local<Object> options = Local<Object>::Cast(args[3]); |
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.
You can use args[3].As<Object>()
here, that's what we use most in core.
src/node_crypto.cc
Outdated
if (EVP_PKEY_CTX_set_rsa_pss_saltlen(pkctx, saltlen) <= 0) | ||
goto err; | ||
} | ||
} |
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.
This could probably be shared with the same logic in Node_SignFinal() with some more effort.
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.
I guess I could add a static function just to check whether it is RSA and set the two parameters if it is. Is that what you suggest?
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.
Moving it into a separate function is what I had in mind, yes.
@bnoordhuis I think I addressed all requested changes with the last commits. @addaleax I do not really understand the build failures. Let's see what failed in build #8393: node-test-binary-arm/6624:
node-test-commit-linux/8401
node-compile-windows/7507 (VS2015)
And later:
node-compile-windows/7507 (VCBT2015)
I do not see any relation to my changes. Maybe some problems with the build system? |
@tniessen Yeah, all of these look like infrastructure-related problems. |
src/node_crypto.cc
Outdated
@@ -3994,6 +3994,19 @@ bool SignBase::GetRSAOptions(Environment* env, v8::Local<v8::Object> options, | |||
return true; | |||
} | |||
|
|||
static bool ApplyRSAOptions(EVP_PKEY* pkey, EVP_PKEY_CTX* pkctx, int padding, int salt_len) { |
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.
Long line. Can you run make test
?
EDIT: Comment crossed with a follow-up commit, disregard.
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.
Already fixed in the last commit, sorry. The problem is that I cannot perform linting on Windows and cannot run the tests on Linux, so I have to push from my Windows machine after running the tests before linting it on my Linux machine.
@tniessen Thoughts on #11705 (comment)? |
@addaleax Looks better, I just don't get why GitHub thinks |
It's a known issue with the CI. The reporter doesn't always report the status correctly for some reason. |
As this is semver-minor, it'll need to be approved in an LTS meeting before being backported. @tniessen you're welcome to raise the PR anyway, but there's always the option that @nodejs/lts will choose to punt on it for this release (and leave it to bake a while longer). |
PR nodejs#11705 switched Node away from using using OpenSSL's legacy EVP_Sign* and EVP_Verify* APIs. Instead, it computes a hash normally via EVP_Digest* and then uses EVP_PKEY_sign and EVP_PKEY_verify to verify the hash directly. This change corrects two problems: 1. The documentation still recommends the signature algorithm EVP_MD names of OpenSSL's legacy APIs. OpenSSL has since moved away from thosee, which is why ECDSA was strangely inconsistent. (This is why "ecdsa-with-SHA256" was missing.) 2. Node_SignFinal copied some code from EVP_SignFinal's internals. This is problematic for OpenSSL 1.1.0 and is missing a critical check that prevents pkey->pkey.ptr from being cast to the wrong type. To resolve this, remove the non-EVP_PKEY_sign codepath. This codepath is no longer necessary. PR nodejs#11705's verify half was already assuming all EVP_PKEYs supported EVP_PKEY_sign and EVP_PKEY_verify. Also, in the documentation, point users towards using hash function names which are more consisent. This avoids an ECDSA special-case and some strangeness around RSA-PSS ("RSA-SHA256" is the OpenSSL name of the sha256WithRSAEncryption OID which is not used for RSA-PSS).
PR nodejs#11705 switched Node away from using using OpenSSL's legacy EVP_Sign* and EVP_Verify* APIs. Instead, it computes a hash normally via EVP_Digest* and then uses EVP_PKEY_sign and EVP_PKEY_verify to verify the hash directly. This change corrects two problems: 1. The documentation still recommends the signature algorithm EVP_MD names of OpenSSL's legacy APIs. OpenSSL has since moved away from thosee, which is why ECDSA was strangely inconsistent. (This is why "ecdsa-with-SHA256" was missing.) 2. Node_SignFinal copied some code from EVP_SignFinal's internals. This is problematic for OpenSSL 1.1.0 and is missing a critical check that prevents pkey->pkey.ptr from being cast to the wrong type. To resolve this, remove the non-EVP_PKEY_sign codepath. This codepath is no longer necessary. PR nodejs#11705's verify half was already assuming all EVP_PKEYs supported EVP_PKEY_sign and EVP_PKEY_verify. Also, in the documentation, point users towards using hash function names which are more consisent. This avoids an ECDSA special-case and some strangeness around RSA-PSS ("RSA-SHA256" is the OpenSSL name of the sha256WithRSAEncryption OID which is not used for RSA-PSS). PR-URL: nodejs#15024 Reviewed-By: Shigeki Ohtsu <ohtsu@ohtsu.org> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
PR nodejs#11705 switched Node away from using using OpenSSL's legacy EVP_Sign* and EVP_Verify* APIs. Instead, it computes a hash normally via EVP_Digest* and then uses EVP_PKEY_sign and EVP_PKEY_verify to verify the hash directly. This change corrects two problems: 1. The documentation still recommends the signature algorithm EVP_MD names of OpenSSL's legacy APIs. OpenSSL has since moved away from thosee, which is why ECDSA was strangely inconsistent. (This is why "ecdsa-with-SHA256" was missing.) 2. Node_SignFinal copied some code from EVP_SignFinal's internals. This is problematic for OpenSSL 1.1.0 and is missing a critical check that prevents pkey->pkey.ptr from being cast to the wrong type. To resolve this, remove the non-EVP_PKEY_sign codepath. This codepath is no longer necessary. PR nodejs#11705's verify half was already assuming all EVP_PKEYs supported EVP_PKEY_sign and EVP_PKEY_verify. Also, in the documentation, point users towards using hash function names which are more consisent. This avoids an ECDSA special-case and some strangeness around RSA-PSS ("RSA-SHA256" is the OpenSSL name of the sha256WithRSAEncryption OID which is not used for RSA-PSS). PR-URL: nodejs#15024 Reviewed-By: Shigeki Ohtsu <ohtsu@ohtsu.org> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
PR #11705 switched Node away from using using OpenSSL's legacy EVP_Sign* and EVP_Verify* APIs. Instead, it computes a hash normally via EVP_Digest* and then uses EVP_PKEY_sign and EVP_PKEY_verify to verify the hash directly. This change corrects two problems: 1. The documentation still recommends the signature algorithm EVP_MD names of OpenSSL's legacy APIs. OpenSSL has since moved away from thosee, which is why ECDSA was strangely inconsistent. (This is why "ecdsa-with-SHA256" was missing.) 2. Node_SignFinal copied some code from EVP_SignFinal's internals. This is problematic for OpenSSL 1.1.0 and is missing a critical check that prevents pkey->pkey.ptr from being cast to the wrong type. To resolve this, remove the non-EVP_PKEY_sign codepath. This codepath is no longer necessary. PR #11705's verify half was already assuming all EVP_PKEYs supported EVP_PKEY_sign and EVP_PKEY_verify. Also, in the documentation, point users towards using hash function names which are more consisent. This avoids an ECDSA special-case and some strangeness around RSA-PSS ("RSA-SHA256" is the OpenSSL name of the sha256WithRSAEncryption OID which is not used for RSA-PSS). PR-URL: #15024 Reviewed-By: Shigeki Ohtsu <ohtsu@ohtsu.org> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Adds support for the PSS padding scheme. Until now, the sign/verify functions used the old EVP_Sign*/EVP_Verify* OpenSSL API, making it impossible to change the padding scheme. Fixed by first computing the message digest and then signing/verifying with a custom EVP_PKEY_CTX, allowing us to specify options such as the padding scheme and the PSS salt length. Fixes: nodejs#1127 PR-URL: nodejs#11705 Reviewed-By: Shigeki Ohtsu <ohtsu@ohtsu.org> Reviewed-By: Sam Roberts <vieuxtech@gmail.com> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Anna Henningsen <anna@addaleax.net>
Adds support for the PSS padding scheme. Until now, the sign/verify functions used the old EVP_Sign*/EVP_Verify* OpenSSL API, making it impossible to change the padding scheme. Fixed by first computing the message digest and then signing/verifying with a custom EVP_PKEY_CTX, allowing us to specify options such as the padding scheme and the PSS salt length. Fixes: #1127 PR-URL: #11705 Reviewed-By: Shigeki Ohtsu <ohtsu@ohtsu.org> Reviewed-By: Sam Roberts <vieuxtech@gmail.com> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Anna Henningsen <anna@addaleax.net>
PR #11705 switched Node away from using using OpenSSL's legacy EVP_Sign* and EVP_Verify* APIs. Instead, it computes a hash normally via EVP_Digest* and then uses EVP_PKEY_sign and EVP_PKEY_verify to verify the hash directly. This change corrects two problems: 1. The documentation still recommends the signature algorithm EVP_MD names of OpenSSL's legacy APIs. OpenSSL has since moved away from thosee, which is why ECDSA was strangely inconsistent. (This is why "ecdsa-with-SHA256" was missing.) 2. Node_SignFinal copied some code from EVP_SignFinal's internals. This is problematic for OpenSSL 1.1.0 and is missing a critical check that prevents pkey->pkey.ptr from being cast to the wrong type. To resolve this, remove the non-EVP_PKEY_sign codepath. This codepath is no longer necessary. PR #11705's verify half was already assuming all EVP_PKEYs supported EVP_PKEY_sign and EVP_PKEY_verify. Also, in the documentation, point users towards using hash function names which are more consisent. This avoids an ECDSA special-case and some strangeness around RSA-PSS ("RSA-SHA256" is the OpenSSL name of the sha256WithRSAEncryption OID which is not used for RSA-PSS). PR-URL: #15024 Reviewed-By: Shigeki Ohtsu <ohtsu@ohtsu.org> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Adds support for the PSS padding scheme. Until now, the sign/verify functions used the old EVP_Sign*/EVP_Verify* OpenSSL API, making it impossible to change the padding scheme. Fixed by first computing the message digest and then signing/verifying with a custom EVP_PKEY_CTX, allowing us to specify options such as the padding scheme and the PSS salt length. Fixes: #1127 PR-URL: #11705 Reviewed-By: Shigeki Ohtsu <ohtsu@ohtsu.org> Reviewed-By: Sam Roberts <vieuxtech@gmail.com> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Anna Henningsen <anna@addaleax.net>
PR #11705 switched Node away from using using OpenSSL's legacy EVP_Sign* and EVP_Verify* APIs. Instead, it computes a hash normally via EVP_Digest* and then uses EVP_PKEY_sign and EVP_PKEY_verify to verify the hash directly. This change corrects two problems: 1. The documentation still recommends the signature algorithm EVP_MD names of OpenSSL's legacy APIs. OpenSSL has since moved away from thosee, which is why ECDSA was strangely inconsistent. (This is why "ecdsa-with-SHA256" was missing.) 2. Node_SignFinal copied some code from EVP_SignFinal's internals. This is problematic for OpenSSL 1.1.0 and is missing a critical check that prevents pkey->pkey.ptr from being cast to the wrong type. To resolve this, remove the non-EVP_PKEY_sign codepath. This codepath is no longer necessary. PR #11705's verify half was already assuming all EVP_PKEYs supported EVP_PKEY_sign and EVP_PKEY_verify. Also, in the documentation, point users towards using hash function names which are more consisent. This avoids an ECDSA special-case and some strangeness around RSA-PSS ("RSA-SHA256" is the OpenSSL name of the sha256WithRSAEncryption OID which is not used for RSA-PSS). PR-URL: #15024 Reviewed-By: Shigeki Ohtsu <ohtsu@ohtsu.org> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Notable Changes: * assert: - assert.fail() can now take one or two arguments (Rich Trott) #12293 * crypto: - add sign/verify support for RSASSA-PSS (Tobias Nießen) #11705 * deps: - upgrade openssl sources to 1.0.2m (Shigeki Ohtsu) #16691 - upgrade libuv to 1.15.0 (cjihrig) #15745 - upgrade libuv to 1.14.1 (cjihrig) #14866 - upgrade libuv to 1.13.1 (cjihrig) #14117 - upgrade libuv to 1.12.0 (cjihrig) #13306 * fs: - Add support for fs.write/fs.writeSync(fd, buffer, cb) and fs.write/fs.writeSync(fd, buffer, offset, cb) as documented (Andreas Lind) #7856 * inspector: - enable --inspect-brk (Refael Ackermann) #12615 * process: - add --redirect-warnings command line argument (James M Snell) #10116 * src: - allow CLI args in env with NODE_OPTIONS (Sam Roberts) #12028) - --abort-on-uncaught-exception in NODE_OPTIONS (Sam Roberts) #13932 - allow --tls-cipher-list in NODE_OPTIONS (Sam Roberts) #13172 - use SafeGetenv() for NODE_REDIRECT_WARNINGS (Sam Roberts) #12677 * test: - remove common.fail() (Rich Trott) #12293 PR-URL: #16263
Notable Changes: * assert: - assert.fail() can now take one or two arguments (Rich Trott) #12293 * crypto: - add sign/verify support for RSASSA-PSS (Tobias Nießen) #11705 * deps: - upgrade openssl sources to 1.0.2m (Shigeki Ohtsu) #16691 - upgrade libuv to 1.15.0 (cjihrig) #15745 - upgrade libuv to 1.14.1 (cjihrig) #14866 - upgrade libuv to 1.13.1 (cjihrig) #14117 - upgrade libuv to 1.12.0 (cjihrig) #13306 * fs: - Add support for fs.write/fs.writeSync(fd, buffer, cb) and fs.write/fs.writeSync(fd, buffer, offset, cb) as documented (Andreas Lind) #7856 * inspector: - enable --inspect-brk (Refael Ackermann) #12615 * process: - add --redirect-warnings command line argument (James M Snell) #10116 * src: - allow CLI args in env with NODE_OPTIONS (Sam Roberts) #12028) - --abort-on-uncaught-exception in NODE_OPTIONS (Sam Roberts) #13932 - allow --tls-cipher-list in NODE_OPTIONS (Sam Roberts) #13172 - use SafeGetenv() for NODE_REDIRECT_WARNINGS (Sam Roberts) #12677 * test: - remove common.fail() (Rich Trott) #12293 PR-URL: #16263
Adds support for the PSS padding scheme. Until now, the sign/verify functions used the old EVP_Sign*/EVP_Verify* OpenSSL API, making it impossible to change the padding scheme. Fixed by first computing the message digest and then signing/verifying with a custom EVP_PKEY_CTX, allowing us to specify options such as the padding scheme and the PSS salt length.
Fixes: #1127
Checklist
make -j4 test
(UNIX), orvcbuild test
(Windows) passesAffected core subsystem(s)
crypto, src, doc, test