Cryptography in TypeScript: Encryption and Hashing in Practice

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Cryptography in TypeScript: Encryption and Hashing — A Complete Guide



Modern web development is unthinkable without ensuring data security. TypeScript, as a superset of JavaScript, provides powerful tools for implementing cryptographic functions both on the client side and on the server (Node.js). In this article, we will thoroughly examine the main cryptographic primitives: symmetric and asymmetric encryption, hashing, and also look at working with digital signatures. All code examples are written in TypeScript and are ready for use in real projects.



1. Fundamentals of Cryptography in TypeScript



In the TypeScript ecosystem, there are two main approaches to cryptography:

  • Web Crypto API — a built-in API for browsers and Node.js (starting from version 15), providing low-level access to cryptographic operations.
  • Third-party libraries — such as crypto-js, node-forge, bcryptjs for specific tasks.


For server-side development on Node.js, it is recommended to use the built-in crypto module, which is part of the platform and does not require installing additional dependencies.



2. Data Hashing



Hashing is a one-way transformation of data into a fixed-length output. It is used for storing passwords, verifying file integrity, and creating checksums.



2.1. SHA-256 using the Web Crypto API



async function hashSHA256(data: string): Promise<string> {  const encoder = new TextEncoder();  const dataBuffer = encoder.encode(data);  const hashBuffer = await crypto.subtle.digest('SHA-256', dataBuffer);  const hashArray = Array.from(new Uint8Array(hashBuffer));  return hashArray.map(b => b.toString(16).padStart(2, '0')).join('');}

// Example usageconst myHash = await hashSHA256('Hello, world!');console.log(myHash); // 64 hex characters


2.2. Password Hashing with bcrypt



For secure password storage, use specialized algorithms with salt, such as bcrypt:



import bcrypt from 'bcryptjs';

async function hashPassword(password: string): Promise<string> { const salt = await bcrypt.genSalt(12); // 12 rounds — a good balance return await bcrypt.hash(password, salt);}

async function verifyPassword(password: string, hash: string): Promise<boolean> { return await bcrypt.compare(password, hash);}

// Exampleconst password = 'MySecurePass!';const hashedPassword = await hashPassword(password);const isValid = await verifyPassword('MySecurePass!', hashedPassword);console.log(isValid); // true


3. Symmetric Encryption



Symmetric encryption uses a single key for both encrypting and decrypting data. The most modern and secure algorithm is AES-GCM, which provides both confidentiality and authentication.



3.1. AES-GCM Encryption and Decryption



interface EncryptedData {  iv: Uint8Array;  ciphertext: Uint8Array;  tag: Uint8Array;}

async function encryptAESGCM( plaintext: string, key: CryptoKey): Promise<EncryptedData> { const encoder = new TextEncoder(); const data = encoder.encode(plaintext); const iv = crypto.getRandomValues(new Uint8Array(12)); // 96-bit IV const encrypted = await crypto.subtle.encrypt( { name: 'AES-GCM', iv }, key, data ); // GCM appends a 16-byte authentication tag at the end const ciphertext = new Uint8Array(encrypted.slice(0, encrypted.byteLength - 16)); const tag = new Uint8Array(encrypted.slice(encrypted.byteLength - 16)); return { iv, ciphertext, tag };}

async function decryptAESGCM( encrypted: EncryptedData, key: CryptoKey): Promise<string> { // Combine ciphertext and tag for Web Cry

Recommendations