File Coverage

blib/lib/Crypt/OpenPGP/Util.pm
Criterion Covered Total %
statement 59 65 90.7
branch 19 24 79.1
condition 5 6 83.3
subroutine 15 15 100.0
pod 7 10 70.0
total 105 120 87.5


line stmt bran cond sub pod time code
1             package Crypt::OpenPGP::Util;
2 12     12   87274 use strict;
  12         20  
  12         449  
3              
4             # For some reason, FastCalc causes problems. Restrict to one of these 3 backends
5 12     12   11438 use Math::BigInt only => 'Pari,GMP,Calc';
  12         309098  
  12         71  
6              
7 12     12   274424 use vars qw( @EXPORT_OK @ISA );
  12         44  
  12         978  
8 12     12   67 use Exporter;
  12         21  
  12         11752  
9             @EXPORT_OK = qw( bitsize bin2bigint bin2mp bigint2bin mp2bin mod_exp mod_inverse
10             dash_escape dash_unescape canonical_text );
11             @ISA = qw( Exporter );
12              
13             sub bitsize {
14 112     112 1 14243 my $bigint = Math::BigInt->new($_[0]);
15 112         5646 return $bigint->bfloor($bigint->blog(2)) + 1;
16             }
17              
18 334 100   334 1 7634 sub bin2bigint { $_[0] ? Math::BigInt->new('0x' . unpack 'H*', $_[0]) : 0 }
19              
20             *bin2mp = \&bin2bigint;
21              
22             sub bigint2bin {
23 116     116 1 8243 my($p) = @_;
24            
25 116         420 $p = _ensure_bigint($p);
26            
27 116         296 my $base = _ensure_bigint(1) << _ensure_bigint(4*8);
28 116         25701 my $res = '';
29 116         395 while ($p != 0) {
30 2418         287504 my $r = $p % $base;
31 2418         946869 $p = ($p-$r) / $base;
32 2418         1210223 my $buf = pack 'N', $r;
33 2418 100       61750 if ($p == 0) {
34 114 100       13489 $buf = $r >= 16777216 ? $buf :
    100          
    100          
35             $r >= 65536 ? substr($buf, -3, 3) :
36             $r >= 256 ? substr($buf, -2, 2) :
37             substr($buf, -1, 1);
38             }
39 2418         317866 $res = $buf . $res;
40             }
41 116         13873 $res;
42             }
43              
44             *mp2bin = \&bigint2bin;
45              
46             sub mod_exp {
47 37     37 1 630 my($a, $exp, $n) = @_;
48            
49 37         149 $a = _ensure_bigint($a);
50            
51 37         180 $a->copy->bmodpow($exp, $n);
52             }
53              
54             sub mod_inverse {
55 13     13 1 1488 my($a, $n) = @_;
56            
57 13         75 $a = _ensure_bigint($a);
58              
59 13         78 $a->copy->bmodinv($n);
60             }
61              
62             sub dash_escape {
63 1     1 1 2 my($data) = @_;
64 1         4 $data =~ s/^-/- -/mg;
65 1         2 $data;
66             }
67              
68             sub dash_unescape {
69 1     1 0 2 my($data) = @_;
70 1         3 $data =~ s/^-\s//mg;
71 1         6 $data;
72             }
73              
74             sub canonical_text {
75 2     2 1 7 my($text) = @_;
76 2         12 my @lines = split /\n/, $text, -1;
77 2         9 for my $l (@lines) {
78             ## pgp2 and pgp5 do not trim trailing whitespace from "canonical text"
79             ## signatures, only from cleartext signatures.
80             ## See:
81             ## http://cert.uni-stuttgart.de/archive/ietf-openpgp/2000/01/msg00033.html
82 8 50       14 if ($Crypt::OpenPGP::Globals::Trim_trailing_ws) {
83 8         98 $l =~ s/[ \t\r\n]*$//;
84             } else {
85 0         0 $l =~ s/[\r\n]*$//;
86             }
87             }
88 2         21 join "\r\n", @lines;
89             }
90              
91              
92             sub _ensure_bigint {
93 398     398   610 my $num = shift;
94              
95 398 100 66     2008 if ($num && (! ref $num || ! $num->isa('Math::BigInt'))) {
      100        
96 292         824 $num = Math::BigInt->new($num);
97             }
98            
99 398         15967 return $num;
100             }
101              
102             sub get_random_bytes {
103 93     93 0 213 my $length = shift;
104 93 50       6075 if (eval 'require Crypt::Random; 1;') {
    50          
105 0         0 return Crypt::Random::makerandom_octet( Length => $length);
106             }
107             elsif (eval 'require Bytes::Random::Secure; 1;') {
108 93         405 return Bytes::Random::Secure::random_bytes($length);
109             }
110             else {
111 0         0 die "No random source available!";
112             }
113             }
114              
115             sub get_random_bigint {
116 23     23 0 17933 my $bits = shift;
117 23 50       1498 if (eval 'require Crypt::Random; 1;') {
    50          
118 0         0 my $pari = Crypt::Random::makerandom( Size => $bits, Strength => 0 );
119 0         0 return Math::BigInt->new($pari);
120             }
121             elsif (eval 'require Bytes::Random::Secure; 1;') {
122 23         153 my $hex = Bytes::Random::Secure::random_bytes_hex(int(($bits + 7) / 8));
123 23         1997 my $val = Math::BigInt->new("0x$hex");
124             # Get exactly the correct number of bits.
125 23 100       12415 $val->brsft(8 - ($bits & 7)) if ($bits & 7);
126             # Make sure the top bit is set.
127 23         4426 $val->bior(Math::BigInt->bone->blsft($bits-1));
128 23         29744 return $val;
129             }
130             else {
131 0           die "No random source available!";
132             }
133             }
134              
135             1;
136             __END__
137              
138             =head1 NAME
139              
140             Crypt::OpenPGP::Util - Miscellaneous utility functions
141              
142             =head1 DESCRIPTION
143              
144             I<Crypt::OpenPGP::Util> contains a set of exportable utility functions
145             used through the I<Crypt::OpenPGP> set of libraries.
146              
147             =head2 bitsize($n)
148              
149             Returns the number of bits in the I<Math::BigInt> integer object
150             I<$n>.
151              
152             =head2 bin2bigint($string)
153              
154             Given a string I<$string> of any length, treats the string as a
155             base-256 representation of an integer, and returns that integer,
156             a I<Math::BigInt> object.
157              
158             I<bin2mp> is an alias for this function, for backwards
159             compatibility reasons.
160              
161             =head2 bigint2bin($int)
162              
163             Given a biginteger I<$int> (a I<Math::BigInt> object), linearizes
164             the integer into an octet string, and returns the octet string.
165              
166             I<mp2bin> is an alias for this function, for backwards
167             compatibility reasons.
168              
169             =head2 mod_exp($a, $exp, $n)
170              
171             Computes $a ^ $exp mod $n and returns the value. The calculations
172             are done using I<Math::BigInt>, and the return value is a I<Math::BigInt>
173             object.
174              
175             =head2 mod_inverse($a, $n)
176              
177             Computes the multiplicative inverse of $a mod $n and returns the
178             value. The calculations are done using I<Math::BigInt>, and the
179             return value is a I<Math::BigInt> object.
180              
181             =head2 canonical_text($text)
182              
183             Takes a piece of text content I<$text> and formats it into PGP canonical
184             text, where: 1) all whitespace at the end of lines is stripped, and
185             2) all line endings are made up of a carriage return followed by a line
186             feed. Returns the canonical form of the text.
187              
188             =head2 dash_escape($text)
189              
190             Escapes I<$text> for use in a cleartext signature; the escaping looks
191             for any line starting with a dash, and on such lines prepends a dash
192             ('-') followed by a space (' '). Returns the escaped text.
193              
194             =head1 AUTHOR & COPYRIGHTS
195              
196             Please see the Crypt::OpenPGP manpage for author, copyright, and
197             license information.
198              
199             =cut