File Coverage

blib/lib/Crypt/XXTEA_XS.pm
Criterion Covered Total %
statement 69 76 90.7
branch 12 30 40.0
condition 1 3 33.3
subroutine 14 15 93.3
pod 3 6 50.0
total 99 130 76.1


line stmt bran cond sub pod time code
1             package Crypt::XXTEA_XS;
2              
3             # ABSTRACT: Implementation of Corrected Block Tiny Encryption Algorithm
4              
5 1     1   573 use strict;
  1         1  
  1         34  
6 1     1   4 use warnings;
  1         1  
  1         30  
7 1     1   10 use utf8;
  1         1  
  1         4  
8              
9 1     1   16 use Carp;
  1         1  
  1         50  
10 1     1   4 use List::Util qw(all);
  1         0  
  1         89  
11 1     1   359 use Scalar::Util::Numeric qw(isint);
  1         491  
  1         82  
12              
13             our $VERSION = '0.01'; # VERSION
14              
15             require XSLoader;
16             XSLoader::load('Crypt::XXTEA_XS', $VERSION);
17              
18              
19             my $FACTOR = 4;
20             my $KEY_SIZE = 16;
21             my $ELEMENTS_IN_KEY = $KEY_SIZE / $FACTOR;
22             my $MIN_BLOCK_SIZE = 8;
23             my $MIN_ELEMENTS_IN_BLOCK = $MIN_BLOCK_SIZE / $FACTOR;
24              
25              
26 1     1   4 use constant keysize => $KEY_SIZE;
  1         1  
  1         46  
27              
28              
29 1     1   2 use constant blocksize => $MIN_BLOCK_SIZE;
  1         1  
  1         447  
30              
31              
32             sub new {
33 2     2 1 589 my $class = shift;
34 2         1 my $key = shift;
35 2         1 my $xxtea_key;
36 2 50       5 croak( 'key is required' ) if not defined $key;
37 2 50       2 if ( my $ref_of_key = ref( $key ) ) {
38 0 0       0 croak( sprintf( 'key must be a %d-byte-long STRING or a reference of ARRAY', $KEY_SIZE ) ) if not $ref_of_key eq 'ARRAY';
39 0 0       0 croak( sprintf( 'key must has %d elements if key is a reference of ARRAY', $ELEMENTS_IN_KEY ) ) if scalar( @{ $key } ) != $ELEMENTS_IN_KEY;
  0         0  
40 0 0   0   0 croak( 'each element of key must be a 32bit Integer if key is a reference of ARRAY' ) if not all { isint( $_ ) != 0 } @{ $key };
  0         0  
  0         0  
41 0         0 $xxtea_key = $key;
42             } else {
43 2 50       5 croak( sprintf( 'key must be a %d-byte-long STRING or a reference of ARRAY', $KEY_SIZE ) ) if length $key != $KEY_SIZE;
44 2         3 $xxtea_key = key_setup($key);
45             }
46 2         2 my $self = {
47             key => $xxtea_key,
48             };
49 2   33     9 bless $self, ref($class) || $class;
50             }
51              
52              
53             sub encrypt {
54 2     2 1 421 my $self = shift;
55 2         2 my $plain_text = shift;
56              
57 2 50       4 croak( sprintf( 'plain_text size must be at least %d bytes', $MIN_BLOCK_SIZE) ) if length($plain_text) < $MIN_BLOCK_SIZE;
58 2 50       4 croak( sprintf( 'plain_text size must be a multiple of %d bytes', $FACTOR) ) if length($plain_text) % $FACTOR != 0;
59              
60 2         4 my @block = unpack 'N*', $plain_text;
61 2         4 my $cipher_text_ref = $self->encrypt_block( \@block );
62 2         2 return pack( 'N*', @{$cipher_text_ref} );
  2         10  
63             }
64              
65              
66             sub decrypt {
67 2     2 1 471 my $self = shift;
68 2         1 my $cipher_text = shift;
69              
70 2 50       4 croak( sprintf( 'cipher_text size must be at least %d bytes', $MIN_BLOCK_SIZE) ) if length($cipher_text) < $MIN_BLOCK_SIZE;
71 2 50       4 croak( sprintf( 'cipher_text size must be a multiple of %d bytes', $FACTOR) ) if length($cipher_text) % $FACTOR != 0;
72              
73 2         5 my @block = unpack 'N*', $cipher_text;
74 2         2 my $plain_text_ref = $self->decrypt_block( \@block );
75 2         2 return pack( 'N*', @{$plain_text_ref} );
  2         4  
76             }
77              
78             sub encrypt_block {
79 2     2 0 2 my $self = shift;
80 2         1 my $block_ref = shift;
81 2         4 my $key_ref = $self->{key};
82              
83 2 50       2 croak( sprintf( 'block must has at least %d elements', $MIN_ELEMENTS_IN_BLOCK ) ) if scalar( @{ $block_ref } ) < $MIN_ELEMENTS_IN_BLOCK;
  2         3  
84 2 50       2 croak( sprintf( 'key must has %d elements', $ELEMENTS_IN_KEY ) ) if scalar( @{ $key_ref } ) != $ELEMENTS_IN_KEY;
  2         4  
85              
86 2         11 return $self->encrypt_block_in_c( $block_ref );
87             }
88              
89             sub decrypt_block {
90 2     2 0 2 my $self = shift;
91 2         2 my $block_ref = shift;
92 2         9 my $key_ref = $self->{key};
93              
94 2 50       2 croak( sprintf( 'block must has at least %d elements', $MIN_ELEMENTS_IN_BLOCK ) ) if scalar( @{ $block_ref } ) < $MIN_ELEMENTS_IN_BLOCK;
  2         5  
95 2 50       1 croak( sprintf( 'key must has %d elements', $ELEMENTS_IN_KEY ) ) if scalar( @{ $key_ref } ) != $ELEMENTS_IN_KEY;
  2         2  
96              
97 2         9 return $self->decrypt_block_in_c( $block_ref );
98             }
99              
100             sub key_setup {
101 2     2 0 1 my $key_str = shift;
102 2 50       2 croak( sprintf( 'key must be %s bytes long', $KEY_SIZE ) ) if length( $key_str ) != $KEY_SIZE;
103 2         7 my @xxtea_key = unpack 'N*', $key_str;
104 2         3 return \@xxtea_key;
105             }
106              
107              
108             1;
109              
110             __END__