Flutter加密解密插件cryptography_flutter_plus的使用
Flutter加密解密插件cryptography_flutter_plus的使用
概述
cryptography_flutter_plus
是一个Flutter插件,它使 cryptography_plus 能够在 Android、iOS 和 Mac OS X 上使用本地API进行加密和解密操作。这个插件提供了更高的安全性和性能,并且在无法使用操作系统API时会回退到纯Dart实现。
为什么选择 cryptography_flutter_plus
- 安全性:操作系统API在安全方面更优。
- 性能:操作系统API比纯Dart实现快100倍。
- 跨平台:当操作系统不支持某些算法时,会回退到纯Dart实现。
开始使用
首先,在你的 pubspec.yaml
文件中添加依赖:
dependencies:
cryptography_plus: ^2.7.0
cryptography_flutter: ^2.3.2
然后运行 flutter pub get
来安装这些依赖。
示例代码
以下是一个完整的示例,展示了如何使用 cryptography_flutter_plus
插件进行加密和解密操作。
import 'dart:convert';
import 'package:cryptography_plus/cryptography_plus.dart';
import 'package:flutter/material.dart';
void main() {
runApp(const MaterialApp(
title: 'Cryptography demo',
home: CipherPage(),
));
}
List<int> _fromHex(String s) {
s = s.replaceAll(' ', '').replaceAll('\n', '');
return List<int>.generate(s.length ~/ 2, (i) {
var byteInHex = s.substring(2 * i, 2 * i + 2);
if (byteInHex.startsWith('0')) {
byteInHex = byteInHex.substring(1);
}
final result = int.tryParse(byteInHex, radix: 16);
if (result == null) {
throw StateError('Not valid hexadecimal bytes: $s');
}
return result;
});
}
String _toHex(List<int> bytes) {
return bytes.map((e) => e.toRadixString(16).padLeft(2, '0')).join(' ');
}
class CipherPage extends StatefulWidget {
const CipherPage({Key? key}) : super(key: key);
@override
State<StatefulWidget> createState() {
return _CipherPageState();
}
}
class _CipherPageState extends State<CipherPage> {
static final _aesGcm128 = AesGcm.with128bits();
static final _chacha20Poly1305 = Chacha20.poly1305Aead();
Cipher _cipher = _aesGcm128;
final _secretKeyController = TextEditingController();
final _nonceController = TextEditingController();
List<int> _clearText = [];
final _cipherTextController = TextEditingController();
final _macController = TextEditingController();
Object? _error;
String _decryptedText = '';
@override
Widget build(BuildContext context) {
final error = _error;
final cipher = _cipher;
return Scaffold(
body: SafeArea(
child: Center(
child: Container(
constraints: const BoxConstraints(maxWidth: 500),
padding: const EdgeInsets.all(20),
child: ListView(
children: [
InputDecorator(
decoration: const InputDecoration(labelText: 'Cipher'),
child: DropdownButton<Cipher>(
value: _cipher,
onChanged: (newValue) {
setState(() {
_cipher = newValue ?? _aesGcm128;
_encrypt();
});
},
items: [
DropdownMenuItem(
value: _aesGcm128,
child: const Text('AES-GCM (128-bits)'),
),
DropdownMenuItem(
value: _chacha20Poly1305,
child: const Text('ChaCha20 + Poly1305'),
),
],
),
),
const SizedBox(height: 10),
Row(children: [
Expanded(
child: TextField(
controller: _secretKeyController,
onChanged: (value) {
_encrypt();
},
minLines: 1,
maxLines: 16,
enableInteractiveSelection: true,
decoration: InputDecoration(
labelText: 'Secret key (${_cipher.secretKeyLength} bytes)'),
),
),
ElevatedButton(
onPressed: () async {
final secretKey = await _cipher.newSecretKey();
final bytes = await secretKey.extractBytes();
_secretKeyController.text = _toHex(bytes);
await _encrypt();
},
child: const Text('Generate'),
),
]),
const SizedBox(height: 10),
Row(children: [
Expanded(
child: TextField(
controller: _nonceController,
onChanged: (value) {
_encrypt();
},
minLines: 1,
maxLines: 16,
enableInteractiveSelection: true,
decoration: InputDecoration(
labelText: 'Nonce (${_cipher.nonceLength} bytes)'),
),
),
ElevatedButton(
onPressed: () async {
_nonceController.text = _toHex(_cipher.newNonce());
await _encrypt();
},
child: const Text('Generate'),
),
]),
const SizedBox(height: 30),
const Text('Encrypt'),
TextField(
onChanged: (newValue) {
try {
_clearText = utf8.encode(newValue);
_encrypt();
} catch (error) {
setState(() {
_error = error;
});
}
},
minLines: 1,
maxLines: 16,
enableInteractiveSelection: true,
decoration: const InputDecoration(labelText: 'Cleartext (text)'),
),
const SizedBox(height: 10),
const Text('Decrypted Text'),
const SizedBox(height: 5),
Container(
color: Colors.grey.shade500,
padding: const EdgeInsets.all(4),
child: Text(_decryptedText),
),
const SizedBox(height: 10),
TextField(
controller: _cipherTextController,
minLines: 1,
maxLines: 16,
enableInteractiveSelection: true,
decoration: const InputDecoration(labelText: 'Ciphertext (hex)'),
),
const SizedBox(height: 10),
TextField(
controller: _macController,
minLines: 1,
maxLines: 16,
enableInteractiveSelection: true,
decoration: const InputDecoration(
labelText: 'Message Authentication Code (MAC)'),
),
const SizedBox(height: 10),
if (error != null) Text(error.toString()),
],
),
),
),
),
);
}
Future<void> _encrypt() async {
try {
final cipher = _cipher;
final secretBox = await cipher.encrypt(
_clearText,
secretKey: SecretKeyData(
_fromHex(_secretKeyController.text),
),
nonce: _fromHex(_nonceController.text),
);
_cipherTextController.text = _toHex(secretBox.cipherText);
_macController.text = _toHex(secretBox.mac.bytes);
_decrypt();
setState(() {
_error = null;
});
} catch (error, stackTrace) {
setState(() {
_error = '$error\n\n$stackTrace';
_cipherTextController.text = '';
_macController.text = '';
});
return;
}
}
Future<void> _decrypt() async {
final cipher = _cipher;
_decryptedText = utf8.decode(await cipher.decrypt(
SecretBox(
_fromHex(_cipherTextController.text),
nonce: _fromHex(_nonceController.text),
mac: Mac(_fromHex(_macController.text)),
),
secretKey: SecretKeyData(
_fromHex(_secretKeyController.text),
),
));
}
}
总结
通过上述步骤和示例代码,你可以轻松地在Flutter应用中集成加密和解密功能。根据你的需求选择合适的加密算法,并确保在生产环境中妥善管理密钥和敏感数据。
更多关于Flutter加密解密插件cryptography_flutter_plus的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter加密解密插件cryptography_flutter_plus的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是如何在Flutter项目中使用cryptography_flutter_plus
插件进行加密和解密的代码示例。这个插件支持多种加密算法,包括AES、RSA等。以下是一个简单的示例,演示如何使用AES进行加密和解密。
1. 添加依赖
首先,在你的pubspec.yaml
文件中添加cryptography_flutter_plus
依赖:
dependencies:
flutter:
sdk: flutter
cryptography_flutter_plus: ^x.y.z # 请使用最新版本号
然后运行flutter pub get
来安装依赖。
2. 导入插件
在你的Dart文件中导入插件:
import 'package:cryptography_flutter_plus/cryptography_flutter_plus.dart';
3. AES加密和解密示例
以下是一个使用AES算法进行加密和解密的完整示例:
import 'package:flutter/material.dart';
import 'package:cryptography_flutter_plus/cryptography_flutter_plus.dart';
import 'dart:convert';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('AES Encryption/Decryption Example'),
),
body: Center(
child: AESExample(),
),
),
);
}
}
class AESExample extends StatefulWidget {
@override
_AESExampleState createState() => _AESExampleState();
}
class _AESExampleState extends State<AESExample> {
final TextEditingController _keyController = TextEditingController();
final TextEditingController _valueController = TextEditingController();
String _encryptedValue = '';
String _decryptedValue = '';
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
TextField(
controller: _keyController,
decoration: InputDecoration(labelText: 'Encryption Key'),
),
TextField(
controller: _valueController,
decoration: InputDecoration(labelText: 'Value to Encrypt'),
),
ElevatedButton(
onPressed: () async {
setState(() {
_encryptedValue = '';
_decryptedValue = '';
});
String key = _keyController.text;
String value = _valueController.text;
if (key.isEmpty || value.isEmpty) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Key and value cannot be empty')),
);
return;
}
// Convert the key and value to Uint8List
Uint8List keyBytes = Uint8List.fromList(key.codeUnits);
Uint8List valueBytes = Uint8List.fromList(value.codeUnits);
// Encrypt
Uint8List encryptedBytes = await Aes.encrypt(
plainText: valueBytes,
key: keyBytes,
);
String encryptedString = base64Encode(encryptedBytes);
setState(() {
_encryptedValue = encryptedString;
});
// Decrypt
Uint8List decryptedBytes = await Aes.decrypt(
cipherText: encryptedBytes,
key: keyBytes,
);
String decryptedString = String.fromCharCodes(decryptedBytes);
setState(() {
_decryptedValue = decryptedString;
});
},
child: Text('Encrypt/Decrypt'),
),
Text('Encrypted Value: $_encryptedValue'),
Text('Decrypted Value: $_decryptedValue'),
],
);
}
}
注意事项
- 密钥管理:在实际应用中,密钥管理非常重要。不要将密钥硬编码在应用中,应使用安全的密钥管理服务。
- 错误处理:在生产代码中,应添加更多的错误处理逻辑,例如捕获异常并显示适当的用户反馈。
- 安全性:确保你了解所选加密算法的安全性和使用场景。AES是一个广泛使用的对称加密算法,但在某些情况下可能需要使用其他算法。
这个示例展示了如何在Flutter应用中使用cryptography_flutter_plus
插件进行AES加密和解密。你可以根据需要调整密钥、值和其他参数。