File Coverage

blib/lib/Crypt/RSA/DataFormat.pm
Criterion Covered Total %
statement 73 83 87.9
branch 19 26 73.0
condition 3 3 100.0
subroutine 15 17 88.2
pod 8 9 88.8
total 118 138 85.5


line stmt bran cond sub pod time code
1             package Crypt::RSA::DataFormat;
2 9     9   79247 use strict;
  9         37  
  9         231  
3 9     9   44 use warnings;
  9         14  
  9         289  
4              
5             ## Crypt::RSA::DataFormat -- Functions for converting, shaping and
6             ## creating and reporting data formats.
7             ##
8             ## Copyright (c) 2001, Vipul Ved Prakash. All rights reserved.
9             ## This code is free software; you can redistribute it and/or modify
10             ## it under the same terms as Perl itself.
11              
12 9     9   38 use vars qw(@ISA);
  9         34  
  9         716  
13 9     9   525724 use Math::BigInt try => 'GMP, Pari';
  9         259160  
  9         54  
14 9     9   1023940 use Bytes::Random::Secure qw/random_bytes/;
  9         63509  
  9         597  
15 9     9   7847 use Digest::SHA qw(sha1);
  9         26949  
  9         702  
16 9     9   62 use Carp;
  9         17  
  9         546  
17              
18 9     9   43 use base qw(Exporter);
  9         19  
  9         8521  
19             our @EXPORT_OK = qw(i2osp os2ip h2osp octet_xor octet_len bitsize
20             generate_random_octet mgf1 steak);
21              
22              
23             sub i2osp {
24 50     50 1 6544 my ($num, $l) = @_;
25 50 50       122 $num = 0 if !defined $num;
26 50 100       142 $l = 0 if !defined $l;
27 50         66 my $result;
28              
29 50 100 100     281 if (ref($num) ne 'Math::BigInt' && $num <= ~0) {
30 32         47 $result = '';
31 32         34 do {
32 35         79 $result = chr($num & 0xFF) . $result;
33 35         108 $num >>= 8;
34             } while $num;
35             } else {
36 18 100       64 $num = Math::BigInt->new("$num") unless ref($num) eq 'Math::BigInt';
37 18         207 my $hex = $num->as_hex;
38             # Remove the 0x and any leading zeros (shouldn't be any)
39 18         33986 $hex =~ s/^0x0*//;
40             # Add a leading zero if needed to line up bytes correctly.
41 18 100       71 substr($hex, 0, 0, '0') if length($hex) % 2;
42             # Pack hex string into a octet string.
43 18         114 $result = pack("H*", $hex);
44             }
45              
46 50 100       249 if ($l) {
47 46         70 my $rlen = length($result);
48             # Return undef if too large to fit
49 46 50       88 return if $l < $rlen;
50             # Zero pad the front if they want a longer string
51 46 100       130 substr( $result, 0, 0, chr(0) x ($l-$rlen) ) if $rlen < $l;
52             }
53 50         277 return $result;
54             }
55              
56              
57             sub os2ip {
58 19     19 1 733 my $string = shift;
59 19         85 my($hex) = unpack('H*', $string);
60 19         201 return Math::BigInt->new("0x$hex");
61             }
62              
63              
64             sub h2osp {
65 1     1 1 751 my $hex = shift;
66 1         12 $hex =~ s/\s//g;
67 1         4 $hex =~ s/^0x0*//;
68             # Add a leading zero if needed to line up bytes correctly.
69 1 50       5 substr($hex, 0, 0, '0') if length($hex) % 2;
70             # Pack into a string.
71 1         7 my $result = pack("H*", $hex);
72 1         5 return $result;
73             }
74              
75              
76             sub generate_random_octet {
77 0     0 1 0 my $l = shift; # Ignore the strength parameter, if any
78 0         0 return random_bytes($l);
79             }
80              
81              
82             sub bitsize {
83 30     30 1 49 my $n = shift;
84 30         40 my $bits = 0;
85 30 50       89 if (ref($n) eq 'Math::BigInt') {
86 30         123 $bits = length($n->as_bin) - 2;
87             } else {
88 0         0 while ($n) { $bits++; $n >>= 1; }
  0         0  
  0         0  
89             }
90 30         50598 $bits;
91             }
92              
93              
94             sub octet_len {
95 20     20 1 71 return int( (bitsize(shift) + 7) / 8 );
96             }
97              
98              
99             # This could be made even faster doing 4 bytes at a time
100             sub octet_xor {
101 13     13 1 727 my ($a, $b) = @_;
102              
103             # Ensure length($a) >= length($b)
104 13 50       34 ($a, $b) = ($b, $a) if length($b) > length($a);
105 13         16 my $alen = length($a);
106             # Prepend null bytes to the beginning of $b to make the lengths equal
107 13 100       38 substr($b, 0, 0, chr(0) x ($alen-length($b))) if $alen > length($b);
108              
109             # xor all bytes
110 13         19 my $r = '';
111 13         411 $r .= chr( ord(substr($a,$_,1)) ^ ord(substr($b,$_,1)) ) for 0 .. $alen-1;
112 13         40 return $r;
113             }
114              
115              
116             # http://rfc-ref.org/RFC-TEXTS/3447/chapter11.html
117             sub mgf1 {
118 10     10 0 21 my ($seed, $l) = @_;
119 10         19 my $hlen = 20; # SHA-1 is 160 bits
120 10         29 my $imax = int(($l + $hlen - 1) / $hlen) - 1;
121 10         15 my $T = "";
122 10         24 foreach my $i (0 .. $imax) {
123 30         65 $T .= sha1($seed . i2osp ($i, 4));
124             }
125 10         37 my ($output) = unpack "a$l", $T;
126 10         38 return $output;
127             }
128              
129              
130             sub steak {
131 0     0 1   my ($text, $blocksize) = @_;
132 0           my $textsize = length($text);
133 0 0         my $chunkcount = $textsize % $blocksize
134             ? int($textsize/$blocksize) + 1 : $textsize/$blocksize;
135 0           my @segments = unpack "a$blocksize"x$chunkcount, $text;
136 0           return @segments;
137             }
138              
139             1;
140              
141             =head1 NAME
142              
143             Crypt::RSA::DataFormat - Data creation, conversion and reporting primitives.
144              
145             =head1 DESCRIPTION
146              
147             This module implements several data creation, conversion and reporting
148             primitives used throughout the Crypt::RSA implementation. Primitives are
149             available as exportable functions.
150              
151             =head1 FUNCTIONS
152              
153             =over 4
154              
155             =item B Integer, Length
156              
157             Integer To Octet String Primitive. Converts an integer into its
158             equivalent octet string representation of length B. If
159             necessary, the resulting string is prefixed with nulls. If
160             B is not provided, returns an octet string of shortest
161             possible length.
162              
163             =item B Hex String
164              
165             Hex To Octet String Primitive. Converts a I into its
166             equivalent octet string representation and returns an octet
167             string of shortest possible length. The hex string is not
168             prefixed with C<0x>, etc.
169              
170             =item B String
171              
172             Octet String to Integer Primitive. Converts an octet string into its
173             equivalent integer representation.
174              
175             =item B Length
176              
177             Generates a random octet string of length B.
178              
179             =item B Integer
180              
181             Returns the length of the B in bits.
182              
183             =item B Integer
184              
185             Returns the octet length of the integer. If the length is not a whole
186             number, the fractional part is dropped to make it whole.
187              
188             =item B String1, String2
189              
190             Returns the result of B XOR B.
191              
192             =item B String, Length
193              
194             Returns an array of segments of length B from B. The final
195             segment can be smaller than B.
196              
197             =back
198              
199             =head1 AUTHOR
200              
201             Vipul Ved Prakash, Email@vipul.netE
202              
203             =cut
204              
205