diff --git a/example/bip32_example.dart b/example/bip32_example.dart index 37d68e8..4100cd2 100644 --- a/example/bip32_example.dart +++ b/example/bip32_example.dart @@ -1,10 +1,12 @@ +import 'dart:typed_data'; import '../lib/bip32.dart' as bip32; import 'package:hex/hex.dart'; main() { - bip32.BIP32 node = bip32.BIP32.fromBase58('xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi'); + bip32.BIP32 node = bip32.BIP32.fromBase58( + 'xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi'); - print(HEX.encode(node.privateKey)); + print(HEX.encode(node.privateKey!)); // => e8f32e723decf4051aefac8e2c93c9c5b214313817cdb01a1494b917c8436b35 bip32.BIP32 nodeNeutered = node.neutered(); @@ -21,7 +23,7 @@ main() { print(child.toBase58()); // => xprv9ww7sMFLzJMzur2oEQDB642fbsMS4q6JRraMVTrM9bTWBq7NDS8ZpmsKVB4YF3mZecqax1fjnsPF19xnsJNfRp4RSyexacULXMKowSACTRc - print(HEX.encode(child.privateKey)); + print(HEX.encode(child.privateKey!)); // => f26cf12f89ab91aeeb8d7324a22e8ba080829db15c9245414b073a8c342322aa bip32.BIP32 childNeutered = child.neutered(); @@ -34,15 +36,19 @@ main() { print(childNeutered.toBase58()); // => xpub6AvUGrnEpfvJ8L7GLRkBTByQ9uBvUHp9o5VxHrFxhvzV4dSWkySpNaBoLR9FpbnwRmTa69yLHF3QfcaxbWT7gWdwws5k4dpmJvqpEuMWwnj - bip32.BIP32 nodeFromSeed = bip32.BIP32.fromSeed(HEX.decode("000102030405060708090a0b0c0d0e0f")); + bip32.BIP32 nodeFromSeed = bip32.BIP32 + .fromSeed(HEX.decode("000102030405060708090a0b0c0d0e0f") as Uint8List); print(nodeFromSeed.toBase58()); // => xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi - bip32.BIP32 nodeFromPub = bip32.BIP32.fromBase58("xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8"); + bip32.BIP32 nodeFromPub = bip32.BIP32.fromBase58( + "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8"); print(nodeFromPub.toBase58()); // => xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8 - var message = HEX.decode("0202020202020202020202020202020202020202020202020202020202020202"); + var message = HEX.decode( + "0202020202020202020202020202020202020202020202020202020202020202") + as Uint8List; var signature = nodeFromSeed.sign(message); print(signature); // => [63, 219, 20, 114, 95, 184, 192, 55, 216, 206, 126, 121, 17, 71, 64, 70, 163, 82, 247, 73, 243, 95, 30, 137, 177, 155, 100, 225, 177, 203, 217, 147, 122, 64, 208, 129, 54, 133, 113, 41, 216, 160, 191, 15, 136, 98, 235, 25, 219, 178, 70, 222, 127, 151, 135, 242, 25, 192, 161, 187, 187, 84, 81, 215] diff --git a/lib/src/bip32_base.dart b/lib/src/bip32_base.dart index bb4397b..69e59b7 100644 --- a/lib/src/bip32_base.dart +++ b/lib/src/bip32_base.dart @@ -9,29 +9,25 @@ import 'dart:convert'; class Bip32Type { int public; int private; - Bip32Type({this.public, this.private}); - + Bip32Type({required this.public, required this.private}); } + class NetworkType { int wif; Bip32Type bip32; - NetworkType({this.wif, this.bip32}); + NetworkType({required this.wif, required this.bip32}); } final _BITCOIN = new NetworkType( - wif: 0x80, - bip32: new Bip32Type( - public: 0x0488b21e, - private: 0x0488ade4 - ) -); + wif: 0x80, bip32: new Bip32Type(public: 0x0488b21e, private: 0x0488ade4)); const HIGHEST_BIT = 0x80000000; const UINT31_MAX = 2147483647; // 2^31 - 1 const UINT32_MAX = 4294967295; // 2^32 - 1 + /// Checks if you are awesome. Spoiler: you are. class BIP32 { - Uint8List _d; - Uint8List _Q; + Uint8List? _d; + Uint8List? _Q; Uint8List chainCode; int depth = 0; int index = 0; @@ -40,11 +36,11 @@ class BIP32 { BIP32(this._d, this._Q, this.chainCode, this.network); Uint8List get publicKey { - if (_Q == null) _Q = ecc.pointFromScalar(_d, true); - return _Q; + if (_Q == null) _Q = ecc.pointFromScalar(_d!, true)!; + return _Q!; } - Uint8List get privateKey => _d; + Uint8List? get privateKey => _d; Uint8List get identifier => hash160(publicKey); Uint8List get fingerprint => identifier.sublist(0, 4); @@ -53,7 +49,8 @@ class BIP32 { } BIP32 neutered() { - final neutered = BIP32.fromPublicKey(this.publicKey, this.chainCode, this.network); + final neutered = + BIP32.fromPublicKey(this.publicKey, this.chainCode, this.network); neutered.depth = this.depth; neutered.index = this.index; neutered.parentFingerprint = this.parentFingerprint; @@ -61,7 +58,8 @@ class BIP32 { } String toBase58() { - final version = (!isNeutered()) ? network.bip32.private : network.bip32.public; + final version = + (!isNeutered()) ? network.bip32.private : network.bip32.public; Uint8List buffer = new Uint8List(78); ByteData bytes = buffer.buffer.asByteData(); bytes.setUint32(0, version); @@ -71,7 +69,7 @@ class BIP32 { buffer.setRange(13, 45, chainCode); if (!isNeutered()) { bytes.setUint8(45, 0); - buffer.setRange(46, 78, privateKey); + buffer.setRange(46, 78, privateKey!); } else { buffer.setRange(45, 78, publicKey); } @@ -83,14 +81,12 @@ class BIP32 { throw new ArgumentError("Missing private key"); } return wif.encode(new wif.WIF( - version: network.wif, - privateKey: privateKey, - compressed: true - )); + version: network.wif, privateKey: privateKey!, compressed: true)); } BIP32 derive(int index) { - if (index > UINT32_MAX || index < 0) throw new ArgumentError("Expected UInt32"); + if (index > UINT32_MAX || index < 0) + throw new ArgumentError("Expected UInt32"); final isHardened = index >= HIGHEST_BIT; Uint8List data = new Uint8List(37); if (isHardened) { @@ -98,7 +94,7 @@ class BIP32 { throw new ArgumentError("Missing private key for hardened child key"); } data[0] = 0x00; - data.setRange(1, 33, privateKey); + data.setRange(1, 33, privateKey!); data.buffer.asByteData().setUint32(33, index); } else { data.setRange(0, 33, publicKey); @@ -112,7 +108,7 @@ class BIP32 { } BIP32 hd; if (!isNeutered()) { - final ki = ecc.privateAdd(privateKey, IL); + final ki = ecc.privateAdd(privateKey!, IL); if (ki == null) return derive(index + 1); hd = BIP32.fromPrivateKey(ki, IR, network); } else { @@ -127,7 +123,8 @@ class BIP32 { } BIP32 deriveHardened(int index) { - if (index > UINT31_MAX || index < 0) throw new ArgumentError("Expected UInt31"); + if (index > UINT31_MAX || index < 0) + throw new ArgumentError("Expected UInt31"); return this.derive(index + HIGHEST_BIT); } @@ -136,10 +133,11 @@ class BIP32 { if (!regex.hasMatch(path)) throw new ArgumentError("Expected BIP32 Path"); List splitPath = path.split("/"); if (splitPath[0] == "m") { - if (parentFingerprint != 0) throw new ArgumentError("Expected master, got child"); + if (parentFingerprint != 0) + throw new ArgumentError("Expected master, got child"); splitPath = splitPath.sublist(1); } - return splitPath.fold(this, (BIP32 prevHd,String indexStr) { + return splitPath.fold(this, (BIP32 prevHd, String indexStr) { int index; if (indexStr.substring(indexStr.length - 1) == "'") { index = int.parse(indexStr.substring(0, indexStr.length - 1)); @@ -152,14 +150,14 @@ class BIP32 { } sign(Uint8List hash) { - return ecc.sign(hash, privateKey); + return ecc.sign(hash, privateKey!); } verify(Uint8List hash, Uint8List signature) { return ecc.verify(hash, publicKey, signature); } - factory BIP32.fromBase58(String string, [NetworkType nw]) { + factory BIP32.fromBase58(String string, [NetworkType? nw]) { Uint8List buffer = bs58check.decode(string); if (buffer.length != 78) throw new ArgumentError("Invalid buffer length"); NetworkType network = nw ?? _BITCOIN; @@ -175,7 +173,8 @@ class BIP32 { // 4 bytes: the fingerprint of the parent's key (0x00000000 if master key) var parentFingerprint = bytes.getUint32(5); if (depth == 0) { - if (parentFingerprint != 0x00000000) throw new ArgumentError("Invalid parent fingerprint"); + if (parentFingerprint != 0x00000000) + throw new ArgumentError("Invalid parent fingerprint"); } // 4 bytes: child number. This is the number i in xi = xpar/i, with xi the key being serialized. @@ -189,7 +188,8 @@ class BIP32 { // 33 bytes: private key data (0x00 + k) if (version == network.bip32.private) { - if (bytes.getUint8(45) != 0x00) throw new ArgumentError("Invalid private key"); + if (bytes.getUint8(45) != 0x00) + throw new ArgumentError("Invalid private key"); Uint8List k = buffer.sublist(46, 78); hd = BIP32.fromPrivateKey(k, chainCode, network); } else { @@ -203,7 +203,8 @@ class BIP32 { return hd; } - factory BIP32.fromPublicKey(Uint8List publicKey, Uint8List chainCode, [NetworkType nw]) { + factory BIP32.fromPublicKey(Uint8List publicKey, Uint8List chainCode, + [NetworkType? nw]) { NetworkType network = nw ?? _BITCOIN; if (!ecc.isPoint(publicKey)) { throw new ArgumentError("Point is not on the curve"); @@ -211,14 +212,18 @@ class BIP32 { return new BIP32(null, publicKey, chainCode, network); } - factory BIP32.fromPrivateKey(Uint8List privateKey, Uint8List chainCode, [NetworkType nw]) { + factory BIP32.fromPrivateKey(Uint8List privateKey, Uint8List chainCode, + [NetworkType? nw]) { NetworkType network = nw ?? _BITCOIN; - if (privateKey.length != 32) throw new ArgumentError("Expected property privateKey of type Buffer(Length: 32)"); - if (!ecc.isPrivate(privateKey)) throw new ArgumentError("Private key not in range [1, n]"); + if (privateKey.length != 32) + throw new ArgumentError( + "Expected property privateKey of type Buffer(Length: 32)"); + if (!ecc.isPrivate(privateKey)) + throw new ArgumentError("Private key not in range [1, n]"); return new BIP32(privateKey, null, chainCode, network); } - factory BIP32.fromSeed(Uint8List seed, [NetworkType nw]) { + factory BIP32.fromSeed(Uint8List seed, [NetworkType? nw]) { if (seed.length < 16) { throw new ArgumentError("Seed should be at least 128 bits"); } @@ -226,7 +231,7 @@ class BIP32 { throw new ArgumentError("Seed should be at most 512 bits"); } NetworkType network = nw ?? _BITCOIN; - final I = hmacSHA512(utf8.encode("Bitcoin seed"), seed); + final I = hmacSHA512(utf8.encode("Bitcoin seed") as Uint8List, seed); final IL = I.sublist(0, 32); final IR = I.sublist(32); return BIP32.fromPrivateKey(IL, IR, network); diff --git a/lib/src/utils/ecurve.dart b/lib/src/utils/ecurve.dart index d6fbf53..a827285 100644 --- a/lib/src/utils/ecurve.dart +++ b/lib/src/utils/ecurve.dart @@ -1,16 +1,20 @@ import 'dart:typed_data'; import 'package:hex/hex.dart'; import "package:pointycastle/ecc/curves/secp256k1.dart"; -import "package:pointycastle/api.dart" show PrivateKeyParameter, PublicKeyParameter; -import 'package:pointycastle/ecc/api.dart' show ECPrivateKey, ECPublicKey, ECSignature, ECPoint; +import "package:pointycastle/api.dart" + show PrivateKeyParameter, PublicKeyParameter; +import 'package:pointycastle/ecc/api.dart' + show ECPrivateKey, ECPublicKey, ECSignature, ECPoint; import "package:pointycastle/signers/ecdsa_signer.dart"; import 'package:pointycastle/macs/hmac.dart'; import "package:pointycastle/digests/sha256.dart"; import 'package:pointycastle/src/utils.dart'; final ZERO32 = Uint8List.fromList(List.generate(32, (index) => 0)); -final EC_GROUP_ORDER = HEX.decode("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141"); -final EC_P = HEX.decode("fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f"); +final EC_GROUP_ORDER = HEX + .decode("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141"); +final EC_P = HEX + .decode("fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f"); final secp256k1 = new ECCurve_secp256k1(); final n = secp256k1.n; final G = secp256k1.G; @@ -24,7 +28,7 @@ const THROW_BAD_SIGNATURE = 'Expected Signature'; bool isPrivate(Uint8List x) { if (!isScalar(x)) return false; return _compare(x, ZERO32) > 0 && // > 0 - _compare(x, EC_GROUP_ORDER) < 0; // < G + _compare(x, EC_GROUP_ORDER as Uint8List) < 0; // < G } bool isPoint(Uint8List p) { @@ -37,7 +41,7 @@ bool isPoint(Uint8List p) { if (_compare(x, ZERO32) == 0) { return false; } - if (_compare(x, EC_P) == 1) { + if (_compare(x, EC_P as Uint8List) == 1) { return false; } try { @@ -52,7 +56,7 @@ bool isPoint(Uint8List p) { if (_compare(y, ZERO32) == 0) { return false; } - if (_compare(y, EC_P) == 1) { + if (_compare(y, EC_P as Uint8List) == 1) { return false; } if (t == 0x04 && p.length == 65) { @@ -67,13 +71,15 @@ bool isScalar(Uint8List x) { bool isOrderScalar(x) { if (!isScalar(x)) return false; - return _compare(x, EC_GROUP_ORDER) < 0; // < G + return _compare(x, EC_GROUP_ORDER as Uint8List) < 0; // < G } bool isSignature(Uint8List value) { Uint8List r = value.sublist(0, 32); Uint8List s = value.sublist(32, 64); - return value.length == 64 && _compare(r, EC_GROUP_ORDER) < 0 && _compare(s, EC_GROUP_ORDER) < 0; + return value.length == 64 && + _compare(r, EC_GROUP_ORDER as Uint8List) < 0 && + _compare(s, EC_GROUP_ORDER as Uint8List) < 0; } bool _isPointCompressed(Uint8List p) { @@ -86,28 +92,28 @@ bool assumeCompression(bool value, Uint8List pubkey) { return value; } -Uint8List pointFromScalar(Uint8List d, bool _compressed) { +Uint8List? pointFromScalar(Uint8List d, bool _compressed) { if (!isPrivate(d)) throw new ArgumentError(THROW_BAD_PRIVATE); BigInt dd = fromBuffer(d); - ECPoint pp = G * dd; + ECPoint pp = (G * dd) as ECPoint; if (pp.isInfinity) return null; return getEncoded(pp, _compressed); } -Uint8List pointAddScalar(Uint8List p, Uint8List tweak, bool _compressed) { +Uint8List? pointAddScalar(Uint8List p, Uint8List tweak, bool _compressed) { if (!isPoint(p)) throw new ArgumentError(THROW_BAD_POINT); if (!isOrderScalar(tweak)) throw new ArgumentError(THROW_BAD_TWEAK); bool compressed = assumeCompression(_compressed, p); ECPoint pp = decodeFrom(p); if (_compare(tweak, ZERO32) == 0) return getEncoded(pp, compressed); BigInt tt = fromBuffer(tweak); - ECPoint qq = G * tt; - ECPoint uu = pp + qq; + ECPoint qq = (G * tt) as ECPoint; + ECPoint uu = (pp + qq) as ECPoint; if (uu.isInfinity) return null; return getEncoded(uu, compressed); } -Uint8List privateAdd(Uint8List d, Uint8List tweak) { +Uint8List? privateAdd(Uint8List d, Uint8List tweak) { if (!isPrivate(d)) throw new ArgumentError(THROW_BAD_PRIVATE); if (!isOrderScalar(tweak)) throw new ArgumentError(THROW_BAD_TWEAK); BigInt dd = fromBuffer(d); @@ -192,7 +198,7 @@ Uint8List toBuffer(BigInt d) { } ECPoint decodeFrom(Uint8List P) { - return secp256k1.curve.decodePoint(P); + return secp256k1.curve.decodePoint(P)!; } Uint8List getEncoded(ECPoint P, compressed) { @@ -201,10 +207,11 @@ Uint8List getEncoded(ECPoint P, compressed) { ECSignature deterministicGenerateK(Uint8List hash, Uint8List x) { final signer = new ECDSASigner(null, new HMac(new SHA256Digest(), 64)); - var pkp = new PrivateKeyParameter(new ECPrivateKey(_decodeBigInt(x), secp256k1)); + var pkp = + new PrivateKeyParameter(new ECPrivateKey(_decodeBigInt(x), secp256k1)); signer.init(true, pkp); // signer.init(false, new PublicKeyParameter(new ECPublicKey(secp256k1.curve.decodePoint(x), secp256k1))); - return signer.generateSignature(hash); + return signer.generateSignature(hash) as ECSignature; } int _compare(Uint8List a, Uint8List b) { @@ -233,7 +240,8 @@ Uint8List _encodeBigInt(BigInt number) { if (number > BigInt.zero) { rawSize = (number.bitLength + 7) >> 3; - needsPaddingByte = ((number >> (rawSize - 1) * 8) & negativeFlag) == negativeFlag ? 1 : 0; + needsPaddingByte = + ((number >> (rawSize - 1) * 8) & negativeFlag) == negativeFlag ? 1 : 0; if (rawSize < 32) { needsPaddingByte = 1; diff --git a/lib/src/utils/wif.dart b/lib/src/utils/wif.dart index 365bbaf..2579bfb 100644 --- a/lib/src/utils/wif.dart +++ b/lib/src/utils/wif.dart @@ -1,21 +1,25 @@ import "package:bs58check/bs58check.dart" as bs58check; import "dart:typed_data"; + class WIF { int version; Uint8List privateKey; bool compressed; - WIF({this.version, this.privateKey, this.compressed}); + WIF( + {required this.version, + required this.privateKey, + required this.compressed}); } -WIF decodeRaw(Uint8List buffer, [int version]) { + +WIF decodeRaw(Uint8List buffer, [int? version]) { if (version != null && buffer[0] != version) { throw new ArgumentError("Invalid network version"); } if (buffer.length == 33) { return new WIF( - version: buffer[0], - privateKey: buffer.sublist(1, 33), - compressed: false - ); + version: buffer[0], + privateKey: buffer.sublist(1, 33), + compressed: false); } if (buffer.length != 34) { throw new ArgumentError("Invalid WIF length"); @@ -24,11 +28,9 @@ WIF decodeRaw(Uint8List buffer, [int version]) { throw new ArgumentError("Invalid compression flag"); } return new WIF( - version: buffer[0], - privateKey: buffer.sublist(1, 33), - compressed: true - ); + version: buffer[0], privateKey: buffer.sublist(1, 33), compressed: true); } + Uint8List encodeRaw(int version, Uint8List privateKey, bool compressed) { if (privateKey.length != 32) { throw new ArgumentError("Invalid privateKey length"); @@ -42,15 +44,12 @@ Uint8List encodeRaw(int version, Uint8List privateKey, bool compressed) { } return result; } -WIF decode(String string, [int version]) { + +WIF decode(String string, [int? version]) { return decodeRaw(bs58check.decode(string), version); } + String encode(WIF wif) { - return bs58check.encode( - encodeRaw( - wif.version, - wif.privateKey, - wif.compressed - ) - ); -} \ No newline at end of file + return bs58check + .encode(encodeRaw(wif.version, wif.privateKey, wif.compressed)); +} diff --git a/pubspec.yaml b/pubspec.yaml index cb94aad..f2fda87 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -5,7 +5,7 @@ homepage: https://github.com/dart-bitcoin/bip32-dart author: anicdh environment: - sdk: ">=2.0.0 <3.0.0" + sdk: ">=2.12.0 <3.0.0" dependencies: pointycastle: ^3.0.1 @@ -13,4 +13,4 @@ dependencies: bs58check: ^1.0.2 dev_dependencies: - test: ^1.0.0 + test: ^1.17.1 diff --git a/test/bip32_test.dart b/test/bip32_test.dart index cfa4e30..9c43378 100644 --- a/test/bip32_test.dart +++ b/test/bip32_test.dart @@ -6,16 +6,12 @@ import 'dart:io'; import 'dart:convert'; final LITECOIN = new NetworkType( - bip32: new Bip32Type( - private: 0x019d9cfe, - public: 0x019da462 - ), - wif: 0xb0 -); + bip32: new Bip32Type(private: 0x019d9cfe, public: 0x019da462), wif: 0xb0); List validAll = []; void main() { - Map fixtures = json.decode(File('./test/fixtures.json').readAsStringSync(encoding: utf8)); + Map fixtures = json + .decode(File('./test/fixtures.json').readAsStringSync(encoding: utf8)); (fixtures['valid'] as List).forEach((f) { f['master']['network'] = f['network']; f['master']['children'] = f['children']; @@ -30,7 +26,7 @@ void main() { setUp(() {}); var network; if (ff['network'] == 'litecoin') { - network = LITECOIN; + network = LITECOIN; } var hdPrv = BIP32.fromBase58(ff['base58Priv'], network); test('works for private key -> HD wallet', () { @@ -44,7 +40,7 @@ void main() { if (ff['seed'] != null) { var seed = HEX.decode(ff['seed']); - var hdSeed = BIP32.fromSeed(seed, network); + var hdSeed = BIP32.fromSeed(seed as Uint8List, network); test('works for seed -> HD wallet', () { verify(hdSeed, true, ff, network); }); @@ -56,11 +52,12 @@ void main() { test('fromBase58 throws', () { (fixtures['invalid']['fromBase58'] as List).forEach((f) { var network; - if (f['network'] != null && f['network'] == 'litecoin') network = LITECOIN; - BIP32 hd; + if (f['network'] != null && f['network'] == 'litecoin') + network = LITECOIN; + BIP32? hd; try { hd = BIP32.fromBase58(f['string'], network); - } catch(err) { + } catch (err) { expect((err as ArgumentError).message, f['exception']); } finally { expect(hd, null); @@ -96,11 +93,12 @@ void main() { final f = fixtures['valid'][0]; final c = f['master']['children'][0]; final master = BIP32.fromBase58(f['master']['base58'] as String); - BIP32 hd; + BIP32? hd; try { hd = master.deriveHardened(c['m']); - } catch(err) { - expect((err as ArgumentError).message, "Missing private key for hardened child key"); + } catch (err) { + expect((err as ArgumentError).message, + "Missing private key for hardened child key"); } finally { expect(hd, null); } @@ -145,7 +143,8 @@ void main() { try { hdFPrv1 = BIP32.fromPrivateKey(new Uint8List(2), ONE32); } catch (err) { - expect((err as ArgumentError).message, "Expected property privateKey of type Buffer(Length: 32)"); + expect((err as ArgumentError).message, + "Expected property privateKey of type Buffer(Length: 32)"); } finally { expect(hdFPrv1, null); } @@ -159,24 +158,29 @@ void main() { }); test("works when private key has leading zeros", () { - const key = "xprv9s21ZrQH143K3ckY9DgU79uMTJkQRLdbCCVDh81SnxTgPzLLGax6uHeBULTtaEtcAvKjXfT7ZWtHzKjTpujMkUd9dDb8msDeAfnJxrgAYhr"; + const key = + "xprv9s21ZrQH143K3ckY9DgU79uMTJkQRLdbCCVDh81SnxTgPzLLGax6uHeBULTtaEtcAvKjXfT7ZWtHzKjTpujMkUd9dDb8msDeAfnJxrgAYhr"; BIP32 hdkey = BIP32.fromBase58(key); - expect(HEX.encode(hdkey.privateKey), "00000055378cf5fafb56c711c674143f9b0ee82ab0ba2924f19b64f5ae7cdbfd"); + expect(HEX.encode(hdkey.privateKey!), + "00000055378cf5fafb56c711c674143f9b0ee82ab0ba2924f19b64f5ae7cdbfd"); BIP32 child = hdkey.derivePath("m/44'/0'/0'/0/0'"); - expect(HEX.encode(child.privateKey), "3348069561d2a0fb925e74bf198762acc47dce7db27372257d2d959a9e6f8aeb"); + expect(HEX.encode(child.privateKey!), + "3348069561d2a0fb925e74bf198762acc47dce7db27372257d2d959a9e6f8aeb"); }); test('derive', () { - final hd = BIP32.fromBase58('xprv9s21ZrQH143K3Jpuz63XbuGs9CH9xG4sniVBBRVm6AJR57D9arxWz6FkXF3JSxSK7jUmVA11AdWa6ZsUtwGztE4QT5i8Y457RRPvMCc39rY'); + final hd = BIP32.fromBase58( + 'xprv9s21ZrQH143K3Jpuz63XbuGs9CH9xG4sniVBBRVm6AJR57D9arxWz6FkXF3JSxSK7jUmVA11AdWa6ZsUtwGztE4QT5i8Y457RRPvMCc39rY'); final d = hd.derivePath("m/1'/199007533'/627785449'/1521366139'/1'"); - expect(d.toBase58(), 'xprvA39a1i4ieYqGUQ7G1KGnaGzGwm7v3emjms3QN4jZ3HPeubXjshA3XjD5XFaiNgWFvoyC2NV5jN4eFcsVhkrWkvwR4qjdPbue3kpt6Ur3JRf'); + expect(d.toBase58(), + 'xprvA39a1i4ieYqGUQ7G1KGnaGzGwm7v3emjms3QN4jZ3HPeubXjshA3XjD5XFaiNgWFvoyC2NV5jN4eFcsVhkrWkvwR4qjdPbue3kpt6Ur3JRf'); }); test("fromSeed", () { (fixtures['invalid']['fromSeed'] as List).forEach((f) { var hd; try { - hd = BIP32.fromSeed(HEX.decode(f['seed'])); + hd = BIP32.fromSeed(HEX.decode(f['seed']) as Uint8List); } catch (err) { expect((err as ArgumentError).message, f['exception']); } finally { @@ -188,8 +192,9 @@ void main() { test("ecdsa", () { Uint8List seed = Uint8List.fromList(List.generate(32, (index) => 1)); Uint8List hash = Uint8List.fromList(List.generate(32, (index) => 2)); - String sigStr = "9636ee2fac31b795a308856b821ebe297dda7b28220fb46ea1fbbd7285977cc04c82b734956246a0f15a9698f03f546d8d96fe006c8e7bd2256ca7c8229e6f5c"; - Uint8List signature = HEX.decode(sigStr); + String sigStr = + "9636ee2fac31b795a308856b821ebe297dda7b28220fb46ea1fbbd7285977cc04c82b734956246a0f15a9698f03f546d8d96fe006c8e7bd2256ca7c8229e6f5c"; + Uint8List signature = HEX.decode(sigStr) as Uint8List; BIP32 node = BIP32.fromSeed(seed); expect(HEX.encode(node.sign(hash)), sigStr); expect(node.verify(hash, signature), true); @@ -206,7 +211,7 @@ void verify(BIP32 hd, prv, f, network) { expect(HEX.encode(hd.publicKey), f['pubKey']); if (prv) { expect(hd.toBase58(), f['base58Priv']); - expect(HEX.encode(hd.privateKey), f['privKey']); + expect(HEX.encode(hd.privateKey!), f['privKey']); expect(hd.toWIF(), f['wif']); } else { expect(hd.privateKey, null); @@ -216,8 +221,9 @@ void verify(BIP32 hd, prv, f, network) { if (f['children'] == null) return; if (!prv && - (f['children'] as List).map((fc) => fc['hardened']).contains( - true)) return; + (f['children'] as List) + .map((fc) => fc['hardened']) + .contains(true)) return; (f['children'] as List).forEach((cf) { var chd = hd.derivePath(cf['path']); @@ -234,11 +240,10 @@ void verify(BIP32 hd, prv, f, network) { shd = shd.deriveHardened(cf['m']); } else { // verify any publicly derived children - if (cf['base58'] != null) verify( - shd.neutered().derive(cf['m']), false, cf, network); + if (cf['base58'] != null) + verify(shd.neutered().derive(cf['m']), false, cf, network); shd = shd.derive(cf['m']); verify(shd, prv, cf, network); } }); } - diff --git a/test/ecc_test.dart b/test/ecc_test.dart index 60383bc..b5c6833 100644 --- a/test/ecc_test.dart +++ b/test/ecc_test.dart @@ -1,9 +1,11 @@ +import 'dart:typed_data'; import 'package:hex/hex.dart'; import 'package:test/test.dart'; import 'package:bip32/src/utils/ecurve.dart' as ecc; import 'package:bip32/bip32.dart' as bip32; -final defichain_testnet = bip32.NetworkType(bip32: bip32.Bip32Type(private: 0x04358394, public: 0x043587cf), wif: 0xef); +final defichain_testnet = bip32.NetworkType( + bip32: bip32.Bip32Type(private: 0x04358394, public: 0x043587cf), wif: 0xef); void main() { group("curve test", () { @@ -12,18 +14,29 @@ void main() { //55b18e96ce3964ef2c81ad69249eca6d42682c11fbe525df6671fcbf0c2be902 private key final hdSeed = bip32.BIP32.fromSeed( - HEX.decode("6607599b768ce88470b3b20919f9c63bff663e2f1ec3e3072d22fd9da3847784c361d5accc3b411019f5c81dd3e4ccf9fd1fddb232bfc9bfe23864e2e6ee793f"), defichain_testnet); + HEX.decode( + "6607599b768ce88470b3b20919f9c63bff663e2f1ec3e3072d22fd9da3847784c361d5accc3b411019f5c81dd3e4ccf9fd1fddb232bfc9bfe23864e2e6ee793f") + as Uint8List, + defichain_testnet); - final xMasterPriv = bip32.BIP32.fromSeed(hdSeed.privateKey, defichain_testnet); + final xMasterPriv = + bip32.BIP32.fromSeed(hdSeed.privateKey!, defichain_testnet); final privateKey = xMasterPriv.derivePath("m/0'/0'/0'"); - final privateKeyHex = HEX.encode(privateKey.privateKey); + final privateKeyHex = HEX.encode(privateKey.privateKey!); - expect("55b18e96ce3964ef2c81ad69249eca6d42682c11fbe525df6671fcbf0c2be902", privateKeyHex); + expect("55b18e96ce3964ef2c81ad69249eca6d42682c11fbe525df6671fcbf0c2be902", + privateKeyHex); }); test("test sign", () { - ecc.sign(HEX.decode("b11d3d5e4ae12b89d5e3872ccc7d1f96d29b0ab888b67dccf1be5164b811cdbe"), HEX.decode("55b18e96ce3964ef2c81ad69249eca6d42682c11fbe525df6671fcbf0c2be902")); + ecc.sign( + HEX.decode( + "b11d3d5e4ae12b89d5e3872ccc7d1f96d29b0ab888b67dccf1be5164b811cdbe") + as Uint8List, + HEX.decode( + "55b18e96ce3964ef2c81ad69249eca6d42682c11fbe525df6671fcbf0c2be902") + as Uint8List); }); }); @@ -34,19 +47,22 @@ void main() { key = 'f92ca9fe5f77afa489214a7ba2bd6b36d30dd4acdb55c70d1378b5c45c831820'; msg = '045a7448dffff67c08023d16279c57c0bd16af6467580c183cc4672e768b8a77'; - sig = ecc.sign(HEX.decode(msg), HEX.decode(key)); + sig = + ecc.sign(HEX.decode(msg) as Uint8List, HEX.decode(key) as Uint8List); print(HEX.encode(sig)); key = '8c39fb3d889b6be22850254dc7ce3247c559d9f968785d88251ee4457633e335'; msg = '6ad99bc30926fd79cf5a977044088fd298a59728c5b0c1040713d3a8e1c1e69b'; - sig = ecc.sign(HEX.decode(msg), HEX.decode(key)); + sig = + ecc.sign(HEX.decode(msg) as Uint8List, HEX.decode(key) as Uint8List); print(HEX.encode(sig)); key = '2de619ea940d31927e0a7bbd5ebf855ab66f488b94a65cf929a1eb70b54ec771'; msg = 'd82a6db2583353856dd4dadc38cdb6373b092ea1f026fa04f03aa3c4e972454f'; - sig = ecc.sign(HEX.decode(msg), HEX.decode(key)); + sig = + ecc.sign(HEX.decode(msg) as Uint8List, HEX.decode(key) as Uint8List); print(HEX.encode(sig)); }); });