Flutter插件keri的介绍与使用方法详解

Flutter插件keri的介绍与使用方法详解

Flutter插件keri概述

Dart客户端用于管理基于KERI的身份标识。要了解更通用的概述和客户端特性,请参阅顶级 README。有关基础设施的更多信息,请访问 KERI 或其 白皮书

重要事项

此插件需要第三方密钥提供者,该提供者可以生成公私钥对并使用Ed25519算法签名字符串。为此用途设计了 Asymmetric crypto primitives 插件。还提供了其 signer 对象与KERI插件一起使用的示例。此外,密钥必须为Base64的 URL安全 变体。

Flutter插件keri使用方法

目前支持的功能包括:

  • initKel - 初始化存储事件的数据库。
  • incept - 创建需要外部签名的创始事件。
  • finalizeInception - 完成创始(引导标识符及其关键事件日志)。
  • rotate - 创建需要外部签名的旋转事件。
  • addWatcher - 创建带有标识符观察者的新的回复消息。它需要外部签名,并通过 finalizeEvent 进行最终化。
  • finalizeEvent - 验证提供的签名是否符合事件,并保存它。
  • resolveOobi - 检查并保存提供的标识符的端点信息。
  • getKel - 返回当前标识符的CESR表示的关键事件日志。
  • anchor - 创建新的交互事件及任意数据。
  • anchorDigest - 创建新的交互事件及提供的自引用标识符。
  • newIdentifier - 从id字符串创建一个 Identifier 对象。
  • queryMailbox - 查询自己的或不同的邮箱关于一个标识符的信息。
  • finalizeQuery - 验证提供的签名是否符合邮箱查询,并保存它。
  • signatureFromHex - 从给定类型和十六进制字符串创建一个 Signature 对象。
  • inceptGroup - 创建需要外部签名的组创始事件。
  • finalizeGroupIncept - 完成组创始。
  • newPublicKey - 从给定的密钥类型和Base64字符串创建一个 PublicKey 对象。
  • newDataAndSignature - 从给定的数据及其十六进制字符串签名创建一个 DataAndSignature 对象。
  • queryWatchers - 查询关于一个标识符的观察者。
  • sendOobiToWatcher - 向连接的观察者发送给定的oobi。
  • notifyWitnesses - 发布事件到见证者。
  • broadcastReceipts - 在见证者之间发送见证人收据。
  • signToCesr - 将提供的有效负载和签名合并成cesr流。
  • verifyFromCesr - 验证来自给定cesr流的签名。
  • splitOobisAndData - 将提供的流拆分为oobis和其他cesr流。
  • getMailboxLocation - 返回可以找到邮箱的地址。
  • anchorPayload - 生成将提供的有效负载锚定在关键事件日志中的交互事件。

术语表

参考资料

  • 测试覆盖在 functions_test.dart 中提供:link

示例代码

import 'dart:convert';
import 'dart:io';

import 'package:asymmetric_crypto_primitives/asymmetric_crypto_primitives.dart';
import 'package:flutter/material.dart';
import 'dart:async';

import 'package:flutter/services.dart';
import 'package:keri/keri.dart';
import 'package:path_provider/path_provider.dart';
import 'package:keri_platform_interface/bridge_generated.dart';

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

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

  [@override](/user/override)
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  late var signer;
  String currentKey = '';
  String nextKey = '';
  String icpEvent = '';
  List<PublicKey> vec1 = [];
  List<PublicKey> vec2 = [];
  List<String> vec3 = [];
  String signature = '';
  late Identifier controller;
  String controllerId = '';
  List<PublicKey> currentKeys = [];
  List<PublicKey> newNextKeys = [];
  String rotationEvent = '';
  String signature2 = '';
  bool finalizedEvent = false;
  String dataForAnchor = 'important data';
  String anchorEvent = '';
  String signature3 = '';
  bool finalizedAnchor = false;
  var dataToSign = '{"hello":"world"}';
  bool isCesrSigned = false;
  bool isCesrVerified = false;
  late var signed;

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

  Future<void> inittKel() async {
    signer = await AsymmetricCryptoPrimitives.establishForEd25519();
    var dir = await getLocalPath();
    var inited = await initKel(inputAppDir: dir);
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Plugin example app'),
        ),
        body: SingleChildScrollView(
          child: Center(
            child: Column(
              children: [
                RawMaterialButton(
                    onPressed: () async {
                      currentKey = await signer.getCurrentPubKey();
                      nextKey = await signer.getNextPubKey();
                      print(currentKey);
                      vec1.add(await newPublicKey(
                          kt: KeyType.Ed25519, keyB64: currentKey));
                      vec2.add(await newPublicKey(
                          kt: KeyType.Ed25519, keyB64: nextKey));
                      setState(() {});
                    },
                    child: const Text('Get keys'),
                    shape: RoundedRectangleBorder(
                        borderRadius: BorderRadius.circular(18.0),
                        side: BorderSide(width: 1))),
                currentKey.isNotEmpty
                    ? Text(
                        "Public keys",
                        style: TextStyle(color: Colors.green),
                      )
                    : Container(),
                Text(currentKey),
                Text(nextKey),
                currentKey.isNotEmpty ? const Divider() : Container(),
                currentKey.isNotEmpty
                    ? RawMaterialButton(
                        onPressed: () async {
                          icpEvent = await incept(
                              publicKeys: vec1,
                              nextPubKeys: vec2,
                              witnesses: vec3,
                              witnessThreshold: 0);
                          setState(() {});
                        },
                        child: const Text('Incept'),
                        shape: RoundedRectangleBorder(
                            borderRadius: BorderRadius.circular(18.0),
                            side: BorderSide(width: 1)))
                    : Container(),
                icpEvent.isNotEmpty
                    ? Text(
                        "ICP event",
                        style: TextStyle(color: Colors.green),
                      )
                    : Container(),
                icpEvent.isNotEmpty ? Text(icpEvent) : Container(),
                icpEvent.isNotEmpty ? const Divider() : Container(),
                icpEvent.isNotEmpty
                    ? RawMaterialButton(
                        onPressed: () async {
                          signature = await signer.sign(icpEvent);
                          setState(() {});
                        },
                        child: const Text('Sign event'),
                        shape: RoundedRectangleBorder(
                            borderRadius: BorderRadius.circular(18.0),
                            side: BorderSide(width: 1)))
                    : Container(),
                signature.isNotEmpty
                    ? Text(
                        "Signature",
                        style: TextStyle(color: Colors.green),
                      )
                    : Container(),
                signature.isNotEmpty ? Text(signature) : Container(),
                signature.isNotEmpty ? const Divider() : Container(),
                signature.isNotEmpty
                    ? RawMaterialButton(
                        onPressed: () async {
                          controller = await finalizeInception(
                              event: icpEvent,
                              signature: await signatureFromHex(
                                  st: SignatureType.Ed25519Sha512,
                                  signature: signature));
                          controllerId = controller.id;
                          setState(() {});
                        },
                        child: const Text('Finalize Inception'),
                        shape: RoundedRectangleBorder(
                            borderRadius: BorderRadius.circular(18.0),
                            side: BorderSide(width: 1)))
                    : Container(),
                controllerId.isNotEmpty
                    ? Text(
                        "Controller identifier",
                        style: TextStyle(color: Colors.green),
                      )
                    : Container(),
                controllerId.isNotEmpty ? Text(controllerId) : Container(),
                controllerId.isNotEmpty ? const Divider() : Container(),
                controllerId.isNotEmpty
                    ? RawMaterialButton(
                        onPressed: () async {
                          await signer.rotateForEd25519();
                          currentKey = await signer.getCurrentPubKey();
                          nextKey = await signer.getNextPubKey();
                          currentKeys.add(await newPublicKey(
                              kt: KeyType.Ed25519, keyB64: currentKey));
                          newNextKeys.add(await newPublicKey(
                              kt: KeyType.Ed25519, keyB64: nextKey));
                          rotationEvent = await rotate(
                              controller: controller,
                              currentKeys: currentKeys,
                              newNextKeys: newNextKeys,
                              witnessToAdd: [],
                              witnessToRemove: [],
                              witnessThreshold: 0);
                          setState(() {});
                        },
                        child: const Text('Rotate'),
                        shape: RoundedRectangleBorder(
                            borderRadius: BorderRadius.circular(18.0),
                            side: BorderSide(width: 1)))
                    : Container(),
                rotationEvent.isNotEmpty
                    ? Text(
                        "Rotation event",
                        style: TextStyle(color: Colors.green),
                      )
                    : Container(),
                rotationEvent.isNotEmpty ? Text(rotationEvent) : Container(),
                rotationEvent.isNotEmpty ? const Divider() : Container(),
                rotationEvent.isNotEmpty
                    ? RawMaterialButton(
                        onPressed: () async {
                          signature2 = await signer.sign(rotationEvent);
                          setState(() {});
                        },
                        child: const Text('Sign event'),
                        shape: RoundedRectangleBorder(
                            borderRadius: BorderRadius.circular(18.0),
                            side: BorderSide(width: 1)))
                    : Container(),
                signature2.isNotEmpty
                    ? Text(
                        "Signature",
                        style: TextStyle(color: Colors.green),
                      )
                    : Container(),
                signature2.isNotEmpty ? Text(signature2) : Container(),
                signature2.isNotEmpty ? const Divider() : Container(),
                signature2.isNotEmpty
                    ? RawMaterialButton(
                        onPressed: () async {
                          finalizedEvent = await finalizeEvent(
                              identifier: controller,
                              event: rotationEvent,
                              signature: await signatureFromHex(
                                  st: SignatureType.Ed25519Sha512,
                                  signature: signature2));
                          setState(() {});
                        },
                        child: const Text('Finalize event'),
                        shape: RoundedRectangleBorder(
                            borderRadius: BorderRadius.circular(18.0),
                            side: BorderSide(width: 1)))
                    : Container(),
                finalizedEvent
                    ? Text(
                        "Rotation event finalized",
                        style: TextStyle(color: Colors.green),
                      )
                    : Container(),
                finalizedEvent ? const Divider() : Container(),
                finalizedEvent
                    ? Text(
                        "Data for anchor",
                        style: TextStyle(color: Colors.green),
                      )
                    : Container(),
                finalizedEvent ? Text(dataForAnchor) : Container(),
                finalizedEvent ? const Divider() : Container(),
                finalizedEvent
                    ? RawMaterialButton(
                        onPressed: () async {
                          anchorEvent = await anchor(
                              controller: controller,
                              data: dataForAnchor,
                              algo: DigestType.blake3256());
                          setState(() {});
                        },
                        child: const Text('Anchor'),
                        shape: RoundedRectangleBorder(
                            borderRadius: BorderRadius.circular(18.0),
                            side: BorderSide(width: 1)))
                    : Container(),
                anchorEvent.isNotEmpty
                    ? Text(
                        "Anchor event",
                        style: TextStyle(color: Colors.green),
                      )
                    : Container(),
                anchorEvent.isNotEmpty ? Text(anchorEvent) : Container(),
                anchorEvent.isNotEmpty ? const Divider() : Container(),
                anchorEvent.isNotEmpty
                    ? RawMaterialButton(
                        onPressed: () async {
                          signature3 = await signer.sign(anchorEvent);
                          setState(() {});
                        },
                        child: const Text('Sign event'),
                        shape: RoundedRectangleBorder(
                            borderRadius: BorderRadius.circular(18.0),
                            side: BorderSide(width: 1)))
                    : Container(),
                signature3.isNotEmpty
                    ? Text(
                        "Signature",
                        style: TextStyle(color: Colors.green),
                      )
                    : Container(),
                signature3.isNotEmpty ? Text(signature3) : Container(),
                signature3.isNotEmpty ? const Divider() : Container(),
                signature3.isNotEmpty
                    ? RawMaterialButton(
                        onPressed: () async {
                          finalizedAnchor = await finalizeEvent(
                              identifier: controller,
                              event: anchorEvent,
                              signature: await signatureFromHex(
                                  st: SignatureType.Ed25519Sha512,
                                  signature: signature3));
                          setState(() {});
                        },
                        child: const Text('Finalize event'),
                        shape: RoundedRectangleBorder(
                            borderRadius: BorderRadius.circular(18.0),
                            side: BorderSide(width: 1)))
                    : Container(),
                finalizedAnchor
                    ? Text(
                        "Anchor event finalized",
                        style: TextStyle(color: Colors.green),
                      )
                    : Container(),
                finalizedAnchor ? const Divider() : Container(),
                Divider(),
                Text("data to sign: $dataToSign"),
                controllerId.isNotEmpty
                    ? RawMaterialButton(
                        onPressed: () async {
                          var hexSig = await signer.sign(dataToSign);
                          await signToCesr(
                                  identifier: controller,
                                  data: dataToSign,
                                  signature: await signatureFromHex(
                                      st: SignatureType.Ed25519Sha512,
                                      signature: hexSig))
                              .then((value) {
                            if (value.isNotEmpty) {
                              print(value);
                              setState(() {
                                isCesrSigned = true;
                                signed = value;
                              });
                            }
                          });
                        },
                        child: const Text('Sign'),
                        shape: RoundedRectangleBorder(
                            borderRadius: BorderRadius.circular(18.0),
                            side: BorderSide(width: 1)))
                    : Container(),
                isCesrSigned ? Text("Successfully signed!") : Container(),
                isCesrSigned
                    ? RawMaterialButton(
                        onPressed: () async {
                          print(await resolveOobi(
                              oobiJson:
                                  '{"cid": "EJEv3VqZ7zaRaqGCrFt5kEM_ZLK1df2XKc-v6xDWT3CG", "role": "witness", "eid": "BDg3H7Sr-eES0XWXiO8nvMxW6mD_1LxLeE1nuiZxhGp4"}'));
                          print(await resolveOobi(
                              oobiJson:
                                  '{\"eid\":\"BSuhyBcPZEZLK-fcw5tzHn2N46wRCG_ZOoeKtWTOunRA\",\"scheme\":\"http\",\"url\":\"http://sandbox.argo.colossi.network:8888/\"}'));
                          var verified = await verifyFromCesr(stream: signed)
                              .then((value) {
                            if (value) {
                              setState(() {
                                isCesrVerified = true;
                              });
                            }
                          });
                        },
                        child: const Text('Verify'),
                        shape: RoundedRectangleBorder(
                            borderRadius: BorderRadius.circular(18.0),
                            side: BorderSide(width: 1)))
                    : Container(),
                isCesrVerified ? Text("Successfully verified!") : Container(),
              ],
            ),
          ),
        ),
      ),
    );
  }

  Future<String> getLocalPath() async {
    final directory = await getApplicationDocumentsDirectory();
    print(directory);
    return directory.path;
  }
}

更多关于Flutter插件keri的介绍与使用方法详解的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter插件keri的介绍与使用方法详解的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


Keri 是一个相对较新的工具或插件,具体功能和使用场景可能因上下文而异。由于“keri”并不是 Flutter 官方或广泛认可的插件,因此它的具体用途和功能可能需要通过以下步骤来探索:

1. 确认插件的来源

  • 检查是否在 pub.dev 上有相关的插件。如果有,可以查看其描述、文档和示例代码。
  • 如果不在 pub.dev 上,检查是否来自 GitHub 或其他开源平台,查看其代码库和文档。

2. 阅读文档

  • 如果插件有文档,仔细阅读以了解其功能、使用方法和注意事项。
  • 查找示例代码或教程,帮助快速上手。

3. 分析代码

  • 如果插件是开源的,可以查看其源代码,分析其实现逻辑和功能。
  • 重点关注插件的主要类和方法,了解其核心功能。

4. 集成到项目中

  • pubspec.yaml 中添加插件的依赖:
    dependencies:
      keri: ^版本号
回到顶部