refactor: organize backend by business responsibility
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
import { createCipheriv, createDecipheriv, randomBytes } from 'node:crypto';
|
||||
|
||||
const VERSION = 1;
|
||||
const NONCE_SIZE = 12;
|
||||
const TAG_SIZE = 16;
|
||||
|
||||
export class TbankCrypto {
|
||||
constructor(private readonly key: Buffer) {}
|
||||
|
||||
static fromBase64(key: string): TbankCrypto {
|
||||
const decoded = Buffer.from(key, 'base64');
|
||||
if (decoded.length !== 32) throw new Error('Invalid token encryption key');
|
||||
return new TbankCrypto(decoded);
|
||||
}
|
||||
|
||||
encrypt(value: string): string {
|
||||
const nonce = randomBytes(NONCE_SIZE);
|
||||
const cipher = createCipheriv('aes-256-gcm', this.key, nonce);
|
||||
const ciphertext = Buffer.concat([
|
||||
cipher.update(value, 'utf8'),
|
||||
cipher.final(),
|
||||
]);
|
||||
return Buffer.concat([
|
||||
Buffer.from([VERSION]),
|
||||
nonce,
|
||||
ciphertext,
|
||||
cipher.getAuthTag(),
|
||||
]).toString('base64');
|
||||
}
|
||||
|
||||
decrypt(payload: string): string {
|
||||
const bytes = Buffer.from(payload, 'base64');
|
||||
if (bytes[0] !== VERSION || bytes.length < 1 + NONCE_SIZE + TAG_SIZE) {
|
||||
throw new Error('Invalid encrypted token');
|
||||
}
|
||||
const nonce = bytes.subarray(1, 1 + NONCE_SIZE);
|
||||
const tag = bytes.subarray(-TAG_SIZE);
|
||||
const decipher = createDecipheriv('aes-256-gcm', this.key, nonce);
|
||||
decipher.setAuthTag(tag);
|
||||
return Buffer.concat([
|
||||
decipher.update(bytes.subarray(1 + NONCE_SIZE, -TAG_SIZE)),
|
||||
decipher.final(),
|
||||
]).toString('utf8');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user