File Coverage

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