Skip to content

Commit

Permalink
feat: remove crypto-js in favour of crypto native dependency
Browse files Browse the repository at this point in the history
  • Loading branch information
fenos committed Jul 23, 2024
1 parent b548ed1 commit a13feb0
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 23 deletions.
11 changes: 0 additions & 11 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@
"axios-retry": "^3.9.1",
"connection-string": "^4.3.6",
"conventional-changelog-conventionalcommits": "^5.0.0",
"crypto-js": "^4.2.0",
"dotenv": "^16.0.0",
"fastify": "^4.8.1",
"fastify-metrics": "^10.2.0",
Expand Down
54 changes: 43 additions & 11 deletions src/internal/auth/crypto.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,53 @@
import AES from 'crypto-js/aes'
import Utf8 from 'crypto-js/enc-utf8'
import { createCipheriv, createDecipheriv, createHash, randomBytes } from 'crypto'
import { getConfig } from '../../config'

const { encryptionKey } = getConfig()

/**
* Decrypts a text with the configured encryption key via ENCRYPTION_KEY env
* @param ciphertext
*/
* Generate CryptoJs.AES key from passphrase
* https://github.com/brix/crypto-js/issues/468
* */
function convertPassphraseToAesKeyBuffer(key: string, salt: Buffer): Buffer {
const password = Buffer.concat([Buffer.from(key, 'binary'), salt])
const hash: Buffer[] = []
let digest = password
for (let i = 0; i < 3; i++) {
hash[i] = createHash('md5').update(digest).digest()
digest = Buffer.concat([hash[i]!, password])
}
return Buffer.concat(hash)
}

/**
* Replicate CryptoJs.AES.decrypt method
* */
export function decrypt(ciphertext: string): string {
return AES.decrypt(ciphertext, encryptionKey).toString(Utf8)
try {
const cipherBuffer = Buffer.from(ciphertext, 'base64')
const salt = cipherBuffer.subarray(8, 16)
const keyDerivation = convertPassphraseToAesKeyBuffer(encryptionKey, salt)
const [key, iv] = [keyDerivation.subarray(0, 32), keyDerivation.subarray(32)]
const contents = cipherBuffer.subarray(16)
const decipher = createDecipheriv('aes-256-cbc', key, iv)
const decrypted = Buffer.concat([decipher.update(contents), decipher.final()])
return decrypted.toString('utf8')
} catch (e) {
throw e
}
}

/**
* Encrypts a text with the configured encryption key via ENCRYPTION_KEY env
* @param plaintext
*/
* Replicate CryptoJs.AES.encrypt method
* */
export function encrypt(plaintext: string): string {
return AES.encrypt(plaintext, encryptionKey).toString()
try {
const salt = randomBytes(8)
const keyDerivation = convertPassphraseToAesKeyBuffer(encryptionKey, salt)
const [key, iv] = [keyDerivation.subarray(0, 32), keyDerivation.subarray(32)]
const cipher = createCipheriv('aes-256-cbc', key, iv)
const contents = Buffer.concat([cipher.update(plaintext), cipher.final()])
const encrypted = Buffer.concat([Buffer.from('Salted__', 'utf8'), salt, contents])
return encrypted.toString('base64')
} catch (e) {
throw e
}
}

0 comments on commit a13feb0

Please sign in to comment.