view release on metacpan or search on metacpan
$keyfile->write_to_file("...");
Signing a transaction:
my $transaction = Blockchain::Ethereum::Transaction::EIP1559->new(
...
);
my $keyfile = Blockchain::Ethereum::Keystore::Keyfile->new;
$keyfile->import_file("...");
$keyfile->private_key->sign_transaction($transaction);
Export private key:
my $keyfile = Blockchain::Ethereum::Keystore::Keyfile->new;
$keyfile->import_file("...");
# private key bytes
print $keyfile->private_key->export;
OVERVIEW
This module provides a collection of Ethereum wallet management
utilities.
Core functionalities:
* Manage Ethereum keyfiles, facilitating import, export, and password
change.
lib/Blockchain/Ethereum/Keystore.pm view on Meta::CPAN
$keyfile->write_to_file("...");
Signing a transaction:
my $transaction = Blockchain::Ethereum::Transaction::EIP1559->new(
...
);
my $keyfile = Blockchain::Ethereum::Keystore::Keyfile->new;
$keyfile->import_file("...");
$keyfile->private_key->sign_transaction($transaction);
Export private key:
my $keyfile = Blockchain::Ethereum::Keystore::Keyfile->new;
$keyfile->import_file("...");
# private key bytes
print $keyfile->private_key->export;
=head1 OVERVIEW
This module provides a collection of Ethereum wallet management utilities.
Core functionalities:
=over 4
=item * Manage Ethereum keyfiles, facilitating import, export, and password change.
lib/Blockchain/Ethereum/Keystore/Key.pm view on Meta::CPAN
use Crypt::Digest::Keccak256 qw(keccak256);
use Crypt::PRNG qw(random_bytes);
use Blockchain::Ethereum::Keystore::Key::PKUtil;
use Blockchain::Ethereum::Keystore::Address;
sub new {
my ($class, %params) = @_;
my $self = bless {}, $class;
if (exists $params{private_key}) {
$self->{private_key} = $params{private_key};
} else {
$self->{private_key} = random_bytes(32);
}
my $importer = Crypt::PK::ECC->new();
$importer->import_key_raw($self->private_key, 'secp256k1');
# Crypt::PK::ECC does not provide support for deterministic keys
$self->{ecc_handler} = bless Crypt::Perl::ECDSA::Parse::private($importer->export_key_der('private')),
'Blockchain::Ethereum::Keystore::Key::PKUtil';
return $self;
}
sub private_key {
return shift->{private_key};
}
sub _ecc_handler {
return shift->{ecc_handler};
}
sub sign_transaction {
my ($self, $transaction) = @_;
croak "transaction must be a reference of Blockchain::Ethereum::Transaction"
lib/Blockchain/Ethereum/Keystore/Key.pm view on Meta::CPAN
my ($x, $y) = Crypt::Perl::ECDSA::Utils::split_G_or_public($self->_ecc_handler->_decompress_public_point);
# address is the hash of the concatenated value of x and y
my $address = substr(keccak256($x . $y), -20);
my $hex_address = unpack("H*", $address);
return Blockchain::Ethereum::Keystore::Address->new(address => "0x$hex_address");
}
sub export {
return shift->private_key;
}
1;
__END__
=pod
=encoding UTF-8
lib/Blockchain/Ethereum/Keystore/Key.pm view on Meta::CPAN
=head1 SYNOPSIS
Generate a new key:
my $key = Blockchain::Ethereum::Key->new;
$key->sign_transaction($transaction); # Blockchain::Ethereum::Transaction
Import existent key:
my $key = Blockchain::Ethereum::Key->new(private_key => $private_key); # private key bytes
$key->sign_transaction($transaction); # Blockchain::Ethereum::Transaction
=head1 OVERVIEW
This is a private key abstraction
If instantiated without a private key, this module uses L<Crypt::PRNG> for the random key generation
=head1 METHODS
lib/Blockchain/Ethereum/Keystore/Key.pm view on Meta::CPAN
Export the L<Blockchain::Ethereum::Keystore::Address> from the imported/generated private key
=over 4
=back
L<Blockchain::Ethereum::Keystore::Address>
=head2 export
Use `private_key` instead this method is deprecated and will be removed.
=over 4
=back
Private key bytes
=head1 AUTHOR
Reginaldo Costa <refeco@cpan.org>
lib/Blockchain/Ethereum/Keystore/Keyfile.pm view on Meta::CPAN
use Crypt::PRNG;
use Net::SSH::Perl::Cipher;
use Blockchain::Ethereum::Keystore::Key;
use Blockchain::Ethereum::Keystore::Keyfile::KDF;
sub new {
my ($class, %params) = @_;
my $self = bless {}, $class;
for (qw(cipher ciphertext mac version iv kdf id private_key)) {
$self->{$_} = $params{$_} if exists $params{$_};
}
return $self;
}
sub cipher {
shift->{cipher};
}
lib/Blockchain/Ethereum/Keystore/Keyfile.pm view on Meta::CPAN
}
sub kdf {
shift->{kdf};
}
sub id {
shift->{id};
}
sub private_key {
shift->{private_key};
}
sub _json {
return shift->{json} //= JSON::MaybeXS->new(utf8 => 1);
}
sub import_file {
my ($self, $file_path, $password) = @_;
my $content = read_file($file_path);
lib/Blockchain/Ethereum/Keystore/Keyfile.pm view on Meta::CPAN
$self->{kdf} = Blockchain::Ethereum::Keystore::Keyfile::KDF->new(
algorithm => $crypto->{kdf}, #
dklen => $header->{dklen},
n => $header->{n},
p => $header->{p},
r => $header->{r},
c => $header->{c},
prf => $header->{prf},
salt => $header->{salt});
$self->{private_key} = $self->_private_key($password);
return $self;
}
sub change_password {
my ($self, $old_password, $new_password) = @_;
return $self->import_key($self->_private_key($old_password), $new_password);
}
sub _private_key {
my ($self, $password) = @_;
return $self->private_key if $self->private_key;
my $cipher = Net::SSH::Perl::Cipher->new(
$self->cipher, #
$self->kdf->decode($password),
pack("H*", $self->iv));
my $key = $cipher->decrypt(pack("H*", $self->ciphertext));
return Blockchain::Ethereum::Keystore::Key->new(private_key => $key);
}
sub import_key {
my ($self, $key, $password) = @_;
# use the internal method here otherwise would not be availble to get the kdf params
# salt if give will be the same as the response, if not will be auto generated by the library
my ($derived_key, $salt, $N, $r, $p);
($derived_key, $salt, $N, $r, $p) = Crypt::ScryptKDF::_scrypt_extra($password);
$self->kdf->{algorithm} = "scrypt";
lib/Blockchain/Ethereum/Keystore/Keyfile.pm view on Meta::CPAN
my $cipher = Net::SSH::Perl::Cipher->new(
"AES128_CTR", #
$derived_key,
$iv
);
my $encrypted = $cipher->encrypt($key->export);
$self->{ciphertext} = unpack "H*", $encrypted;
$self->{private_key} = $key;
return $self;
}
sub _write_to_object {
my $self = shift;
croak "KDF algorithm and parameters are not set" unless $self->kdf;
my $file = {
lib/Blockchain/Ethereum/Keystore/Keyfile.pm view on Meta::CPAN
=over 4
=item * C<keyfile> - L<Blockchain::Ethereum::Keystore::Key>
=back
self
=head2 write_to_file
Write the imported keyfile/private_key to a keyfile in the file system
=over 4
=item * C<file_path> - file path to save the data
=back
returns 1 upon successfully writing the file or undef if it encountered an error
=head1 AUTHOR
lib/Blockchain/Ethereum/Keystore/Seed.pm view on Meta::CPAN
$change = 0 unless $change;
my $path = Bitcoin::Crypto::BIP44->new(
index => $index,
purpose => $purpose,
coin_type => $coin_type,
account => $account,
change => $change,
);
return Blockchain::Ethereum::Keystore::Key->new(private_key => $self->_hdw_handler->derive_key($path)->get_basic_key->to_serialized);
}
1;
__END__
=pod
=encoding UTF-8
#!/usr/bin/env perl
use strict;
use warnings;
use Test::More;
use Blockchain::Ethereum::Keystore::Key;
subtest "0x008AeEda4D805471dF9b2A5B0f38A0C3bCBA786b" => sub {
my $private_key = pack "H*", "7a28b5ba57c53603b0b07b56bba752f7784bf506fa95edc395f5cf6c7514fe9d";
my $key = Blockchain::Ethereum::Keystore::Key->new(private_key => $private_key);
is $key->address, '0x008AeEda4D805471dF9b2A5B0f38A0C3bCBA786b';
};
subtest "0x9d8A62f656a8d1615C1294fd71e9CFb3E4855A4F" => sub {
my $private_key = pack "H*", "4646464646464646464646464646464646464646464646464646464646464646";
my $key = Blockchain::Ethereum::Keystore::Key->new(private_key => $private_key);
is $key->address, '0x9d8A62f656a8d1615C1294fd71e9CFb3E4855A4F';
};
done_testing();
t/keyfile.t view on Meta::CPAN
#!/usr/bin/env perl
use strict;
use warnings;
use Test::More;
use Blockchain::Ethereum::Keystore::Keyfile;
# https://ethereum.org/pt-br/developers/docs/data-structures-and-encoding/web3-secret-storage/#PBKDF2-SHA-256
subtest "v3_pbkdf2_ctr" => sub {
my $private_key = pack "H*", "7a28b5ba57c53603b0b07b56bba752f7784bf506fa95edc395f5cf6c7514fe9d";
my $password = "testpassword";
my $keyfile = Blockchain::Ethereum::Keystore::Keyfile->new;
my $key = $keyfile->import_file("./t/resources/pbkdf2_v3.json", $password);
is $key->private_key->export, $private_key;
$key = $keyfile->import_key(Blockchain::Ethereum::Keystore::Key->new(private_key => $private_key), $password);
is $key->private_key->export, $private_key;
};
# https://ethereum.org/pt-br/developers/docs/data-structures-and-encoding/web3-secret-storage/#scrypt
subtest "v3_scrypt_ctr" => sub {
my $private_key = pack "H*", "7a28b5ba57c53603b0b07b56bba752f7784bf506fa95edc395f5cf6c7514fe9d";
my $password = "testpassword";
my $keyfile = Blockchain::Ethereum::Keystore::Keyfile->new;
my $key = $keyfile->import_file("./t/resources/scrypt_v3.json", $password);
is $key->private_key->export, $private_key;
$key = $keyfile->import_key(Blockchain::Ethereum::Keystore::Key->new(private_key => $private_key), $password);
is $key->private_key->export, $private_key;
};
done_testing;