Flutter电子签名插件bls_signatures_ffi的使用

Flutter电子签名插件bls_signatures_ffi的使用

使用方法

要使用此插件,你需要在pubspec.yaml文件中添加bls_signatures_ffi作为依赖项。

dependencies:
  bls_signatures_ffi: ^版本号

需求

Android

构建bls-signatures需要cmake版本3.14.0+。但大多数最近版本的Android Studio默认安装的是cmake版本3.10.2,因此你需要通过Android Studio的SDK管理器更新cmake版本。

iOS

iOS构建C/C++代码使用XCode而不是cmake。但你仍然需要下载cmake来构建bls-signatures,确保其版本高于3.14.0

创建密钥和签名

以下是一个创建密钥和签名的示例:

import 'dart:typed_data';
import 'package:bls_signatures_ffi/bls_signatures_ffi.dart';

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> {
  Uint8List? _seed;
  PrivateKey? _sk;
  G1Element? _pk;
  int? _fingerprint;
  Exception? _exception;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('BLS example app'),
        ),
        body: Container(
          width: double.infinity,
          padding: const EdgeInsets.symmetric(horizontal: 15),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              ElevatedButton(
                onPressed: () async {
                  await genKey();
                },
                child: const Text('Generate Key'),
              ),
              const SizedBox(height: 5),
              if (_exception != null) Text(_exception.toString()),
              const SizedBox(height: 5),
              const SizedBox(height: 10),
              const Text('Seed'),
              const SizedBox(height: 5),
              Text(_seed == null ? 'Press Generate Key' : _seed.toString()),
              const SizedBox(height: 10),
              const Text('Secret Key'),
              const SizedBox(height: 5),
              Text(_sk == null ? 'Press Generate Key' : _sk!.hexString()),
              const SizedBox(height: 10),
              const Text('Public Key'),
              const SizedBox(height: 5),
              Text(_pk == null ? 'Press Generate Key' : _pk!.hexString()),
              const SizedBox(height: 10),
              const Text('Fingerprint'),
              const SizedBox(height: 5),
              Text(
                _fingerprint == null
                    ? 'Press Generate Key'
                    : _fingerprint.toString(),
              ),
            ],
          ),
        ),
      ),
    );
  }

  Future<void> genKey() async {
    setState(() {
      _exception = null;
    });
    final seed = genSeed();
    final scheme = AugSchemeMPL();
    try {
      final sk = scheme.keyGen(seed);
      final pk = sk.g1Element();
      final fingerprint = pk.fingerprint();

      setState(() {
        _seed = seed;
        _sk = sk;
        _pk = pk;
        _fingerprint = fingerprint;
      });
    } on Exception catch (e) {
      setState(() {
        _exception = e;
      });
    } finally {
      scheme.free();
    }
  }

  Uint8List genSeed() {
    final data = [];
    final random = Random();
    for (var i = 0; i < 32; i++) {
      data.add(random.nextInt(255));
    }
    return Uint8List.fromList(data);
  }

  @override
  void dispose() {
    _sk?.free();
    _pk?.free();
    super.dispose();
  }
}

序列化密钥和签名到字节

你可以将密钥和签名序列化为字节列表,以便于存储或传输。

final skBytes = sk.serialize();
final pkBytes = pk.serialize();
final sigBytes = sig.serialize();

从字节加载密钥和签名

你可以从字节列表重新加载密钥和签名。

final sk = PrivateKey.fromBytes(data: skBytes);
final pk = G1Element.fromBytes(data: pkBytes);
final sig = G2Element.fromBytes(data: sigBytes);

print(sk.hexString()); // 32 bytes printed in hex
print(pk.hexString()); // 48 bytes printed in hex
print(sig.hexString()); // 96 bytes printed in hex

创建聚合签名

你可以组合多个签名以创建聚合签名。

final sk1 = scheme.keyGen(Uint8List.fromList(seed)..[0] = 1);
final sk2 = scheme.keyGen(Uint8List.fromList(seed)..[0] = 2);
final message2 = Uint8List.fromList([1, 2, 3, 4, 5]);

final pk1 = sk1.g1Element();
final sig1 = scheme.sign(sk1, message);

final pk2 = sk2.g1Element();
final sig2 = scheme.sign(sk2, message2);

final aggSig = scheme.aggregateSigs([sig1, sig2]);

print('Verification result: ${scheme.aggregateVerify([pk1, pk2], [message, message2], aggSig)}');

创建任意树形结构的聚合签名

你可以创建更复杂的树形结构的聚合签名。

final sk3 = scheme.keyGen(Uint8List.fromList(seed)..[0] = 3);
final pk3 = sk3.g1Element();
final message3 = Uint8List.fromList([100, 2, 254, 88, 90, 45, 23]);
final sig3 = scheme.sign(sk3, message3);

final aggSigFinal = scheme.aggregateSigs([aggSig, sig3]);
print('Verification result: ${scheme.aggregateVerify([pk1, pk2, pk3], [message, message2, message3], aggSigFinal)}');

使用证明所有权方案进行快速验证

如果你对相同的消息进行签名,可以使用证明所有权(Proof of Possession, PopScheme)以提高效率。

final popScheme = PopSchemeMPL();
final popSig1 = popScheme.sign(sk1, message);
final popSig2 = popScheme.sign(sk2, message);
final popSig3 = popScheme.sign(sk3, message);
final pop1 = popScheme.popProve(sk1);
final pop2 = popScheme.popProve(sk2);
final pop3 = popScheme.popProve(sk3);

print('Verification result: ${popScheme.popVerify(pk1, pop1)}');
print('Verification result: ${popScheme.popVerify(pk2, pop2)}');
print('Verification result: ${popScheme.popVerify(pk3, pop3)}');

final popSigAgg = popScheme.aggregateSigs([popSig1, popSig2, popSig3]);
print('Verification result: ${popScheme.fastAggregateVerify([pk1, pk2, pk3], message, popSigAgg)}');

final popAggPk = pk1 + pk2 + pk3;
print('Verification result: ${popScheme.verify(popAggPk, message, popSigAgg)}');

final aggSk = PrivateKey.aggregate([sk1, sk2, sk3]);
print('Verification result: ${popScheme.sign(aggSk, message) == popSigAgg}');

使用EIP-2333创建分层密钥

你可以从任何密钥派生出“子”密钥,以创建任意树形结构。

final masterSk = scheme.keyGen(seed);
final child = scheme.deriveChildSk(masterSk, 152);
final grandChild = scheme.deriveChildSk(child, 952);

final masterPk = masterSk.g1Element();
final childU = scheme.deriveChildSkUnhardened(masterSk, 22);
final grandChildU = scheme.deriveChildSkUnhardened(childU, 0);

final childUPk = scheme.deriveChildPkUnhardened(masterPk, 22);
final grandChildUPk = scheme.deriveChildPkUnhardened(childUPk, 0);

print('Verification result: ${grandChildUPk == grandChildU.g1Element()}');

重要提示

任何由该库创建的实例不会被Dart垃圾回收机制清理。因此,你需要手动调用free()方法来释放资源。未来可能会实现终结器。相关问题参见Dart SDK IssueDart Language Issue

运行测试

运行测试需要连接设备(物理设备或模拟器),然后进入example目录并运行flutter驱动程序。

cd example
flutter drive --driver=test_driver/integration_test.dart --target=test_driver/main.dart

更多关于Flutter电子签名插件bls_signatures_ffi的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter电子签名插件bls_signatures_ffi的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


bls_signatures_ffi 是一个用于在 Flutter 中实现 BLS(Boneh–Lynn–Shacham)签名的插件。BLS 签名是一种基于椭圆曲线的数字签名方案,通常用于区块链技术和分布式系统中。

以下是如何在 Flutter 项目中使用 bls_signatures_ffi 插件的基本步骤:

1. 添加依赖

首先,在 pubspec.yaml 文件中添加 bls_signatures_ffi 依赖:

dependencies:
  flutter:
    sdk: flutter
  bls_signatures_ffi: ^1.0.0  # 请检查最新版本

然后运行 flutter pub get 来获取依赖。

2. 导入包

在你的 Dart 文件中导入 bls_signatures_ffi 包:

import 'package:bls_signatures_ffi/bls_signatures_ffi.dart';

3. 初始化 BLS

在使用 BLS 签名之前,你需要初始化 BLS 库:

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await BLS.init();
  runApp(MyApp());
}

4. 生成密钥对

你可以生成一个 BLS 密钥对:

final privateKey = PrivateKey.generate();
final publicKey = privateKey.getPublicKey();

5. 签名和验证

使用私钥对消息进行签名,然后使用公钥验证签名:

final message = 'Hello, BLS!';
final signature = privateKey.sign(message);

final isValid = publicKey.verify(message, signature);
print('Signature is valid: $isValid');

6. 聚合签名

BLS 签名的一个强大特性是支持签名聚合。你可以将多个签名聚合为一个签名,并使用聚合的公钥进行验证:

final privateKey1 = PrivateKey.generate();
final privateKey2 = PrivateKey.generate();

final publicKey1 = privateKey1.getPublicKey();
final publicKey2 = privateKey2.getPublicKey();

final message = 'Aggregated BLS signature';

final signature1 = privateKey1.sign(message);
final signature2 = privateKey2.sign(message);

final aggregatedSignature = Signature.aggregate([signature1, signature2]);
final aggregatedPublicKey = PublicKey.aggregate([publicKey1, publicKey2]);

final isValid = aggregatedPublicKey.verify(message, aggregatedSignature);
print('Aggregated signature is valid: $isValid');

7. 清理资源

在应用程序退出时,释放 BLS 库的资源:

void dispose() {
  BLS.dispose();
}

8. 处理错误

在使用过程中,可能会遇到各种错误,例如无效的签名或密钥。确保在使用时进行适当的错误处理。

try {
  final isValid = publicKey.verify(message, signature);
  print('Signature is valid: $isValid');
} catch (e) {
  print('Error verifying signature: $e');
}

9. 其他功能

bls_signatures_ffi 还提供了其他功能,如从字节数组生成密钥、序列化和反序列化密钥和签名等。你可以查阅官方文档以获取更多信息。

10. 示例代码

以下是一个完整的示例代码:

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

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await BLS.init();
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('BLS Signatures Example')),
        body: Center(
          child: BLSExample(),
        ),
      ),
    );
  }
}

class BLSExample extends StatefulWidget {
  [@override](/user/override)
  _BLSExampleState createState() => _BLSExampleState();
}

class _BLSExampleState extends State<BLSExample> {
  String _result = '';

  [@override](/user/override)
  void initState() {
    super.initState();
    _testBLSSignature();
  }

  void _testBLSSignature() async {
    final privateKey = PrivateKey.generate();
    final publicKey = privateKey.getPublicKey();

    final message = 'Hello, BLS!';
    final signature = privateKey.sign(message);

    final isValid = publicKey.verify(message, signature);

    setState(() {
      _result = 'Signature is valid: $isValid';
    });
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Text(_result);
  }

  [@override](/user/override)
  void dispose() {
    BLS.dispose();
    super.dispose();
  }
}
回到顶部