Search code examples
javascriptnode.jsencryptioncryptographycryptojs

NodeJS crypto module: clean cipher reuse


I'm a bit new to the crypto module in Node. I wrote an encryption function that works perfectly fine but looks awful. This there a better way to write this?

const encrypt = data => {
  const iv = crypto.randomBytes(16);
  const key = crypto.randomBytes(32).toString('hex').slice(0, 32);

  const cipher1 = crypto.createCipheriv(algorithm, new Buffer(key), iv);
  const cipher2 = crypto.createCipheriv(algorithm, new Buffer(key), iv);
  const cipher3 = crypto.createCipheriv(algorithm, new Buffer(key), iv);

  const encryptedFile = Buffer.concat([cipher1.update(data.file), cipher1.final()]);
  const encryptedFileName = Buffer.concat([cipher2.update(data.fileName), cipher2.final()]).toString('hex');
  const encryptedId = Buffer.concat([cipher3.update(data.Id), cipher3.final()]).toString('hex');

  return {
    file: encryptedFile,
    fileName: encryptedFileName,
    id: iv.toString('hex') + ':' + encryptedId.toString('hex'),
    key
  };
};

Input is an object of this structure:

{
  file: <Buffer>,
  fileName: <String>,
  Id: <String>
}

I need to encrypt all of the values with the same key + iv, but not the whole object at once. Is there a way to refactor this to avoid duplication?


Solution

  • Try this:

    const encrypt = (data, key, iv) => {
        const cipher = crypto.createCipheriv(algorithm, new Buffer(key), iv);
    
        return Buffer.concat([cipher.update(data), cipher.final()]);
    };
    
    const encrypt = data => {
        const iv = crypto.randomBytes(16);
        const key = crypto
          .randomBytes(32)
          .toString('hex')
          .slice(0, 32);
    
        return {
          file: encrypt(data.file, key, iv),
          fileName: encrypt(data.fileName, key, iv).toString('hex'),
          id: `${iv.toString('hex')}:${encrypt(data.Id, key, iv).toString('hex')}`,
          key,
        };
      };