feature: the credential store keeps credentials of any kind in config.json with encrypted secrets, with its routes and its dialog.
Release / release (push) Successful in 1m4s

This commit is contained in:
slawek committed 2026-10-28 20:28:22 +01:00
1 parent 57ac5296cb
commit b0b7a4bb7f
13 files changed
+723 -30

No files matched your search

+38
View File
@@ -0,0 +1,38 @@
import { createCipheriv, createDecipheriv, createHash, randomBytes } from 'node:crypto'
import { readFileSync } from 'node:fs'
const ALGORITHM = 'aes-256-gcm'
const IV_BYTES = 12
const TAG_BYTES = 16
/**
* The key of the secrets: the SHA-256 of ENCRYPTION_KEY, else of the content of the file ENCRYPTION_KEY_FILE names
* without its final newline; null when neither is set. A file that cannot be read throws with the reason.
*/
export function encryptionKey(): Buffer | null {
let secret = process.env.ENCRYPTION_KEY
if (!secret && process.env.ENCRYPTION_KEY_FILE) {
try {
secret = readFileSync(process.env.ENCRYPTION_KEY_FILE, 'utf8').replace(/\r?\n$/, '')
} catch (error) {
throw new Error(`ENCRYPTION_KEY_FILE ${process.env.ENCRYPTION_KEY_FILE} cannot be read: ${(error as Error).message}`)
}
}
return secret ? createHash('sha256').update(secret, 'utf8').digest() : null
}
/** The text encrypted with AES-256-GCM: base64 of a random IV, the ciphertext and the authentication tag. */
export function encrypt(text: string, key: Buffer): string {
const iv = randomBytes(IV_BYTES)
const cipher = createCipheriv(ALGORITHM, key, iv)
const data = Buffer.concat([cipher.update(text, 'utf8'), cipher.final()])
return Buffer.concat([iv, data, cipher.getAuthTag()]).toString('base64')
}
/** The text of encrypt's answer; another key, or a changed answer, throws. */
export function decrypt(encrypted: string, key: Buffer): string {
const bytes = Buffer.from(encrypted, 'base64')
const decipher = createDecipheriv(ALGORITHM, key, bytes.subarray(0, IV_BYTES))
decipher.setAuthTag(bytes.subarray(bytes.length - TAG_BYTES))
return Buffer.concat([decipher.update(bytes.subarray(IV_BYTES, bytes.length - TAG_BYTES)), decipher.final()]).toString('utf8')
}