Comprehensive Encryption and Security Service in NestJS: Argon2 Hashing, Token Generation, and AES Encryption

Published on Nov 11, 2024 | Reading time: 4 min


This technical guide presents a production-ready security service implementation for NestJS applications, integrating essential cryptographic operations while adhering to industry-standard security protocols. The EncryptionService encapsulates critical functionality for modern backend systems, featuring Argon2 password hashing, AES-256 data encryption, and secure token generation within a modular architecture.


Core Service Configuration

The foundation establishes environment-aware cryptographic parameters using NestJS configuration patterns:

import {
  BadRequestException,
  Injectable,
  InternalServerErrorException,
  Logger,
} from "@nestjs/common";
import { ConfigService } from "@nestjs/config";
import * as argon2 from "argon2";
import { createCipheriv, createDecipheriv, createHash } from "crypto";
import * as uuid from "uuid";
import * as base64url from "base64url";

@Injectable()
export class EncryptionService {
  private readonly logger = new Logger(EncryptionService.name);
  private readonly algorithm = "aes-256-cbc";
  private readonly ivLength = 16;
  private readonly secretKey: string;

  constructor(private configService: ConfigService) {
    this.secretKey = this.configService.get<string>("ENCRYPTION_SECRET", "default_secret");
  }

Security Architecture


Password Security Implementation

1. Argon2 Password Hashing

Implements memory-hard hashing for credential protection:

  async hashPassword(rawPassword: string): Promise<string> {
    if (!rawPassword) {
      this.logger.error("Password is required");
      throw new BadRequestException("Password is required");
    }

    try {
      return await argon2.hash(rawPassword);
    } catch (err) {
      this.logger.error("Failed to hash password", err);
      throw new InternalServerErrorException("Failed to hash password");
    }
  }

  async verifyPassword(rawPassword: string = "", hashedPassword: string = ""): Promise<boolean> {
    if (!rawPassword) {
      this.logger.error("Password is required");
      throw new BadRequestException("Password is required");
    }

    try {
      return await argon2.verify(hashedPassword, rawPassword);
    } catch (err) {
      this.logger.error("Failed to verify password", err);
      throw new InternalServerErrorException("Failed to verify password");
    }
  }

Enterprise Security Features


2. Temporary Password Generation

Implements complex password synthesis for recovery workflows:

  generateTemporaryPassword(length = 10) {
    const lowercaseChars = "abcdefghijklmnopqrstuvwxyz";
    const uppercaseChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    const numericChars = "0123456789";
    const specialChars = "!@#$%^&*()-_+=";

    const allChars = lowercaseChars + uppercaseChars + numericChars + specialChars;
    let password = "";

    try {
      for (let i = 0; i < length; i++) {
        const randomIndex = Math.floor(Math.random() * allChars.length);
        password += allChars[randomIndex];
      }
    } catch (error) {
      throw new InternalServerErrorException("Failed to generate a password");
    }

    return password;
  }

Security Considerations


Cryptographic Token Management

UUID-Based Token Generation

Creates collision-resistant identifiers for session management:

  generateUniqueToken(length: number = 3): string {
    const mergedUuid = Array.from({ length }, () => uuid.v4()).join("");
    const tokenBuffer = Buffer.from(mergedUuid.replace(/-/g, ""), "hex");
    return base64url.default(tokenBuffer);
  }

Cryptographic Properties


Symmetric Data Encryption

1. AES-256-CBC Encryption

Implements FIPS 197-compliant data protection:

  encryptString(text: string): string {
    if (!text) throw new Error("Text is required for encryption");

    try {
      const key = createHash("sha256").update(this.secretKey).digest("base64").slice(0, 32);
      const iv = Buffer.alloc(this.ivLength, 0);

      const cipher = createCipheriv(this.algorithm, key, iv);
      let encrypted = cipher.update(text, "utf8", "base64");
      encrypted += cipher.final("base64");

      return encrypted.replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
    } catch (error) {
      this.logger.error("Encryption failed", error);
      throw new InternalServerErrorException("Encryption failed");
    }
  }

2. AES-256-CBC Decryption

Ensures reliable data recovery process:

  decryptString(cipherText: string): string {
    if (!cipherText) throw new Error("Cipher text is required for decryption");

    try {
      const base64Text = cipherText.replace(/-/g, "+").replace(/_/g, "/");
      const key = createHash("sha256").update(this.secretKey).digest("base64").slice(0, 32);
      const iv = Buffer.alloc(this.ivLength, 0);

      const decipher = createDecipheriv(this.algorithm, key, iv);
      let decrypted = decipher.update(base64Text, "base64", "utf8");
      decrypted += decipher.final("utf8");

      return decrypted;
    } catch (error) {
      this.logger.error("Decryption failed", error);
      throw new InternalServerErrorException("Decryption failed");
    }
  }

Cryptographic Implementation Details


Service Modularization

Global module declaration enables cross-application accessibility:

import { Global, Module } from "@nestjs/common";
import { EncryptionService } from "./encryption.service";

@Global()
@Module({
  providers: [EncryptionService],
  exports: [EncryptionService],
})
export class EncryptionModule {}

Architectural Benefits


Production Deployment Considerations

  1. Secret Management

    • Implement rotational policies for encryption secrets
    • Integrate with vault services for secure key storage
  2. Performance Optimization

    • Benchmark Argon2 parameters against server capabilities
    • Consider hardware acceleration for cryptographic operations
  3. Compliance Requirements

    • Align with PCI-DSS for payment data handling
    • Implement FIPS 140-2 validation where required
  4. Attack Mitigation

    • Rate-limiting for password verification attempts
    • Automated secret rotation mechanisms

This implementation provides a robust security foundation for NestJS applications, addressing critical requirements for:

The modular design facilitates seamless integration with enterprise security ecosystems, providing a critical layer in defense-in-depth strategies while maintaining developer productivity through standardized cryptographic primitives.