Bitcoin-Crypto
view release on metacpan or search on metacpan
lib/Bitcoin/Crypto/Key/Private.pm view on Meta::CPAN
use v5.14;
use warnings;
use Mooish::Base -standard;
use Bitcoin::BIP39 qw(bip39_mnemonic_to_entropy entropy_to_bip39_mnemonic);
use Types::Common -sigs;
use List::Util qw(none);
use Bitcoin::Crypto::Key::Public;
use Bitcoin::Crypto::Base58 qw(encode_base58check decode_base58check);
use Bitcoin::Crypto::Constants qw(:key);
use Bitcoin::Crypto::Network;
use Bitcoin::Crypto::Util::Internal qw(validate_wif);
use Bitcoin::Crypto::Helpers qw(ensure_length);
use Bitcoin::Crypto::Exception;
use Bitcoin::Crypto::Types -types;
extends qw(Bitcoin::Crypto::Key::Base);
sub _is_private { 1 }
sub to_wif
{
my ($self) = @_;
my $bytes = $self->to_serialized();
# wif network - 1B
my $wifdata = $self->network->wif_byte;
# key entropy - 32B
$wifdata .= ensure_length $bytes, KEY_MAX_LENGTH;
# additional byte for compressed key - 1B
$wifdata .= WIF_COMPRESSED_BYTE if $self->compressed;
return encode_base58check($wifdata);
}
signature_for from_serialized => (
method => !!1,
positional => [BitcoinSecret],
);
signature_for from_wif => (
method => !!1,
positional => [BitcoinSecret, Maybe [Str], {default => undef}],
);
sub from_wif
{
my ($class, $secret, $network) = @_;
return $secret->unmask_to(
sub {
my ($wif) = @_;
Bitcoin::Crypto::Exception::KeyCreate->raise(
'base58 string is not valid WIF'
) unless validate_wif($wif);
my $decoded = decode_base58check($wif);
my $private = substr $decoded, 1;
my $compressed = 0;
if (length($private) > KEY_MAX_LENGTH) {
chop $private;
$compressed = 1;
}
my $wif_network_byte = substr $decoded, 0, 1;
my @found_networks =
Bitcoin::Crypto::Network->find(sub { shift->wif_byte eq $wif_network_byte });
@found_networks = grep { $_ eq $network } @found_networks
if defined $network;
if (@found_networks > 1) {
my $default_network = Bitcoin::Crypto::Network->get->id;
Bitcoin::Crypto::Exception::KeyCreate->raise(
'found multiple networks possible for given WIF: ' . join ', ', @found_networks
) if none { $_ eq $default_network } @found_networks;
@found_networks = ($default_network);
}
Bitcoin::Crypto::Exception::KeyCreate->raise(
"network name $network cannot be used for given WIF"
) if @found_networks == 0 && defined $network;
Bitcoin::Crypto::Exception::NetworkConfig->raise(
"couldn't find network for WIF byte $wif_network_byte"
) if @found_networks == 0;
my $instance = $class->from_serialized($private);
$instance->set_compressed($compressed);
$instance->set_network(@found_networks);
return $instance;
}
);
}
sub get_public_key
{
my ($self) = @_;
my $public = Bitcoin::Crypto::Key::Public->new(
_key_instance => $self->raw_key('public'),
compressed => $self->compressed,
network => $self->network,
purpose => $self->purpose,
taproot_output => $self->taproot_output,
);
return $public;
}
1;
__END__
=head1 NAME
Bitcoin::Crypto::Key::Private - Bitcoin private keys
=head1 SYNOPSIS
use Bitcoin::Crypto::Key::Private;
# get Bitcoin::Crypto::Key::Public instance from private key
my $pub = $priv->get_public_key();
( run in 1.017 second using v1.01-cache-2.11-cpan-39bf76dae61 )