Bitcoin-Crypto
view release on metacpan or search on metacpan
lib/Bitcoin/Crypto/Role/Key.pm view on Meta::CPAN
use warnings;
use Mooish::Base -standard, -role;
use Types::Common -sigs;
use Feature::Compat::Try;
use Bitcoin::Crypto::Types -types;
use Bitcoin::Crypto::Constants qw(:key);
use Bitcoin::Crypto::Util::Internal qw(get_key_type);
use Bitcoin::Crypto::Helpers qw(ensure_length ecc);
use Bitcoin::Crypto::Exception;
use Bitcoin::Crypto::Secret;
# ByteStr or BitcoinSecret or SecretBuffer
has param '_key_instance' => (
writer => 1,
);
has param 'purpose' => (
isa => BIP44Purpose,
writer => 1,
clearer => 1,
required => 0,
);
with qw(Bitcoin::Crypto::Role::Network);
requires qw(
_is_private
);
sub _run_with_key
{
my ($self, $sub_ref) = @_;
if ($self->_is_private) {
return $self->_key_instance->unmask_to($sub_ref);
}
else {
return $sub_ref->($self->_key_instance);
}
}
sub _validate_key
{
state $sig = signature(method => !!1, positional => [ByteStr]);
my ($self, $entropy) = $sig->(@_);
my $is_private = get_key_type $entropy;
Bitcoin::Crypto::Exception::KeyCreate->raise(
'invalid entropy data passed to key creation method'
) unless defined $is_private;
Bitcoin::Crypto::Exception::KeyCreate->raise(
'trying to create key from unknown key data'
) unless $is_private == $self->_is_private;
if ($is_private) {
Bitcoin::Crypto::Exception::KeyCreate->raise(
'private key is not valid'
) unless ecc->verify_private_key(ensure_length $entropy, KEY_MAX_LENGTH);
}
else {
try {
# keep public keys in compressed form always
$self->_set_key_instance(ecc->compress_public_key($entropy));
}
catch ($e) {
Bitcoin::Crypto::Exception::KeyCreate->raise(
'public key is not valid'
);
}
}
}
sub BUILD
{
my ($self) = @_;
state $type_secret = BitcoinSecret;
$self->_set_key_instance($type_secret->assert_coerce($self->_key_instance))
if $self->_is_private;
$self->_run_with_key(
sub {
$self->_validate_key($_[0]);
}
);
}
signature_for has_purpose => (
method => !!1,
positional => [BIP44Purpose],
);
sub has_purpose
{
my ($self, $purpose) = @_;
return !$self->purpose || $self->purpose == $purpose;
}
signature_for raw_key => (
method => !!1,
positional => [Maybe [Enum [qw(private public public_compressed public_xonly)]], {default => undef}],
);
# helpers for raw_key
sub __full_private
{
state $sig = signature(positional => [ByteStr]);
my ($key) = $sig->(@_);
return ensure_length $key, KEY_MAX_LENGTH;
}
sub __private_to_public
{
my ($key) = @_;
return ecc->create_public_key(__full_private($key));
}
( run in 0.839 second using v1.01-cache-2.11-cpan-5837b0d9d2c )