ExpressJs

⌘K
  1. Home
  2. Docs
  3. ExpressJs
  4. এনক্রিপশন (Encryption)...
  5. Data Encryption Using TypeORM and crypto Library

Data Encryption Using TypeORM and crypto Library

In this tutorial, we’ll create a simple CRUD application for managing Student entities using TypeORM with MySQL. We’ll use the crypto library for encrypting data at rest (stored data) to ensure data security. We will not cover data in transit encryption here, but typically HTTPS is used for that purpose.

1. Set Up the Project

  1. Initialize a Node.js Project
mkdir student-crud
cd student-crud
npm init -y

Install Dependencies

Install the necessary packages:

npm install express typeorm mysql2 crypto

2. Configure TypeORM with MySQL

  1. Create a ormconfig.js FileConfigure TypeORM to connect to your MySQL database:
// ormconfig.js
module.exports = {
  type: 'mysql',
  host: 'localhost',
  port: 3306,
  username: 'root', // Replace with your MySQL username
  password: 'password', // Replace with your MySQL password
  database: 'testdb', // Replace with your database name
  entities: [__dirname + '/src/entity/*.js'],
  synchronize: true, // Set to false in production
};

Create the Student Entity

Use EntitySchema for defining the Student entity:

// src/entity/Student.js
const { EntitySchema } = require('typeorm');

module.exports = new EntitySchema({
  name: 'Student',
  tableName: 'students',
  columns: {
    id: {
      type: 'int',
      primary: true,
      generated: true,
    },
    name: {
      type: 'varchar',
      length: 255,
      nullable: false,
    },
    email: {
      type: 'varchar',
      length: 255,
      unique: true,
      nullable: false,
    },
    age: {
      type: 'int',
      nullable: false,
    },
    encryptedData: {
      type: 'varchar',
      length: 255,
      nullable: true,
    },
  },
});

3. Create Encryption Helper Functions

  1. Create cryptoHelper.js for EncryptionCreate functions for encrypting and decrypting data:
// src/cryptoHelper.js
const crypto = require('crypto');

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

const encrypt = (text) => {
  let cipher = crypto.createCipheriv(algorithm, Buffer.from(key), iv);
  let encrypted = cipher.update(text);
  encrypted = Buffer.concat([encrypted, cipher.final()]);
  return { iv: iv.toString('hex'), encryptedData: encrypted.toString('hex') };
};

const decrypt = (text, iv) => {
  let ivBuffer = Buffer.from(iv, 'hex');
  let encryptedText = Buffer.from(text, 'hex');
  let decipher = crypto.createDecipheriv(algorithm, Buffer.from(key), ivBuffer);
  let decrypted = decipher.update(encryptedText);
  decrypted = Buffer.concat([decrypted, decipher.final()]);
  return decrypted.toString();
};

module.exports = { encrypt, decrypt };

4. Create a Simple CRUD Application

  1. Create app.jsSet up Express, connect to the database, and create CRUD endpoints. We will integrate the encryption helper functions into our CRUD operations:
// app.js
const express = require('express');
const { createConnection, getRepository } = require('typeorm');
const Student = require('./src/entity/Student');
const { encrypt, decrypt } = require('./src/cryptoHelper');

const app = express();
app.use(express.json());

// Connect to the database
createConnection().then(() => {
  console.log('Connected to the database');

  // Create a new student
  app.post('/students', async (req, res) => {
    const studentRepository = getRepository(Student);
    try {
      const { name, email, age, sensitiveData } = req.body;
      const encrypted = encrypt(sensitiveData); // Encrypt sensitive data
      const student = studentRepository.create({
        name,
        email,
        age,
        encryptedData: JSON.stringify(encrypted),
      });
      await studentRepository.save(student);
      res.status(201).json(student);
    } catch (error) {
      console.error('Error creating student:', error);
      res.status(500).json({ message: 'Failed to create student' });
    }
  });

  // Get all students
  app.get('/students', async (req, res) => {
    const studentRepository = getRepository(Student);
    try {
      const students = await studentRepository.find();
      // Decrypt data if needed
      students.forEach(student => {
        if (student.encryptedData) {
          const { encryptedData, iv } = JSON.parse(student.encryptedData);
          student.decryptedData = decrypt(encryptedData, iv); // Decrypt data
        }
      });
      res.json(students);
    } catch (error) {
      console.error('Error getting students:', error);
      res.status(500).json({ message: 'Failed to get students' });
    }
  });

  // Get a student by ID
  app.get('/students/:id', async (req, res) => {
    const studentRepository = getRepository(Student);
    try {
      const student = await studentRepository.findOne(req.params.id);
      if (!student) {
        return res.status(404).json({ message: 'Student not found' });
      }
      // Decrypt data if needed
      if (student.encryptedData) {
        const { encryptedData, iv } = JSON.parse(student.encryptedData);
        student.decryptedData = decrypt(encryptedData, iv); // Decrypt data
      }
      res.json(student);
    } catch (error) {
      console.error('Error getting student:', error);
      res.status(500).json({ message: 'Failed to get student' });
    }
  });

  // Update a student
  app.put('/students/:id', async (req, res) => {
    const studentRepository = getRepository(Student);
    try {
      const student = await studentRepository.findOne(req.params.id);
      if (!student) {
        return res.status(404).json({ message: 'Student not found' });
      }
      const { name, email, age, sensitiveData } = req.body;
      if (sensitiveData) {
        const encrypted = encrypt(sensitiveData); // Encrypt sensitive data
        student.encryptedData = JSON.stringify(encrypted);
      }
      student.name = name || student.name;
      student.email = email || student.email;
      student.age = age || student.age;
      await studentRepository.save(student);
      res.json(student);
    } catch (error) {
      console.error('Error updating student:', error);
      res.status(500).json({ message: 'Failed to update student' });
    }
  });

  // Delete a student
  app.delete('/students/:id', async (req, res) => {
    const studentRepository = getRepository(Student);
    try {
      const student = await studentRepository.findOne(req.params.id);
      if (!student) {
        return res.status(404).json({ message: 'Student not found' });
      }
      await studentRepository.remove(student);
      res.status(204).end();
    } catch (error) {
      console.error('Error deleting student:', error);
      res.status(500).json({ message: 'Failed to delete student' });
    }
  });

  // Start the server
  app.listen(3000, () => {
    console.log('Server is running on port 3000');
  });
}).catch(error => {
  console.error('Database connection failed', error);
});

Brief Explanation

  • Encryption Helper: cryptoHelper.js provides functions to encrypt and decrypt data.
    • encrypt(text): Encrypts the input text and returns the encrypted data and IV.
    • decrypt(encryptedText, iv): Decrypts the input data using the provided IV.
  • CRUD Operations:
    • Create: Encrypt sensitive data before saving it to the database.
    • Read: Decrypt sensitive data when retrieving it from the database.
    • Update: Encrypt data before updating the record in the database.
    • Delete: Standard CRUD operation without encryption.
  • TypeORM: Manages database interactions using the Student entity schema.

By following these steps, you’ll have a simple CRUD application with data encryption for sensitive information stored in a MySQL database.

How can we help?