Crypto AES for authentication Is it secure to use authentication strategy like this:


store key in database - crypto.randomBytes(32)
store IV and encrypted data in user cookies - crypto.randomBytes(16)


On request decrypt encrypted data using cookies.iv, cookies.data, database.key. If decrypt was successful proceed with request.

Encrypted data is random string with no value.

If database key was hacked, login is impossible because IV that stored in user cookies is needed.

If cookies was stolen, than I think it's user problem.

My only concern is that there is a way decrypt will be successful for some random attacker key. And that decrypt will be heavy for performance for most of the requests.



Example code for cookie encryption / decryption:

/**
 * @param {string} data dummy
 * @param {string} userKey from database or create new
 * @return {object} {iv, key, encryptedData}
 */
function encrypt(data, userKey) {
  let key = userKey ? Buffer.from(userKey, 'hex') : crypto.randomBytes(32)
  let iv = crypto.randomBytes(16)
  let cipher = crypto.createCipheriv('aes-256-cbc', Buffer.from(key), iv)
  let encrypted = cipher.update(data)
  encrypted = Buffer.concat([encrypted, cipher.final()])
  return { iv: iv.toString('hex'), key: key.toString('hex'), encryptedData: encrypted.toString('hex') }
}

/**
 * @param {string} iv
 * @param {string} key
 * @param {string} encryptedData
 * @return {string} decrupted dummy data
 */
function decrypt(iv, key, encryptedData) {
  try {
    iv = Buffer.from(iv, 'hex')
    key = Buffer.from(key, 'hex')
    encryptedData = Buffer.from(encryptedData, 'hex')
    let decipher = crypto.createDecipheriv('aes-256-cbc', key, iv)
    let decrypted = decipher.update(encryptedData)
    decrypted = Buffer.concat([decrypted, decipher.final()])
    return decrypted.toString()
  } catch (err) {
    return false
  }
}
The aspects regarding IV has already addressed @Maarten - reinstate Monica. There are some more issues.

1) If you store encrypted data in cookies once for all future requests, then it will not work, because many users clean cookies and local storage regularly. Some do that manually, some use add-ons that clean up cookies and local storage on browser exit or every 2-3 hours. Some users cannot even control that, because in serious companies users have no admin permissions and usage of such add-ons is just enforced.

2) If you set encrypted data to cookies each time for login purpose, then cleaning cookies doesn't break your solution. But if an attacker stole the key database, then he can easily decrypt whatever your send him during login.

3) The idea that user should prove he knows the key without sending this key to the server is good. But it is good only if user obtains the key via some channel other than channel used later on for authentication. Where as you want to transfer key via the same channel (same HTTPS connection) as later on authentication/decryption request. Thus you don't have more security. This would be more complexity without any additional security. I would discourage you from doing that.