Skip to content

Commit 2c9c78c

Browse files
committed
Initial
1 parent 1020f28 commit 2c9c78c

File tree

13 files changed

+326
-25
lines changed

13 files changed

+326
-25
lines changed

lib/src/crypto/tron/entities/tron_address.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import 'dart:typed_data';
22
import 'package:walletkit_dart/src/crypto/utxo/utils/pubkey_to_address.dart';
33
import 'package:walletkit_dart/src/crypto/utxo/utils/ecurve.dart';
44
import 'package:walletkit_dart/src/utils/base58.dart';
5+
import 'package:walletkit_dart/src/utils/crypto.dart';
56
import 'package:walletkit_dart/src/utils/keccak.dart';
67
import 'package:walletkit_dart/walletkit_dart.dart';
78

lib/src/crypto/tron/entities/tron_transaction_utils.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import 'package:fixnum/fixnum.dart';
33
import 'package:walletkit_dart/src/crypto/tron/repositories/rpc/core/Tron.pb.dart';
44

55
import 'package:walletkit_dart/src/crypto/utxo/utils/pubkey_to_address.dart';
6+
import 'package:walletkit_dart/src/utils/crypto.dart';
67
import 'package:walletkit_dart/walletkit_dart.dart';
78
import 'package:walletkit_dart/src/crypto/tron/repositories/rpc/core/Tron.pb.dart'
89
as tron;

lib/src/crypto/utxo/entities/payments/p2h.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import 'package:walletkit_dart/src/crypto/utxo/entities/op_codes.dart';
66
import 'package:walletkit_dart/src/crypto/utxo/utils/pubkey_to_address.dart';
77
import 'package:walletkit_dart/src/domain/exceptions.dart';
88
import 'package:walletkit_dart/src/utils/base32.dart';
9+
import 'package:walletkit_dart/src/utils/crypto.dart';
910
import 'package:walletkit_dart/walletkit_dart.dart';
1011

1112
class P2Hash {

lib/src/crypto/utxo/entities/raw_transaction/raw_transaction.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import 'package:walletkit_dart/src/crypto/utxo/entities/payments/pk_script_conve
55
import 'package:walletkit_dart/src/crypto/utxo/utils/pubkey_to_address.dart';
66
import 'package:walletkit_dart/src/crypto/utxo/entities/raw_transaction/input.dart';
77
import 'package:walletkit_dart/src/crypto/utxo/entities/raw_transaction/output.dart';
8+
import 'package:walletkit_dart/src/utils/crypto.dart';
89
import 'package:walletkit_dart/src/utils/int.dart';
910
import 'package:walletkit_dart/src/utils/var_uint.dart';
1011
import 'package:walletkit_dart/walletkit_dart.dart';

lib/src/crypto/utxo/utils/eurocoin_signing.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import 'package:bip32/bip32.dart' as bip32;
44
import 'package:hex/hex.dart';
55
import 'package:walletkit_dart/src/crypto/utxo/utils/pubkey_to_address.dart';
66
import 'package:walletkit_dart/src/domain/exceptions.dart';
7+
import 'package:walletkit_dart/src/utils/crypto.dart';
78
import 'package:walletkit_dart/walletkit_dart.dart';
89
import 'package:pointycastle/src/utils.dart' as p_utils;
910
import 'package:bip32/src/utils/ecurve.dart' as ecc;

lib/src/crypto/utxo/utils/proof_of_payment.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import 'package:walletkit_dart/src/crypto/utxo/entities/raw_transaction/output.d
55
import 'package:walletkit_dart/src/crypto/utxo/entities/op_codes.dart';
66
import 'package:walletkit_dart/src/crypto/utxo/utils/pubkey_to_address.dart';
77
import 'package:walletkit_dart/src/crypto/utxo/repositories/electrum_json_rpc_client.dart';
8+
import 'package:walletkit_dart/src/utils/crypto.dart';
89
import 'package:walletkit_dart/src/utils/int.dart';
910
import 'package:walletkit_dart/src/utils/var_uint.dart';
1011
import 'package:walletkit_dart/walletkit_dart.dart';

lib/src/crypto/utxo/utils/pubkey_to_address.dart

Lines changed: 1 addition & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import 'package:walletkit_dart/src/utils/base32.dart';
66
import 'package:convert/convert.dart' show hex;
77
import 'package:bs58check/bs58check.dart' as bs58check;
88
import 'package:walletkit_dart/src/utils/base58.dart';
9+
import 'package:walletkit_dart/src/utils/crypto.dart';
910
import 'package:walletkit_dart/walletkit_dart.dart';
1011

1112
String pubKeyHexToAddress(
@@ -118,31 +119,6 @@ String pubKeyHashToP2SHAddress(Uint8List pubKeyHash, int scriptHashPrefix) {
118119
return base58Encode(prefixedHashWithChecksum);
119120
}
120121

121-
///
122-
/// Ripmed160 Hash of Sha256 Hash
123-
///
124-
Uint8List ripmed160Sha256Hash(Uint8List buffer) {
125-
final ripmed160 = RIPEMD160Digest();
126-
final sha256 = SHA256Digest();
127-
return ripmed160.process(sha256.process(buffer));
128-
}
129-
130-
///
131-
/// Sha256 Hash of Sha256 Hash
132-
///
133-
Uint8List sha256Sha256Hash(Uint8List buffer) {
134-
final sha256 = SHA256Digest();
135-
return sha256.process(sha256.process(buffer));
136-
}
137-
138-
///
139-
/// Sha256 Hash
140-
///
141-
Uint8List sha256Hash(Uint8List buffer) {
142-
final sha256 = SHA256Digest();
143-
return sha256.process(buffer);
144-
}
145-
146122
///
147123
/// BCH CashAddr
148124
///

lib/src/utils/crypto.dart

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import 'dart:typed_data';
2+
import 'package:pointycastle/export.dart';
3+
4+
///
5+
/// Ripmed160 Hash of Sha256 Hash
6+
///
7+
Uint8List ripmed160Sha256Hash(Uint8List buffer) {
8+
final ripmed160 = RIPEMD160Digest();
9+
final sha256 = SHA256Digest();
10+
return ripmed160.process(sha256.process(buffer));
11+
}
12+
13+
///
14+
/// Sha256 Hash of Sha256 Hash
15+
///
16+
Uint8List sha256Sha256Hash(Uint8List buffer) {
17+
final sha256 = SHA256Digest();
18+
return sha256.process(sha256.process(buffer));
19+
}
20+
21+
///
22+
/// Sha256 Hash
23+
///
24+
Uint8List sha256Hash(Uint8List buffer) {
25+
final sha256 = SHA256Digest();
26+
return sha256.process(buffer);
27+
}
28+
29+
///
30+
/// HMAC Sha256
31+
///
32+
Uint8List hmacSHA512(Uint8List key, Uint8List data) {
33+
final hmac = HMac(SHA512Digest(), 128)..init(KeyParameter(key));
34+
return hmac.process(data);
35+
}

lib/src/wallet/hd_node.dart

Lines changed: 266 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,266 @@
1+
import 'dart:convert';
2+
import 'dart:typed_data';
3+
4+
import 'package:walletkit_dart/src/crypto/utxo/utils/ecurve.dart' as ecurve;
5+
import 'package:walletkit_dart/src/utils/base58.dart';
6+
import 'package:walletkit_dart/src/utils/crypto.dart';
7+
import 'package:walletkit_dart/src/utils/int.dart';
8+
9+
const HIGHEST_BIT = 0x80000000;
10+
const UINT31_MAX = 2147483647; // 2^31 - 1
11+
const UINT32_MAX = 4294967295; // 2^32 - 1
12+
13+
class HDNode {
14+
final Uint8List _q;
15+
final Uint8List? _p;
16+
final Uint8List chainCode;
17+
18+
final int depth;
19+
final int index;
20+
final int parentFingerprint;
21+
22+
bool get isNeutered => _p == null;
23+
24+
Uint8List? get privateKey => _p;
25+
26+
Uint8List get publicKey => _q;
27+
28+
Uint8List get identifier => ripmed160Sha256Hash(publicKey);
29+
30+
Uint8List get fingerprint => identifier.sublist(0, 4);
31+
32+
HDNode derivePath(String path) {
33+
final regex = new RegExp(r"^(m\/)?(\d+'?\/)*\d+'?$");
34+
if (!regex.hasMatch(path)) {
35+
throw ArgumentError("Expected BIP32 Path");
36+
}
37+
38+
var splitPath = path.split("/");
39+
if (splitPath[0] == "m") {
40+
if (parentFingerprint != 0) {
41+
throw ArgumentError("Expected master node but got child node");
42+
}
43+
splitPath = splitPath.sublist(1);
44+
}
45+
46+
return splitPath.fold(
47+
this,
48+
(HDNode prevHd, String indexStr) {
49+
int index;
50+
if (indexStr.substring(indexStr.length - 1) == "'") {
51+
index = int.parse(indexStr.substring(0, indexStr.length - 1));
52+
return prevHd.deriveHardened(index);
53+
} else {
54+
index = int.parse(indexStr);
55+
return prevHd.derive(index);
56+
}
57+
},
58+
);
59+
}
60+
61+
String? extendedPrivateKey(int version) {
62+
if (version.isUint(32) == false) {
63+
throw ArgumentError("Expected UInt32 for version");
64+
}
65+
66+
if (isNeutered) {
67+
return null;
68+
}
69+
70+
final buffer = Uint8List(78);
71+
final bytes = buffer.buffer.asByteData();
72+
73+
bytes.setUint32(0, version);
74+
bytes.setUint8(4, depth);
75+
bytes.setUint32(5, parentFingerprint);
76+
bytes.setUint32(9, index);
77+
buffer.setRange(13, 45, chainCode);
78+
bytes.setUint8(45, 0);
79+
buffer.setRange(46, 78, privateKey!);
80+
81+
return base58Encode(buffer);
82+
}
83+
84+
String extendedPublicKey(int version) {
85+
if (version.isUint(32) == false) {
86+
throw ArgumentError("Expected UInt32 for version");
87+
}
88+
89+
final buffer = Uint8List(78);
90+
final bytes = buffer.buffer.asByteData();
91+
92+
bytes.setUint32(0, version);
93+
bytes.setUint8(4, depth);
94+
bytes.setUint32(5, parentFingerprint);
95+
bytes.setUint32(9, index);
96+
buffer.setRange(13, 45, chainCode);
97+
buffer.setRange(45, 78, publicKey);
98+
99+
return base58Encode(buffer);
100+
}
101+
102+
String toWIF() {
103+
throw UnimplementedError();
104+
}
105+
106+
HDNode deriveHardened(int index) {
107+
if (index > UINT31_MAX || index < 0) {
108+
throw ArgumentError("Expected UInt31");
109+
}
110+
return derive(index + HIGHEST_BIT);
111+
}
112+
113+
HDNode derive(int index) {
114+
if (index > UINT32_MAX || index < 0) {
115+
throw ArgumentError("Expected UInt32");
116+
}
117+
final isHardened = index >= HIGHEST_BIT;
118+
final data = Uint8List(37);
119+
120+
if (isHardened) {
121+
if (isNeutered) {
122+
throw ArgumentError("Cannot derive hardened key from neutered parent");
123+
}
124+
data[0] = 0x00;
125+
data.setRange(1, 33, privateKey!);
126+
} else {
127+
data.setRange(0, 33, publicKey);
128+
}
129+
data.buffer.asByteData().setUint32(33, index);
130+
131+
final I = hmacSHA512(chainCode, data);
132+
final IL = I.sublist(0, 32);
133+
final IR = I.sublist(32);
134+
if (ecurve.isPrivate(IL) == false) {
135+
return derive(index + 1);
136+
}
137+
138+
if (isNeutered) {
139+
final ki = ecurve.pointAddScalar(publicKey, IL, true);
140+
if (ki == null) {
141+
return derive(index + 1);
142+
}
143+
return HDNode._fromPublicKey(
144+
publicKey: ki,
145+
chainCode: IR,
146+
depth: depth + 1,
147+
index: index,
148+
parentFingerprint: fingerprint.buffer.asByteData().getUint32(0),
149+
);
150+
} else {
151+
final ki = ecurve.privateAdd(privateKey!, IL);
152+
if (ki == null) {
153+
return derive(index + 1);
154+
}
155+
return HDNode._fromI(
156+
IL: ki,
157+
IR: IR,
158+
depth: depth + 1,
159+
index: index,
160+
parentFingerprint: fingerprint.buffer.asByteData().getUint32(0),
161+
);
162+
}
163+
}
164+
165+
HDNode neutered() {
166+
return HDNode(
167+
q: _q,
168+
p: null,
169+
chainCode: chainCode,
170+
depth: depth,
171+
index: index,
172+
parentFingerprint: parentFingerprint,
173+
);
174+
}
175+
176+
factory HDNode._fromI({
177+
required Uint8List IL,
178+
required Uint8List IR,
179+
required int depth,
180+
required int index,
181+
required int parentFingerprint,
182+
}) {
183+
if (IL.length != 32) {
184+
throw ArgumentError("IL should be 32 bytes");
185+
}
186+
if (ecurve.isPrivate(IL) == false) {
187+
throw ArgumentError("IL should be a private key");
188+
}
189+
190+
final q = ecurve.pointFromScalar(IL, true)!;
191+
192+
return HDNode(
193+
q: q,
194+
p: IL,
195+
chainCode: IR,
196+
depth: depth,
197+
index: index,
198+
parentFingerprint: parentFingerprint,
199+
);
200+
}
201+
202+
bool verify(Uint8List hash, Uint8List signature) {
203+
return ecurve.verify(hash, _q, signature);
204+
}
205+
206+
Uint8List sign(Uint8List hash) {
207+
if (_p == null) {
208+
throw ArgumentError("HDNode is not private");
209+
}
210+
211+
return ecurve.sign(hash, _p!);
212+
}
213+
214+
factory HDNode._fromPublicKey({
215+
required Uint8List publicKey,
216+
required Uint8List chainCode,
217+
required int depth,
218+
required int index,
219+
required int parentFingerprint,
220+
}) {
221+
if (ecurve.isPoint(publicKey) == false) {
222+
throw ArgumentError("Point is not on the curve");
223+
}
224+
225+
return HDNode(
226+
q: publicKey,
227+
p: null,
228+
chainCode: chainCode,
229+
depth: depth,
230+
index: index,
231+
parentFingerprint: parentFingerprint,
232+
);
233+
}
234+
235+
const HDNode({
236+
required Uint8List q,
237+
required Uint8List? p,
238+
required this.chainCode,
239+
required this.depth,
240+
required this.index,
241+
required this.parentFingerprint,
242+
}) : _q = q,
243+
_p = p;
244+
245+
factory HDNode.fromSeed(Uint8List seed) {
246+
if (seed.length < 16) {
247+
throw new ArgumentError("Seed should be at least 128 bits");
248+
}
249+
if (seed.length > 64) {
250+
throw new ArgumentError("Seed should be at most 512 bits");
251+
}
252+
253+
final key = utf8.encode("Bitcoin seed");
254+
final I = hmacSHA512(key, seed);
255+
final IL = I.sublist(0, 32);
256+
final IR = I.sublist(32);
257+
258+
return HDNode._fromI(
259+
IL: IL,
260+
IR: IR,
261+
depth: 0,
262+
index: 0,
263+
parentFingerprint: 0,
264+
);
265+
}
266+
}

lib/src/wallet/wallet.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
class HDWallet {}

0 commit comments

Comments
 (0)