Skip to main content
The Encryption module provides encryption and decryption functionality with support for multiple algorithms including ChaCha20-Poly1305, AES-256-GCM, AES-256-CBC, and AES-SIV.

Import

import { Encryption, EncryptionManager, Hmac, BaseDriver } from '@adonisjs/core/encryption'
import { defineConfig, drivers, errors } from '@adonisjs/core/encryption'
import type { EncryptionConfig } from '@adonisjs/core/types/encryption'

Overview

The Encryption module provides classes and utilities for encrypting and decrypting sensitive data. It supports purpose binding, multiple encryption keys, and various encryption algorithms.

Classes

Encryption

Main encryption class for encrypting and decrypting values.

Constructor

config
object
required
Configuration object
key
string
required
The encryption key

Methods

encrypt
Encrypts a string or object value.
value
string | object
required
The value to encrypt
purpose
string
Optional purpose for binding the encrypted value to a specific use case
return
string
The encrypted string
const encryption = new Encryption({ key: 'secret-key' })
const encrypted = encryption.encrypt('sensitive data')
const encryptedWithPurpose = encryption.encrypt('api-key', 'api-authentication')
decrypt
Decrypts an encrypted value.
payload
string
required
The encrypted string to decrypt
purpose
string
Optional purpose that must match the purpose used during encryption
return
string | object
The decrypted value
const decrypted = encryption.decrypt(encrypted)
const decryptedWithPurpose = encryption.decrypt(encryptedWithPurpose, 'api-authentication')

EncryptionManager

Manager class for handling multiple encryption instances.

Constructor

config
object
required
Configuration object
default
string
required
The default encryptor name
list
object
required
Map of encryptor configurations

Methods

use
Returns a specific encryption instance.
name
string
Optional encryptor name. If omitted, returns the default encryptor.
return
Encryption
The encryption instance
const manager = new EncryptionManager({
  default: 'app',
  list: {
    app: {
      driver: (key) => new AES256GCM({ key }),
      keys: ['app-key']
    }
  }
})

const encryptor = manager.use('app')
const encrypted = encryptor.encrypt('data')

Hmac

HMAC (Hash-based Message Authentication Code) class for creating and verifying message authentication codes.

Constructor

key
string
required
The secret key for HMAC generation

Methods

generate
Generates an HMAC signature for a message.
message
string
required
The message to sign
return
string
The HMAC signature
const hmac = new Hmac('secret-key')
const signature = hmac.generate('message')
verify
Verifies an HMAC signature.
message
string
required
The original message
signature
string
required
The signature to verify
return
boolean
Returns true if the signature is valid
const isValid = hmac.verify('message', signature)

BaseDriver

Base class for implementing custom encryption drivers.
Extend this class to create custom encryption implementations that can be used with the EncryptionManager.
class CustomDriver extends BaseDriver {
  encrypt(value: string) {
    // Custom encryption logic
  }
  
  decrypt(payload: string) {
    // Custom decryption logic
  }
}

Functions

defineConfig

Defines the encryption configuration for the application.
config
object
required
The encryption configuration object
default
string
Optional default encryptor name
list
object
required
Map of encryptor names to their configurations or providers
return
ConfigProvider<ResolvedConfig>
A configuration provider that lazily resolves encryption drivers
import { defineConfig, drivers } from '@adonisjs/core/encryption'
import env from '@adonisjs/core/services/env'

const encryptionConfig = defineConfig({
  default: 'app',
  list: {
    app: drivers.aes256gcm({
      id: 'app',
      keys: [env.get('APP_KEY')]
    }),
    backup: drivers.chacha20({
      id: 'backup',
      keys: [env.get('BACKUP_KEY')]
    })
  }
})

Drivers

The drivers object provides factory functions for creating encryption driver configurations.

drivers.chacha20

Creates a ChaCha20-Poly1305 encryption driver configuration.
ChaCha20-Poly1305 is a modern authenticated encryption algorithm that provides excellent performance on systems without AES hardware acceleration.
config
ChaCha20Poly1305DriverConfig
required
id
string
required
Unique identifier for this encryptor
keys
string[]
required
Array of encryption keys (supports key rotation)
chacha20: drivers.chacha20({
  id: 'app',
  keys: [env.get('APP_KEY')]
})

drivers.aes256cbc

Creates an AES-256-CBC encryption driver configuration.
AES-256-CBC is widely supported but consider using AES-256-GCM for new applications as it provides authenticated encryption.
config
AES256CBCDriverConfig
required
id
string
required
Unique identifier for this encryptor
keys
string[]
required
Array of encryption keys
aes256cbc: drivers.aes256cbc({
  id: 'legacy',
  keys: [env.get('LEGACY_KEY')]
})

drivers.aes256gcm

Creates an AES-256-GCM encryption driver configuration.
AES-256-GCM is an authenticated encryption algorithm that provides both confidentiality and integrity. It offers excellent performance on systems with AES hardware acceleration.
config
AES256GCMDriverConfig
required
id
string
required
Unique identifier for this encryptor
keys
string[]
required
Array of encryption keys
aes256gcm: drivers.aes256gcm({
  id: 'app',
  keys: [env.get('APP_KEY')]
})

drivers.aessiv

Creates an AES-SIV encryption driver configuration.
config
AESSIVDriverConfig
required
id
string
required
Unique identifier for this encryptor
key
string
required
Single encryption key
aessiv: drivers.aessiv({
  id: 'app',
  key: env.get('APP_KEY')
})

drivers.legacy

Creates a Legacy encryption driver configuration for compatibility with AdonisJS v6.
The Legacy driver maintains compatibility with the old AdonisJS v6 encryption format using AES-256-CBC with HMAC SHA-256. Use this when migrating from older versions.
config
LegacyDriverConfig
required
keys
string[]
required
Array of encryption keys
legacy: drivers.legacy({
  keys: [env.get('APP_KEY')]
})

Errors

The errors object contains encryption-specific exceptions.

E_BLIND_INDEX_NOT_SUPPORTED

Raised when attempting to compute blind indexes using the legacy driver.
import { errors } from '@adonisjs/core/encryption'

try {
  // Some operation
} catch (error) {
  if (error instanceof errors.E_BLIND_INDEX_NOT_SUPPORTED) {
    console.error('Blind indexes not supported')
  }
}

Example Usage

Configuration

// config/encryption.ts
import { defineConfig, drivers } from '@adonisjs/core/encryption'
import env from '@adonisjs/core/services/env'

export default defineConfig({
  default: 'app',
  
  list: {
    app: drivers.aes256gcm({
      id: 'app',
      keys: [env.get('APP_KEY')]
    }),
    
    api: drivers.chacha20({
      id: 'api',
      keys: [env.get('API_KEY')]
    }),
    
    legacy: drivers.legacy({
      keys: [env.get('OLD_APP_KEY')]
    })
  }
})

Basic Usage

import encryption from '@adonisjs/core/services/encryption'

// Encrypt data
const encrypted = encryption.encrypt('sensitive data')

// Decrypt data
const decrypted = encryption.decrypt(encrypted)

// Encrypt with purpose binding
const apiToken = encryption.encrypt('api-token-value', 'api-authentication')
const decryptedToken = encryption.decrypt(apiToken, 'api-authentication')

// Use specific encryptor
const apiEncryption = encryption.use('api')
const encryptedData = apiEncryption.encrypt('data')

Encrypting User Data

import encryption from '@adonisjs/core/services/encryption'
import User from '#models/user'

class UserController {
  async store({ request, response }: HttpContext) {
    const data = request.only(['name', 'email', 'ssn'])
    
    // Encrypt sensitive data
    const encryptedSSN = encryption.encrypt(data.ssn, 'user-ssn')
    
    const user = await User.create({
      name: data.name,
      email: data.email,
      ssn: encryptedSSN
    })
    
    return response.json(user)
  }
  
  async show({ params, response }: HttpContext) {
    const user = await User.findOrFail(params.id)
    
    // Decrypt sensitive data
    const decryptedSSN = encryption.decrypt(user.ssn, 'user-ssn')
    
    return response.json({
      ...user.toJSON(),
      ssn: decryptedSSN
    })
  }
}

HMAC Signatures

import { Hmac } from '@adonisjs/core/encryption'
import env from '@adonisjs/core/services/env'

const hmac = new Hmac(env.get('HMAC_KEY'))

// Generate signature
const message = 'Important message'
const signature = hmac.generate(message)

// Verify signature
const isValid = hmac.verify(message, signature)
if (isValid) {
  console.log('Signature is valid')
}

// Use case: Sign API requests
class ApiClient {
  private hmac = new Hmac(env.get('API_SECRET'))
  
  async makeRequest(endpoint: string, data: any) {
    const payload = JSON.stringify(data)
    const signature = this.hmac.generate(payload)
    
    return fetch(endpoint, {
      method: 'POST',
      headers: {
        'X-Signature': signature,
        'Content-Type': 'application/json'
      },
      body: payload
    })
  }
}

Key Rotation

// config/encryption.ts
export default defineConfig({
  default: 'app',
  list: {
    app: drivers.aes256gcm({
      id: 'app',
      keys: [
        env.get('NEW_APP_KEY'),  // New key (first = used for encryption)
        env.get('OLD_APP_KEY')   // Old key (still able to decrypt)
      ]
    })
  }
})

// The first key is used for encryption
// All keys are tried for decryption (supports seamless key rotation)

Notes

  • Always use environment variables for encryption keys
  • Purpose binding adds an extra layer of security by binding encrypted data to a specific use case
  • Key rotation is supported by providing multiple keys (first key encrypts, all keys can decrypt)
  • AES-256-GCM is recommended for new applications
  • Use the Legacy driver only when migrating from AdonisJS v6
  • Encrypted values are URL-safe base64 encoded strings