Crypt-Rijndael-PP

 view release on metacpan or  search on metacpan

lib/Crypt/Rijndael/PP.pm  view on Meta::CPAN

    0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
    0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
    0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
    0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
    0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
);
#>>>

#<<< Don't Tidy the Round Constansts
Readonly my @RCONST => (
    0x8d000000, 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000, 0x40000000,
    0x80000000, 0x1b000000, 0x36000000, 0x6c000000, 0xd8000000, 0xab000000, 0x4d000000, 0x9a000000,
    0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39,
    0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a,
    0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8,
    0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef,
    0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc,
    0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b,
    0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3,
    0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94,
    0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20,
    0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35,
    0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f,
    0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04,
    0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63,
    0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd,
    0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d
);
#>>>

Readonly my $NUM_ROUNDS => {
    128 => 10,
    192 => 12,
    256 => 14,
};

sub new {
    my $class = shift;
    my $key   = shift;
    my $mode  = shift;

    if( !$mode ) {
        $mode = MODE_ECB();
    }

    my $self = {
        key  => $key,
        mode => $mode,
        iv   => get_weak(16),
    };

    bless $self, $class;

    return $self;
}

sub MODE_ECB {
    return 1;
}

sub MODE_CBC {
    return 2;
}

sub MODE_CTR {
    return 3;
}

sub MODE_CFB {
    return 4;
}

sub MODE_OFB {
    return 5;
}

sub blocksize {
    return 16;
}

sub keysize {
    return 32;
}

sub set_iv {
    my $self = shift;
    my $iv   = shift;

    if( length( $iv ) != 16 ) {
        croak 'set_iv: initial value must be the blocksize (16 bytes), but was '
            . length( $iv ) . ' bytes';
    }

    $self->{iv} = $iv;

    return $self;
}

sub get_iv {
    my $self = shift;

    return $self->{iv};
}

sub _increment_nonce {
    my $self         = shift;
    my $packed_nonce = shift;

    my @nonce_parts = unpack( 'N4', $packed_nonce );

    ### Nonce Part 0 : unpack( 'A4', $nonce_parts[0] ) . ' - ' . unpack( 'B32', $nonce_parts[0] )
    ### Nonce Part 1 : unpack( 'A4', $nonce_parts[1] ) . ' - ' . unpack( 'B32', $nonce_parts[1] )
    ### Nonce Part 2 : unpack( 'A4', $nonce_parts[2] ) . ' - ' . unpack( 'B32', $nonce_parts[2] )
    ### Nonce Part 3 : unpack( 'A4', $nonce_parts[3] ) . ' - ' . unpack( 'B32', $nonce_parts[3] )

    for my $nonce_part_index ( 0 .. 3 ) {
        my $original_nonce_part = $nonce_parts[ 3 - $nonce_part_index ];
        $nonce_parts[ 3 - $nonce_part_index ]++;

        ### Nonce Part Index       : ( $nonce_part_index )
        ### Original Nonce Part    : unpack( 'A4', $original_nonce_part ) . ' - ' . unpack( 'B32', $original_nonce_part )
        ### Incremented Nonce Part : unpack( 'A4', $nonce_parts[ 3 - $nonce_part_index ] ) . ' - ' . unpack( 'B32', $nonce_parts[ 3 - $nonce_part_index ] )

        if( $original_nonce_part < $nonce_parts[ 3 - $nonce_part_index ] ) {
            last;
        }
    }

    return pack( 'N4', @nonce_parts );
}

sub encrypt {
    my $self  = shift;
    my $input = shift;

    ## no critic (ControlStructures::ProhibitCascadingIfElse)
    if( $self->{mode} == MODE_ECB() ) {
        return $self->_encrypt_mode_ecb( $input );
    }
    elsif( $self->{mode} == MODE_CBC() ) {
        return $self->_encrypt_mode_cbc( $input );
    }
    elsif( $self->{mode} == MODE_CTR() ) {
        return $self->_encrypt_mode_ctr( $input );
    }
    elsif( $self->{mode} == MODE_CFB() ) {
        return $self->_encrypt_mode_cfb( $input );
    }
    elsif( $self->{mode} == MODE_OFB() ) {
        return $self->_encrypt_mode_ofb( $input );
    }
    else {
        croak "Invalid Mode specified";
    }
    ## use critic
}

sub _encrypt_mode_ecb {
    my $self  = shift;
    my $input = shift;

    my $cipher_text = '';
    for( my $block_index = 0; $block_index < ( length($input) / 16 ); $block_index++ ) {
        my $block = substr( $input, $block_index * 16, 16 );

        $cipher_text .= $self->encrypt_block( $block, $self->{key} );
    }

    return $cipher_text;
}

sub _encrypt_mode_cbc {
    my $self  = shift;
    my $input = shift;

    my $last_block = $self->{iv};

    my $cipher_text = '';
    for( my $block_index = 0; $block_index < ( length($input) / 16 ); $block_index++ ) {
        my $block = substr( $input, $block_index * 16, 16 );

        $block = $block ^ $last_block;

        $last_block = $self->encrypt_block( $block, $self->{key} );

        $cipher_text .= $last_block;
    }

    return $cipher_text;
}

sub _encrypt_mode_ctr {
    my $self  = shift;
    my $input = shift;

    my $nonce = $self->{iv};

    my $cipher_text = '';
    for( my $block_index = 0; $block_index < ( length($input) / 16 ); $block_index++ ) {
        my $block = substr( $input, $block_index * 16, 16 );

lib/Crypt/Rijndael/PP.pm  view on Meta::CPAN

        ### Nonce Bit String : ( unpack( 'B128', $packed_nonce ) )

        my $ctr_block = $self->encrypt_block( unpack( 'A16', $packed_nonce ), $self->{key} );

        $cipher_text .= $ctr_block ^ $block;
        $packed_nonce = $self->_increment_nonce( $packed_nonce );

        ### Nonce + 1 Bit String: ( unpack( 'B128', $packed_nonce ) )
        $nonce = unpack('A16', $packed_nonce );
    }

    return $cipher_text;
}

sub _encrypt_mode_cfb {
    my $self  = shift;
    my $input = shift;

    my $last_block = $self->{iv};

    my $cipher_text = '';
    for( my $block_index = 0; $block_index < ( length($input) / 16 ); $block_index++ ) {
        my $block = substr( $input, $block_index * 16, 16 );

        my $cfb_block = $self->encrypt_block( $last_block, $self->{key} );

        $last_block  = $block ^ $cfb_block;
        $cipher_text .= $last_block;
    }

    return $cipher_text;
}

sub _encrypt_mode_ofb {
    my $self  = shift;
    my $input = shift;

    my $last_block = $self->{iv};

    my $cipher_text = '';
    for( my $block_index = 0; $block_index < ( length($input) / 16 ); $block_index++ ) {
        my $block = substr( $input, $block_index * 16, 16 );

        my $ofb_block = $self->encrypt_block( $last_block, $self->{key} );

        $cipher_text .= $block ^ $ofb_block;
        $last_block   = $ofb_block;
    }

    return $cipher_text;
}

sub decrypt {
    my $self  = shift;
    my $input = shift;

    ## no critic (ControlStructures::ProhibitCascadingIfElse)
    if( $self->{mode} == MODE_ECB() ) {
        return $self->_decrypt_mode_ecb( $input );
    }
    elsif( $self->{mode} == MODE_CBC() ) {
        return $self->_decrypt_mode_cbc( $input );
    }
    elsif( $self->{mode} == MODE_CTR() ) {
        return $self->_decrypt_mode_ctr( $input );
    }
    elsif( $self->{mode} == MODE_CFB() ) {
        return $self->_decrypt_mode_cfb( $input );
    }
    elsif( $self->{mode} == MODE_OFB() ) {
        return $self->_decrypt_mode_ofb( $input );
    }
    else {
        croak "Invalid Mode specified";
    }
    ## use critic
}

sub _decrypt_mode_ecb {
    my $self  = shift;
    my $input = shift;

    my $plain_text = '';
    for( my $block_index = 0; $block_index < ( length($input) / 16 ); $block_index++ ) {
        my $cipher_block = substr( $input, $block_index * 16, 16 );

        $plain_text .= $self->decrypt_block( $cipher_block, $self->{key} );
    }

    return $plain_text;
}

sub _decrypt_mode_cbc {
    my $self  = shift;
    my $input = shift;

    my $last_cipher_block;

    my $plain_text = '';
    for( my $block_index = 0; $block_index < ( length($input) / 16 ); $block_index++ ) {
        my $cipher_block = substr( $input, $block_index * 16, 16 );

        my $plain_block = $self->decrypt_block( $cipher_block, $self->{key} );

        if( $block_index == 0 ) {
            $plain_block = $plain_block ^ $self->{iv};
        }
        else {
            $plain_block = $plain_block ^ $last_cipher_block;
        }

        $last_cipher_block = $cipher_block;
        $plain_text       .= $plain_block;
    }

    return $plain_text;
}

sub _decrypt_mode_ctr {
    my $self  = shift;
    my $input = shift;



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