File Coverage

blib/lib/Crypt/XTEA.pm
Criterion Covered Total %
statement 71 78 91.0
branch 15 32 46.8
condition 3 6 50.0
subroutine 14 15 93.3
pod 3 6 50.0
total 106 137 77.3


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