You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Flutter+Dart+SQLite应用中向数据库存储数据时如何加密密码?

Flutter + SQLite 场景下密码及敏感信息加密实现方案

一、密码加密实现(必选)

密码绝对不要使用对称加密存储,必须采用不可逆的加盐哈希算法,避免数据库泄露后密码被还原,Dart生态直接使用成熟的crypto库实现即可。

  • 第一步:添加依赖到pubspec.yaml
dependencies:
  crypto: ^3.0.3
  # 如果你已经接入SQLite,sqlite3相关依赖已经存在可以跳过
  sqlite3_flutter_libs: ^0.5.18
  path_provider: ^2.1.0
  • 第二步:实现加盐哈希工具方法
    每个用户要生成独立的随机盐,不要全局共用同一个盐,降低撞库风险:
import 'dart:convert';
import 'dart:math';
import 'package:crypto/crypto.dart';

// 生成16位随机盐
String generateSalt() {
  final random = Random.secure();
  final saltBytes = List<int>.generate(16, (_) => random.nextInt(256));
  return base64Encode(saltBytes);
}

// 结合盐生成密码哈希值
String hashPassword(String plainPassword, String salt) {
  final bytes = utf8.encode('$plainPassword$salt');
  final hashResult = sha256.convert(bytes);
  return hashResult.toString();
}
  • 第三步:调整用户表结构,存储哈希值和盐
    不要存储明文密码,把盐和哈希后的密码一起存入SQLite:
CREATE TABLE users (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  username TEXT UNIQUE NOT NULL,
  password_hash TEXT NOT NULL,
  salt TEXT NOT NULL,
  -- 其他自定义用户字段
  phone TEXT,
  email TEXT
);
  • 第四步:注册/登录逻辑适配
    • 注册时:先为用户生成唯一盐,用明文密码+盐计算哈希值,最后把盐、哈希密码存入数据库
    • 登录校验时:先根据用户名从库中取出对应的盐和存储的哈希值,把用户输入的密码+盐计算哈希,和库中存储的哈希值对比,一致则校验通过
bool verifyLogin(String inputPassword, String storedSalt, String storedHash) {
  final currentHash = hashPassword(inputPassword, storedSalt);
  return currentHash == storedHash;
}

二、其他个人敏感信息加密(可选)

如果手机号、邮箱等个人信息也需要加密存储,使用AES对称加密即可,因为这类信息后续可能需要解密读取使用。

  • 第一步:添加依赖
dependencies:
  encrypt: ^5.0.1
  # 用于存储AES密钥,不要硬编码密钥在代码中
  flutter_secure_storage: ^8.0.0
  • 第二步:实现加解密工具类
    AES密钥要存在系统级安全存储(钥匙串/Keystore)中,不要存在SQLite或普通本地文件:
import 'package:encrypt/encrypt.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';

class SensitivesEncryptUtil {
  static const _aesKeyStorageKey = 'app_aes_secret_key';
  static const _storage = FlutterSecureStorage();

  // APP首次启动时调用一次,生成全局AES密钥存入安全存储
  static Future<void> initAesKey() async {
    final existedKey = await _storage.read(key: _aesKeyStorageKey);
    if (existedKey == null) {
      final key = Key.fromSecureRandom(32); // 256位强度AES密钥
      await _storage.write(key: _aesKeyStorageKey, value: key.base64);
    }
  }

  // 加密敏感内容
  static Future<String> encrypt(String plainText) async {
    final keyBase64 = await _storage.read(key: _aesKeyStorageKey);
    final key = Key.fromBase64(keyBase64!);
    final iv = IV.fromSecureRandom(16); // 每个加密内容生成独立IV
    final encrypter = Encrypter(AES(key));
    final encryptedResult = encrypter.encrypt(plainText, iv: iv);
    // IV和加密结果拼接后存储,解密时拆分即可
    return '${iv.base64}:${encryptedResult.base64}';
  }

  // 解密敏感内容
  static Future<String> decrypt(String encryptedStr) async {
    final keyBase64 = await _storage.read(key: _aesKeyStorageKey);
    final key = Key.fromBase64(keyBase64!);
    final parts = encryptedStr.split(':');
    final iv = IV.fromBase64(parts[0]);
    final encryptedData = Encrypted.fromBase64(parts[1]);
    final encrypter = Encrypter(AES(key));
    return encrypter.decrypt(encryptedData, iv: iv);
  }
}
  • 第三步:数据库读写逻辑适配
    存入SQLite前先对敏感字段调用加密方法,读取后调用解密方法还原即可。

注意事项

  • 不要自行实现加密算法,直接使用成熟开源库,避免安全漏洞
  • 密码哈希算法优先用sha256及以上强度,不要使用md5、sha1等已经被破解的弱算法
  • AES密钥绝对不要硬编码在代码里,必须存在系统安全存储中

内容的提问来源于stack exchange,提问作者Terin Tittu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 23:45:04