Skip to content

Commit 87e62bd

Browse files
committed
crypto: implement privateEncrypt/publicDecrypt
PR-URL: #625 Reviewed-By: Ben Noordhuis <[email protected]> Fix #477
1 parent b50fea4 commit 87e62bd

File tree

5 files changed

+51
-18
lines changed

5 files changed

+51
-18
lines changed

doc/api/crypto.markdown

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -707,6 +707,14 @@ treated as the key with no passphrase and will use `RSA_PKCS1_OAEP_PADDING`.
707707

708708
NOTE: All paddings are defined in `constants` module.
709709

710+
## crypto.privateEncrypt(private_key, buffer)
711+
712+
See above for details. Has the same API as `crypto.privateDecrypt`.
713+
714+
## crypto.publicDecrypt(public_key, buffer)
715+
716+
See above for details. Has the same API as `crypto.publicEncrypt`.
717+
710718
## crypto.DEFAULT_ENCODING
711719

712720
The default encoding to use for functions that can take either strings

lib/crypto.js

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -337,19 +337,31 @@ Verify.prototype.verify = function(object, signature, sigEncoding) {
337337
return this._handle.verify(toBuf(object), toBuf(signature, sigEncoding));
338338
};
339339

340-
exports.publicEncrypt = function(options, buffer) {
341-
var key = options.key || options;
342-
var padding = options.padding || constants.RSA_PKCS1_OAEP_PADDING;
343-
return binding.publicEncrypt(toBuf(key), buffer, padding);
344-
};
340+
function rsaPublic(method, defaultPadding) {
341+
return function(options, buffer) {
342+
var key = options.key || options;
343+
var padding = options.padding || defaultPadding;
344+
return method(toBuf(key), buffer, padding);
345+
};
346+
}
345347

346-
exports.privateDecrypt = function(options, buffer) {
347-
var key = options.key || options;
348-
var passphrase = options.passphrase || null;
349-
var padding = options.padding || constants.RSA_PKCS1_OAEP_PADDING;
350-
return binding.privateDecrypt(toBuf(key), buffer, padding, passphrase);
351-
};
348+
function rsaPrivate(method, defaultPadding) {
349+
return function(options, buffer) {
350+
var key = options.key || options;
351+
var passphrase = options.passphrase || null;
352+
var padding = options.padding || defaultPadding;
353+
return method(toBuf(key), buffer, padding, passphrase);
354+
};
355+
}
352356

357+
exports.publicEncrypt = rsaPublic(binding.publicEncrypt,
358+
constants.RSA_PKCS1_OAEP_PADDING);
359+
exports.publicDecrypt = rsaPublic(binding.publicDecrypt,
360+
constants.RSA_PKCS1_PADDING);
361+
exports.privateEncrypt = rsaPrivate(binding.privateEncrypt,
362+
constants.RSA_PKCS1_PADDING);
363+
exports.privateDecrypt = rsaPrivate(binding.privateDecrypt,
364+
constants.RSA_PKCS1_OAEP_PADDING);
353365

354366

355367
exports.createDiffieHellman = exports.DiffieHellman = DiffieHellman;

src/node_crypto.cc

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3561,12 +3561,12 @@ bool PublicKeyCipher::Cipher(const char* key_pem,
35613561

35623562
// Check if this is a PKCS#8 or RSA public key before trying as X.509 and
35633563
// private key.
3564-
if (operation == kEncrypt &&
3564+
if (operation == kPublic &&
35653565
strncmp(key_pem, PUBLIC_KEY_PFX, PUBLIC_KEY_PFX_LEN) == 0) {
35663566
pkey = PEM_read_bio_PUBKEY(bp, nullptr, nullptr, nullptr);
35673567
if (pkey == nullptr)
35683568
goto exit;
3569-
} else if (operation == kEncrypt &&
3569+
} else if (operation == kPublic &&
35703570
strncmp(key_pem, PUBRSA_KEY_PFX, PUBRSA_KEY_PFX_LEN) == 0) {
35713571
RSA* rsa = PEM_read_bio_RSAPublicKey(bp, nullptr, nullptr, nullptr);
35723572
if (rsa) {
@@ -3577,7 +3577,7 @@ bool PublicKeyCipher::Cipher(const char* key_pem,
35773577
}
35783578
if (pkey == nullptr)
35793579
goto exit;
3580-
} else if (operation == kEncrypt &&
3580+
} else if (operation == kPublic &&
35813581
strncmp(key_pem, CERTIFICATE_PFX, CERTIFICATE_PFX_LEN) == 0) {
35823582
x509 = PEM_read_bio_X509(bp, nullptr, CryptoPemCallback, nullptr);
35833583
if (x509 == nullptr)
@@ -5038,13 +5038,21 @@ void InitCrypto(Handle<Object> target,
50385038
env->SetMethod(target, "getCiphers", GetCiphers);
50395039
env->SetMethod(target, "getHashes", GetHashes);
50405040
env->SetMethod(target, "publicEncrypt",
5041-
PublicKeyCipher::Cipher<PublicKeyCipher::kEncrypt,
5041+
PublicKeyCipher::Cipher<PublicKeyCipher::kPublic,
50425042
EVP_PKEY_encrypt_init,
50435043
EVP_PKEY_encrypt>);
50445044
env->SetMethod(target, "privateDecrypt",
5045-
PublicKeyCipher::Cipher<PublicKeyCipher::kDecrypt,
5045+
PublicKeyCipher::Cipher<PublicKeyCipher::kPrivate,
50465046
EVP_PKEY_decrypt_init,
50475047
EVP_PKEY_decrypt>);
5048+
env->SetMethod(target, "privateEncrypt",
5049+
PublicKeyCipher::Cipher<PublicKeyCipher::kPrivate,
5050+
EVP_PKEY_sign_init,
5051+
EVP_PKEY_sign>);
5052+
env->SetMethod(target, "publicDecrypt",
5053+
PublicKeyCipher::Cipher<PublicKeyCipher::kPublic,
5054+
EVP_PKEY_verify_recover_init,
5055+
EVP_PKEY_verify_recover>);
50485056
}
50495057

50505058
} // namespace crypto

src/node_crypto.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -553,8 +553,8 @@ class PublicKeyCipher {
553553
const unsigned char *in, size_t inlen);
554554

555555
enum Operation {
556-
kEncrypt,
557-
kDecrypt
556+
kPublic,
557+
kPrivate
558558
};
559559

560560
template <Operation operation,

test/parallel/test-crypto.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -841,6 +841,11 @@ assert.equal(bad_dh.verifyError, constants.DH_NOT_SUITABLE_GENERATOR);
841841
decryptedBuffer = crypto.privateDecrypt(keyPem, encryptedBuffer);
842842
assert.equal(input, decryptedBuffer.toString());
843843

844+
encryptedBuffer = crypto.privateEncrypt(keyPem, bufferToEncrypt);
845+
846+
decryptedBuffer = crypto.publicDecrypt(keyPem, encryptedBuffer);
847+
assert.equal(input, decryptedBuffer.toString());
848+
844849
assert.throws(function() {
845850
crypto.privateDecrypt({
846851
key: rsaKeyPemEncrypted,

0 commit comments

Comments
 (0)