Flutter助记词管理插件slip39的使用

Flutter助记词管理插件slip39的使用

该插件实现了SLIP39标准,用于Shamir的密钥共享算法。以下是该插件的详细使用说明。

摘要

SLIP39插件实现了一个用于生成和恢复助记词的工具,基于Shamir的密钥共享算法。

免责声明

该项目仍处于早期开发阶段,请谨慎使用。

描述

此SLIP39实现使用了高度为3(l=3)且分支数为16(d=16)的树结构(T),表示为第二级节点(组,G)的数组。

树的高度(l)为3,分支数(d)为16,这意味着最多可以有d^(l-1),即16^2个叶节点(M)。

第一级(l=1)节点是根节点(R),第二级节点是SSS组(Gs或组节点),例如 [G0, …, Gd]。

最后一级节点是唯一的叶节点(M,组成员),包含生成的助记词。

每个节点有两个值:

  • N(阈值)
  • M(成员数)

这意味着需要N个M个子节点来重构节点的秘密。

格式

有两种格式表示助记词份额:

  • JSON格式,详情见这里
  • 简单的数组/List格式

树的人类友好表示形式仅使用第二级节点(组)作为数组。 例如:[[1,1], [1,1], [3,5], [2,6]]

组的第一个参数是N(组阈值),第二个参数是M,即组中成员的数量。详情见示例

安装

pubspec.yaml文件中添加以下依赖:

dependencies:
  slip39: ^0.2.1

示例

以下是一个完整的示例,展示了如何使用slip39插件生成和恢复助记词:

import 'dart:convert';
import 'dart:typed_data';

import 'package:slip39/slip39.dart';

void main() {
  // 阈值(N)数量的组份额需要重构主密钥。
  final threshold = 2;
  final masterSecret = "ABCDEFGHIJKLMNOP";
  final passphrase = "TREZOR";

  // 4个组份额,需要2个来重构主密钥。
  final groups = [
    // Alice 组份额。1 个足以重构一个组份额,
    // 因此她至少需要两个组份额才能被重构,
    [1, 1],
    [1, 1],
    // 3个5个朋友的份额需要重构这个组份额
    [3, 5],
    // 2个6个家庭的份额需要重构这个组份额
    [2, 6]
  ];

  final slip = Slip39.from(groups,
      masterSecret: Uint8List.fromList(masterSecret.codeUnits),
      passphrase: passphrase,
      threshold: threshold);

  // Alice 的一个份额
  final aliceShare = slip.fromPath('r/0').mnemonics;

  // 任意两个家庭的份额。
  var familyShares = slip.fromPath('r/3/3').mnemonics;
  familyShares = familyShares..addAll(slip.fromPath('r/3/2').mnemonics);

  final allShares = aliceShare..addAll(familyShares);

  print("Shares used for restoring the master secret:");
  for (var s in allShares) {
    print(s);
  }

  final recoveredSecret = String.fromCharCodes(
      Slip39.recoverSecret(allShares, passphrase: passphrase));
  print('\nMaster secret: $masterSecret');
  print("Recovered one: $recoveredSecret");
  assert(masterSecret == recoveredSecret);

  print('JSON generated from the \'array\' parameter:');
  print(jsonEncode(slip.fromPath('r')));
}

TODO

  • 添加单元测试。
  • 使用参考代码的测试向量进行测试。
  • 将辅助函数重构成不同的辅助类,如 CryptoHelper()ShamirHelper() 等。
  • 添加 JSON 表示,见JSON表示
  • 重构为更简单的代码。

JSON表示

以下是从example/example.dart中提取的一个示例代码:

import 'dart:convert';

import 'package:slip39/slip39.dart';

void main() {
  String masterSecret = "ABCDEFGHIJKLMNOP";
  String passphrase = "TREZOR";

  //
  // RFC 4627兼容的JSON
  //
  final jsonString = '''
{
  "name": "Alice's shares",
  "threshold": 2,
  "shares" : [
    {
      "name": "Primary",
      "threshold": 1,
      "shares": ["Primary share"]
    },
    {
      "name": "Secondary",
      "threshold": 1,
      "shares": ["Secondary share"]
    },
    {
      "name": "Friends",
      "threshold": 3,
      "shares": ["Albert", "Ben", "Carol", "David", "Edward", "Fred"]
    },
    {
      "name": "Family",
      "threshold": 2,
      "shares": ["Adam", "Brenda", "Cecil", "Donald", "Elissa"]
    }
  ]
}
''';

  final json = jsonDecode(jsonString);

  final slip = Slip39.from(
    json,
    masterSecret: masterSecret.codeUnits,
    passphrase: passphrase,
  );

  final masterNode = slip.fromPath('r');

  final jsonText = jsonEncode(masterNode);
  assert(jsonEncode(json) == jsonText);

  final familyNode = masterNode.derive(3);
  final familyNode2 = masterNode.deriveByName('Family');
  assert(familyNode == familyNode2);

  var familyShares = familyNode.mnemonics..shuffle();
  familyShares = familyShares.sublist(0, 2);

  // 从三个朋友的份额和两个家庭的份额中恢复
  // 三个朋友的份额
  var friendsShares = masterNode.deriveByName('Friends').mnemonics..shuffle();
  friendsShares = friendsShares.sublist(0, 3);

  final allShares = familyShares..addAll(friendsShares);

  print("Shares used for restoring the master secret:");
  allShares..forEach((s) => print(s));

  final recoveredSecret = String.fromCharCodes(
      Slip39.recoverSecret(allShares, passphrase: passphrase));
  print('\nMaster secret: $masterSecret');
  print("Recovered one: $recoveredSecret");
  assert(masterSecret == recoveredSecret);
}

更多关于Flutter助记词管理插件slip39的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter助记词管理插件slip39的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


slip39 是一个用于生成和管理 Slip-0039 助记词的 Dart 库,适用于 Flutter 和 Dart 项目。Slip-0039 是一种用于生成和恢复加密货币钱包助记词的标准,它支持分片(Shamir’s Secret Sharing),允许将助记词分片并分配给多个参与者,只有达到一定数量的分片才能恢复原始助记词。

安装 slip39 插件

首先,你需要在 pubspec.yaml 文件中添加 slip39 依赖:

dependencies:
  flutter:
    sdk: flutter
  slip39: ^1.1.0

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

使用 slip39 生成助记词

以下是一个简单的例子,展示如何使用 slip39 生成助记词及其分片:

import 'package:slip39/slip39.dart';

void main() {
  // 生成一个 12 词的 BIP-39 助记词
  final mnemonic = Slip39.generateMnemonic();

  print('Generated Mnemonic: $mnemonic');

  // 使用 Slip39 将助记词分片
  final slip = Slip39.fromMnemonic(
    mnemonic: mnemonic,
    passphrase: '', // 可选的密码
    groupThreshold: 1,
    groups: [
      // 分片组配置
      Slip39Group(threshold: 2, count: 3), // 3 个分片,至少需要 2 个来恢复
    ],
  );

  // 生成分片
  final shares = slip.generateShares();

  print('Generated Shares:');
  for (var share in shares) {
    print(share);
  }

  // 恢复助记词
  final recoveredMnemonic = Slip39.recoverMnemonic(
    shares: shares.sublist(0, 2), // 使用 2 个分片来恢复
    passphrase: '',
  );

  print('Recovered Mnemonic: $recoveredMnemonic');
}

代码解释

  1. 生成助记词: 使用 Slip39.generateMnemonic() 生成一个 12 词的 BIP-39 助记词。
  2. 分片助记词: 使用 Slip39.fromMnemonic() 将助记词分片。你可以指定分片的组数和每个组的阈值。
  3. 生成分片: 使用 generateShares() 方法生成分片。
  4. 恢复助记词: 使用 Slip39.recoverMnemonic() 方法,传入足够数量的分片来恢复原始助记词。

分片配置

Slip39.fromMnemonic() 方法中,你可以配置分片的组数和阈值。例如:

final slip = Slip39.fromMnemonic(
  mnemonic: mnemonic,
  passphrase: '',
  groupThreshold: 1,
  groups: [
    Slip39Group(threshold: 2, count: 3), // 需要至少 2 个分片来恢复
    Slip39Group(threshold: 3, count: 5), // 需要至少 3 个分片来恢复
  ],
);
回到顶部