File Coverage

blib/lib/Crypt/Passphrase/Util/Crypt64.pm
Criterion Covered Total %
statement 45 45 100.0
branch 1 2 50.0
condition n/a
subroutine 8 8 100.0
pod 3 4 75.0
total 57 59 96.6


line stmt bran cond sub pod time code
1             package Crypt::Passphrase::Util::Crypt64;
2             $Crypt::Passphrase::Util::Crypt64::VERSION = '0.023';
3 4     4   310812 use strict;
  4         7  
  4         141  
4 4     4   15 use warnings;
  4         8  
  4         204  
5              
6 4     4   19 use Exporter 'import';
  4         6  
  4         457  
7             my @strings = qw/encode_crypt64 decode_crypt64/;
8             my @numbers = qw/encode_crypt64_number decode_crypt64_number/;
9             our @EXPORT_OK = (@strings, @numbers);
10             our %EXPORT_TAGS = (
11             all => \@EXPORT_OK,
12             strings => \@strings,
13             numbers => \@numbers,
14             );
15              
16 4     4   25 use Carp 'croak';
  4         34  
  4         2557  
17              
18             my $base64_digits = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
19              
20             sub encode_crypt64 {
21 19     19 1 176202 my $bytes = shift;
22 19         43 my $nbytes = length $bytes;
23 19         59 my $npadbytes = 2 - ($nbytes + 2) % 3;
24 19         88 $bytes .= "\0" x $npadbytes;
25 19         36 my $digits = '';
26 19         103 for (my $i = 0; $i < $nbytes; $i += 3) {
27 75         257 my $v = ord(substr $bytes, $i, 1) |
28             (ord(substr $bytes, $i + 1, 1) << 8) |
29             (ord(substr $bytes, $i + 2, 1) << 16);
30 75         349 $digits .= substr($base64_digits, $v & 0x3f, 1) .
31             substr($base64_digits, ($v >> 6) & 0x3f, 1) .
32             substr($base64_digits, ($v >> 12) & 0x3f, 1) .
33             substr($base64_digits, ($v >> 18) & 0x3f, 1);
34             }
35 19         59 substr $digits, -$npadbytes, $npadbytes, '';
36 19         62 return $digits;
37             }
38              
39             sub decode_crypt64 {
40 3     3 1 1266 my $digits = shift;
41 3         9 my $ndigits = length($digits);
42 3         7 my $npadbytes = 3 - ($ndigits + 3) % 4;
43 3         9 $digits .= '.' x $npadbytes;
44 3         6 my $bytes = '';
45 3         12 for(my $i = 0; $i < $ndigits; $i += 4) {
46 11         49 my $v = index($base64_digits, substr $digits, $i, 1) |
47             (index($base64_digits, substr $digits, $i + 1, 1) << 6) |
48             (index($base64_digits, substr $digits, $i + 2, 1) << 12) |
49             (index($base64_digits, substr $digits, $i + 3, 1) << 18);
50 11         43 $bytes .= chr($v & 0xff) . chr(($v >> 8) & 0xff) . chr(($v >> 16) & 0xff);
51             }
52 3         8 substr $bytes, -$npadbytes, $npadbytes, '';
53 3         12 return $bytes;
54             }
55              
56             sub encode_crypt64_number {
57 7     7 0 3608 my ($input, $length) = @_;
58 7         43 my $output = '';
59 7         26 for (1 .. $length) {
60 27         51 my $remainder = $input % 64;
61 27         53 $output .= substr $base64_digits, $remainder, 1;
62 27         115 $input = int($input / 64);
63             }
64 7 50       50 croak "Number doesn't fit in $length characters" if $input != 0;
65 7         31 return $output;
66             }
67              
68             sub decode_crypt64_number {
69 6     6 1 2834 my $input = shift;
70 6         18 my $result = 0;
71 6         19 for (0 .. length($input) - 1) {
72 22         59 $result += index($base64_digits, substr $input, $_, 1) * (1 << (6 * $_));
73             }
74 6         19 return $result;
75             }
76              
77             1;
78              
79             # ABSTRACT: An implementation of the crypt64 encoding
80              
81             __END__