Расшифровка шифрования AES 256 GCM в nodejs - PullRequest
0 голосов
/ 12 ноября 2018

Я реализую базовый набор функций шифрования / дешифрования в nodejs и продолжаю получать следующую ошибку в части дешифрования:
Error: Unsupported state or unable to authenticate data

Это мой код:

import crypto from 'crypto'
import logger from './logger'

const ALGORITHM = 'aes-256-gcm'

export const encrypt = (keyBuffer, dataBuffer, aadBuffer) => {
  // iv stands for "initialization vector"
  const iv = Buffer.from(crypto.randomBytes(12), 'utf8')
  logger.debug('iv: ', iv)
  const encryptor = crypto.createCipheriv(ALGORITHM, keyBuffer, iv)
  logger.debug('encryptor: ', encryptor)
  logger.debug('dataBuffer: ', dataBuffer)
  return Buffer.concat([iv, encryptor.update(dataBuffer, 'utf8'), encryptor.final()])
}

export const decrypt = (keyBuffer, dataBuffer, aadBuffer) => {
  const iv = dataBuffer.slice(0, 96)

  const decryptor = crypto.createDecipheriv(ALGORITHM, keyBuffer, iv)
  return Buffer.concat([decryptor.update(dataBuffer.slice(96), 'utf8'), decryptor.final()])
}

Моя ошибка происходит в последней строке функции расшифровки. Я храню iv как часть dataBuffer.

Заранее спасибо!

Ответы [ 2 ]

0 голосов
/ 23 марта 2019

Зачем изобретать велосипед? kruptein поддерживает большинство режимов и размеров клавиш AES и использует функции authTag и AAD, доступные в режимах CCM, GCM и OCB.

const kruptein = require('kruptein');

kruptein.init({secret: 'squirrel'});

let ciphertext = kruptein.set('Foo Bar!');
let plaintext = kruptein.get(ciphertext);
0 голосов
/ 13 ноября 2018

Я понял, что допустил пару ошибок с исходным кодом, который я разместил, одной из которых, как заметил @TheGreatContini, был размер среза, который выполнялся в битах, а не в байтах, как и должно быть. Тем не менее, самая большая часть, которую мне не хватало, это authTag, который всегда должен быть включен в настройку функции расшифровки.

Вот мой рабочий код для тех, кто заинтересован в будущих ссылках:

import crypto from 'crypto'
import logger from './logger'

const ALGORITHM = 'aes-256-gcm'

export const encrypt = (keyBuffer, dataBuffer, aadBuffer) => {
  // iv stands for "initialization vector"
  const iv = crypto.randomBytes(12)
  const cipher = crypto.createCipheriv(ALGORITHM, keyBuffer, iv)
  const encryptedBuffer = Buffer.concat([cipher.update(dataBuffer), cipher.final()])
  const authTag = cipher.getAuthTag()
  let bufferLength = Buffer.alloc(1)
  bufferLength.writeUInt8(iv.length, 0)
  return Buffer.concat([bufferLength, iv, authTag, encryptedBuffer])
}

export const decrypt = (keyBuffer, dataBuffer, aadBuffer) => {
  const ivSize = dataBuffer.readUInt8(0)
  const iv = dataBuffer.slice(1, ivSize + 1)
  // The authTag is by default 16 bytes in AES-GCM
  const authTag = dataBuffer.slice(ivSize + 1, ivSize + 17)
  const decipher = crypto.createDecipheriv(ALGORITHM, keyBuffer, iv)
  decipher.setAuthTag(authTag)
  return Buffer.concat([decipher.update(dataBuffer.slice(ivSize + 17)), decipher.final()])
}
...