Securing SQLite3 Data in ElectronJS: Persistent and Protected Database Storage

Securing SQLite3 Data in ElectronJS: Persistent and Protected Database Storage

Saving details in SQLite3 in an ElectronJS application and securing the database file can be approached in a few steps. Here’s a comprehensive guide to achieve this:

1. Setting Up SQLite3 in Electron

First, you'll need to install the sqlite3 package and integrate it into your Electron application.

bashCopy codenpm install sqlite3
npm install --save-dev electron-rebuild

Run electron-rebuild to ensure compatibility:

bashCopy code./node_modules/.bin/electron-rebuild

2. Creating and Using the SQLite Database

Here's an example of how to set up and use an SQLite database in your Electron application:

main.js

javascriptCopy codeconst { app, BrowserWindow } = require('electron');
const path = require('path');
const sqlite3 = require('sqlite3').verbose();

let db;

// Initialize the database
function initDatabase() {
  const dbPath = path.join(app.getPath('userData'), 'database.sqlite');
  db = new sqlite3.Database(dbPath, (err) => {
    if (err) {
      console.error('Error opening database', err);
    } else {
      db.run('CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT, email TEXT)');
    }
  });
}

// Create the main window
function createWindow() {
  const mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js')
    }
  });

  mainWindow.loadFile('index.html');
}

// Initialize the app
app.whenReady().then(() => {
  initDatabase();
  createWindow();

  app.on('activate', () => {
    if (BrowserWindow.getAllWindows().length === 0) {
      createWindow();
    }
  });
});

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit();
  }
});

app.on('before-quit', () => {
  db.close();
});

preload.js

javascriptCopy codeconst { contextBridge } = require('electron');
const sqlite3 = require('sqlite3').verbose();
const path = require('path');

const dbPath = path.join(require('electron').remote.app.getPath('userData'), 'database.sqlite');
const db = new sqlite3.Database(dbPath);

contextBridge.exposeInMainWorld('api', {
  addUser: (name, email) => {
    db.run('INSERT INTO users (name, email) VALUES (?, ?)', [name, email], (err) => {
      if (err) {
        console.error(err.message);
      }
    });
  },
  getUsers: (callback) => {
    db.all('SELECT * FROM users', [], (err, rows) => {
      if (err) {
        console.error(err.message);
        callback([]);
      } else {
        callback(rows);
      }
    });
  }
});

3. Securing the Database

To secure the database file, you can:

  • Store it in a Protected Location: Place the database file in a directory that is less accessible to users. For example, you can store it in app.getPath('userData').

  • Encrypt the Database: Use an SQLite encryption extension like sqlcipher to encrypt the database file.

4. Preventing Database Reset on Update

When you update the software, ensure that the userData directory is not overwritten. This is the default behavior for Electron applications, but it's important to confirm:

  • User Data Directory: The app.getPath('userData') is designed to persist data across application updates.

5. Encrypting the Database with sqlcipher

Here’s how you can use sqlcipher:

bashCopy codenpm install sqlcipher
npm install --save-dev electron-rebuild
./node_modules/.bin/electron-rebuild

main.js

javascriptCopy codeconst sqlite3 = require('sqlite3').verbose();
const SQLCipher = require('sqlcipher');
const dbPath = path.join(app.getPath('userData'), 'secure_database.sqlite');

const db = new SQLCipher.Database(dbPath);

db.serialize(() => {
  db.run("PRAGMA key = 'your_secure_key';");
  db.run('CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT, email TEXT)');
});

Conclusion

By following these steps, you can create a secure SQLite3 database within your Electron application, ensuring that it persists across updates and is protected from unauthorized access.

Did you find this article valuable?

Support Mandeep Singh Blog by becoming a sponsor. Any amount is appreciated!