File Coverage

blib/lib/Bitcoin/Crypto/Key/ExtPrivate.pm
Criterion Covered Total %
statement 62 71 87.3
branch 4 6 66.6
condition n/a
subroutine 17 20 85.0
pod 3 3 100.0
total 86 100 86.0


line stmt bran cond sub pod time code
1             package Bitcoin::Crypto::Key::ExtPrivate;
2             $Bitcoin::Crypto::Key::ExtPrivate::VERSION = '2.000_01'; # TRIAL
3             $Bitcoin::Crypto::Key::ExtPrivate::VERSION = '2.00001';
4 8     8   74956 use v5.10;
  8         48  
5 8     8   53 use strict;
  8         20  
  8         200  
6 8     8   111 use warnings;
  8         63  
  8         201  
7 8     8   1241 use Moo;
  8         15165  
  8         75  
8 8     8   10136 use Crypt::Mac::HMAC qw(hmac);
  8         15395  
  8         501  
9 8     8   1694 use Bitcoin::BIP39 qw(bip39_mnemonic_to_entropy);
  8         4848  
  8         474  
10 8     8   1949 use Type::Params -sigs;
  8         265688  
  8         122  
11              
12 8     8   9090 use Bitcoin::Crypto::BIP44;
  8         40  
  8         317  
13 8     8   4229 use Bitcoin::Crypto::Key::ExtPublic;
  8         40  
  8         403  
14 8     8   67 use Bitcoin::Crypto::Constants;
  8         24  
  8         248  
15 8     8   54 use Bitcoin::Crypto::Helpers qw(ensure_length carp_once);
  8         45  
  8         520  
16 8     8   68 use Bitcoin::Crypto::Util qw(mnemonic_to_seed);
  8         37  
  8         678  
17 8     8   91 use Bitcoin::Crypto::Types qw(Object Str ByteStr HashRef Maybe);
  8         32  
  8         101  
18 8     8   26400 use Bitcoin::Crypto::Exception;
  8         28  
  8         189  
19              
20 8     8   49 use namespace::clean;
  8         42  
  8         124  
21              
22             with qw(Bitcoin::Crypto::Role::ExtendedKey);
23              
24 841     841   5720 sub _is_private { 1 }
25              
26             sub generate_mnemonic
27             {
28 0     0 1 0 shift;
29 0         0 carp_once 'Bitcoin::Crypto::Key::ExtPrivate->generate_mnemonic is deprecated.'
30             . ' Use generate_mnemonic function from Bitcoin::Crypto::Util instead.';
31              
32 0         0 goto \&Bitcoin::Crypto::Util::generate_mnemonic;
33             }
34              
35             sub mnemonic_from_entropy
36             {
37 0     0 1 0 shift;
38 0         0 carp_once 'Bitcoin::Crypto::Key::ExtPrivate->mnemonic_from_entropy is deprecated.'
39             . ' Use mnemonic_from_entropy function from Bitcoin::Crypto::Util instead.';
40              
41 0         0 goto \&Bitcoin::Crypto::Util::mnemonic_from_entropy;
42             }
43              
44             signature_for from_mnemonic => (
45             method => Str,
46             positional => [Str, Maybe [Str], {default => ''}, Maybe [Str], {default => undef}],
47             );
48              
49             sub from_mnemonic
50             {
51             my ($class, $mnemonic, $password, $lang) = @_;
52              
53             if (defined $lang) {
54              
55             # checks validity of seed in given language
56             # requires Wordlist::LANG::BIP39 module for given LANG
57             Bitcoin::Crypto::Exception::MnemonicCheck->trap_into(
58             sub {
59             bip39_mnemonic_to_entropy(
60             mnemonic => $mnemonic,
61             language => $lang
62             );
63             }
64             );
65             }
66              
67             return $class->from_seed(mnemonic_to_seed($mnemonic, $password));
68             }
69              
70             signature_for from_seed => (
71             method => Str,
72             positional => [ByteStr],
73             );
74              
75             sub from_seed
76             {
77             my ($class, $seed) = @_;
78              
79             my $bytes = hmac('SHA512', 'Bitcoin seed', $seed);
80             my $key = substr $bytes, 0, 32;
81             my $cc = substr $bytes, 32, 32;
82              
83             return $class->new(
84             key_instance => $key,
85             chain_code => $cc,
86             );
87             }
88              
89             signature_for get_public_key => (
90             method => Object,
91             positional => [],
92             );
93              
94             sub get_public_key
95             {
96             my ($self) = @_;
97              
98             my $public = Bitcoin::Crypto::Key::ExtPublic->new(
99             key_instance => $self->raw_key('public'),
100             chain_code => $self->chain_code,
101             child_number => $self->child_number,
102             parent_fingerprint => $self->parent_fingerprint,
103             depth => $self->depth,
104             network => $self->network,
105             purpose => $self->purpose,
106             );
107              
108             return $public;
109             }
110              
111             signature_for derive_key_bip44 => (
112             method => Object,
113             positional => [HashRef, {slurpy => 1}],
114             );
115              
116             sub derive_key_bip44
117             {
118             my ($self, $data) = @_;
119             my $path = Bitcoin::Crypto::BIP44->new(
120             %{$data},
121             coin_type => $self,
122             );
123              
124             return $self->derive_key($path);
125             }
126              
127             sub _derive_key_partial
128             {
129 185     185   496 my ($self, $child_num, $hardened) = @_;
130              
131 185         298 my $hmac_data;
132 185 100       493 if ($hardened) {
133              
134             # zero byte
135 80         174 $hmac_data .= "\x00";
136              
137             # key data - 32 bytes
138 80         270 $hmac_data .= ensure_length $self->raw_key, Bitcoin::Crypto::Constants::key_max_length;
139             }
140             else {
141             # public key data - SEC compressed form
142 105         343 $hmac_data .= $self->raw_key('public_compressed');
143             }
144              
145             # child number - 4 bytes
146 185         969 $hmac_data .= ensure_length pack('N', $child_num), 4;
147              
148 185         2339 my $data = hmac('SHA512', $self->chain_code, $hmac_data);
149 185         557 my $chain_code = substr $data, 32, 32;
150              
151 185         995 my $number = Math::BigInt->from_bytes(substr $data, 0, 32);
152 185         21621 my $key_num = Math::BigInt->from_bytes($self->raw_key);
153 185         17281 my $n_order = $self->curve_order;
154              
155 185 50       49364 Bitcoin::Crypto::Exception::KeyDerive->raise(
156             "key $child_num in sequence was found invalid"
157             ) if $number->bge($n_order);
158              
159 185         6314 $number->badd($key_num);
160 185         12366 $number->bmod($n_order);
161              
162 185 50       15378 Bitcoin::Crypto::Exception::KeyDerive->raise(
163             "key $child_num in sequence was found invalid"
164             ) if $number->beq(0);
165              
166 185         36346 return $self->new(
167             key_instance => $number->as_bytes,
168             chain_code => $chain_code,
169             child_number => $child_num,
170             parent_fingerprint => $self->get_fingerprint,
171             depth => $self->depth + 1,
172             );
173             }
174              
175             ### DEPRECATED
176              
177             sub from_hex_seed
178             {
179 0     0 1   my ($class, $seed) = @_;
180              
181 0           carp_once "$class->from_hex_seed(\$seed) is now deprecated. Use $class->from_seed([hex => \$seed]) instead";
182              
183 0           return $class->from_seed([hex => $seed]);
184             }
185              
186             1;
187              
188             __END__
189             =head1 NAME
190              
191             Bitcoin::Crypto::Key::ExtPrivate - Bitcoin extended private keys
192              
193             =head1 SYNOPSIS
194              
195             use Bitcoin::Crypto qw(btc_extprv);
196             use Bitcoin::Crypto::Util qw(generate_mnemonic to_format)
197              
198             # generate mnemonic words first
199             my $mnemonic = generate_mnemonic;
200             print "Your mnemonic is: $mnemonic";
201              
202             # create ExtPrivateKey from mnemonic (without password)
203             my $key = btc_extprv->from_mnemonic($mnemonic);
204             my $ser_key = to_format [base58 => $key->to_serialized];
205             print "Your exported master key is: $ser_key";
206              
207             # derive child private key
208             my $path = "m/0'";
209             my $child_key = $key->derive_key($path);
210             my $ser_child_key = to_format [base58 => $child_key->to_serialized];
211             print "Your exported $path child key is: $ser_child_key";
212              
213             # create basic keypair
214             my $basic_private = $child_key->get_basic_key;
215             my $basic_public = $child_key->get_public_key->get_basic_key;
216              
217             =head1 DESCRIPTION
218              
219             This class allows you to create an extended private key instance.
220              
221             You can use an extended private key to:
222              
223             =over 2
224              
225             =item * generate extended public keys
226              
227             =item * derive extended keys using a path
228              
229             =item * restore keys from mnemonic codes, seeds and base58 format
230              
231             =back
232              
233             see L<Bitcoin::Crypto::Network> if you want to work with other networks than
234             Bitcoin Mainnet.
235              
236             =head1 METHODS
237              
238             =head2 new
239              
240             Constructor is reserved for internal and advanced use only. Use
241             L</from_mnemonic>, L</from_seed> or L</from_serialized> instead.
242              
243             =head2 generate_mnemonic
244              
245             $mnemonic = $class->generate_mnemonic($len = 128, $lang = 'en')
246              
247             Deprecated - see L<Bitcoin::Crypto::Util/generate_mnemonic>.
248              
249             =head2 mnemonic_from_entropy
250              
251             $mnemonic = $class->mnemonic_from_entropy($bytes, $lang = 'en')
252              
253             Deprecated - see L<Bitcoin::Crypto::Util/mnemonic_from_entropy>.
254              
255             =head2 from_mnemonic
256              
257             $key_object = $class->from_mnemonic($mnemonic, $password = '', $lang = undef)
258              
259             Creates a new key from given mnemonic and password.
260              
261             Note that technically any password is correct and there's no way to tell if it
262             was mistaken.
263              
264             If you need to validate if C<$mnemonic> is a valid mnemonic you should specify
265             C<$lang>, e.g. 'en'.
266              
267             If no C<$lang> is given then any string passed as C<$mnemonic> will produce a
268             valid key.
269              
270             Returns a new instance of this class.
271              
272             B<Important note about unicode:> this function only accepts UTF8-decoded
273             strings (both C<$mnemonic> and C<$password>), but can't detect whether it got
274             it or not. This will only become a problem if you use non-ascii mnemonic and/or
275             password. If there's a possibility of non-ascii, always use utf8 and set
276             binmodes to get decoded (wide) characters to avoid problems recovering your
277             wallet.
278              
279             =head2 from_seed
280              
281             $key_object = $class->from_seed($seed)
282              
283             Creates and returns a new key from seed, which can be any data of any length.
284             C<$seed> is expected to be a byte string.
285              
286             =head2 from_hex_seed
287              
288             Deprecated. Use C<< $class->from_seed([hex => $seed]) >> instead.
289              
290             =head2 to_serialized
291              
292             $serialized = $object->to_serialized()
293              
294             Returns the key serialized in format specified in BIP32 as byte string.
295              
296             =head2 to_serialized_base58
297              
298             Deprecated. Use C<< to_format [base58 => $key->to_serialized] >> instead.
299              
300             =head2 from_serialized
301              
302             $key_object = $class->from_serialized($serialized, $network = undef)
303              
304             Tries to unserialize byte string C<$serialized> with format specified in BIP32.
305              
306             Dies on errors. If multiple networks match serialized data specify C<$network>
307             manually (id of the network) to avoid exception.
308              
309             =head2 from_serialized_base58
310              
311             Deprecated. Use C<< $class->from_serialized([base58 => $base58]) >> instead.
312              
313             =head2 set_network
314              
315             $key_object = $object->set_network($val)
316              
317             Change key's network state to C<$val>. It can be either network name present in
318             L<Bitcoin::Crypto::Network> package or an instance of this class.
319              
320             Returns current key instance.
321              
322             =head2 get_public_key
323              
324             $public_key_object = $object->get_public_key()
325              
326             Returns instance of L<Bitcoin::Crypto::Key::ExtPublic> generated from the
327             private key.
328              
329             =head2 get_basic_key
330              
331             $basic_key_object = $object->get_basic_key()
332              
333             Returns the key in basic format: L<Bitcoin::Crypto::Key::Private>
334              
335             =head2 derive_key
336              
337             $derived_key_object = $object->derive_key($path)
338              
339             Performs extended key derivation as specified in BIP32 on the current key with
340             C<$path>. Dies on error.
341              
342             See BIP32 document for details on derivation paths and methods.
343              
344             Returns a new extended key instance - result of a derivation.
345              
346             =head2 derive_key_bip44
347              
348             $derived_key_object = $object->derive_key_bip44(%data)
349              
350             A helper that constructs a L<Bitcoin::Crypto::BIP44> path from C<%data> and
351             calls L</derive_key> with it. Refer to L<Bitcoin::Crypto::BIP44/Attributes> to
352             see what you can include in C<%data>.
353              
354             Using this method instead of specifying BIP44 path yourself will make sure all
355             features of BIP44 derivation will be enabled, like different prefixes for
356             extended keys (C<xprv> / C<yprv> / C<zprv>) and address type generation
357             checking.
358              
359             I<Note: coin_type parameter will be ignored, and the current network
360             configuration set in the extended key will be used.>
361              
362             =head2 get_fingerprint
363              
364             $fingerprint = $object->get_fingerprint($len = 4)
365              
366             Returns a fingerprint of the extended key of C<$len> length (byte string)
367              
368             =head1 EXCEPTIONS
369              
370             This module throws an instance of L<Bitcoin::Crypto::Exception> if it
371             encounters an error. It can produce the following error types from the
372             L<Bitcoin::Crypto::Exception> namespace:
373              
374             =over 2
375              
376             =item * MnemonicGenerate - mnemonic couldn't be generated correctly
377              
378             =item * MnemonicCheck - mnemonic didn't pass the validity check
379              
380             =item * KeyDerive - key couldn't be derived correctly
381              
382             =item * KeyCreate - key couldn't be created correctly
383              
384             =item * NetworkConfig - incomplete or corrupted network configuration
385              
386             =back
387              
388             =head1 SEE ALSO
389              
390             =over 2
391              
392             =item L<Bitcoin::Crypto::Key::ExtPublic>
393              
394             =item L<Bitcoin::Crypto::Network>
395              
396             =back
397              
398             =cut
399