File Coverage

blib/lib/Digest/SipHash/PP.pm
Criterion Covered Total %
statement 75 75 100.0
branch 2 2 100.0
condition 2 4 50.0
subroutine 17 17 100.0
pod 1 1 100.0
total 97 99 97.9


line stmt bran cond sub pod time code
1             package Digest::SipHash::PP;
2 1     1   71451 use strict;
  1         13  
  1         35  
3 1     1   5 use warnings;
  1         2  
  1         28  
4 1     1   1320 use Math::BigInt;
  1         29380  
  1         6  
5              
6             our $VERSION = sprintf "%d.%02d", q$Revision: 0.12 $ =~ /(\d+)/g;
7 1     1   25119 use base 'Exporter';
  1         2  
  1         157  
8             our @EXPORT_OK = qw/siphash siphash32/;
9              
10 1     1   8 use constant USE64BITINT => eval { pack 'Q', 1 };
  1         2  
  1         3  
  1         65  
11 1     1   7 use constant MASK64 => Math::BigInt->new('0xffff_ffff_ffff_ffff');
  1         2  
  1         8  
12              
13             push @EXPORT_OK, 'siphash64' if USE64BITINT;
14             our %EXPORT_TAGS = ( all => [@EXPORT_OK] );
15             our $DEFAULT_SEED = pack 'C16', map { int( rand(256) ) } ( 0 .. 0xF );
16              
17 32     32   104 sub _new { Math::BigInt->new(shift) }
18 16     16   54 sub _u64 { _new($_[1])->blsft(32)->bior($_[0]) }
19 128     128   393 sub _add { $_[0]->badd($_[1])->band(MASK64) }
20 176     176   3968 sub _xor { $_[0]->bxor($_[1]) }
21             sub _rot {
22 192     192   500 my $lo = $_[0]->copy->brsft(64 - $_[1]);
23 192         70175 $_[0]->blsft($_[1])->bior($lo)->band(MASK64);
24             }
25              
26             sub _compress {
27 32     32   23373 _add( $_[0], $_[1] );
28 32         17013 _add( $_[2], $_[3] );
29 32         16344 _rot( $_[1], 13 );
30 32         28910 _rot( $_[3], 16 );
31 32         28538 _xor( $_[1], $_[0] );
32 32         15228 _xor( $_[3], $_[2] );
33 32         15703 _rot( $_[0], 32 );
34 32         39701 _add( $_[2], $_[1] );
35 32         15481 _add( $_[0], $_[3] );
36 32         15432 _rot( $_[1], 17 );
37 32         38356 _rot( $_[3], 21 );
38 32         32025 _xor( $_[1], $_[2] );
39 32         15856 _xor( $_[3], $_[0] );
40 32         16291 _rot( $_[2], 32 );
41             }
42              
43             sub _digest {
44 1     1   1744 use bytes;
  1         15  
  1         6  
45 4   50 4   21 my $str = shift || '';
46 4   50     24 my $seed = shift || "\0" x 16;
47 4         27 my @k = unpack 'V4', $seed;
48 4         23 my $k0 = _u64( @k[ 0, 1 ] );
49 4         3004 my $k1 = _u64( @k[ 2, 3 ] );
50 4         3490 my $v0 = _new('0x736f6d6570736575');
51 4         1190 my $v1 = _new('0x646f72616e646f6d');
52 4         1051 my $v2 = _new('0x6c7967656e657261');
53 4         1006 my $v3 = _new('0x7465646279746573');
54 4         975 _xor( $v0, $k0 );
55 4         1791 _xor( $v1, $k1 );
56 4         1756 _xor( $v2, $k0 );
57 4         1563 _xor( $v3, $k1 );
58 4         2093 my $slen = length($str);
59 4         21 $str .= "\0" x ( 7 - $slen % 8 ) . chr( $slen % 256 );
60 4         20 my @u32 = unpack 'V*', $str;
61              
62 4         24 while ( my ( $lo, $hi ) = splice @u32, 0, 2 ) {
63 8         1943 my $u64 = _u64( $lo, $hi );
64 8         6676 _xor( $v3, $u64 );
65 8         3610 _compress( $v0, $v1, $v2, $v3 ) for 0 .. 1;
66 8         9600 _xor( $v0, $u64 );
67             }
68 4         1708 _xor( $v2, 0xff );
69 4         1175 _compress( $v0, $v1, $v2, $v3 ) for 0 .. 3;
70 4         5551 _xor( _xor( $v0, $v1 ), _xor( $v2, $v3 ) );
71             }
72              
73             sub siphash {
74 3     3 1 965 my $u64 = _digest(@_);
75 3         1399 my $lo = 0 + $u64->copy->band(0xffff_ffff);
76 3 100       1853 return $lo unless wantarray;
77 1         8 my $hi = 0 + $u64->brsft(32);
78 1         454 return ( $lo, $hi );
79             }
80              
81             *siphash32 = \&siphash;
82              
83             if (USE64BITINT) {
84             *siphash64 = sub {
85 1     1   388 use integer;
  1         3  
  1         6  
86 1     1   11286 0+_digest(@_);
87             };
88             }
89              
90             1;
91              
92             __END__