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
- 生成将提供的有效负载锚定在关键事件日志中的交互事件。
术语表
- Controller - 管理标识符;
- KERI - 请参见 https://keri.one/ 页面;
参考资料
- 测试覆盖在
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: ^版本号