diff options
author | Fedor Indutny <fedor@indutny.com> | 2014-08-23 17:38:32 +0400 |
---|---|---|
committer | Fedor Indutny <fedor@indutny.com> | 2014-08-27 00:24:57 +0400 |
commit | 6adf3ecebb42c05662f7c6a792953589ffdfd4dc (patch) | |
tree | aeee42cb757d6a5e13959dc11c8e225c269e685b | |
parent | 8a7d7f8b2b40f670d2fceb14d7d16cda1bea6bcf (diff) | |
download | nodejs-6adf3ecebb42c05662f7c6a792953589ffdfd4dc.tar.gz nodejs-6adf3ecebb42c05662f7c6a792953589ffdfd4dc.tar.bz2 nodejs-6adf3ecebb42c05662f7c6a792953589ffdfd4dc.zip |
crypto: allow padding in RSA methods
Reviewed-By: Trevor Norris <trevnorris@gmail.com>
-rw-r--r-- | doc/api/crypto.markdown | 23 | ||||
-rw-r--r-- | lib/crypto.js | 9 | ||||
-rw-r--r-- | src/node_constants.cc | 24 | ||||
-rw-r--r-- | src/node_crypto.cc | 9 | ||||
-rw-r--r-- | src/node_crypto.h | 1 | ||||
-rw-r--r-- | test/simple/test-crypto.js | 24 |
6 files changed, 83 insertions, 7 deletions
diff --git a/doc/api/crypto.markdown b/doc/api/crypto.markdown index d1ed68300..cc13acacc 100644 --- a/doc/api/crypto.markdown +++ b/doc/api/crypto.markdown @@ -597,17 +597,36 @@ Exports the encoded challenge associated with the SPKAC. Encrypts `buffer` with `public_key`. Only RSA is currently supported. +`public_key` can be an object or a string. If `public_key` is a string, it is +treated as the key with no passphrase and will use `RSA_PKCS1_OAEP_PADDING`. + +`public_key`: + +* `key` : A string holding the PEM encoded private key +* `padding` : An optional padding value, one of the following: + * `constants.RSA_NO_PADDING` + * `constants.RSA_PKCS1_PADDING` + * `constants.RSA_PKCS1_OAEP_PADDING` + +NOTE: All paddings are defined in `constants` module. + ## crypto.privateDecrypt(private_key, buffer) Decrypts `buffer` with `private_key`. `private_key` can be an object or a string. If `private_key` is a string, it is -treated as the key with no passphrase. +treated as the key with no passphrase and will use `RSA_PKCS1_OAEP_PADDING`. `private_key`: * `key` : A string holding the PEM encoded private key -* `passphrase` : A string of passphrase for the private key +* `passphrase` : An optional string of passphrase for the private key +* `padding` : An optional padding value, one of the following: + * `constants.RSA_NO_PADDING` + * `constants.RSA_PKCS1_PADDING` + * `constants.RSA_PKCS1_OAEP_PADDING` + +NOTE: All paddings are defined in `constants` module. ## crypto.DEFAULT_ENCODING diff --git a/lib/crypto.js b/lib/crypto.js index 16a3e38e2..828c0f431 100644 --- a/lib/crypto.js +++ b/lib/crypto.js @@ -355,14 +355,17 @@ Verify.prototype.verify = function(object, signature, sigEncoding) { return this._handle.verify(toBuf(object), toBuf(signature, sigEncoding)); }; -exports.publicEncrypt = function(object, buffer) { - return binding.publicEncrypt(toBuf(object), buffer); +exports.publicEncrypt = function(options, buffer) { + var key = options.key || options; + var padding = options.padding || constants.RSA_PKCS1_OAEP_PADDING; + return binding.publicEncrypt(toBuf(key), buffer, padding); }; exports.privateDecrypt = function(options, buffer) { var key = options.key || options; var passphrase = options.passphrase || null; - return binding.privateDecrypt(toBuf(key), buffer, passphrase); + var padding = options.padding || constants.RSA_PKCS1_OAEP_PADDING; + return binding.privateDecrypt(toBuf(key), buffer, padding, passphrase); }; diff --git a/src/node_constants.cc b/src/node_constants.cc index dc7dc8067..430a09c68 100644 --- a/src/node_constants.cc +++ b/src/node_constants.cc @@ -950,6 +950,30 @@ void DefineOpenSSLConstants(Handle<Object> target) { #define NPN_ENABLED 1 NODE_DEFINE_CONSTANT(target, NPN_ENABLED); #endif + +#ifdef RSA_PKCS1_PADDING + NODE_DEFINE_CONSTANT(target, RSA_PKCS1_PADDING); +#endif + +#ifdef RSA_SSLV23_PADDING + NODE_DEFINE_CONSTANT(target, RSA_SSLV23_PADDING); +#endif + +#ifdef RSA_NO_PADDING + NODE_DEFINE_CONSTANT(target, RSA_NO_PADDING); +#endif + +#ifdef RSA_PKCS1_OAEP_PADDING + NODE_DEFINE_CONSTANT(target, RSA_PKCS1_OAEP_PADDING); +#endif + +#ifdef RSA_X931_PADDING + NODE_DEFINE_CONSTANT(target, RSA_X931_PADDING); +#endif + +#ifdef RSA_PKCS1_PSS_PADDING + NODE_DEFINE_CONSTANT(target, RSA_PKCS1_PSS_PADDING); +#endif } void DefineSystemConstants(Handle<Object> target) { diff --git a/src/node_crypto.cc b/src/node_crypto.cc index 9fa1e2cfc..6085a18a4 100644 --- a/src/node_crypto.cc +++ b/src/node_crypto.cc @@ -3552,6 +3552,7 @@ template <PublicKeyCipher::Operation operation, bool PublicKeyCipher::Cipher(const char* key_pem, int key_pem_len, const char* passphrase, + int padding, const unsigned char* data, int len, unsigned char** out, @@ -3610,8 +3611,9 @@ bool PublicKeyCipher::Cipher(const char* key_pem, goto exit; if (EVP_PKEY_cipher_init(ctx) <= 0) goto exit; - if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) <= 0) + if (EVP_PKEY_CTX_set_rsa_padding(ctx, padding) <= 0) goto exit; + if (EVP_PKEY_cipher(ctx, NULL, out_len, data, len) <= 0) goto exit; @@ -3649,7 +3651,9 @@ void PublicKeyCipher::Cipher(const FunctionCallbackInfo<Value>& args) { char* buf = Buffer::Data(args[1]); ssize_t len = Buffer::Length(args[1]); - String::Utf8Value passphrase(args[2]); + int padding = args[2]->Uint32Value(); + + String::Utf8Value passphrase(args[3]); unsigned char* out_value = NULL; size_t out_len = -1; @@ -3658,6 +3662,7 @@ void PublicKeyCipher::Cipher(const FunctionCallbackInfo<Value>& args) { kbuf, klen, args.Length() >= 3 && !args[2]->IsNull() ? *passphrase : NULL, + padding, reinterpret_cast<const unsigned char*>(buf), len, &out_value, diff --git a/src/node_crypto.h b/src/node_crypto.h index 9531df0ca..2a02c89bc 100644 --- a/src/node_crypto.h +++ b/src/node_crypto.h @@ -577,6 +577,7 @@ class PublicKeyCipher { static bool Cipher(const char* key_pem, int key_pem_len, const char* passphrase, + int padding, const unsigned char* data, int len, unsigned char** out, diff --git a/test/simple/test-crypto.js b/test/simple/test-crypto.js index fd9896663..74baaa71a 100644 --- a/test/simple/test-crypto.js +++ b/test/simple/test-crypto.js @@ -857,6 +857,30 @@ assert.equal(bad_dh.verifyError, constants.DH_NOT_SUITABLE_GENERATOR); }); })(); +function test_rsa(padding) { + var input = new Buffer(padding === 'RSA_NO_PADDING' ? 1024 / 8 : 32); + for (var i = 0; i < input.length; i++) + input[i] = (i * 7 + 11) & 0xff; + var bufferToEncrypt = new Buffer(input); + + padding = constants[padding]; + + var encryptedBuffer = crypto.publicEncrypt({ + key: rsaPubPem, + padding: padding + }, bufferToEncrypt); + + var decryptedBuffer = crypto.privateDecrypt({ + key: rsaKeyPem, + padding: padding + }, encryptedBuffer); + assert.equal(input, decryptedBuffer.toString()); +} + +test_rsa('RSA_NO_PADDING'); +test_rsa('RSA_PKCS1_PADDING'); +test_rsa('RSA_PKCS1_OAEP_PADDING'); + // Test RSA key signing/verification var rsaSign = crypto.createSign('RSA-SHA1'); var rsaVerify = crypto.createVerify('RSA-SHA1'); |