summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFedor Indutny <fedor@indutny.com>2014-08-23 17:38:32 +0400
committerFedor Indutny <fedor@indutny.com>2014-08-27 00:24:57 +0400
commit6adf3ecebb42c05662f7c6a792953589ffdfd4dc (patch)
treeaeee42cb757d6a5e13959dc11c8e225c269e685b
parent8a7d7f8b2b40f670d2fceb14d7d16cda1bea6bcf (diff)
downloadnodejs-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.markdown23
-rw-r--r--lib/crypto.js9
-rw-r--r--src/node_constants.cc24
-rw-r--r--src/node_crypto.cc9
-rw-r--r--src/node_crypto.h1
-rw-r--r--test/simple/test-crypto.js24
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');