1.21SQLCipher 简介

发布于:2025-06-21 ⋅ 阅读:(21) ⋅ 点赞:(0)

SQLCipher 是一个基于 SQLite 的扩展,提供了透明的数据库加密功能。与普通 SQLite 不同,SQLCipher 在数据写入磁盘前自动加密,读取时自动解密,无需开发者手动处理加密逻辑。这使得它非常适合移动应用、桌面应用等需要本地数据加密的场景。

特性 SQLCipher
开发语言 C(原生 SQLite 扩展)
加密方式 内置 AES-256 加密,透明化处理
API 兼容性 完全兼容 SQLite API
跨平台支持 原生支持多平台(iOS、Android、Web)

Node.js 操作 SQLCipher 的实现

在 Node.js 环境中操作 SQLCipher,我们可以使用sqlcipher包,它是 SQLCipher 的 Node.js 绑定。下面详细介绍如何在 Node.js 中使用 SQLCipher:

1. 安装依赖

首先需要安装sqlcipher包:

npm install sqlcipher
2. 基本操作示例

以下是一个完整的示例,展示了如何在 Node.js 中使用 SQLCipher 进行数据库操作:

const sqlcipher = require('sqlcipher');
sqlcipher.verbose();

// 打开或创建数据库
const db = new sqlcipher.Database('encrypted.db');

// 数据库操作封装为Promise
const execute = (db, sql, params = []) => {
  return new Promise((resolve, reject) => {
    db.run(sql, params, function(err) {
      if (err) {
        reject(err);
      } else {
        resolve(this);
      }
    });
  });
};

const get = (db, sql, params = []) => {
  return new Promise((resolve, reject) => {
    db.get(sql, params, (err, row) => {
      if (err) {
        reject(err);
      } else {
        resolve(row);
      }
    });
  });
};

const all = (db, sql, params = []) => {
  return new Promise((resolve, reject) => {
    db.all(sql, params, (err, rows) => {
      if (err) {
        reject(err);
      } else {
        resolve(rows);
      }
    });
  });
};

// 初始化数据库
async function initDatabase() {
  try {
    // 打开数据库连接
    await new Promise((resolve, reject) => {
      db.open((err) => {
        if (err) {
          reject(err);
        } else {
          resolve();
        }
      });
    });
    
    // 设置加密密钥(非常重要!)
    await execute(db, `PRAGMA key = 'your-strong-password-here';`);
    await execute(db, `PRAGMA cipher_compatibility = 4;`);
    
    // 创建表
    await execute(db, `
      CREATE TABLE IF NOT EXISTS users (
        id INTEGER PRIMARY KEY,
        username TEXT NOT NULL,
        email TEXT UNIQUE NOT NULL,
        created_at DATETIME DEFAULT CURRENT_TIMESTAMP
      )
    `);
    
    console.log('数据库初始化完成');
  } catch (error) {
    console.error('数据库初始化失败:', error);
    throw error;
  }
}

// 插入数据示例
async function insertUser(username, email) {
  try {
    const result = await execute(
      db, 
      'INSERT INTO users (username, email) VALUES (?, ?)', 
      [username, email]
    );
    console.log(`插入用户成功,ID: ${result.lastID}`);
    return result.lastID;
  } catch (error) {
    console.error('插入用户失败:', error);
    throw error;
  }
}

// 查询数据示例
async function getUsers() {
  try {
    const users = await all(db, 'SELECT * FROM users');
    return users;
  } catch (error) {
    console.error('查询用户失败:', error);
    throw error;
  }
}

// 更新数据示例
async function updateUserEmail(userId, newEmail) {
  try {
    await execute(
      db, 
      'UPDATE users SET email = ? WHERE id = ?', 
      [newEmail, userId]
    );
    console.log(`更新用户邮箱成功,ID: ${userId}`);
  } catch (error) {
    console.error('更新用户邮箱失败:', error);
    throw error;
  }
}

// 删除数据示例
async function deleteUser(userId) {
  try {
    await execute(db, 'DELETE FROM users WHERE id = ?', [userId]);
    console.log(`删除用户成功,ID: ${userId}`);
  } catch (error) {
    console.error('删除用户失败:', error);
    throw error;
  }
}

// 关闭数据库
async function closeDatabase() {
  try {
    await new Promise((resolve, reject) => {
      db.close((err) => {
        if (err) {
          reject(err);
        } else {
          resolve();
        }
      });
    });
    console.log('数据库已关闭');
  } catch (error) {
    console.error('关闭数据库失败:', error);
    throw error;
  }
}

// 使用示例
async function runExample() {
  try {
    // 初始化数据库
    await initDatabase();
    
    // 插入数据
    const userId = await insertUser('john_doe', 'john@example.com');
    
    // 查询数据
    const users = await getUsers();
    console.log('所有用户:', users);
    
    // 更新数据
    await updateUserEmail(userId, 'john.doe@example.com');
    
    // 再次查询数据
    const updatedUsers = await getUsers();
    console.log('更新后的用户:', updatedUsers);
    
    // 删除数据
    await deleteUser(userId);
    
    // 最后查询数据
    const finalUsers = await getUsers();
    console.log('删除后的用户:', finalUsers);
  } catch (error) {
    console.error('操作失败:', error);
  } finally {
    // 关闭数据库连接
    await closeDatabase();
  }
}

// 执行示例
runExample();

关键操作说明

1. 数据库加密设置
// 设置加密密钥
await execute(db, `PRAGMA key = 'your-strong-password-here';`);

// 设置加密兼容性(版本4是最新的加密算法)
await execute(db, `PRAGMA cipher_compatibility = 4;`);

这两行代码非常关键,必须在打开数据库后立即执行。如果密钥不正确,后续的数据库操作将失败。

2. 安全注意事项
  1. 密钥管理:不要在代码中硬编码密钥,尤其是在生产环境中。可以使用环境变量、配置文件或密钥管理服务来存储密钥。

  2. 防止 SQL 注入:始终使用参数化查询(如上面示例中的?占位符),避免直接拼接 SQL 字符串。

  3. 数据库文件权限:确保数据库文件的访问权限设置正确,避免未授权访问。

3. 性能考虑

SQLCipher 的加密操作会带来一定的性能开销,通常比普通 SQLite 慢 10-20%。在性能敏感的应用中,可以考虑:

  1. 使用批量操作减少加密 / 解密次数
  2. 优化查询以减少不必要的数据处理
  3. 在内存中缓存频繁访问的数据
1. 备份加密数据库
async function backupDatabase() {
  try {
    const backupDb = new sqlcipher.Database('backup.db');
    
    await new Promise((resolve, reject) => {
      backupDb.open((err) => {
        if (err) {
          reject(err);
        } else {
          resolve();
        }
      });
    });
    
    // 设置备份数据库的密钥(必须与源数据库相同)
    await execute(backupDb, `PRAGMA key = 'your-strong-password-here';`);
    
    // 执行备份
    const backup = db.backup(backupDb);
    
    backup.step(1, (err, state) => {
      if (err) {
        console.error('备份失败:', err);
      } else if (state === 1) {
        console.log('备份完成');
      }
      backup.finish();
      backupDb.close();
    });
  } catch (error) {
    console.error('备份数据库失败:', error);
    throw error;
  }
}
2. 自定义加密选项
// 设置加密算法(默认是 AES-256-CBC)
await execute(db, `PRAGMA cipher = 'aes-256-cfb';`);

// 设置加密迭代次数(影响密钥派生)
await execute(db, `PRAGMA kdf_iter = 64000;`);

这些选项可以根据安全需求进行调整,但需要注意不同的设置可能会影响兼容性和性能。


网站公告

今日签到

点亮在社区的每一天
去签到