一、为什么我们需要密码学

在现代互联网应用中,数据安全是重中之重。无论是用户的登录信息、支付数据,还是敏感的业务数据,都需要在存储和传输过程中进行加密保护。Dart 作为 Flutter 开发的主要语言,也提供了强大的密码学支持,帮助开发者实现安全的数据处理。

密码学的主要目标包括:

  1. 机密性:确保数据只能被授权的人访问。
  2. 完整性:防止数据在传输或存储过程中被篡改。
  3. 认证:确认数据的来源是否可信。

在 Dart 中,我们可以使用 cryptopointycastle 等库来实现各种加密算法。接下来,我们会通过具体示例来演示如何实现这些功能。

二、Dart 中的加密库介绍

Dart 提供了多个加密相关的库,其中最常用的是:

  • crypto:Dart 官方提供的轻量级加密库,支持常见的哈希算法(如 SHA-256、MD5)。
  • pointycastle:一个功能强大的密码学库,支持 AES、RSA、ECC 等高级加密算法。

示例1:使用 crypto 计算 SHA-256 哈希

import 'package:crypto/crypto.dart';
import 'dart:convert'; // 用于字符串编码转换

void main() {
  // 待加密的原始数据
  String rawData = "Hello, Dart Cryptography!";
  
  // 转换为 UTF-8 字节数组
  List<int> bytes = utf8.encode(rawData);
  
  // 计算 SHA-256 哈希
  Digest sha256Hash = sha256.convert(bytes);
  
  // 输出哈希值(16进制格式)
  print("SHA-256 Hash: ${sha256Hash.toString()}");
}

注释说明

  • utf8.encode 将字符串转换为字节数组,因为哈希算法需要字节输入。
  • sha256.convert 计算哈希值,返回 Digest 对象。
  • 最终结果是一个 64 字符的 16 进制字符串。

三、对称加密:AES 算法

对称加密使用相同的密钥进行加密和解密,AES(Advanced Encryption Standard)是目前最常用的对称加密算法之一。

示例2:使用 pointycastle 实现 AES-256 加密

import 'dart:convert';
import 'dart:typed_data';
import 'package:pointycastle/pointycastle.dart';

void main() {
  // 待加密的明文
  String plainText = "Sensitive Data to Encrypt";
  
  // 密钥(32字节,AES-256要求)
  String keyString = "ThisIsASecretKeyForAES256Encryption!!";
  Uint8List key = Uint8List.fromList(utf8.encode(keyString));
  
  // 初始化向量(IV,16字节)
  Uint8List iv = Uint8List.fromList(List.generate(16, (i) => i));
  
  // 加密
  Uint8List encrypted = aesEncrypt(plainText, key, iv);
  print("Encrypted: ${base64.encode(encrypted)}");
  
  // 解密
  String decrypted = aesDecrypt(encrypted, key, iv);
  print("Decrypted: $decrypted");
}

Uint8List aesEncrypt(String plainText, Uint8List key, Uint8List iv) {
  // 创建加密器(AES/CBC/PKCS7)
  final cipher = CBCBlockCipher(AESEngine())
    ..init(true, ParametersWithIV(KeyParameter(key), iv));
  
  // 填充明文(PKCS7)
  Uint8List paddedText = PKCS7Padding().pad(Uint8List.fromList(utf8.encode(plainText)));
  
  // 执行加密
  Uint8List encrypted = cipher.process(paddedText);
  return encrypted;
}

String aesDecrypt(Uint8List encrypted, Uint8List key, Uint8List iv) {
  // 创建解密器
  final cipher = CBCBlockCipher(AESEngine())
    ..init(false, ParametersWithIV(KeyParameter(key), iv));
  
  // 执行解密
  Uint8List decrypted = cipher.process(encrypted);
  
  // 去除填充
  Uint8List unpadded = PKCS7Padding().unpad(decrypted);
  return utf8.decode(unpadded);
}

注释说明

  • AES-256 需要 32 字节的密钥,CBC 模式还需要 16 字节的 IV。
  • PKCS7Padding 确保数据长度符合加密块要求。
  • 加密后的数据通常用 Base64 编码存储或传输。

四、非对称加密:RSA 算法

非对称加密使用公钥加密、私钥解密,适用于安全密钥交换或数字签名。

示例3:使用 pointycastle 实现 RSA 加密

import 'dart:convert';
import 'package:pointycastle/pointycastle.dart';
import 'package:pointycastle/key_generators/rsa_key_generator.dart';
import 'package:pointycastle/random/fortuna_random.dart';

void main() {
  // 生成 RSA 密钥对
  final keyPair = generateRSAKeyPair();
  
  // 明文
  String message = "Confidential Message";
  
  // 使用公钥加密
  Uint8List encrypted = rsaEncrypt(message, keyPair.publicKey);
  print("Encrypted: ${base64.encode(encrypted)}");
  
  // 使用私钥解密
  String decrypted = rsaDecrypt(encrypted, keyPair.privateKey);
  print("Decrypted: $decrypted");
}

RSAPublicKey generateRSAKeyPair() {
  final random = FortunaRandom();
  final keyParams = RSAKeyGeneratorParameters(BigInt.parse('65537'), 2048, 12);
  final generator = RSAKeyGenerator();
  generator.init(ParametersWithRandom(keyParams, random));
  
  final keyPair = generator.generateKeyPair();
  return keyPair.publicKey as RSAPublicKey;
}

Uint8List rsaEncrypt(String plainText, RSAPublicKey publicKey) {
  final encryptor = OAEPEncoding(RSAEngine())
    ..init(true, PublicKeyParameter<RSAPublicKey>(publicKey));
  return encryptor.process(Uint8List.fromList(utf8.encode(plainText)));
}

String rsaDecrypt(Uint8List encrypted, RSAPrivateKey privateKey) {
  final decryptor = OAEPEncoding(RSAEngine())
    ..init(false, PrivateKeyParameter<RSAPrivateKey>(privateKey));
  Uint8List decrypted = decryptor.process(encrypted);
  return utf8.decode(decrypted);
}

注释说明

  • RSA 密钥对通常用于加密小数据(如 AES 密钥)。
  • OAEP 填充比 PKCS#1 更安全,推荐使用。

五、应用场景与注意事项

应用场景

  1. 用户密码存储:使用 SHA-256 + Salt 哈希存储。
  2. HTTPS 通信:TLS 底层依赖 AES/RSA。
  3. 本地数据加密:如 Flutter 应用的敏感配置。

技术优缺点

算法 优点 缺点
AES 速度快,适合大数据 密钥管理复杂
RSA 无需共享密钥 计算慢,不适合大数据

注意事项

  1. 密钥管理:避免硬编码密钥,使用环境变量或密钥管理服务。
  2. IV 唯一性:AES CBC 模式的 IV 必须每次不同。
  3. 算法选择:优先使用 AES-256 和 RSA-2048 以上强度。

六、总结

Dart 提供了强大的密码学支持,无论是哈希、对称加密还是非对称加密,都能满足现代应用的安全需求。通过合理选择算法并遵循最佳实践,我们可以确保数据在存储和传输过程中的安全性。