App-locket
view release on metacpan or search on metacpan
lib/App/locket/Locket.pm view on Meta::CPAN
$reader =~ s/^\s*[|<]//;
my $pipe = $reader;
CORE::open( my $cipher, '-|', $pipe );
my $plainstore = join '', <$cipher>;
chomp $plainstore;
return "$plainstore\n";
die "*** Unknown/invalid reader ($reader)";
}
sub load {
my $self = shift;
my $plainstore = $self->plainstore;
my $store;
try {
if ( $plainstore =~ m/^\s*\{/ )
{ $store = $JSON->decode( $plainstore ) }
else { $store = YAML::XS::Load( $plainstore ) }
};
die sprintf "*** Unable to parse store (%d)", length $plainstore if !$store;
return App::locket::Store->new( store => $store );
}
sub reload {
my $self = shift;
$self->clear_plainstore;
$self->clear_store;
$self->store;
}
# ~
# Cipher
# ~
sub random ($) {
my $length = shift;
return makerandom_octet Length => $length, Strength => 1;
}
sub generate_keylet {
my $self = shift;
return {
master_seed => random 32,
transform_seed => random 32,
transform_count => 50_000,
iv => random 16,
};
}
sub generate_cipher {
my $self = shift;
my $keylet = shift;
my $passphrase = shift;
my $key_cipher = Crypt::Rijndael->new( $keylet->{ master_seed }, Crypt::Rijndael::MODE_ECB );
my $key = sha256 $passphrase;
$key = $key_cipher->encrypt( $key ) for 1 .. $keylet->{ transform_count };
$key = sha256 $key;
$key = sha256 $keylet->{ transform_seed }, $key;
my $cipher = Crypt::Rijndael->new( $key, Crypt::Rijndael::MODE_CBC() );
$cipher->set_iv( $keylet->{ iv } );
return $cipher;
}
sub encrypt {
my $self = shift;
my $keylet = shift;
my $passphrase = shift;
my $plaintext = shift;
my $cipher = $self->generate_cipher( $keylet, $passphrase );
my $base64 = encode_base64 $plaintext, '';
$base64 .= '=' x ( 16 - length( $base64 ) % 16 );
return $cipher->encrypt( $base64 );
}
sub decrypt {
my $self = shift;
my $keylet = shift;
my $passphrase = shift;
my $ciphertext = shift;
my $cipher = $self->generate_cipher( $keylet, $passphrase );
my $base64 = $cipher->decrypt( $ciphertext );
return decode_base64 $base64;
}
sub pickle {
my $self = shift;
my $keylet = shift;
my $passphrase = shift;
my $plaintext = shift;
my %options = @_;
my $plaintext_digest = sha256_hex $plaintext;
my $pickle_keylet = { %$keylet };
$_ = unpack 'h*', $_ for @$pickle_keylet{qw/ master_seed transform_seed iv /};
my $pickle = {
keylet => $pickle_keylet,
plaintext_digest => $plaintext_digest,
ciphertext => encode_base64( $self->encrypt( $keylet, $passphrase, $plaintext ), '' ),
};
if ( $options{ json } ) {
$pickle = $JSON->encode( $pickle );
}
return $pickle;
}
sub unpickle {
my $self = shift;
my $passphrase = shift;
my $pickle = shift;
my %options = @_;
( run in 1.181 second using v1.01-cache-2.11-cpan-e1769b4cff6 )