0
$\begingroup$

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
  }
}
$\endgroup$
  • $\begingroup$ @kelalaka key is crypto.randomBytes(32). It's stored as is in db. I store it in db to verify user. I don't know how to simplify code, as it's contains iternal as how encrypt/decrypt function works. $\endgroup$ – RTW Dec 30 '19 at 21:25
  • $\begingroup$ @kelalaka and? iv is stored on user side and accesable for attacker. Key is stored in database, not accesable and used for decrypt on server side only. $\endgroup$ – RTW Dec 30 '19 at 21:31
  • $\begingroup$ @kelalaka yes, smt like PAKE $\endgroup$ – RTW Dec 30 '19 at 21:32
  • 1
    $\begingroup$ I've already written about the IV issue on StackOverflow. It's OK to ask somewhere else if it is deleted on the other site, but not before. That's called cross posting and it is considered very inappropriate. Please delete the question on SO if you want your question to remain here. $\endgroup$ – Maarten Bodewes Dec 31 '19 at 0:38
  • 1
    $\begingroup$ As written there "Note that the IV, in CBC mode, only affects the (security of) the first block encrypted with AES..." ... "Check the modes of operation article on Wikipedia. If you decrypt the second ciphertext block and then XOR it with the first ciphertext block then you will retrieve the plaintext (and so forth for the next blocks). The Initialization Vector is, for CBC, just the first vector." $\endgroup$ – Maarten Bodewes Dec 31 '19 at 0:39
3
$\begingroup$

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.

|improve this answer|||||
$\endgroup$
  • $\begingroup$ 1) If cookies was cleaned, he can just relogin and get new one. 2) encrypted data and iv set one time on server and user send it with every request. $\endgroup$ – RTW Dec 31 '19 at 9:47
  • 1
    $\begingroup$ @RTW: If the key on server side is generated once and is used for all future logins and only IV changes, then in case key database is stolen the attacker can generate any data with this key and will be successfully authenticated. If a new key is generated for each login of the same user, then ecnrypting/decripting of a random string has no advantages compared to sending plain random string (like typical GUID used as a session ID). Could you comment that? $\endgroup$ – mentallurg Dec 31 '19 at 10:11
  • 1
    $\begingroup$ No. IDs are generated for each login and have some reasonable time-to-live. So when DB is stolen, before it is used all the keys there will be expired. Stolen DB makes sense only when keys there are used for a long period of time. $\endgroup$ – mentallurg Dec 31 '19 at 10:43
  • 1
    $\begingroup$ To the copy of encrypt function: It is recommended to follow the Kerckhoffs's principle and assume that the attacker knows the encryption function. You get more security when you rely not on a secret function, but on a secret data (key/password). $\endgroup$ – mentallurg Dec 31 '19 at 10:46
  • 1
    $\begingroup$ For many devices you can generate many keys (tokens, IDs, whatever you name it) and associate them with the same user in your database. Request from one device will contain a cookie with the key (token) for this device, request from another device for the same user will contain another key (token). $\endgroup$ – mentallurg Dec 31 '19 at 10:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.