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:

## 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:

## 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.