From f04a29dfef2dff3859c1f30197d57abaa899689a Mon Sep 17 00:00:00 2001 From: Michael Drury Date: Mon, 14 Feb 2022 21:37:40 +0000 Subject: [PATCH] Using 10K iteration string stretching for encryption. --- .../src/middleware/authenticated.js | 5 ++-- .../backend-core/src/security/encryption.js | 26 ++++++++++++------- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/packages/backend-core/src/middleware/authenticated.js b/packages/backend-core/src/middleware/authenticated.js index 0cb56b5b69..1e920739c4 100644 --- a/packages/backend-core/src/middleware/authenticated.js +++ b/packages/backend-core/src/middleware/authenticated.js @@ -23,9 +23,10 @@ async function checkApiKey(apiKey, populateUser) { if (apiKey === env.INTERNAL_API_KEY) { return { valid: true } } - apiKey = decrypt(apiKey) - const tenantId = apiKey.split(SEPARATOR)[0] + const decrypted = decrypt(apiKey) + const tenantId = decrypted.split(SEPARATOR)[0] const db = getGlobalDB(tenantId) + // api key is encrypted in the database const userId = await queryGlobalView( ViewNames.BY_API_KEY, { diff --git a/packages/backend-core/src/security/encryption.js b/packages/backend-core/src/security/encryption.js index 8bb7def541..c31f597652 100644 --- a/packages/backend-core/src/security/encryption.js +++ b/packages/backend-core/src/security/encryption.js @@ -3,24 +3,30 @@ const env = require("../environment") const ALGO = "aes-256-ctr" const SECRET = env.JWT_SECRET -const SEPARATOR = "/" +const SEPARATOR = "-" +const ITERATIONS = 10000 +const RANDOM_BYTES = 16 +const STRETCH_LENGTH = 32 + +function stretchString(string, salt) { + return crypto.pbkdf2Sync(string, salt, ITERATIONS, STRETCH_LENGTH, "sha512") +} exports.encrypt = input => { - const random = crypto.randomBytes(16) - const cipher = crypto.createCipheriv(ALGO, SECRET, random) + const salt = crypto.randomBytes(RANDOM_BYTES) + const stretched = stretchString(SECRET, salt) + const cipher = crypto.createCipheriv(ALGO, stretched, salt) const base = cipher.update(input) const final = cipher.final() const encrypted = Buffer.concat([base, final]).toString("hex") - return `${random.toString("hex")}${SEPARATOR}${encrypted}` + return `${salt.toString("hex")}${SEPARATOR}${encrypted}` } exports.decrypt = input => { - const [random, encrypted] = input.split(SEPARATOR) - const decipher = crypto.createDecipheriv( - ALGO, - SECRET, - Buffer.from(random, "hex") - ) + const [salt, encrypted] = input.split(SEPARATOR) + const saltBuffer = Buffer.from(salt, "hex") + const stretched = stretchString(SECRET, saltBuffer) + const decipher = crypto.createDecipheriv(ALGO, stretched, saltBuffer) const base = decipher.update(Buffer.from(encrypted, "hex")) const final = decipher.final() return Buffer.concat([base, final]).toString()