File Coverage

blib/lib/Digest/SHA3.pm
Criterion Covered Total %
statement 41 95 43.1
branch 15 60 25.0
condition 0 9 0.0
subroutine 9 13 69.2
pod 3 3 100.0
total 68 180 37.7


line stmt bran cond sub pod time code
1             package Digest::SHA3;
2              
3             require 5.003000;
4              
5 13     13   5479 use strict;
  13         82  
  13         316  
6 13     13   56 use warnings;
  13         20  
  13         425  
7 13     13   68 use vars qw($VERSION @ISA @EXPORT_OK $errmsg);
  13         22  
  13         894  
8 13     13   68 use Fcntl qw(O_RDONLY O_RDWR);
  13         35  
  13         728  
9 13     13   67 use Cwd qw(getcwd);
  13         21  
  13         614  
10 13     13   5571 use integer;
  13         154  
  13         56  
11              
12             $VERSION = '1.05';
13              
14             require Exporter;
15             @ISA = qw(Exporter);
16             @EXPORT_OK = qw(
17             $errmsg
18             shake128 shake128_base64 shake128_hex
19             shake256 shake256_base64 shake256_hex
20             sha3_224 sha3_224_base64 sha3_224_hex
21             sha3_256 sha3_256_base64 sha3_256_hex
22             sha3_384 sha3_384_base64 sha3_384_hex
23             sha3_512 sha3_512_base64 sha3_512_hex);
24              
25             # Inherit from Digest::base if possible
26              
27             eval {
28             require Digest::base;
29             push(@ISA, 'Digest::base');
30             };
31              
32             # The following routines aren't time-critical, so they can be left in Perl
33              
34             sub new {
35 18     18 1 1082 my($class, $alg) = @_;
36 18 100       62 $alg =~ s/\D+//g if defined $alg;
37 18 100       91 $alg =~ s/^3?(224|256|384|512|128000|256000)$/$1/ if defined $alg;
38 18 50       123 if (ref($class)) { # instance method
39 0 0 0     0 if (!defined($alg) || ($alg == $class->algorithm)) {
40 0         0 sharewind($class);
41 0         0 return($class);
42             }
43 0 0       0 return shainit($class, $alg) ? $class : undef;
44             }
45 18 100       37 $alg = 224 unless defined $alg;
46 18         126 return newSHA3($class, $alg);
47             }
48              
49 13     13   11978 BEGIN { *reset = \&new }
50              
51             sub add_bits {
52 23     23 1 246 my($self, $data, $nbits, $lsb) = @_;
53 23 100       45 if (defined $nbits) {
54 18         30 my $max = length($data) * 8;
55 18 50       46 $nbits = $max if $nbits > $max;
56             }
57 23 100       41 if ($lsb) {
58 17         111 shawrite($data, $nbits, $self);
59 17         140 return($self);
60             }
61 6 100       8 unless (defined $nbits) {
62 5         6 $nbits = length($data);
63 5         15 $data = pack("B*", $data);
64             }
65 6 50       12 if ($nbits % 8) {
66 6         13 my $b = unpack("C", substr($data, -1));
67 6         12 $b >>= (8 - $nbits % 8);
68 6         10 substr($data, -1) = pack("C", $b);
69             }
70 6         16 shawrite($data, $nbits, $self);
71 6         48 return($self);
72             }
73              
74             sub _bail {
75 0     0     my $msg = shift;
76              
77 0           $errmsg = $!;
78 0           $msg .= ": $!";
79 0           require Carp;
80 0           Carp::croak($msg);
81             }
82              
83             {
84             my $_can_T_filehandle;
85              
86             sub _istext {
87 0     0     local *FH = shift;
88 0           my $file = shift;
89              
90 0 0         if (! defined $_can_T_filehandle) {
91 0           local $^W = 0;
92 0           my $istext = eval { -T FH };
  0            
93 0 0         $_can_T_filehandle = $@ ? 0 : 1;
94 0 0         return $_can_T_filehandle ? $istext : -T $file;
95             }
96 0 0         return $_can_T_filehandle ? -T FH : -T $file;
97             }
98             }
99              
100             sub _addfile {
101 0     0     my ($self, $handle) = @_;
102              
103 0           my $n;
104 0           my $buf = "";
105              
106 0           while (($n = read($handle, $buf, 4096))) {
107 0           $self->add($buf);
108             }
109 0 0         _bail("Read failed") unless defined $n;
110              
111 0           $self;
112             }
113              
114             sub addfile {
115 0     0 1   my ($self, $file, $mode) = @_;
116              
117 0 0         return(_addfile($self, $file)) unless ref(\$file) eq 'SCALAR';
118              
119 0 0         $mode = defined($mode) ? $mode : "";
120             my ($binary, $UNIVERSAL, $BITS) =
121 0           map { $_ eq $mode } ("b", "U", "0");
  0            
122              
123             ## Always interpret "-" to mean STDIN; otherwise use
124             ## sysopen to handle full range of POSIX file names.
125             ## If $file is a directory, force an EISDIR error
126             ## by attempting to open with mode O_RDWR
127              
128 0           local *FH;
129 0 0         if ($file eq '-') {
130 0 0         if (-d STDIN) {
131 0 0         sysopen(FH, getcwd(), O_RDWR)
132             or _bail('Open failed');
133             }
134 0 0         open(FH, '< -')
135             or _bail('Open failed');
136             }
137             else {
138 0 0         sysopen(FH, $file, -d $file ? O_RDWR : O_RDONLY)
    0          
139             or _bail('Open failed');
140             }
141              
142 0 0         if ($BITS) {
143 0           my ($n, $buf, $bits) = (0, "", "");
144 0           while (($n = read(FH, $buf, 4096))) {
145 0           $buf =~ tr/01//cd;
146 0           $bits .= $buf;
147 0 0         if (length($bits) >= 4096) {
148 0           $self->add_bits(substr($bits, 0, 4096));
149 0           $bits = substr($bits, 4096);
150             }
151             }
152 0 0         $self->add_bits($bits) if length($bits) > 0;
153 0 0         _bail("Read failed") unless defined $n;
154 0           close(FH);
155 0           return($self);
156             }
157              
158 0 0 0       binmode(FH) if $binary || $UNIVERSAL;
159 0 0 0       if ($UNIVERSAL && _istext(*FH, $file)) {
160 0           $self->_addfileuniv(*FH);
161             }
162 0           else { $self->_addfilebin(*FH) }
163 0           close(FH);
164              
165 0           $self;
166             }
167              
168             eval {
169             require XSLoader;
170             XSLoader::load('Digest::SHA3', $VERSION);
171             1;
172             } or do {
173             require DynaLoader;
174             push @ISA, 'DynaLoader';
175             Digest::SHA3->bootstrap($VERSION);
176             };
177              
178             1;
179             __END__