File Coverage

blib/lib/Crypt/XTEA.pm
Criterion Covered Total %
statement 69 76 90.7
branch 11 28 39.2
condition 2 6 33.3
subroutine 14 15 93.3
pod 3 6 50.0
total 99 131 75.5


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