File Coverage

blib/lib/Crypt/Rhash.pm
Criterion Covered Total %
statement 184 194 94.8
branch 14 34 41.1
condition 5 10 50.0
subroutine 58 60 96.6
pod 14 16 87.5
total 275 314 87.5


line stmt bran cond sub pod time code
1             package Crypt::Rhash;
2              
3 3     3   220009 use 5.006001;
  3         30  
4 3     3   17 use strict;
  3         5  
  3         78  
5 3     3   17 use warnings;
  3         5  
  3         494  
6              
7             require Exporter;
8             our @ISA = (qw(Exporter));
9              
10             # possible tags for export
11             our %EXPORT_TAGS = (
12             Functions => [qw(raw2hex raw2base32 raw2base64)],
13             Constants => [qw(RHASH_CRC32 RHASH_CRC32C RHASH_MD4 RHASH_MD5
14             RHASH_SHA1 RHASH_TIGER RHASH_TTH RHASH_BTIH RHASH_ED2K
15             RHASH_AICH RHASH_WHIRLPOOL RHASH_RIPEMD160 RHASH_GOST94
16             RHASH_GOST94_CRYPTOPRO RHASH_GOST12_256 RHASH_GOST12_512
17             RHASH_SHA224 RHASH_SHA256 RHASH_SHA384 RHASH_SHA512
18             RHASH_SHA3_224 RHASH_SHA3_256 RHASH_SHA3_384 RHASH_SHA3_512
19             RHASH_BLAKE2S RHASH_BLAKE2B RHASH_EDONR256 RHASH_EDONR512
20             RHASH_HAS160 RHASH_SNEFRU128 RHASH_SNEFRU256 RHASH_ALL)]
21             );
22              
23             Exporter::export_tags( );
24             Exporter::export_ok_tags( qw(Functions Constants) );
25              
26             our $VERSION = '1.00';
27              
28             require XSLoader;
29             XSLoader::load('Crypt::Rhash', $VERSION);
30              
31             ##############################################################################
32             # ids of hash functions
33 3     3   22 use constant RHASH_CRC32 => 0x01;
  3         5  
  3         345  
34 3     3   22 use constant RHASH_MD4 => 0x02;
  3         6  
  3         144  
35 3     3   17 use constant RHASH_MD5 => 0x04;
  3         5  
  3         151  
36 3     3   18 use constant RHASH_SHA1 => 0x08;
  3         6  
  3         159  
37 3     3   20 use constant RHASH_TIGER => 0x10;
  3         3  
  3         156  
38 3     3   17 use constant RHASH_TTH => 0x20;
  3         15  
  3         173  
39 3     3   25 use constant RHASH_BTIH => 0x40;
  3         6  
  3         170  
40 3     3   19 use constant RHASH_ED2K => 0x80;
  3         8  
  3         150  
41 3     3   16 use constant RHASH_AICH => 0x100;
  3         5  
  3         171  
42 3     3   21 use constant RHASH_WHIRLPOOL => 0x200;
  3         4  
  3         122  
43 3     3   29 use constant RHASH_RIPEMD160 => 0x400;
  3         19  
  3         269  
44 3     3   21 use constant RHASH_GOST94 => 0x800;
  3         5  
  3         160  
45 3     3   20 use constant RHASH_GOST94_CRYPTOPRO => 0x1000;
  3         6  
  3         190  
46 3     3   21 use constant RHASH_HAS160 => 0x2000;
  3         5  
  3         179  
47 3     3   19 use constant RHASH_GOST12_256 => 0x4000;
  3         5  
  3         163  
48 3     3   23 use constant RHASH_GOST12_512 => 0x8000;
  3         6  
  3         136  
49 3     3   15 use constant RHASH_SHA224 => 0x10000;
  3         6  
  3         142  
50 3     3   19 use constant RHASH_SHA256 => 0x20000;
  3         5  
  3         119  
51 3     3   15 use constant RHASH_SHA384 => 0x40000;
  3         5  
  3         196  
52 3     3   24 use constant RHASH_SHA512 => 0x80000;
  3         5  
  3         142  
53 3     3   17 use constant RHASH_EDONR256 => 0x100000;
  3         5  
  3         123  
54 3     3   17 use constant RHASH_EDONR512 => 0x200000;
  3         13  
  3         191  
55 3     3   18 use constant RHASH_SHA3_224 => 0x0400000;
  3         5  
  3         159  
56 3     3   28 use constant RHASH_SHA3_256 => 0x0800000;
  3         5  
  3         151  
57 3     3   17 use constant RHASH_SHA3_384 => 0x1000000;
  3         16  
  3         141  
58 3     3   18 use constant RHASH_SHA3_512 => 0x2000000;
  3         6  
  3         137  
59 3     3   18 use constant RHASH_CRC32C => 0x4000000;
  3         6  
  3         126  
60 3     3   18 use constant RHASH_SNEFRU128 => 0x8000000;
  3         29  
  3         157  
61 3     3   19 use constant RHASH_SNEFRU256 => 0x10000000;
  3         6  
  3         154  
62 3     3   25 use constant RHASH_BLAKE2S => 0x20000000;
  3         7  
  3         147  
63 3     3   18 use constant RHASH_BLAKE2B => 0x40000000;
  3         5  
  3         146  
64 3     3   40 use constant RHASH_ALL => 0x7FFFFFFF;
  3         8  
  3         2224  
65              
66             ##############################################################################
67             # Rhash class methods
68              
69             # Rhash object constructor
70             sub new($$@)
71             {
72 5     5 0 365 my $hash_id = 0;
73 5         12 shift;
74 5 50       21 scalar(@_) > 0 or die "hash_id not specified";
75 5         15 for my $id (@_) {
76 5         9 $hash_id |= scalar($id);
77 5 50 33     33 if(!scalar($id) || (scalar($id) & RHASH_ALL) != $id) {
78 0         0 die "bad hash_id = " . scalar($id);
79             }
80             }
81 5 50       121 my $context = rhash_init($hash_id) or return undef;
82 5         19 my $self = {
83             context => $context,
84             };
85 5         22 return bless $self;
86             }
87              
88             # destructor
89             sub DESTROY($)
90             {
91 3     3   6 my $self = shift;
92             # the 'if' added as workaround for perl 'global destruction' bug
93             # ($self->{context} can disappear on global destruction)
94 3 50       26 rhash_free($self->{context}) if $self->{context};
95             }
96              
97             sub update($$)
98             {
99 4     4 1 19 my $self = shift;
100 4         10 my $message = shift;
101 4         75 rhash_update($self->{context}, $message);
102 4         18 return $self;
103             }
104              
105             sub update_fd($$;$$)
106             {
107 3     3 1 9 my ($self, $fd, $start, $size) = @_;
108 3         6 my $res = 0;
109 3         4 my $num = 0;
110              
111 3         8 binmode($fd);
112 3 100       9 if(defined($start)) {
113 1 50       13 seek($fd, scalar($start), 0) or return undef;
114             }
115              
116 3         6 my $data;
117 3 100       8 if(defined($size)) {
118 1         4 for(my $left = scalar($size); $left > 0; $left -= 8192) {
119 1 50       24 ($res = read($fd, $data,
    50          
120             ($left < 8192 ? $left : 8192))) || last;
121 1         7 rhash_update($self->{context}, $data);
122 1         4 $num += $res;
123             }
124             } else {
125 2         46 while( ($res = read($fd, $data, 8192)) ) {
126 2         12 rhash_update($self->{context}, $data);
127 2         7 $num += $res;
128             }
129             }
130              
131 3 50       14 return (defined($res) ? $num : undef); # return undef on read error
132             }
133              
134             sub update_file($$;$$)
135             {
136 2     2 1 10 my ($self, $file, $start, $size) = @_;
137 2 50       78 open(my $fd, "<", $file) or return undef;
138 2         11 my $res = $self->update_fd($fd, $start, $size);
139 2         23 close($fd);
140 2         17 return $res;
141             }
142              
143             sub final($)
144             {
145 3     3 1 6 my $self = shift;
146 3         444 rhash_final($self->{context});
147 3         12 return $self;
148             }
149              
150             sub reset($)
151             {
152 3     3 1 8 my $self = shift;
153 3         14 rhash_reset($self->{context});
154 3         11 return $self;
155             }
156              
157             sub hashed_length($)
158             {
159 1     1 1 3 my $self = shift;
160 1         9 return rhash_get_hashed_length($self->{context});
161             }
162              
163             sub hash_id($)
164             {
165 1     1 1 23 my $self = shift;
166 1         16 return rhash_get_hash_id($self->{context});
167             }
168              
169             ##############################################################################
170             # Message digest formatting functions
171              
172             # printing constants
173 3     3   24 use constant RHPR_DEFAULT => 0x0;
  3         5  
  3         184  
174 3     3   19 use constant RHPR_RAW => 0x1;
  3         5  
  3         170  
175 3     3   20 use constant RHPR_HEX => 0x2;
  3         5  
  3         156  
176 3     3   17 use constant RHPR_BASE32 => 0x3;
  3         7  
  3         133  
177 3     3   18 use constant RHPR_BASE64 => 0x4;
  3         4  
  3         151  
178 3     3   18 use constant RHPR_UPPERCASE => 0x8;
  3         10  
  3         152  
179 3     3   19 use constant RHPR_REVERSE => 0x10;
  3         5  
  3         2082  
180              
181             sub hash($;$$)
182             {
183 42     42 1 86 my $self = shift;
184 42   100     109 my $hash_id = scalar(shift) || 0;
185 42   100     132 my $print_flags = scalar(shift) || RHPR_DEFAULT;
186 42         435 return rhash_print($self->{context}, $hash_id, $print_flags);
187             }
188              
189             sub hash_base32($;$)
190             {
191 1     1 1 4 hash($_[0], $_[1], RHPR_BASE32);
192             }
193              
194             sub hash_base64($;$)
195             {
196 0     0 1 0 hash($_[0], $_[1], RHPR_BASE64);
197             }
198              
199             sub hash_hex($;$)
200             {
201 2     2 1 8 hash($_[0], $_[1], RHPR_HEX);
202             }
203              
204             sub hash_rhex($;$)
205             {
206 1     1 1 5 hash($_[0], $_[1], RHPR_HEX | RHPR_REVERSE);
207             }
208              
209             sub hash_raw($;$)
210             {
211 1     1 0 4 hash($_[0], $_[1], RHPR_RAW);
212             }
213              
214             sub magnet_link($;$$)
215             {
216 3     3 1 10 my ($self, $filename, $hash_mask) = @_;
217 3         43 return rhash_print_magnet($self->{context}, $filename, $hash_mask);
218             }
219              
220             our $AUTOLOAD;
221              
222             # report error if a script called unexisting method/field
223             sub AUTOLOAD
224             {
225 0     0   0 my ($self, $field, $type, $pkg) = ($_[0], $AUTOLOAD, undef, __PACKAGE__);
226 0         0 $field =~ s/.*://;
227 0 0       0 die "function $field does not exist" if $field =~ /^(rhash_|raw2)/;
228 0 0       0 die "no arguments specified to $field()" if !@_;
229 0 0       0 die "the $field() argument is undefined" if !defined $self;
230              
231 0 0 0     0 ($type = ref($self)) && $type eq $pkg || die "the $field() argument is not a $pkg reference";
232 0 0       0 my $text = (exists $self->{$field} ? "is not accessible" : "does not exist");
233 0         0 die "the method $field() $text in the class $pkg";
234             }
235              
236             # static functions
237              
238             sub msg($$)
239             {
240 1     1 1 5469 my ($hash_id, $msg) = @_;
241 1         16 my $raw = rhash_msg_raw($hash_id, $msg); # get a binary message digest
242 1 50       13 return (is_base32($hash_id) ? raw2base32($raw) : raw2hex($raw));
243             }
244              
245             1;
246             __END__