DEV Community

Mofajjal Rasul
Mofajjal Rasul

Posted on • Edited on

1

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

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");
  }
Enter fullscreen mode Exit fullscreen mode

Security Architecture

  • Algorithm Selection: AES-256-CBC provides FIPS-approved symmetric encryption
  • IV Management: Fixed-length initialization vector for CBC mode compatibility
  • Secret Handling: Environment variable injection prevents key hardcoding
  • Fallback Mechanism: Default secret enables development environments while enforcing production configuration

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");
    }
  }
Enter fullscreen mode Exit fullscreen mode

Enterprise Security Features

  • Timing Attack Resistance: Constant-time verification implementation
  • Memory Hardness: Configurable memory/iteration parameters (implicit in argon2.hash)
  • Validation Enforcement: Strict input checking prevents empty credential processing

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;
  }
Enter fullscreen mode Exit fullscreen mode

Security Considerations

  • Character Diversity: Four distinct character classes minimize pattern predictability
  • Length Configuration: Adjustable complexity through parameterization
  • Entropy Management: Combined character pools enhance combinatorial complexity

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);
  }
Enter fullscreen mode Exit fullscreen mode

Cryptographic Properties

  • UUID v4 Utilization: 122-bit random number space guarantees uniqueness
  • Base64URL Encoding: URL-safe representation for web compatibility
  • Concatenation Strategy: Multiple UUIDs enhance token entropy

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");
    }
  }
Enter fullscreen mode Exit fullscreen mode

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");
    }
  }
Enter fullscreen mode Exit fullscreen mode

Cryptographic Implementation Details

  • Key Derivation: SHA-256 hashing ensures fixed-length key material
  • IV Strategy: Zero-byte initialization vector (production implementations should use random IVs)
  • Encoding Handling: Base64URL conversion for web-safe ciphertext representation

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 {}
Enter fullscreen mode Exit fullscreen mode

Architectural Benefits

  • Singleton Pattern: Single service instance across application modules
  • Dependency Management: Centralized cryptographic functionality
  • Security Consistency: Uniform implementation across application layers

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:

  • Credential Protection: Memory-hard hashing prevents brute-force attacks
  • Data Confidentiality: Strong encryption safeguards sensitive information
  • Session Security: Unpredictable tokens mitigate session hijacking risks
  • Operational Reliability: Comprehensive error handling ensures system stability

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.

AWS Security LIVE! Stream

Stream AWS Security LIVE!

The best security feels invisible. Learn how solutions from AWS and AWS Partners make it a reality on Security LIVE!

Learn More

Top comments (0)

ACI image

ACI.dev: Best Open-Source Composio Alternative (AI Agent Tooling)

100% open-source tool-use platform (backend, dev portal, integration library, SDK/MCP) that connects your AI agents to 600+ tools with multi-tenant auth, granular permissions, and access through direct function calling or a unified MCP server.

Star our GitHub!

👋 Kindness is contagious

Value this insightful article and join the thriving DEV Community. Developers of every skill level are encouraged to contribute and expand our collective knowledge.

A simple “thank you” can uplift someone’s spirits. Leave your appreciation in the comments!

On DEV, exchanging expertise lightens our path and reinforces our bonds. Enjoyed the read? A quick note of thanks to the author means a lot.

Okay