Enhance encryption methods in admin configuration to use AES-256-GCM with key derivation
Build And Push Image / docker (push) Successful in 3m6s
Details
Build And Push Image / docker (push) Successful in 3m6s
Details
This commit is contained in:
parent
ce0cbdc980
commit
d0d7a34ae7
|
|
@ -1,6 +1,6 @@
|
||||||
import { readFile, writeFile, mkdir, access, constants } from 'fs/promises';
|
import { readFile, writeFile, mkdir, access, constants } from 'fs/promises';
|
||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
import { createCipher, createDecipher } from 'crypto';
|
import { createCipheriv, createDecipheriv, randomBytes, pbkdf2Sync } from 'crypto';
|
||||||
import type { NocoDBSettings } from '~/utils/types';
|
import type { NocoDBSettings } from '~/utils/types';
|
||||||
|
|
||||||
interface AdminConfiguration {
|
interface AdminConfiguration {
|
||||||
|
|
@ -49,10 +49,23 @@ function encryptSensitiveData(data: string): string {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const cipher = createCipher('aes256', encryptionKey);
|
// Use AES-256-GCM for modern encryption
|
||||||
|
const algorithm = 'aes-256-gcm';
|
||||||
|
const iv = randomBytes(16);
|
||||||
|
const salt = randomBytes(16);
|
||||||
|
|
||||||
|
// Derive key from the encryption key
|
||||||
|
const key = pbkdf2Sync(encryptionKey, salt, 100000, 32, 'sha256');
|
||||||
|
|
||||||
|
const cipher = createCipheriv(algorithm, key, iv);
|
||||||
let encrypted = cipher.update(data, 'utf8', 'hex');
|
let encrypted = cipher.update(data, 'utf8', 'hex');
|
||||||
encrypted += cipher.final('hex');
|
encrypted += cipher.final('hex');
|
||||||
return encrypted;
|
|
||||||
|
const authTag = cipher.getAuthTag();
|
||||||
|
|
||||||
|
// Combine salt, iv, authTag, and encrypted data
|
||||||
|
const combined = salt.toString('hex') + ':' + iv.toString('hex') + ':' + authTag.toString('hex') + ':' + encrypted;
|
||||||
|
return combined;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('[admin-config] Encryption failed:', error);
|
console.error('[admin-config] Encryption failed:', error);
|
||||||
return data;
|
return data;
|
||||||
|
|
@ -71,9 +84,33 @@ function decryptSensitiveData(encryptedData: string): string {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const decipher = createDecipher('aes256', encryptionKey);
|
// Check if data contains our modern format with colons
|
||||||
let decrypted = decipher.update(encryptedData, 'hex', 'utf8');
|
if (!encryptedData.includes(':')) {
|
||||||
|
// Legacy data, return as-is
|
||||||
|
console.warn('[admin-config] Legacy encrypted data format detected, returning as-is');
|
||||||
|
return encryptedData;
|
||||||
|
}
|
||||||
|
|
||||||
|
const parts = encryptedData.split(':');
|
||||||
|
if (parts.length !== 4) {
|
||||||
|
throw new Error('Invalid encrypted data format');
|
||||||
|
}
|
||||||
|
|
||||||
|
const [saltHex, ivHex, authTagHex, encrypted] = parts;
|
||||||
|
const salt = Buffer.from(saltHex, 'hex');
|
||||||
|
const iv = Buffer.from(ivHex, 'hex');
|
||||||
|
const authTag = Buffer.from(authTagHex, 'hex');
|
||||||
|
|
||||||
|
// Derive key from the encryption key
|
||||||
|
const key = pbkdf2Sync(encryptionKey, salt, 100000, 32, 'sha256');
|
||||||
|
|
||||||
|
const algorithm = 'aes-256-gcm';
|
||||||
|
const decipher = createDecipheriv(algorithm, key, iv);
|
||||||
|
decipher.setAuthTag(authTag);
|
||||||
|
|
||||||
|
let decrypted = decipher.update(encrypted, 'hex', 'utf8');
|
||||||
decrypted += decipher.final('utf8');
|
decrypted += decipher.final('utf8');
|
||||||
|
|
||||||
return decrypted;
|
return decrypted;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('[admin-config] Decryption failed:', error);
|
console.error('[admin-config] Decryption failed:', error);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue