Crypt-RNCryptor

 view release on metacpan or  search on metacpan

META.json  view on Meta::CPAN

            "Test::MinimumVersion::Fast" : "0.04",
            "Test::PAUSE::Permissions" : "0.04",
            "Test::Pod" : "1.41",
            "Test::Spellunker" : "v0.2.7"
         }
      },
      "runtime" : {
         "requires" : {
            "Carp" : "0",
            "Class::Accessor::Lite" : "0",
            "Crypt::CBC" : "0",
            "Crypt::OpenSSL::AES" : "0",
            "Crypt::PBKDF2" : "0",
            "Digest::SHA" : "0",
            "perl" : "5.008001"
         }
      },
      "test" : {
         "requires" : {
            "Test::More" : "0.98",
            "Test::Pretty" : "0"

META.yml  view on Meta::CPAN

    - builder
provides:
  Crypt::RNCryptor:
    file: lib/Crypt/RNCryptor.pm
    version: '0.01'
  Crypt::RNCryptor::V3:
    file: lib/Crypt/RNCryptor/V3.pm
requires:
  Carp: '0'
  Class::Accessor::Lite: '0'
  Crypt::CBC: '0'
  Crypt::OpenSSL::AES: '0'
  Crypt::PBKDF2: '0'
  Digest::SHA: '0'
  perl: '5.008001'
resources:
  bugtracker: https://github.com/s-shin/p5-Crypt-RNCryptor/issues
  homepage: https://github.com/s-shin/p5-Crypt-RNCryptor
  repository: git://github.com/s-shin/p5-Crypt-RNCryptor.git
version: '0.01'

README.md  view on Meta::CPAN


    # encrypt
    $ciphertext = $cryptor->encrypt('plaintext');

    # decrypt
    $plaintext = $cryptor->decrypt($ciphertext);

# DESCRIPTION

Crypt::RNCryptor is a Perl implementation of RNCryptor,
which is one of data format for AES-256 (CBC mode) encryption.

Crypt::RNCryptor class is the base of Crypt::RNCryptor::V\* class
and declare some abstract methods.

# METHODS

## CLASS METHODS

- my $cryptor = Crypt::RNCryptor->new(%opts);

cpanfile  view on Meta::CPAN

requires 'perl', '5.008001';
requires 'Carp';
requires 'Digest::SHA';
requires 'Crypt::PBKDF2';
requires 'Crypt::OpenSSL::AES';
requires 'Crypt::CBC';
requires 'Class::Accessor::Lite';

on 'test' => sub {
    requires 'Test::More', '0.98';
    requires 'Test::Pretty';
};

cpanfile.snapshot  view on Meta::CPAN

  Class-Load-XS-0.08
    pathname: E/ET/ETHER/Class-Load-XS-0.08.tar.gz
    provides:
      Class::Load::XS 0.08
    requirements:
      Class::Load 0.20
      ExtUtils::MakeMaker 6.30
      XSLoader 0
      strict 0
      warnings 0
  Crypt-CBC-2.33
    pathname: L/LD/LDS/Crypt-CBC-2.33.tar.gz
    provides:
      Crypt::CBC 2.33
    requirements:
      Digest::MD5 2.00
      ExtUtils::MakeMaker 0
  Crypt-OpenSSL-AES-0.02
    pathname: T/TT/TTAR/Crypt-OpenSSL-AES-0.02.tar.gz
    provides:
      Crypt::OpenSSL::AES 0.02
    requirements:
      ExtUtils::MakeMaker 0
  Crypt-PBKDF2-0.142390

lib/Crypt/RNCryptor.pm  view on Meta::CPAN


    # encrypt
    $ciphertext = $cryptor->encrypt('plaintext');

    # decrypt
    $plaintext = $cryptor->decrypt($ciphertext);

=head1 DESCRIPTION

Crypt::RNCryptor is a Perl implementation of RNCryptor,
which is one of data format for AES-256 (CBC mode) encryption.

Crypt::RNCryptor class is the base of Crypt::RNCryptor::V* class
and declare some abstract methods.

=head1 METHODS

=head2 CLASS METHODS

=over 4

lib/Crypt/RNCryptor/V3.pm  view on Meta::CPAN

package Crypt::RNCryptor::V3;
use strict;
use warnings;
use parent 'Crypt::RNCryptor';
use Carp;
use Crypt::PBKDF2;
use Crypt::CBC;
use Digest::SHA qw(hmac_sha256);

use constant {
    VERSION => 3,
    # option
    OPTION_USE_PASSWORD => 1,
    OPTION_NOT_USE_PASSWORD => 0,
    # size
    VERSION_SIZE => 1,
    OPTIONS_SIZE => 1,

lib/Crypt/RNCryptor/V3.pm  view on Meta::CPAN

    $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) = @_;

lib/Crypt/RNCryptor/V3.pm  view on Meta::CPAN


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)
    my $hmac = hmac_sha256($cipherdata, $hmac_key);
    # Message = Header || Ciphertext || HMAC
    pack('a*a*', $cipherdata, $hmac);
}

sub encrypt_with_keys {
    my ($self, $plaintext, %opts) = @_;
    my $iv = $opts{iv} || Crypt::CBC->random_bytes(IV_SIZE);
    my $encryption_key = $opts{encryption_key} || $self->encryption_key;
    my $hmac_key = $opts{hmac_key} || $self->hmac_key;
    # Header = 3 || 0 || IV
    my $header = pack('CCa*', VERSION, OPTION_NOT_USE_PASSWORD, $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)
    my $hmac = hmac_sha256($cipherdata, $hmac_key);
    # Message = Header || Ciphertext || HMAC
    pack('a*a*', $cipherdata, $hmac);
}

sub decrypt {
    my $self = shift;

lib/Crypt/RNCryptor/V3.pm  view on Meta::CPAN

    };
    my ($version, $options, $iv) = do {
        my $fmt = sprintf('CCa%d', IV_SIZE);
        unpack($fmt, $header);
    };

    # compare HMAC
    my $computed_hmac = hmac_sha256(pack('a*a*', $header, $ciphertext), $hmac_key);
    die "HMAC is not matched.\n" unless $computed_hmac eq $hmac;

    # Plaintext = AES256Decrypt(Ciphertext, ModeCBC, IV, EncryptionKey)
    $self->aes256cbc($encryption_key, $iv)->decrypt($ciphertext);
}

1;

__END__

=encoding utf-8

=head1 NAME



( run in 1.077 second using v1.01-cache-2.11-cpan-e1769b4cff6 )