diff --git a/doc/api/crypto.markdown b/doc/api/crypto.markdown index b6834d0a945979..e93fc1b0b62b30 100644 --- a/doc/api/crypto.markdown +++ b/doc/api/crypto.markdown @@ -678,10 +678,13 @@ 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`. +Since RSA public keys may be derived from private keys you may pass a private +key to this method. `public_key`: * `key` : A string holding the PEM encoded 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` diff --git a/lib/crypto.js b/lib/crypto.js index f8efffda483ec7..84517f7397b248 100644 --- a/lib/crypto.js +++ b/lib/crypto.js @@ -336,16 +336,17 @@ Verify.prototype.verify = function(object, signature, sigEncoding) { return this._handle.verify(toBuf(object), toBuf(signature, sigEncoding)); }; -function rsaPublic(method, defaultPadding) { - return function(options, buffer) { +function makeRsaPublic(method, defaultPadding) { + return function rsaPublic(options, buffer) { var key = options.key || options; var padding = options.padding || defaultPadding; - return method(toBuf(key), buffer, padding); + var passphrase = options.passphrase || null; + return method(toBuf(key), buffer, padding, passphrase); }; } -function rsaPrivate(method, defaultPadding) { - return function(options, buffer) { +function makeRsaPrivate(method, defaultPadding) { + return function rsaPrivate(options, buffer) { var key = options.key || options; var passphrase = options.passphrase || null; var padding = options.padding || defaultPadding; @@ -353,14 +354,14 @@ function rsaPrivate(method, defaultPadding) { }; } -exports.publicEncrypt = rsaPublic(binding.publicEncrypt, - constants.RSA_PKCS1_OAEP_PADDING); -exports.publicDecrypt = rsaPublic(binding.publicDecrypt, - constants.RSA_PKCS1_PADDING); -exports.privateEncrypt = rsaPrivate(binding.privateEncrypt, - constants.RSA_PKCS1_PADDING); -exports.privateDecrypt = rsaPrivate(binding.privateDecrypt, - constants.RSA_PKCS1_OAEP_PADDING); +exports.publicEncrypt = makeRsaPublic(binding.publicEncrypt, + constants.RSA_PKCS1_OAEP_PADDING); +exports.publicDecrypt = makeRsaPublic(binding.publicDecrypt, + constants.RSA_PKCS1_PADDING); +exports.privateEncrypt = makeRsaPrivate(binding.privateEncrypt, + constants.RSA_PKCS1_PADDING); +exports.privateDecrypt = makeRsaPrivate(binding.privateDecrypt, + constants.RSA_PKCS1_OAEP_PADDING); exports.createDiffieHellman = exports.DiffieHellman = DiffieHellman; diff --git a/test/parallel/test-crypto.js b/test/parallel/test-crypto.js index 8198a6c9d601de..f5001fd24a0345 100644 --- a/test/parallel/test-crypto.js +++ b/test/parallel/test-crypto.js @@ -831,6 +831,28 @@ assert.equal(bad_dh.verifyError, constants.DH_NOT_SUITABLE_GENERATOR); }, encryptedBuffer); assert.equal(input, decryptedBufferWithPassword.toString()); + encryptedBuffer = crypto.publicEncrypt({ + key: rsaKeyPemEncrypted, + passphrase: 'password' + }, bufferToEncrypt); + + decryptedBufferWithPassword = crypto.privateDecrypt({ + key: rsaKeyPemEncrypted, + passphrase: 'password' + }, encryptedBuffer); + assert.equal(input, decryptedBufferWithPassword.toString()); + + encryptedBuffer = crypto.privateEncrypt({ + key: rsaKeyPemEncrypted, + passphrase: new Buffer('password') + }, bufferToEncrypt); + + decryptedBufferWithPassword = crypto.publicDecrypt({ + key: rsaKeyPemEncrypted, + passphrase: new Buffer('password') + }, encryptedBuffer); + assert.equal(input, decryptedBufferWithPassword.toString()); + encryptedBuffer = crypto.publicEncrypt(certPem, bufferToEncrypt); decryptedBuffer = crypto.privateDecrypt(keyPem, encryptedBuffer); @@ -850,6 +872,25 @@ assert.equal(bad_dh.verifyError, constants.DH_NOT_SUITABLE_GENERATOR); crypto.privateDecrypt({ key: rsaKeyPemEncrypted, passphrase: 'wrong' + }, bufferToEncrypt); + }); + + assert.throws(function() { + crypto.publicEncrypt({ + key: rsaKeyPemEncrypted, + passphrase: 'wrong' + }, encryptedBuffer); + }); + + assert.throws(function() { + encryptedBuffer = crypto.privateEncrypt({ + key: rsaKeyPemEncrypted, + passphrase: new Buffer('password') + }, bufferToEncrypt); + + crypto.publicDecrypt({ + key: rsaKeyPemEncrypted, + passphrase: [].concat.apply([], new Buffer('password')) }, encryptedBuffer); }); })();