File Coverage

blib/lib/Crypt/XTEA.pm
Criterion Covered Total %
statement 65 74 87.8
branch 15 32 46.8
condition 3 6 50.0
subroutine 12 15 80.0
pod 5 8 62.5
total 100 135 74.0


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   1064 use strict;
  2         2  
  2         47  
6 2     2   6 use warnings;
  2         3  
  2         41  
7 2     2   13 use utf8;
  2         3  
  2         10  
8              
9 2     2   32 use Carp;
  2         1  
  2         111  
10 2     2   7 use List::Util qw(all);
  2         2  
  2         154  
11 2     2   755 use Scalar::Util::Numeric qw(isint);
  2         1034  
  2         1180  
12              
13             our $VERSION = '0.0108'; # 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 0     0 1 0 sub keysize { $KEY_SIZE }
27              
28              
29 0     0 1 0 sub blocksize { $BLOCK_SIZE }
30              
31              
32             sub new {
33 8     8 1 2100 my $class = shift;
34 8         6 my $key = shift;
35 8   66     24 my $rounds = shift // $ROUNDS;
36 8         14 my %opts = (little_endian => 0, @_);
37 8         5 my $xtea_key;
38 8 50       14 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       17 croak( sprintf( 'key must be a %d-byte-long STRING or a reference of ARRAY', $KEY_SIZE ) ) if length $key != $KEY_SIZE;
46 8         10 $xtea_key = key_setup($key, $opts{little_endian});
47             }
48 8 50       21 croak( 'rounds must be a positive NUMBER' ) if isint( $rounds ) != 1;
49             my $self = {
50             key => $xtea_key,
51             rounds => $rounds,
52 8 100       25 endianness => $opts{little_endian} ? 'V*' : 'N*',
53             };
54 8   33     35 bless $self, ref($class) || $class;
55             }
56              
57              
58             sub encrypt {
59 8     8 1 1315 my $self = shift;
60 8         5 my $plain_text = shift;
61 8 50       17 croak( sprintf( 'plain_text block size must be %d bytes', $BLOCK_SIZE) ) if length($plain_text) != $BLOCK_SIZE;
62 8         20 my @block = unpack $self->{endianness}, $plain_text;
63 8         14 my $cipher_text_ref = $self->encrypt_block( \@block );
64 8         6 return pack( $self->{endianness}, @{$cipher_text_ref} );
  8         43  
65             }
66              
67              
68             sub decrypt {
69 8     8 1 1406 my $self = shift;
70 8         3 my $cipher_text = shift;
71 8 50       18 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         10 my $plain_text_ref = $self->decrypt_block( \@block );
74 8         6 return pack( $self->{endianness}, @{$plain_text_ref} );
  8         17  
75             }
76              
77             sub encrypt_block {
78 8     8 0 13 my $self = shift;
79 8         3 my $block_ref = shift;
80 8         7 my $key_ref = $self->{key};
81              
82 8 50       7 croak( sprintf( 'block must has %d elements', $ELEMENTS_IN_BLOCK ) ) if scalar( @{ $block_ref } ) != $ELEMENTS_IN_BLOCK;
  8         16  
83 8 50       5 croak( sprintf( 'key must has %d elements', $ELEMENTS_IN_KEY ) ) if scalar( @{ $key_ref } ) != $ELEMENTS_IN_KEY;
  8         11  
84              
85 8         32 return $self->encrypt_block_in_c( $block_ref );
86             }
87              
88             sub decrypt_block {
89 8     8 0 7 my $self = shift;
90 8         7 my $block_ref = shift;
91 8         5 my $key_ref = $self->{key};
92              
93 8 50       8 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         19  
95              
96 8         30 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       10 my $endianness = (shift) ? 'V*' : 'N*';
102 8 50       11 croak( sprintf( 'key must be %s bytes long', $KEY_SIZE ) ) if length( $key_str ) != $KEY_SIZE;
103 8         21 my @xtea_key = unpack $endianness, $key_str;
104 8         13 return \@xtea_key;
105             }
106              
107              
108             1;
109              
110             __END__