Flutter安全存储插件secure_enclave的使用

发布于 1周前 作者 eggper 来自 Flutter

Flutter安全存储插件secure_enclave的使用

什么是Secure Enclave? 👮

Secure Enclave是Apple系统芯片(SoC)中集成的一个专用安全子系统。它与主处理器隔离,提供额外的安全层,即使应用处理器内核被攻破,也能确保敏感用户数据的安全。

Secure Enclave Diagram

功能集 ✨

  • ✅ 检查标签状态
  • ✅ 生成密钥对
  • ✅ 获取公钥
  • ✅ 加密
  • ✅ 使用公钥加密
  • ✅ 解密
  • ✅ 签名
  • ✅ 验证
  • ✅ 标志(参考链接)
    • devicePasscode ✅
    • biometryAny ✅
    • biometryCurrentSet ✅
    • userPresence ✅
    • watch ✅
    • and ✅
    • or ✅
    • applicationPassword ✅
    • privateKeyUsage ✅

如何使用 🚀

示例项目结构

以下是一个完整的Flutter应用程序示例,演示如何使用secure_enclave插件进行各种操作。

主文件 lib/main.dart

import 'package:flutter/material.dart';
import 'dashboard.dart';

final _messangerKey = GlobalKey<ScaffoldMessengerState>();

void main() {
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      scaffoldMessengerKey: _messangerKey,
      home: const Dashboard(),
    );
  }
}

仪表盘文件 lib/dashboard.dart

import 'package:flutter/material.dart';
import 'package:secure_enclave/secure_enclave.dart';

class Dashboard extends StatelessWidget {
  const Dashboard({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Secure Enclave Demo')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            ElevatedButton(
              onPressed: () async {
                final secureEnclavePlugin = SecureEnclave();

                // 检查标签状态
                final bool status = (await secureEnclavePlugin.isKeyCreated(tag: 'kota')).value;
                print('Tag Status: $status');

                // 生成密钥对
                ResultModel res = await secureEnclavePlugin.generateKeyPair(
                  accessControl: AccessControlModel(
                    password: 'jakarta123',
                    options: [
                      AccessControlOption.applicationPassword,
                      AccessControlOption.privateKeyUsage,
                    ],
                    tag: 'kota',
                  ),
                );

                if (res.error != null) {
                  print(res.error!.desc.toString());
                } else {
                  print('Key Pair Generated');
                }

                // 获取公钥
                res = await secureEnclavePlugin.getPublicKey(tag: 'kota');
                if (res.error != null) {
                  print(res.error!.desc.toString());
                } else {
                  print('Public Key: ${res.value}');
                }

                // 加密
                res = await secureEnclavePlugin.encrypt(
                  message: 'hello jakarta',
                  tag: 'kota',
                  password: 'jakarta123',
                );

                if (res.error != null) {
                  print(res.error!.desc.toString());
                } else {
                  print('Encrypted Message: ${res.value}');
                }

                // 解密
                res = await secureEnclavePlugin.decrypt(
                  message: Uint8List.fromList(hex.decode('iasjfoiaj2EL3EL')),
                  tag: 'kota',
                  password: 'jakarta123',
                );

                if (res.error != null) {
                  print(res.error!.desc.toString());
                } else {
                  print('Decrypted Message: ${res.value}');
                }

                // 签名
                res = await secureEnclavePlugin.sign(
                  message: Uint8List.fromList('hello jakarta'.codeUnits),
                  tag: 'kota',
                  password: 'jakarta123',
                );

                if (res.error != null) {
                  print(res.error!.desc.toString());
                } else {
                  print('Signature: ${res.value}');
                }

                // 验证
                res = await secureEnclavePlugin.verify(
                  plainText: 'hello jakarta',
                  signature: 'fDrPlGl48R8DPCGNTsAticYfx3RoWPKxEHQ2pHWrBDGk887UwWYGVTSSUj6LciietChBULEs ',
                  tag: 'kota',
                  password: 'jakarta123',
                );

                if (res.error != null) {
                  print(res.error!.desc.toString());
                } else {
                  print('Verification Success: ${res.value}');
                }
              },
              child: const Text('Run Secure Enclave Operations'),
            ),
          ],
        ),
      ),
    );
  }
}

以上代码展示了如何在Flutter应用中使用secure_enclave插件执行各种安全操作,包括检查标签状态、生成密钥对、获取公钥、加密、解密、签名和验证。


这个Markdown文档提供了关于如何使用Flutter的`secure_enclave`插件的详细指南,并包含了一个完整的示例程序来展示其功能。

更多关于Flutter安全存储插件secure_enclave的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter安全存储插件secure_enclave的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,关于Flutter中的secure_enclave插件的使用,下面是一个基本的代码示例,展示了如何使用该插件来安全地存储和检索数据。请注意,secure_enclave插件主要用于iOS平台,因为它依赖于Apple的Secure Enclave硬件安全模块。在Android上,类似的功能通常通过KeyStore API实现,但secure_enclave插件在Android上可能提供类似的抽象。

首先,确保你已经在pubspec.yaml文件中添加了secure_enclave依赖:

dependencies:
  flutter:
    sdk: flutter
  secure_enclave: ^x.y.z  # 请替换为最新版本号

然后,运行flutter pub get来安装依赖。

以下是一个简单的Flutter应用示例,展示了如何使用secure_enclave插件:

import 'package:flutter/material.dart';
import 'package:secure_enclave/secure_enclave.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Secure Enclave Example'),
        ),
        body: SecureEnclaveExample(),
      ),
    );
  }
}

class SecureEnclaveExample extends StatefulWidget {
  @override
  _SecureEnclaveExampleState createState() => _SecureEnclaveExampleState();
}

class _SecureEnclaveExampleState extends State<SecureEnclaveExample> {
  final SecureEnclave _secureEnclave = SecureEnclave();
  String _retrievedData = '';

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(16.0),
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          TextField(
            decoration: InputDecoration(labelText: 'Data to store'),
            onChanged: (value) {
              // 当文本改变时,不执行任何操作,仅用于输入
            },
            onEditingComplete: () async {
              // 当用户完成编辑时,存储数据
              final String inputData = value;
              try {
                await _secureEnclave.storeData('my_key', inputData);
                ScaffoldMessenger.of(context).showSnackBar(
                  SnackBar(content: Text('Data stored successfully')),
                );
              } catch (e) {
                ScaffoldMessenger.of(context).showSnackBar(
                  SnackBar(content: Text('Failed to store data: $e')),
                );
              }
            },
          ),
          SizedBox(height: 20),
          ElevatedButton(
            onPressed: () async {
              try {
                final String? data = await _secureEnclave.retrieveData('my_key');
                setState(() {
                  _retrievedData = data ?? 'No data found';
                });
              } catch (e) {
                ScaffoldMessenger.of(context).showSnackBar(
                  SnackBar(content: Text('Failed to retrieve data: $e')),
                );
              }
            },
            child: Text('Retrieve Data'),
          ),
          SizedBox(height: 20),
          Text('Retrieved Data: $_retrievedData'),
        ],
      ),
    );
  }
}

在这个示例中,我们创建了一个简单的Flutter应用,用户可以输入一些数据,然后点击文本字段外部的任意位置来完成编辑并触发数据存储。数据被存储在一个由my_key标识的键下。之后,用户可以通过点击“Retrieve Data”按钮来检索之前存储的数据。

请注意,这个示例仅用于演示目的,并没有处理所有可能的安全考虑。在实际应用中,你可能需要添加更多的错误处理和验证逻辑来确保数据的安全性和完整性。

另外,由于secure_enclave插件依赖于iOS的Secure Enclave硬件,因此在Android上运行时,它可能会回退到软件级别的加密存储,这取决于插件的具体实现。如果你需要Android上的硬件级安全存储,你可能需要直接使用Android的KeyStore API或寻找一个同时支持iOS和Android硬件安全存储的Flutter插件。

回到顶部