File Coverage

blib/lib/Crypt/RSA/DataFormat.pm
Criterion Covered Total %
statement 78 83 93.9
branch 22 26 84.6
condition 3 3 100.0
subroutine 16 17 94.1
pod 8 9 88.8
total 127 138 92.0


line stmt bran cond sub pod time code
1             package Crypt::RSA::DataFormat;
2 17     17   55151 use strict;
  17         37  
  17         419  
3 17     17   85 use warnings;
  17         80  
  17         421  
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 17     17   77 use vars qw(@ISA);
  17         52  
  17         718  
13 17     17   14695 use Math::BigInt try => 'GMP, Pari';
  17         332455  
  17         92  
14 17     17   308152 use Math::Prime::Util qw/random_bytes/;
  17         35763  
  17         133  
15 17     17   9136 use Digest::SHA qw(sha1);
  17         35355  
  17         1105  
16 17     17   123 use Carp;
  17         45  
  17         797  
17              
18 17     17   96 use base qw(Exporter);
  17         35  
  17         11257  
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 2216     2216 1 13539 my ($num, $l) = @_;
25 2216 50       5434 $num = 0 if !defined $num;
26 2216 100       5065 $l = 0 if !defined $l;
27 2216         3600 my $result;
28              
29 2216 100 100     10215 if (ref($num) ne 'Math::BigInt' && $num <= ~0) {
30 1622         2776 $result = '';
31 1622         2388 do {
32 1625         3925 $result = chr($num & 0xFF) . $result;
33 1625         4306 $num >>= 8;
34             } while $num;
35             } else {
36 594 100       2168 $num = Math::BigInt->new("$num") unless ref($num) eq 'Math::BigInt';
37 594         3107 my $hex = $num->as_hex;
38             # Remove the 0x and any leading zeros (shouldn't be any)
39 594         1195281 $hex =~ s/^0x0*//;
40             # Add a leading zero if needed to line up bytes correctly.
41 594 100       2668 substr($hex, 0, 0, '0') if length($hex) % 2;
42             # Pack hex string into a octet string.
43 594         3655 $result = pack("H*", $hex);
44             }
45              
46 2216 100       5217 if ($l) {
47 2206         3566 my $rlen = length($result);
48             # Return undef if too large to fit
49 2206 100       4954 return if $l < $rlen;
50             # Zero pad the front if they want a longer string
51 2201 100       6370 substr( $result, 0, 0, chr(0) x ($l-$rlen) ) if $rlen < $l;
52             }
53 2211         12110 return $result;
54             }
55              
56              
57             sub os2ip {
58 597     597 1 2139 my $string = shift;
59 597         2296 my($hex) = unpack('H*', $string);
60 597         4148 return Math::BigInt->new("0x$hex");
61             }
62              
63              
64             sub h2osp {
65 36     36 1 425 my $hex = shift;
66 36         359 $hex =~ s/\s//g;
67 36         89 $hex =~ s/^0x0*//;
68             # Add a leading zero if needed to line up bytes correctly.
69 36 50       122 substr($hex, 0, 0, '0') if length($hex) % 2;
70             # Pack into a string.
71 36         183 my $result = pack("H*", $hex);
72 36         113 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 1187     1187 1 14018 my $n = shift;
84 1187         2347 my $bits = 0;
85 1187 50       3582 if (ref($n) eq 'Math::BigInt') {
86 1187         4773 $bits = length($n->as_bin) - 2;
87             } else {
88 0         0 while ($n) { $bits++; $n >>= 1; }
  0         0  
  0         0  
89             }
90 1187         2388744 $bits;
91             }
92              
93              
94             sub octet_len {
95 600     600 1 2046 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 1055     1055 1 2560 my ($a, $b) = @_;
102              
103             # Ensure length($a) >= length($b)
104 1055 50       3294 ($a, $b) = ($b, $a) if length($b) > length($a);
105 1055         1888 my $alen = length($a);
106             # Prepend null bytes to the beginning of $b to make the lengths equal
107 1055 100       2840 substr($b, 0, 0, chr(0) x ($alen-length($b))) if $alen > length($b);
108              
109             # xor all bytes
110 1055         1814 my $r = '';
111 1055         12769 $r .= chr( ord(substr($a,$_,1)) ^ ord(substr($b,$_,1)) ) for 0 .. $alen-1;
112 1055         3045 return $r;
113             }
114              
115              
116             # http://rfc-ref.org/RFC-TEXTS/3447/chapter11.html
117             sub mgf1 {
118 1052     1052 0 2738 my ($seed, $l) = @_;
119 1052         1761 my $hlen = 20; # SHA-1 is 160 bits
120 1052         2910 my $imax = int(($l + $hlen - 1) / $hlen) - 1;
121 1052         1848 my $T = "";
122 1052         2645 foreach my $i (0 .. $imax) {
123 1620         3770 $T .= sha1($seed . i2osp ($i, 4));
124             }
125 1052         3893 my ($output) = unpack "a$l", $T;
126 1052         3494 return $output;
127             }
128              
129              
130             sub steak {
131 2     2 1 7 my ($text, $blocksize) = @_;
132 2         5 my $textsize = length($text);
133 2 100       10 my $chunkcount = $textsize % $blocksize
134             ? int($textsize/$blocksize) + 1 : $textsize/$blocksize;
135 2         142 my @segments = unpack "a$blocksize"x$chunkcount, $text;
136 2         82 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