Skip to content

Commit 6adf3ec

Browse files
committed
crypto: allow padding in RSA methods
Reviewed-By: Trevor Norris <[email protected]>
1 parent 8a7d7f8 commit 6adf3ec

File tree

6 files changed

+83
-7
lines changed

6 files changed

+83
-7
lines changed

doc/api/crypto.markdown

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -597,17 +597,36 @@ Exports the encoded challenge associated with the SPKAC.
597597

598598
Encrypts `buffer` with `public_key`. Only RSA is currently supported.
599599

600+
`public_key` can be an object or a string. If `public_key` is a string, it is
601+
treated as the key with no passphrase and will use `RSA_PKCS1_OAEP_PADDING`.
602+
603+
`public_key`:
604+
605+
* `key` : A string holding the PEM encoded private key
606+
* `padding` : An optional padding value, one of the following:
607+
* `constants.RSA_NO_PADDING`
608+
* `constants.RSA_PKCS1_PADDING`
609+
* `constants.RSA_PKCS1_OAEP_PADDING`
610+
611+
NOTE: All paddings are defined in `constants` module.
612+
600613
## crypto.privateDecrypt(private_key, buffer)
601614

602615
Decrypts `buffer` with `private_key`.
603616

604617
`private_key` can be an object or a string. If `private_key` is a string, it is
605-
treated as the key with no passphrase.
618+
treated as the key with no passphrase and will use `RSA_PKCS1_OAEP_PADDING`.
606619

607620
`private_key`:
608621

609622
* `key` : A string holding the PEM encoded private key
610-
* `passphrase` : A string of passphrase for the private key
623+
* `passphrase` : An optional string of passphrase for the private key
624+
* `padding` : An optional padding value, one of the following:
625+
* `constants.RSA_NO_PADDING`
626+
* `constants.RSA_PKCS1_PADDING`
627+
* `constants.RSA_PKCS1_OAEP_PADDING`
628+
629+
NOTE: All paddings are defined in `constants` module.
611630

612631
## crypto.DEFAULT_ENCODING
613632

lib/crypto.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -355,14 +355,17 @@ Verify.prototype.verify = function(object, signature, sigEncoding) {
355355
return this._handle.verify(toBuf(object), toBuf(signature, sigEncoding));
356356
};
357357

358-
exports.publicEncrypt = function(object, buffer) {
359-
return binding.publicEncrypt(toBuf(object), buffer);
358+
exports.publicEncrypt = function(options, buffer) {
359+
var key = options.key || options;
360+
var padding = options.padding || constants.RSA_PKCS1_OAEP_PADDING;
361+
return binding.publicEncrypt(toBuf(key), buffer, padding);
360362
};
361363

362364
exports.privateDecrypt = function(options, buffer) {
363365
var key = options.key || options;
364366
var passphrase = options.passphrase || null;
365-
return binding.privateDecrypt(toBuf(key), buffer, passphrase);
367+
var padding = options.padding || constants.RSA_PKCS1_OAEP_PADDING;
368+
return binding.privateDecrypt(toBuf(key), buffer, padding, passphrase);
366369
};
367370

368371

src/node_constants.cc

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -950,6 +950,30 @@ void DefineOpenSSLConstants(Handle<Object> target) {
950950
#define NPN_ENABLED 1
951951
NODE_DEFINE_CONSTANT(target, NPN_ENABLED);
952952
#endif
953+
954+
#ifdef RSA_PKCS1_PADDING
955+
NODE_DEFINE_CONSTANT(target, RSA_PKCS1_PADDING);
956+
#endif
957+
958+
#ifdef RSA_SSLV23_PADDING
959+
NODE_DEFINE_CONSTANT(target, RSA_SSLV23_PADDING);
960+
#endif
961+
962+
#ifdef RSA_NO_PADDING
963+
NODE_DEFINE_CONSTANT(target, RSA_NO_PADDING);
964+
#endif
965+
966+
#ifdef RSA_PKCS1_OAEP_PADDING
967+
NODE_DEFINE_CONSTANT(target, RSA_PKCS1_OAEP_PADDING);
968+
#endif
969+
970+
#ifdef RSA_X931_PADDING
971+
NODE_DEFINE_CONSTANT(target, RSA_X931_PADDING);
972+
#endif
973+
974+
#ifdef RSA_PKCS1_PSS_PADDING
975+
NODE_DEFINE_CONSTANT(target, RSA_PKCS1_PSS_PADDING);
976+
#endif
953977
}
954978

955979
void DefineSystemConstants(Handle<Object> target) {

src/node_crypto.cc

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3552,6 +3552,7 @@ template <PublicKeyCipher::Operation operation,
35523552
bool PublicKeyCipher::Cipher(const char* key_pem,
35533553
int key_pem_len,
35543554
const char* passphrase,
3555+
int padding,
35553556
const unsigned char* data,
35563557
int len,
35573558
unsigned char** out,
@@ -3610,8 +3611,9 @@ bool PublicKeyCipher::Cipher(const char* key_pem,
36103611
goto exit;
36113612
if (EVP_PKEY_cipher_init(ctx) <= 0)
36123613
goto exit;
3613-
if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) <= 0)
3614+
if (EVP_PKEY_CTX_set_rsa_padding(ctx, padding) <= 0)
36143615
goto exit;
3616+
36153617
if (EVP_PKEY_cipher(ctx, NULL, out_len, data, len) <= 0)
36163618
goto exit;
36173619

@@ -3649,7 +3651,9 @@ void PublicKeyCipher::Cipher(const FunctionCallbackInfo<Value>& args) {
36493651
char* buf = Buffer::Data(args[1]);
36503652
ssize_t len = Buffer::Length(args[1]);
36513653

3652-
String::Utf8Value passphrase(args[2]);
3654+
int padding = args[2]->Uint32Value();
3655+
3656+
String::Utf8Value passphrase(args[3]);
36533657

36543658
unsigned char* out_value = NULL;
36553659
size_t out_len = -1;
@@ -3658,6 +3662,7 @@ void PublicKeyCipher::Cipher(const FunctionCallbackInfo<Value>& args) {
36583662
kbuf,
36593663
klen,
36603664
args.Length() >= 3 && !args[2]->IsNull() ? *passphrase : NULL,
3665+
padding,
36613666
reinterpret_cast<const unsigned char*>(buf),
36623667
len,
36633668
&out_value,

src/node_crypto.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -577,6 +577,7 @@ class PublicKeyCipher {
577577
static bool Cipher(const char* key_pem,
578578
int key_pem_len,
579579
const char* passphrase,
580+
int padding,
580581
const unsigned char* data,
581582
int len,
582583
unsigned char** out,

test/simple/test-crypto.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -857,6 +857,30 @@ assert.equal(bad_dh.verifyError, constants.DH_NOT_SUITABLE_GENERATOR);
857857
});
858858
})();
859859

860+
function test_rsa(padding) {
861+
var input = new Buffer(padding === 'RSA_NO_PADDING' ? 1024 / 8 : 32);
862+
for (var i = 0; i < input.length; i++)
863+
input[i] = (i * 7 + 11) & 0xff;
864+
var bufferToEncrypt = new Buffer(input);
865+
866+
padding = constants[padding];
867+
868+
var encryptedBuffer = crypto.publicEncrypt({
869+
key: rsaPubPem,
870+
padding: padding
871+
}, bufferToEncrypt);
872+
873+
var decryptedBuffer = crypto.privateDecrypt({
874+
key: rsaKeyPem,
875+
padding: padding
876+
}, encryptedBuffer);
877+
assert.equal(input, decryptedBuffer.toString());
878+
}
879+
880+
test_rsa('RSA_NO_PADDING');
881+
test_rsa('RSA_PKCS1_PADDING');
882+
test_rsa('RSA_PKCS1_OAEP_PADDING');
883+
860884
// Test RSA key signing/verification
861885
var rsaSign = crypto.createSign('RSA-SHA1');
862886
var rsaVerify = crypto.createVerify('RSA-SHA1');

0 commit comments

Comments
 (0)