crypto: implement privateEncrypt/publicDecrypt
PR-URL: https://github.com/iojs/io.js/pull/625 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Fix iojs/io.js#477
This commit is contained in:
parent
b50fea4d49
commit
87e62bd4c8
@ -707,6 +707,14 @@ treated as the key with no passphrase and will use `RSA_PKCS1_OAEP_PADDING`.
|
||||
|
||||
NOTE: All paddings are defined in `constants` module.
|
||||
|
||||
## crypto.privateEncrypt(private_key, buffer)
|
||||
|
||||
See above for details. Has the same API as `crypto.privateDecrypt`.
|
||||
|
||||
## crypto.publicDecrypt(public_key, buffer)
|
||||
|
||||
See above for details. Has the same API as `crypto.publicEncrypt`.
|
||||
|
||||
## crypto.DEFAULT_ENCODING
|
||||
|
||||
The default encoding to use for functions that can take either strings
|
||||
|
@ -337,19 +337,31 @@ Verify.prototype.verify = function(object, signature, sigEncoding) {
|
||||
return this._handle.verify(toBuf(object), toBuf(signature, sigEncoding));
|
||||
};
|
||||
|
||||
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);
|
||||
};
|
||||
function rsaPublic(method, defaultPadding) {
|
||||
return function(options, buffer) {
|
||||
var key = options.key || options;
|
||||
var padding = options.padding || defaultPadding;
|
||||
return method(toBuf(key), buffer, padding);
|
||||
};
|
||||
}
|
||||
|
||||
exports.privateDecrypt = function(options, buffer) {
|
||||
var key = options.key || options;
|
||||
var passphrase = options.passphrase || null;
|
||||
var padding = options.padding || constants.RSA_PKCS1_OAEP_PADDING;
|
||||
return binding.privateDecrypt(toBuf(key), buffer, padding, passphrase);
|
||||
};
|
||||
function rsaPrivate(method, defaultPadding) {
|
||||
return function(options, buffer) {
|
||||
var key = options.key || options;
|
||||
var passphrase = options.passphrase || null;
|
||||
var padding = options.padding || defaultPadding;
|
||||
return method(toBuf(key), buffer, padding, passphrase);
|
||||
};
|
||||
}
|
||||
|
||||
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.createDiffieHellman = exports.DiffieHellman = DiffieHellman;
|
||||
|
@ -3561,12 +3561,12 @@ bool PublicKeyCipher::Cipher(const char* key_pem,
|
||||
|
||||
// Check if this is a PKCS#8 or RSA public key before trying as X.509 and
|
||||
// private key.
|
||||
if (operation == kEncrypt &&
|
||||
if (operation == kPublic &&
|
||||
strncmp(key_pem, PUBLIC_KEY_PFX, PUBLIC_KEY_PFX_LEN) == 0) {
|
||||
pkey = PEM_read_bio_PUBKEY(bp, nullptr, nullptr, nullptr);
|
||||
if (pkey == nullptr)
|
||||
goto exit;
|
||||
} else if (operation == kEncrypt &&
|
||||
} else if (operation == kPublic &&
|
||||
strncmp(key_pem, PUBRSA_KEY_PFX, PUBRSA_KEY_PFX_LEN) == 0) {
|
||||
RSA* rsa = PEM_read_bio_RSAPublicKey(bp, nullptr, nullptr, nullptr);
|
||||
if (rsa) {
|
||||
@ -3577,7 +3577,7 @@ bool PublicKeyCipher::Cipher(const char* key_pem,
|
||||
}
|
||||
if (pkey == nullptr)
|
||||
goto exit;
|
||||
} else if (operation == kEncrypt &&
|
||||
} else if (operation == kPublic &&
|
||||
strncmp(key_pem, CERTIFICATE_PFX, CERTIFICATE_PFX_LEN) == 0) {
|
||||
x509 = PEM_read_bio_X509(bp, nullptr, CryptoPemCallback, nullptr);
|
||||
if (x509 == nullptr)
|
||||
@ -5038,13 +5038,21 @@ void InitCrypto(Handle<Object> target,
|
||||
env->SetMethod(target, "getCiphers", GetCiphers);
|
||||
env->SetMethod(target, "getHashes", GetHashes);
|
||||
env->SetMethod(target, "publicEncrypt",
|
||||
PublicKeyCipher::Cipher<PublicKeyCipher::kEncrypt,
|
||||
PublicKeyCipher::Cipher<PublicKeyCipher::kPublic,
|
||||
EVP_PKEY_encrypt_init,
|
||||
EVP_PKEY_encrypt>);
|
||||
env->SetMethod(target, "privateDecrypt",
|
||||
PublicKeyCipher::Cipher<PublicKeyCipher::kDecrypt,
|
||||
PublicKeyCipher::Cipher<PublicKeyCipher::kPrivate,
|
||||
EVP_PKEY_decrypt_init,
|
||||
EVP_PKEY_decrypt>);
|
||||
env->SetMethod(target, "privateEncrypt",
|
||||
PublicKeyCipher::Cipher<PublicKeyCipher::kPrivate,
|
||||
EVP_PKEY_sign_init,
|
||||
EVP_PKEY_sign>);
|
||||
env->SetMethod(target, "publicDecrypt",
|
||||
PublicKeyCipher::Cipher<PublicKeyCipher::kPublic,
|
||||
EVP_PKEY_verify_recover_init,
|
||||
EVP_PKEY_verify_recover>);
|
||||
}
|
||||
|
||||
} // namespace crypto
|
||||
|
@ -553,8 +553,8 @@ class PublicKeyCipher {
|
||||
const unsigned char *in, size_t inlen);
|
||||
|
||||
enum Operation {
|
||||
kEncrypt,
|
||||
kDecrypt
|
||||
kPublic,
|
||||
kPrivate
|
||||
};
|
||||
|
||||
template <Operation operation,
|
||||
|
@ -841,6 +841,11 @@ assert.equal(bad_dh.verifyError, constants.DH_NOT_SUITABLE_GENERATOR);
|
||||
decryptedBuffer = crypto.privateDecrypt(keyPem, encryptedBuffer);
|
||||
assert.equal(input, decryptedBuffer.toString());
|
||||
|
||||
encryptedBuffer = crypto.privateEncrypt(keyPem, bufferToEncrypt);
|
||||
|
||||
decryptedBuffer = crypto.publicDecrypt(keyPem, encryptedBuffer);
|
||||
assert.equal(input, decryptedBuffer.toString());
|
||||
|
||||
assert.throws(function() {
|
||||
crypto.privateDecrypt({
|
||||
key: rsaKeyPemEncrypted,
|
||||
|
Loading…
x
Reference in New Issue
Block a user