Learning encryption and decryption in TypeScript involves understanding cryptographic concepts and utilizing cryptographic libraries to perform secure encryption and decryption operations.

In the digital age, data security has become paramount. Protecting sensitive information from unauthorized access has led to the widespread use of encryption and decryption techniques. TypeScript, a superset of JavaScript, provides a robust platform for learning and implementing encryption and decryption processes, ensuring data remains secure despite potential breaches. In this article, you will be introduced to cryptographic concepts and different ways of encrypting and decrypting data using TypeScript.

Understanding cryptographic concepts

Cryptography forms the backbone of modern data protection mechanisms, and before delving into TypeScript implementations of encryption and decryption, it's imperative to grasp the foundational concepts underpinning these operations.

Encryption and decryption fundamentals

Encryption involves transforming plaintext data, which is the original readable form of information, into an unintelligible and scrambled format known as ciphertext. This transformation is achieved through the application of an encryption algorithm and a special secret value called a key. The key serves as the primary element in ensuring the security of encrypted data. It determines how the encryption algorithm operates and what specific transformation is applied to the plaintext.

Decryption, however, is the reverse process of encryption. It involves taking the ciphertext and using the appropriate decryption algorithm and the same secret key to transform the ciphertext back into its original plaintext form. Thus, authorized parties can access and understand the original data without compromising its security during storage or transmission.

Key cryptographic concepts

  • Key: The concept of a key is central to cryptography. It's a piece of secret information that determines how encryption and decryption algorithms operate. The strength and secrecy of the key significantly impact the overall security of the cryptographic process.
  • Plaintext: This is the human-readable, unencrypted form of data that you want to protect. It could be anything from a simple message to sensitive personal information.
  • Ciphertext: The encrypted form of plaintext data produced by applying an encryption algorithm. It appears as a random and seemingly unintelligible sequence of characters.
  • Symmetric Encryption: In symmetric encryption, the same key is used for both encryption and decryption. This approach offers fast and efficient data protection, but the challenge lies in securely distributing and managing the secret key among authorized parties.
  • Asymmetric Encryption: Asymmetric encryption employs a pair of related keys: a public key and a private key. The public key is used for encryption, allowing anyone to encrypt data intended for the holder of the corresponding private key. Only the private key holder can decrypt the data. Asymmetric encryption solves the key distribution problem of symmetric encryption but is generally slower due to the complexity of the algorithms involved.
  • Public Key: This key is meant to be distributed widely and is used by others to encrypt data that can only be decrypted using the corresponding private key. It's safe to share the public key openly.
  • Private Key: As the counterpart to the public key, the private key is kept secret and used for decrypting data encrypted with the associated public key. Losing control of a private key could lead to security breaches.

Symmetric encryption and decryption in TypeScript

Symmetric encryption employs the same key for both encryption and decryption. TypeScript offers various cryptographic libraries that make it easier to implement symmetric encryption. One such library is the crypto module, available in Node.js environments. Here's a an example of how to use the crypto module for symmetric encryption and decryption:

import * as crypto from 'crypto';

const algorithm = 'aes-256-cbc';
const key = crypto.randomBytes(32);
const iv = crypto.randomBytes(16);

function encrypt(text: string): string {
    const cipher = crypto.createCipheriv(algorithm, key, iv);
    let encrypted = cipher.update(text, 'utf-8', 'hex');
    encrypted += cipher.final('hex');
    return encrypted;
}

function decrypt(encryptedText: string): string {
    const decipher = crypto.createDecipheriv(algorithm, key, iv);
    let decrypted = decipher.update(encryptedText, 'hex', 'utf-8');
    decrypted += decipher.final('utf-8');
    return decrypted;
}

const originalText = 'Sensitive information';
const encryptedText = encrypt(originalText);
const decryptedText = decrypt(encryptedText);

console.log('Original:', originalText);
console.log('Encrypted:', encryptedText);
console.log('Decrypted:', decryptedText);

In the code above, the algorithm variable specifies the encryption algorithm to be used (aes-256-cbc in this case). The key variable is generated using crypto.randomBytes(32) to create a random 32-byte (256-bit) key for the encryption process. The iv variable is also generated using crypto.randomBytes(16) and represents the initialization vector, which is used to increase the security of the encryption process.

The encrypt function takes plaintext text as input and returns the encrypted ciphertext in hexadecimal format. The crypto.createCipheriv method creates a new Cipher object with the specified algorithm, key, and initialization vector (iv). The cipher.update method processes the input text in utf-8 encoding and produces encrypted output in hex encoding. The result is accumulated in the encrypted variable.

The cipher.final method finalizes the encryption process, producing the last portion of encrypted data in hex format, which is then added to the encrypted variable. The decrypt function takes an encrypted encryptedText in hexadecimal format and returns the decrypted plaintext. The crypto.createDecipheriv function creates a new Decipher object with the same algorithm, key, and initialization vector (IV) used for encryption. The decipher.update method processes the input encryptedText in 'hex' encoding and produces decrypted output in utf-8 encoding. The decipher.final method finalizes the decryption process, producing the last portion of decrypted data in utf-8 format, which is then added to the decrypted variable.

We can use the ts-node package to execute TypeScript files from the command line.

npm install -g ts-node

When you run the code above, you should see the following on your terminal:

Symmetric encryption

Asymmetric encryption and decryption in TypeScript

Asymmetric encryption involves using a pair of keys: a public key for encryption and a private key for decryption. TypeScript provides libraries like node-forge that facilitate asymmetric encryption. Below is an example using node-forge:

import * as forge from 'node-forge';

const keyPair = forge.pki.rsa.generateKeyPair({ bits: 2048 });

function encryptWithPublicKey(text: string): string {
    const publicKey = keyPair.publicKey;
    const encrypted = publicKey.encrypt(text);
    return forge.util.encode64(encrypted);
}

function decryptWithPrivateKey(encryptedText: string): string {
    const privateKey = keyPair.privateKey;
    const encrypted = forge.util.decode64(encryptedText);
    const decrypted = privateKey.decrypt(encrypted);
    return decrypted;
}

const originalText = 'Confidential data';
const encryptedText = encryptWithPublicKey(originalText);
const decryptedText = decryptWithPrivateKey(encryptedText);

console.log('Original:', originalText);
console.log('Encrypted:', encryptedText);
console.log('Decrypted:', decryptedText);

The generateKeyPair function is used to generate an RSA key pair with a specified key size of 2,048 bits. RSA is an asymmetric encryption algorithm that uses a pair of keys: a public key for encryption and a private key for decryption.

Encrypting with public key function

  • The encryptWithPublicKey function takes plaintext text as input and returns the encrypted ciphertext in base64 encoding.
  • keyPair.publicKey retrieves the public key from the generated key pair.
  • publicKey.encrypt(text) encrypts the input text using the RSA public key. The encrypted data is returned.
  • forge.util.encode64(encrypted) encodes the encrypted data in base64 format, which is commonly used for representing binary data in a text format. The base64-encoded encrypted data is returned.

Decrypting with private key function

  • The decryptWithPrivateKey function takes an encryptedText in base64 format as input and returns the decrypted plaintext.
  • keyPair.privateKey retrieves the private key from the generated key pair.
  • forge.util.decode64(encryptedText) decodes the base64-encoded encryptedText into its binary form.
  • privateKey.decrypt(encrypted): Decrypts the binary encrypted data using the RSA private key. The decrypted data is returned.

Now install the node-forge module. Open a terminal and navigate to your project directory. Run the following command to install the node-forge module:

npm install node-forge

To install type declarations for node-forge, you can run:

npm install --save-dev @types/node-forge

When you run the code above, you should see the following on your terminal:

Asymmetric encryption

Conclusion

In conclusion, learning encryption and decryption in TypeScript involves grasping the foundational cryptographic concepts and leveraging appropriate libraries for implementation. Whether you're securing sensitive information using symmetric encryption or establishing secure communication channels through asymmetric encryption, TypeScript offers a powerful platform to enhance data security in your applications.

You could build on the knowledge gained from this article by adding encryption to parts of your application, such as the user authentication systems.

Get the Honeybadger newsletter

Each month we share news, best practices, and stories from the DevOps & monitoring community—exclusively for developers like you.
    author photo
    Muhammed Ali

    Muhammed is a Software Developer with a passion for technical writing and open source contribution. His areas of expertise are full-stack web development and DevOps.

    More articles by Muhammed Ali
    An advertisement for Honeybadger that reads 'Turn your logs into events.'

    "Splunk-like querying without having to sell my kidneys? nice"

    That’s a direct quote from someone who just saw Honeybadger Insights. It’s a bit like Papertrail or DataDog—but with just the good parts and a reasonable price tag.

    Best of all, Insights logging is available on our free tier as part of a comprehensive monitoring suite including error tracking, uptime monitoring, status pages, and more.

    Start logging for FREE
    Simple 5-minute setup — No credit card required