slip39 0.1.5

  • Readme
  • Changelog
  • Example
  • Installing
  • 50

slip39-dart #

pub package

The dart implementation of the SLIP39 for Shamir's Secret-Sharing for Mnemonic Codes.

The code based on the Reference implementation of SLIP-0039.

DISCLAIMER #

This project is still in early development phase. Use it at your own risk.

Description #

This SLIP39 implementation uses a 3 level height (l=3) of a 16 degree (d=16) tree (T), which is represented as an array of the level two nodes (groups, G).

The degree (d) and the level (l) of the tree are 16 and 3 respectively, which means that max d^(l-1), i.e. 16^2, leaf nodes (M) can be in a complete tree (or forest).

The first level (l=1) node of the tree is the the root (R), the level 2 ones are the SSS groups (Gs or group nodes) e.g. [G0, ..., Gd].

The last, the third, level nodes are the only leafs (M, group members) which contains the generated mnemonics.

Every node has two values:

  • the N and
  • M i.e. n(N,M).

Whihc means, that N (threshold) number of M children are required to reconstruct the node's secret.

Format #

There are two formats for representing the shares:

  • The JSON format, see details here
  • and a simplye array/List format.

The The tree's human friendly array representation only uses the group (l=2) nodes as arrays. For example. : [[1,1], [1,1], [3,5], [2,6]] The group's first parameter is the N (group threshold) while the second is the M, the number of members in the group. See, details in Example.

Installing #

Add the following into the pubspec.yaml:

dependencies:
  slip39: ^0.1.5

Example #

  import 'package:slip39/slip39dart';

  int main() {
  // threshold (N) number of group shares required to reconstruct the master secret.
  final threshold = 2;
  final masterSecret = "ABCDEFGHIJKLMNOP";
  final passphrase = "TREZOR";

  // 4 groups shares and 2 are required to reconstruct the master secret.
  final groups = [
    // Alice group shares. 1 is enough to reconstruct a group share,
    // therefore she needs at least two group shares to be reconstructed,
    [1, 1],
    [1, 1],
    // 3 of 5 Friends' shares are required to reconstruct this group share
    [3, 5],
    // 2 of 6 Family's shares are required to reconstruct this group share
    [2, 6]
  ];

  final slip = Slip39.fromArray(
      masterSecret: masterSecret,
      passphrase: passphrase,
      threshold: threshold,
      groups: groups);

  // One of Alice's share
  final aliceShare = slip.fromPath('r/0').mnemonics;

  // and any two of family's shares.
  var familyShares = slip.fromPath('r/3/1').mnemonics;
  familyShares = familyShares..addAll(slip.fromPath('r/3/3').mnemonics);

  final allShares = aliceShare..addAll(familyShares);

  print("Shares used for restoring the master secret:");
  allShares..forEach((s) => print(s));
  
  final recoveredSecret = Slip39.recoverSecret(allShares, passphrase);
  assert(masterSecret == recoveredSecret);
  print("Recovered secret: $recoveredSecret");
}

TODOS #

  • [x] Add unit tests.
  • [x] Test with the reference code's test vectors.
  • [ ] Refactor the helpers to different helper classes e.g. CryptoHelper(), ShamirHelper() etc.
  • [x] Add JSON representation, see JSON representation below.
  • [ ] Refactor to much simpler code.

JSON Representation #

See in an example code from eample/example.dart below:

import 'dart:convert';

import 'package:slip39/slip39.dart';

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

  //
  // RFC 4627 compliant 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);

  // Recover from: 3 of 5 firend's shares and 2 of 6 of family shares
  // three Friend's shares
  final friendsShares = masterNode.deriveByName('Friends').mnemonics
    ..shuffle()
    ..sublist(0, 3);
  final allShares = friendsShares
    ..addAll(familyNode.mnemonics
      ..shuffle()
      ..sublist(0, 2));

  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);
}

Package Direcotry Structure #

The dart package directory structure follows the official dart's recommendations.

LICENSE #

CopyRight (c) 2019 Pal Dorogi "iLap" pal.dorogi@gmail.com

MIT License

v0.1.0

  • Initial release

v0.1.1

  • Made it Dart 2 compatible

v0.1.2

  • Changed SDK constraint in pubspec.yaml to allow Dart 2.0.0 release

v0.1.3

  • Updated formatting

v0.1.4

  • Added unittests, fixed minor issues, cleaned code

v0.1.5-dev.1

  • Changed versioning format.

v0.1.5

  • Added JSON representaion of the shares.
  • Added more unittests.
  • Added dart analyzer option file.

example/main.dart

import 'package:slip39/slip39.dart';

void main() {
  // threshold (N) number of group shares required to reconstruct the master secret.
  final threshold = 2;
  final masterSecret = "ABCDEFGHIJKLMNOP";
  final passphrase = "TREZOR";

  // 4 groups shares and 2 are required to reconstruct the master secret.
  final groups = [
    // Alice group shares. 1 is enough to reconstruct a group share,
    // therefore she needs at least two group shares to be reconstructed,
    [1, 1],
    [1, 1],
    // 3 of 5 Friends' shares are required to reconstruct this group share
    [3, 5],
    // 2 of 6 Family's shares are required to reconstruct this group share
    [2, 6]
  ];

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

  // One of Alice's share
  final aliceShare = slip.fromPath('r/0').mnemonics;

  // and any two of family's shares.
  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:");
  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);
}

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:


dependencies:
  slip39: ^0.1.5

2. Install it

You can install packages from the command line:

with pub:


$ pub get

with Flutter:


$ flutter pub get

Alternatively, your editor might support pub get or flutter pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:


import 'package:slip39/slip39.dart';
  
Popularity:
Describes how popular the package is relative to other packages. [more]
0
Health:
Code health derived from static analysis. [more]
100
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
100
Overall:
Weighted score of the above. [more]
50
Learn more about scoring.

We analyzed this package on Nov 15, 2019, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.6.0
  • pana: 0.12.21

Platforms

Detected platforms: Flutter, web, other

No platform restriction found in primary library package:slip39/slip39.dart.

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.0.0 <3.0.0
hex ^0.1.2 0.1.2
pointycastle ^1.0.1 1.0.2
test ^1.6.5 1.9.4
Transitive dependencies
_fe_analyzer_shared 1.0.0
analyzer 0.39.1
args 1.5.2
async 2.4.0
boolean_selector 1.0.5
charcode 1.1.2
collection 1.14.12
convert 2.1.1
coverage 0.13.3+1
crypto 2.1.3
csslib 0.16.1
front_end 0.1.29
glob 1.2.0
html 0.14.0+3
http 0.12.0+2
http_multi_server 2.1.0
http_parser 3.1.3
io 0.3.3
js 0.6.1+1
kernel 0.3.29
logging 0.11.3+2
matcher 0.12.6
meta 1.1.8
mime 0.9.6+3
multi_server_socket 1.0.2
node_interop 1.0.3
node_io 1.0.1+2
node_preamble 1.4.8
package_config 1.1.0
package_resolver 1.0.10
path 1.6.4
pedantic 1.8.0+1
pool 1.4.0
pub_semver 1.4.2
shelf 0.7.5
shelf_packages_handler 1.0.4
shelf_static 0.2.8
shelf_web_socket 0.2.3
source_map_stack_trace 1.1.5
source_maps 0.10.8
source_span 1.5.5
stack_trace 1.9.3
stream_channel 2.0.0
string_scanner 1.0.5
term_glyph 1.1.0
test_api 0.2.11
test_core 0.2.15
typed_data 1.1.6
vm_service 2.1.1
watcher 0.9.7+12
web_socket_channel 1.1.0
yaml 2.2.0