Blockchain-Ethereum
view release on metacpan or search on metacpan
lib/Blockchain/Ethereum/Keystore/File.pm view on Meta::CPAN
package Blockchain::Ethereum::Keystore::File;
use v5.26;
use strict;
use warnings;
# ABSTRACT: Ethereum keystore file abstraction
our $AUTHORITY = 'cpan:REFECO'; # AUTHORITY
our $VERSION = '0.021'; # VERSION
use Carp;
use JSON::MaybeXS;
use Crypt::PRNG;
use Crypt::Mode::CTR;
use Crypt::Digest::Keccak256 qw(keccak256);
use Scalar::Util qw(blessed);
use Data::UUID;
use Blockchain::Ethereum::Key;
use Blockchain::Ethereum::Keystore::KDF;
my $json = JSON::MaybeXS->new(
utf8 => 1,
pretty => 1,
canonical => 1
);
sub from_key {
my ($class, $key) = @_;
croak 'key must be a Blockchain::Ethereum::Key instance'
unless blessed $key && $key->isa('Blockchain::Ethereum::Key');
my $self = bless {private_key => $key}, $class;
return $self;
}
sub from_file {
my ($class, $file_path, $password) = @_;
my $self = bless {}, $class;
my $content;
{
open my $fh, '<:raw', $file_path
or croak "Could not read file '$file_path': $!";
local $/; # Enable slurp mode
$content = <$fh>;
close $fh;
}
my $decoded = $json->decode(lc $content);
croak 'Version not supported' unless $decoded->{version} && $decoded->{version} == 3;
croak 'Password is required to decrypt the keystore' unless defined $password;
$self->{password} = $password;
return $self->_from_v3($decoded);
}
sub cipher {
shift->{cipher} //= Crypt::Mode::CTR->new('AES', 1);
}
sub ciphertext {
my $self = shift;
$self->{ciphertext} //= $self->_generate_ciphertext;
}
sub mac {
my $self = shift;
$self->{mac} //= $self->_generate_mac;
}
sub version {
shift->{version} //= 3;
}
sub iv {
my $self = shift;
$self->{iv} //= $self->_generate_random_iv;
}
sub kdf {
my $self = shift;
$self->{kdf} //= $self->_generate_kdf;
}
sub id {
my $self = shift;
$self->{id} //= $self->_generate_id;
}
sub private_key {
shift->{private_key};
}
sub password {
shift->{password};
}
sub _from_v3 {
my ($self, $object) = @_;
my $crypto = $object->{crypto};
$self->{ciphertext} = $crypto->{ciphertext};
$self->{mac} = $crypto->{mac};
$self->{iv} = $crypto->{cipherparams}->{iv};
$self->{version} = $object->{version};
$self->{id} = $object->{id};
my $header = $crypto->{kdfparams};
$self->{kdf} = Blockchain::Ethereum::Keystore::KDF->new(
algorithm => $crypto->{kdf}, #
dklen => $header->{dklen},
( run in 1.351 second using v1.01-cache-2.11-cpan-39bf76dae61 )