diff --git a/lib/internal/crypto/cipher.js b/lib/internal/crypto/cipher.js index 118fc1da5b7c2c..d1c45bfdce0e0d 100644 --- a/lib/internal/crypto/cipher.js +++ b/lib/internal/crypto/cipher.js @@ -33,7 +33,7 @@ const { StringDecoder } = require('string_decoder'); const { inherits } = require('util'); const { normalizeEncoding } = require('internal/util'); -function rsaPublic(method, defaultPadding) { +function rsaFunctionFor(method, defaultPadding) { return function(options, buffer) { const key = options.key || options; const padding = options.padding || defaultPadding; @@ -42,19 +42,10 @@ function rsaPublic(method, defaultPadding) { }; } -function rsaPrivate(method, defaultPadding) { - return function(options, buffer) { - const key = options.key || options; - const passphrase = options.passphrase || null; - const padding = options.padding || defaultPadding; - return method(toBuf(key), buffer, padding, passphrase); - }; -} - -const publicEncrypt = rsaPublic(_publicEncrypt, RSA_PKCS1_OAEP_PADDING); -const publicDecrypt = rsaPublic(_publicDecrypt, RSA_PKCS1_PADDING); -const privateEncrypt = rsaPrivate(_privateEncrypt, RSA_PKCS1_PADDING); -const privateDecrypt = rsaPrivate(_privateDecrypt, RSA_PKCS1_OAEP_PADDING); +const publicEncrypt = rsaFunctionFor(_publicEncrypt, RSA_PKCS1_OAEP_PADDING); +const publicDecrypt = rsaFunctionFor(_publicDecrypt, RSA_PKCS1_PADDING); +const privateEncrypt = rsaFunctionFor(_privateEncrypt, RSA_PKCS1_PADDING); +const privateDecrypt = rsaFunctionFor(_privateDecrypt, RSA_PKCS1_OAEP_PADDING); function getDecoder(decoder, encoding) { encoding = normalizeEncoding(encoding); @@ -73,10 +64,21 @@ function getUIntOption(options, key) { return -1; } -function Cipher(cipher, password, options) { - if (!(this instanceof Cipher)) - return new Cipher(cipher, password, options); +function createCipherBase(cipher, credential, options, decipher, iv) { + const authTagLength = getUIntOption(options, 'authTagLength'); + + this._handle = new CipherBase(decipher); + if (iv === undefined) { + this._handle.init(cipher, credential, authTagLength); + } else { + this._handle.initiv(cipher, credential, iv, authTagLength); + } + this._decoder = null; + LazyTransform.call(this, options); +} + +function createCipher(cipher, password, options, decipher) { if (typeof cipher !== 'string') throw new ERR_INVALID_ARG_TYPE('cipher', 'string', cipher); @@ -89,14 +91,38 @@ function Cipher(cipher, password, options) { ); } - const authTagLength = getUIntOption(options, 'authTagLength'); + createCipherBase.call(this, cipher, password, options, decipher); +} - this._handle = new CipherBase(true); +function createCipherWithIV(cipher, key, options, decipher, iv) { + if (typeof cipher !== 'string') + throw new ERR_INVALID_ARG_TYPE('cipher', 'string', cipher); - this._handle.init(cipher, password, authTagLength); - this._decoder = null; + key = toBuf(key); + if (!isArrayBufferView(key)) { + throw new ERR_INVALID_ARG_TYPE( + 'key', + ['string', 'Buffer', 'TypedArray', 'DataView'], + key + ); + } - LazyTransform.call(this, options); + iv = toBuf(iv); + if (iv !== null && !isArrayBufferView(iv)) { + throw new ERR_INVALID_ARG_TYPE( + 'iv', + ['string', 'Buffer', 'TypedArray', 'DataView'], + iv + ); + } + createCipherBase.call(this, cipher, key, options, decipher, iv); +} + +function Cipher(cipher, password, options) { + if (!(this instanceof Cipher)) + return new Cipher(cipher, password, options); + + createCipher.call(this, cipher, password, options, true); } inherits(Cipher, LazyTransform); @@ -198,130 +224,43 @@ function Cipheriv(cipher, key, iv, options) { if (!(this instanceof Cipheriv)) return new Cipheriv(cipher, key, iv, options); - if (typeof cipher !== 'string') - throw new ERR_INVALID_ARG_TYPE('cipher', 'string', cipher); - - key = toBuf(key); - if (!isArrayBufferView(key)) { - throw new ERR_INVALID_ARG_TYPE( - 'key', - ['string', 'Buffer', 'TypedArray', 'DataView'], - key - ); - } - - iv = toBuf(iv); - if (iv !== null && !isArrayBufferView(iv)) { - throw new ERR_INVALID_ARG_TYPE( - 'iv', - ['string', 'Buffer', 'TypedArray', 'DataView'], - iv - ); - } - - const authTagLength = getUIntOption(options, 'authTagLength'); - - this._handle = new CipherBase(true); - this._handle.initiv(cipher, key, iv, authTagLength); - this._decoder = null; + createCipherWithIV.call(this, cipher, key, options, true, iv); +} - LazyTransform.call(this, options); +function addCipherPrototypeFunctions(constructor) { + constructor.prototype._transform = Cipher.prototype._transform; + constructor.prototype._flush = Cipher.prototype._flush; + constructor.prototype.update = Cipher.prototype.update; + constructor.prototype.final = Cipher.prototype.final; + constructor.prototype.setAutoPadding = Cipher.prototype.setAutoPadding; + constructor.prototype.getAuthTag = Cipher.prototype.getAuthTag; + constructor.prototype.setAuthTag = Cipher.prototype.setAuthTag; + constructor.prototype.setAAD = Cipher.prototype.setAAD; } inherits(Cipheriv, LazyTransform); - -Cipheriv.prototype._transform = Cipher.prototype._transform; -Cipheriv.prototype._flush = Cipher.prototype._flush; -Cipheriv.prototype.update = Cipher.prototype.update; -Cipheriv.prototype.final = Cipher.prototype.final; -Cipheriv.prototype.setAutoPadding = Cipher.prototype.setAutoPadding; -Cipheriv.prototype.getAuthTag = Cipher.prototype.getAuthTag; -Cipheriv.prototype.setAuthTag = Cipher.prototype.setAuthTag; -Cipheriv.prototype.setAAD = Cipher.prototype.setAAD; - +addCipherPrototypeFunctions(Cipheriv); function Decipher(cipher, password, options) { if (!(this instanceof Decipher)) return new Decipher(cipher, password, options); - if (typeof cipher !== 'string') - throw new ERR_INVALID_ARG_TYPE('cipher', 'string', cipher); - - password = toBuf(password); - if (!isArrayBufferView(password)) { - throw new ERR_INVALID_ARG_TYPE( - 'password', - ['string', 'Buffer', 'TypedArray', 'DataView'], - password - ); - } - - const authTagLength = getUIntOption(options, 'authTagLength'); - - this._handle = new CipherBase(false); - this._handle.init(cipher, password, authTagLength); - this._decoder = null; - - LazyTransform.call(this, options); + createCipher.call(this, cipher, password, options, false); } inherits(Decipher, LazyTransform); - -Decipher.prototype._transform = Cipher.prototype._transform; -Decipher.prototype._flush = Cipher.prototype._flush; -Decipher.prototype.update = Cipher.prototype.update; -Decipher.prototype.final = Cipher.prototype.final; -Decipher.prototype.setAutoPadding = Cipher.prototype.setAutoPadding; -Decipher.prototype.getAuthTag = Cipher.prototype.getAuthTag; -Decipher.prototype.setAuthTag = Cipher.prototype.setAuthTag; -Decipher.prototype.setAAD = Cipher.prototype.setAAD; +addCipherPrototypeFunctions(Decipher); function Decipheriv(cipher, key, iv, options) { if (!(this instanceof Decipheriv)) return new Decipheriv(cipher, key, iv, options); - if (typeof cipher !== 'string') - throw new ERR_INVALID_ARG_TYPE('cipher', 'string', cipher); - - key = toBuf(key); - if (!isArrayBufferView(key)) { - throw new ERR_INVALID_ARG_TYPE( - 'key', - ['string', 'Buffer', 'TypedArray', 'DataView'], - key - ); - } - - iv = toBuf(iv); - if (iv !== null && !isArrayBufferView(iv)) { - throw new ERR_INVALID_ARG_TYPE( - 'iv', - ['string', 'Buffer', 'TypedArray', 'DataView'], - iv - ); - } - - const authTagLength = getUIntOption(options, 'authTagLength'); - - this._handle = new CipherBase(false); - this._handle.initiv(cipher, key, iv, authTagLength); - this._decoder = null; - - LazyTransform.call(this, options); + createCipherWithIV.call(this, cipher, key, options, false, iv); } inherits(Decipheriv, LazyTransform); - -Decipheriv.prototype._transform = Cipher.prototype._transform; -Decipheriv.prototype._flush = Cipher.prototype._flush; -Decipheriv.prototype.update = Cipher.prototype.update; -Decipheriv.prototype.final = Cipher.prototype.final; -Decipheriv.prototype.setAutoPadding = Cipher.prototype.setAutoPadding; -Decipheriv.prototype.getAuthTag = Cipher.prototype.getAuthTag; -Decipheriv.prototype.setAuthTag = Cipher.prototype.setAuthTag; -Decipheriv.prototype.setAAD = Cipher.prototype.setAAD; - +addCipherPrototypeFunctions(Decipheriv); module.exports = { Cipher,