diff --git a/modules/encryption/define_config.ts b/modules/encryption/define_config.ts index 8a81971e..1b19b4fa 100644 --- a/modules/encryption/define_config.ts +++ b/modules/encryption/define_config.ts @@ -12,6 +12,7 @@ import { configProvider } from '../../src/config_provider.ts' import { type ConfigProvider } from '../../src/types.ts' import { + type AESSIVDriverConfig, type AES256CBCDriverConfig, type AES256GCMDriverConfig, type ChaCha20Poly1305DriverConfig, @@ -198,6 +199,21 @@ export const drivers: { */ aes256gcm: (config: AES256GCMDriverConfig) => ConfigProvider + /** + * Creates an AES-SIV encryption driver configuration. + * + * @param config - The AES-SIV driver configuration + * + * @example + * ```ts + * drivers.aessiv({ + * id: 'app', + * key: env.get('APP_KEY') + * }) + * ``` + */ + aessiv: (config: AESSIVDriverConfig) => ConfigProvider + /** * Creates a Legacy encryption driver configuration. * @@ -251,6 +267,17 @@ export const drivers: { }) }, + aessiv: (config) => { + return configProvider.create(async () => { + const { AESSIV } = await import('./drivers/aes_siv.ts') + debug('configuring aessiv encryption driver') + return { + driver: (key) => new AESSIV({ id: config.id, key }), + keys: [config.key].filter((key) => !!key), + } + }) + }, + legacy: (config) => { return configProvider.create(async () => { const { Legacy } = await import('./drivers/legacy.ts') diff --git a/modules/encryption/drivers/aes_siv.ts b/modules/encryption/drivers/aes_siv.ts new file mode 100644 index 00000000..163fb0e8 --- /dev/null +++ b/modules/encryption/drivers/aes_siv.ts @@ -0,0 +1,28 @@ +/* + * @adonisjs/core + * + * (c) AdonisJS + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * AES-SIV encryption driver implementation. + * + * This driver provides deterministic authenticated encryption using AES-SIV + * (Synthetic Initialization Vector). It is useful when you need equality + * queries over encrypted values while preserving authenticity guarantees. + * + * @example + * ```ts + * const driver = new AESSIV({ + * id: 'app', + * key: 'your-256-bit-key-here' + * }) + * + * const encrypted = driver.encrypt('sensitive data') + * const decrypted = driver.decrypt(encrypted) + * ``` + */ +export { AESSIV } from '@boringnode/encryption/drivers/aes_siv' diff --git a/modules/encryption/drivers/legacy.ts b/modules/encryption/drivers/legacy.ts index 2867f0de..da79a7c6 100644 --- a/modules/encryption/drivers/legacy.ts +++ b/modules/encryption/drivers/legacy.ts @@ -16,6 +16,7 @@ import type { EncryptOptions, } from '@boringnode/encryption/types' import { errors } from '@boringnode/encryption' +import { E_LEGACY_BLIND_INDEX_NOT_SUPPORTED } from '../errors.ts' /** * Configuration for the Legacy encryption driver. @@ -183,4 +184,18 @@ export class Legacy extends BaseDriver implements EncryptionDriverContract { return null } } + + /** + * Legacy driver does not support blind indexes. + */ + blindIndex(_payload: any, _purpose: string): string { + throw new E_LEGACY_BLIND_INDEX_NOT_SUPPORTED() + } + + /** + * Legacy driver does not support blind indexes. + */ + blindIndexes(_payload: any, _purpose: string): string[] { + throw new E_LEGACY_BLIND_INDEX_NOT_SUPPORTED() + } } diff --git a/modules/encryption/errors.ts b/modules/encryption/errors.ts new file mode 100644 index 00000000..39d5487c --- /dev/null +++ b/modules/encryption/errors.ts @@ -0,0 +1,27 @@ +/* + * @adonisjs/core + * + * (c) AdonisJS + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +import { createError } from '../../src/exceptions.ts' +import { errors as boringnodeErrors } from '@boringnode/encryption' + +/** + * Raised when attempting to compute blind indexes using the legacy driver. + */ +export const E_LEGACY_BLIND_INDEX_NOT_SUPPORTED = createError( + 'Blind indexes are not supported by the legacy encryption driver', + 'E_LEGACY_BLIND_INDEX_NOT_SUPPORTED' +) + +/** + * Encryption errors exposed by this package. + */ +export const errors = { + ...boringnodeErrors, + E_LEGACY_BLIND_INDEX_NOT_SUPPORTED, +} diff --git a/modules/encryption/main.ts b/modules/encryption/main.ts index 6352af51..b8ab931d 100644 --- a/modules/encryption/main.ts +++ b/modules/encryption/main.ts @@ -81,6 +81,11 @@ export { Hmac } from '@boringnode/encryption' */ export { BaseDriver } from '@boringnode/encryption' +/** + * Encryption module specific exceptions. + */ +export { errors } from './errors.ts' + /** * Defines the encryption configuration for the application. * @@ -91,8 +96,8 @@ export { defineConfig } from './define_config.ts' /** * Collection of built-in encryption driver factory functions. * - * Includes factories for ChaCha20-Poly1305, AES-256-CBC, and - * AES-256-GCM encryption algorithms. + * Includes factories for ChaCha20-Poly1305, AES-256-CBC, + * AES-256-GCM, and AES-SIV encryption algorithms. * * @see {drivers} in define_config.ts for detailed documentation */ diff --git a/package.json b/package.json index 87a3cb13..9b59726b 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,7 @@ "./encryption": "./build/modules/encryption/main.js", "./encryption/drivers/aes_256_cbc": "./build/modules/encryption/drivers/aes_256_cbc.js", "./encryption/drivers/aes_256_gcm": "./build/modules/encryption/drivers/aes_256_gcm.js", + "./encryption/drivers/aes_siv": "./build/modules/encryption/drivers/aes_siv.js", "./encryption/drivers/chacha20_poly1305": "./build/modules/encryption/drivers/chacha20_poly1305.js", "./env": "./build/modules/env/main.js", "./dumper": "./build/modules/dumper/main.js", @@ -129,7 +130,7 @@ "@adonisjs/fold": "^11.0.0-next.4", "@adonisjs/hash": "^10.0.0-next.2", "@adonisjs/health": "^3.1.0-next.1", - "@adonisjs/http-server": "^8.0.0-next.18", + "@adonisjs/http-server": "^8.0.0-next.19", "@adonisjs/http-transformers": "^2.2.0", "@adonisjs/logger": "^7.1.0-next.3", "@adonisjs/repl": "^5.0.0-next.2", diff --git a/tests/encryption/legacy.spec.ts b/tests/encryption/legacy.spec.ts index c03cd03c..f538cbac 100644 --- a/tests/encryption/legacy.spec.ts +++ b/tests/encryption/legacy.spec.ts @@ -272,3 +272,23 @@ test.group('Legacy | defineConfig', () => { assert.deepEqual(config.list.legacy.keys, [SECRET_KEY]) }) }) + +test.group('Legacy | blind indexes', () => { + test('throw when computing blind index', ({ assert }) => { + const encryption = new Legacy({ key: SECRET_KEY }) + + assert.throws( + () => encryption.blindIndex('foo@example.com', 'users.email'), + 'Blind indexes are not supported by the legacy encryption driver' + ) + }) + + test('throw when computing blind indexes', ({ assert }) => { + const encryption = new Legacy({ key: SECRET_KEY }) + + assert.throws( + () => encryption.blindIndexes('foo@example.com', 'users.email'), + 'Blind indexes are not supported by the legacy encryption driver' + ) + }) +}) diff --git a/types/encryption.ts b/types/encryption.ts index 336c7c8b..e079865d 100644 --- a/types/encryption.ts +++ b/types/encryption.ts @@ -42,6 +42,13 @@ export type { AES256CBCDriverConfig } from '@boringnode/encryption/drivers/aes_2 */ export type { AES256GCMDriverConfig } from '@boringnode/encryption/drivers/aes_256_gcm' +/** + * Configuration options for the AES-SIV encryption driver. + * + * Includes the driver identifier and a single encryption key. + */ +export type { AESSIVDriverConfig } from '@boringnode/encryption/drivers/aes_siv' + /** * Configuration options for the ChaCha20-Poly1305 encryption driver. *