Flutter加密解密插件sodium的使用
Flutter加密解密插件sodium的使用
sodium
是一个为Dart提供的libsodium绑定库,支持VM和JS环境,无需Flutter依赖。它提供了简单的API来访问libsodium的主要功能,并尽可能地与原始C API保持一致。本文将详细介绍如何在Flutter项目中使用sodium
进行加密解密操作。
目录
特性
sodium
提供了以下特性:
- 简单易用的Dart API,适用于VM和JS环境。
- 提供所有主要的libsodium API(详见API状态)。
- 支持本地API以实现更紧密的集成。
API状态
libsodium API | VM | JS | Sumo | 文档 |
---|---|---|---|---|
padding | ✔️ | ✔️ | 链接 | |
memory | ✔️ | ❌ | 链接 | |
randombytes | ✔️ | ✔️ | 链接 | |
crypto_secretbox | ✔️ | ✔️ | 链接 | |
… | … | … | … | … |
安装
在 pubspec.yaml
文件中添加 sodium
依赖并运行 flutter pub get
:
dependencies:
sodium: ^latest_version
对于Flutter用户,建议使用 sodium_libs,它可以为每个Flutter平台提供嵌入式的二进制文件。
使用
Sodium vs SodiumSumo
如果你只使用原生版本(即你的应用程序不会被转译成JS),你可以总是使用sumo变体。如果你想同时支持原生和Web,则需要检查你需要的API是否在标准版或sumo版中可用。
加载libsodium
VM - 加载动态库
在Dart VM中,使用 dart:ffi
加载libsodium动态库:
import 'dart:ffi';
import 'package:sodium/sodium.dart';
DynamicLibrary loadLibsodium() {
return DynamicLibrary.open('/path/to/libsodium.XXX'); // 或者 DynamicLibrary.process()
}
final sodium = await SodiumInit.init2(loadLibsodium);
转译JavaScript - 加载JavaScript代码
对于浏览器环境,可以使用 sodium.js
:
import 'package:sodium/sodium.dart';
dynamic loadSodiumJS() {
return ...; // 例如通过<script>标签加载
}
final sodium = await SodiumInit.init2(loadSodiumJS);
通过Dart加载sodium.js到浏览器
@JS()
library interop;
import 'package:js/js.dart';
import 'package:sodium/sodium.dart';
@JS()
@anonymous
class SodiumBrowserInit {
external void Function(dynamic sodium) get onload;
external factory SodiumBrowserInit({void Function(dynamic sodium) onload});
}
Future<dynamic> loadSodiumInBrowser() async {
final completer = Completer<dynamic>();
setProperty(window, 'sodium', SodiumBrowserInit(
onload: allowInterop(completer.complete),
));
final script = ScriptElement();
script
..type = 'text/javascript'
..async = true
..src = 'sodium.js'; // 使用你服务器上的路径
document.head!.append(script);
return completer.future;
}
final sodium = await SodiumInit.init2(loadSodiumInBrowser);
使用API
获取 Sodium
实例后,使用API非常简单。以下是加密示例:
final sodium = // 加载libsodium
final String message = 'my very secret message';
final Uint8List messageBytes = Uint8List.fromList(message.codeUnits);
final nonce = sodium.randombytes.buf(sodium.crypto.secretBox.nonceBytes);
final SecureKey key = sodium.crypto.secretBox.keygen();
final encryptedData = sodium.crypto.secretBox.easy(
message: messageBytes,
nonce: nonce,
key: key,
);
print(encryptedData);
key.dispose();
在单独的隔离区运行计算
对于耗时较长的操作(如密码哈希),可以在隔离区中运行以避免阻塞UI:
final subkeyId = BigInt.from(42);
final masterKey = sodium.crypto.kdf.keygen();
final derivedKey = await sodium.runIsolated(
secureKeys: [masterKey],
(sodium, secureKeys, keyPairs) {
final [masterKey] = secureKeys;
return sodium.crypto.kdf.deriveFromKey(
masterKey: masterKey,
context: 'computed',
subkeyId: subkeyId,
subkeyLen: 64,
);
}
);
使用自定义隔离区
对于更复杂的场景,可以使用低级隔离区API:
Future<SecureKey> deriveKey() {
final subkeyId = BigInt.from(42);
final masterKey = sodium.crypto.kdf.keygen();
final sodiumFactory = sodium.isolateFactory;
final transferrableMasterKey = sodium.createTransferrableSecureKey(masterKey);
final result = compute(_deriveKey, (sodiumFactory, transferrableMasterKey, subkeyId));
return sodium.materializeTransferrableSecureKey(result);
}
Future<TransferrableSecureKey> _deriveKey((SodiumFactory, TransferrableSecureKey, BigInt) message) async {
final (sodiumFactory, transferrableMasterKey, subkeyId) = message;
final sodium = await sodiumFactory();
final masterKey = sodium.materializeTransferrableSecureKey(transferrableMasterKey);
final derivedKey = sodium.crypto.kdf.deriveFromKey(
masterKey: masterKey,
context: 'computed',
subkeyId: subkeyId,
subkeyLen: 64,
);
return sodium.createTransferrableSecureKey(derivedKey);
}
文档
希望以上内容能帮助你在Flutter项目中顺利使用sodium
进行加密解密操作!如果有任何问题,请随时提问。
更多关于Flutter加密解密插件sodium的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter加密解密插件sodium的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,下面是一个关于如何在Flutter项目中使用sodium
插件进行加密和解密的示例代码。sodium
是基于libsodium库的加密库,提供了多种加密、解密、签名等功能。在Flutter中,你可以通过sodium
插件来使用这些功能。
首先,确保你已经在你的pubspec.yaml
文件中添加了sodium
插件的依赖:
dependencies:
flutter:
sdk: flutter
sodium: ^x.y.z # 请使用最新版本号
然后,运行flutter pub get
来获取依赖。
以下是一个完整的示例代码,展示了如何使用sodium
插件进行对称加密和解密:
import 'package:flutter/material.dart';
import 'package:sodium/sodium.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Sodium Encryption/Decryption Example'),
),
body: Center(
child: EncryptDecryptExample(),
),
),
);
}
}
class EncryptDecryptExample extends StatefulWidget {
@override
_EncryptDecryptExampleState createState() => _EncryptDecryptExampleState();
}
class _EncryptDecryptExampleState extends State<EncryptDecryptExample> {
String? plainText;
String? encryptedText;
String? decryptedText;
@override
void initState() {
super.initState();
// 初始化Sodium库
Sodium.init().then((_) {
setState(() {
// 示例明文
plainText = "Hello, Flutter!";
// 生成随机密钥
var key = Sodium.randombytes_buf(Sodium.crypto_secretbox_KEYBYTES);
// 加密明文
var nonce = Sodium.randombytes_buf(Sodium.crypto_secretbox_NONCEBYTES);
var cipherText = Sodium.crypto_secretbox_easy(
plainText!.codeUnits,
nonce,
key
);
// 将加密后的数据转换为Base64字符串以便显示
encryptedText = Sodium.bin_to_hex(cipherText);
// 解密数据
var decryptedBytes = Sodium.crypto_secretbox_open_easy(
cipherText,
nonce,
key
);
// 将解密后的数据转换为字符串
decryptedText = String.fromCharCodes(decryptedBytes!);
// 更新UI
setState(() {});
});
});
}
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text("Plain Text: ${plainText ?? 'Loading...'}"),
SizedBox(height: 20),
Text("Encrypted Text: ${encryptedText ?? 'Loading...'}"),
SizedBox(height: 20),
Text("Decrypted Text: ${decryptedText ?? 'Loading...'}"),
],
);
}
}
解释
-
初始化Sodium库: 在
initState
方法中,使用Sodium.init()
来初始化库。这是一个异步操作,因此使用then
来处理完成后的逻辑。 -
生成密钥和随机数: 使用
Sodium.randombytes_buf
生成密钥和随机数(nonce)。密钥用于加密和解密,随机数用于确保每次加密的结果都不同,即使明文和密钥相同。 -
加密: 使用
Sodium.crypto_secretbox_easy
方法进行加密。该方法接受明文、随机数和密钥,返回加密后的数据。 -
解密: 使用
Sodium.crypto_secretbox_open_easy
方法进行解密。该方法接受加密后的数据、随机数和密钥,返回解密后的明文。 -
显示结果: 将明文、加密后的数据(转换为Base64字符串以便显示)和解密后的数据显示在UI上。
注意事项
- 在实际使用中,请确保密钥和随机数的安全存储和传输。
- 加密和解密操作通常应该在后台线程中进行,以避免阻塞UI线程。
- 示例代码中的加密和解密操作是同步的,但在实际应用中,你可能需要使用异步操作来处理较大的数据或进行更复杂的操作。
希望这个示例能帮助你理解如何在Flutter中使用sodium
插件进行加密和解密。