Crypt-RNCryptor
view release on metacpan or search on metacpan
lib/Crypt/RNCryptor/V3.pm view on Meta::CPAN
HMAC_SALT_SIZE => 8,
IV_SIZE => 16,
HMAC_SIZE => 32,
# PBKDF2
DEFAULT_PBKDF2_ITERATIONS => 10000,
PBKDF2_OUTPUT_SIZE => 32,
};
use Class::Accessor::Lite (
ro => [qw(
password pbkdf2_iterations
encryption_key hmac_key
)],
);
sub new {
my ($class, %opts) = @_;
if ($opts{password} && ($opts{encryption_key} || $opts{hmac_key})) {
confess 'Cannot set the "password" option with "encryption_key" or "hmac_key" option.';
}
if ($opts{pbkdf2_iterations}) {
confess 'v3.1 is not supported still yet.';
}
bless {
password => $opts{password},
encryption_key => $opts{encryption_key},
hmac_key => $opts{hmac_key},
pbkdf2_iterations => DEFAULT_PBKDF2_ITERATIONS,
}, $class;
}
sub pbkdf2 {
my ($self, $password, $salt, $iterations) = @_;
$iterations ||= $self->pbkdf2_iterations;
Crypt::PBKDF2->new(
hash_class => 'HMACSHA1',
iterations => $iterations,
output_len => PBKDF2_OUTPUT_SIZE,
)->PBKDF2($salt, $password);
}
sub aes256cbc {
my ($self, $encryption_key, $iv) = @_;
Crypt::CBC->new(
-literal_key => 1,
-key => $encryption_key,
-iv => $iv,
-header => 'none',
-cipher => 'Crypt::OpenSSL::AES',
);
}
sub make_options {
my ($self, $use_password, $pbkdf2_iterations) = @_;
confess 'TODO';
}
sub encrypt {
my $self = shift;
return $self->encrypt_with_password(@_) if $self->password;
return $self->encrypt_with_keys(@_) if $self->encryption_key && $self->hmac_key;
confess 'Cannot encrypt.';
}
sub encrypt_with_password {
my ($self, $plaintext, %opts) = @_;
my $iv = $opts{iv} || Crypt::CBC->random_bytes(IV_SIZE);
my $encryption_salt = $opts{encryption_salt} || Crypt::CBC->random_bytes(ENCRYPTION_SALT_SIZE);
my $hmac_salt = $opts{hmac_salt} || Crypt::CBC->random_bytes(HMAC_SALT_SIZE);
my $password = $opts{password} || $self->password;
my $pbkdf2_iterations = $opts{pbkdf2_iterations} || $self->pbkdf2_iterations;
my $encryption_key = $self->pbkdf2($password, $encryption_salt);
my $hmac_key = $self->pbkdf2($password, $hmac_salt);
# Header = 3 || 1 || EncryptionSalt || HMACSalt || IV
my $header = pack('CCa*a*a*', VERSION, OPTION_USE_PASSWORD, $encryption_salt, $hmac_salt, $iv);
# Ciphertext = AES256(plaintext, ModeCBC, IV, EncryptionKey)
my $ciphertext = $self->aes256cbc($encryption_key, $iv)->encrypt($plaintext);
my $cipherdata = pack('a*a*', $header, $ciphertext);
# HMAC = HMAC(Header || Ciphertext, HMACKey, SHA-256)
lib/Crypt/RNCryptor/V3.pm view on Meta::CPAN
=head2 CLASS METHODS
=over 4
=item my $cryptor = Crypt::RNCryptor->new(%opts);
Create a cryptor instance.
%opts = (
password => 'any length password',
pbkdf2_iterations => DEFAULT_PBKDF2_ITERATIONS,
# or
encryption_key => '32 length key',
hmac_key => '32 length key',
);
=back
=head2 INSTANCE METHODS
=over 4
( run in 0.962 second using v1.01-cache-2.11-cpan-71847e10f99 )