| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
# Create a PGP signature for data, securely. |
|
2
|
|
|
|
|
|
|
# |
|
3
|
|
|
|
|
|
|
# THIS IS NOT A GENERAL PGP MODULE. |
|
4
|
|
|
|
|
|
|
# |
|
5
|
|
|
|
|
|
|
# For a general PGP module that handles encryption and decryption, key ring |
|
6
|
|
|
|
|
|
|
# management, and all of the other wonderful things you want to do with PGP, |
|
7
|
|
|
|
|
|
|
# see the PGP module directory on CPAN. This module is designed to do one and |
|
8
|
|
|
|
|
|
|
# only one thing and do it fast, well, and securely -- create and check |
|
9
|
|
|
|
|
|
|
# detached signatures for some block of data. |
|
10
|
|
|
|
|
|
|
# |
|
11
|
|
|
|
|
|
|
# This above all: to thine own self be true, |
|
12
|
|
|
|
|
|
|
# And it must follow, as the night the day, |
|
13
|
|
|
|
|
|
|
# Thou canst not then be false to any man. |
|
14
|
|
|
|
|
|
|
# -- William Shakespeare, _Hamlet_ |
|
15
|
|
|
|
|
|
|
# |
|
16
|
|
|
|
|
|
|
# SPDX-License-Identifier: GPL-1.0-or-later OR Artistic-1.0-Perl |
|
17
|
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
############################################################################## |
|
19
|
|
|
|
|
|
|
# Modules and declarations |
|
20
|
|
|
|
|
|
|
############################################################################## |
|
21
|
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
package PGP::Sign 1.03; |
|
23
|
|
|
|
|
|
|
|
|
24
|
5
|
|
|
5
|
|
1491555
|
use 5.020; |
|
|
5
|
|
|
|
|
81
|
|
|
25
|
5
|
|
|
5
|
|
43
|
use autodie; |
|
|
5
|
|
|
|
|
23
|
|
|
|
5
|
|
|
|
|
113
|
|
|
26
|
5
|
|
|
5
|
|
31153
|
use warnings; |
|
|
5
|
|
|
|
|
11
|
|
|
|
5
|
|
|
|
|
370
|
|
|
27
|
|
|
|
|
|
|
|
|
28
|
5
|
|
|
5
|
|
36
|
use Carp qw(croak); |
|
|
5
|
|
|
|
|
12
|
|
|
|
5
|
|
|
|
|
684
|
|
|
29
|
5
|
|
|
5
|
|
35
|
use Exporter qw(import); |
|
|
5
|
|
|
|
|
11
|
|
|
|
5
|
|
|
|
|
204
|
|
|
30
|
5
|
|
|
5
|
|
4072
|
use File::Temp (); |
|
|
5
|
|
|
|
|
71949
|
|
|
|
5
|
|
|
|
|
169
|
|
|
31
|
5
|
|
|
5
|
|
38
|
use IO::Handle; |
|
|
5
|
|
|
|
|
11
|
|
|
|
5
|
|
|
|
|
339
|
|
|
32
|
5
|
|
|
5
|
|
4751
|
use IPC::Run qw(finish run start timeout); |
|
|
5
|
|
|
|
|
132852
|
|
|
|
5
|
|
|
|
|
393
|
|
|
33
|
5
|
|
|
5
|
|
45
|
use Scalar::Util qw(blessed); |
|
|
5
|
|
|
|
|
12
|
|
|
|
5
|
|
|
|
|
11697
|
|
|
34
|
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
# Export pgp_sign and pgp_verify by default for backwards compatibility. |
|
36
|
|
|
|
|
|
|
## no critic (Modules::ProhibitAutomaticExportation) |
|
37
|
|
|
|
|
|
|
our @EXPORT = qw(pgp_sign pgp_verify); |
|
38
|
|
|
|
|
|
|
our @EXPORT_OK = qw(pgp_error); |
|
39
|
|
|
|
|
|
|
## use critic |
|
40
|
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
# The flags to use with the various PGP styles. |
|
42
|
|
|
|
|
|
|
my %SIGN_FLAGS = ( |
|
43
|
|
|
|
|
|
|
GPG => [ |
|
44
|
|
|
|
|
|
|
qw( |
|
45
|
|
|
|
|
|
|
--detach-sign --armor |
|
46
|
|
|
|
|
|
|
--quiet --textmode --batch --no-tty --pinentry-mode=loopback |
|
47
|
|
|
|
|
|
|
--no-greeting --no-permission-warning |
|
48
|
|
|
|
|
|
|
), |
|
49
|
|
|
|
|
|
|
], |
|
50
|
|
|
|
|
|
|
GPG1 => [ |
|
51
|
|
|
|
|
|
|
qw( |
|
52
|
|
|
|
|
|
|
--detach-sign --armor |
|
53
|
|
|
|
|
|
|
--quiet --textmode --batch --no-tty --no-use-agent |
|
54
|
|
|
|
|
|
|
--no-greeting --no-permission-warning |
|
55
|
|
|
|
|
|
|
--force-v3-sigs --allow-weak-digest-algos |
|
56
|
|
|
|
|
|
|
), |
|
57
|
|
|
|
|
|
|
], |
|
58
|
|
|
|
|
|
|
); |
|
59
|
|
|
|
|
|
|
my %VERIFY_FLAGS = ( |
|
60
|
|
|
|
|
|
|
GPG => [ |
|
61
|
|
|
|
|
|
|
qw( |
|
62
|
|
|
|
|
|
|
--verify |
|
63
|
|
|
|
|
|
|
--quiet --batch --no-tty |
|
64
|
|
|
|
|
|
|
--no-greeting --no-permission-warning |
|
65
|
|
|
|
|
|
|
--no-auto-key-retrieve --no-auto-check-trustdb |
|
66
|
|
|
|
|
|
|
--allow-weak-digest-algos |
|
67
|
|
|
|
|
|
|
--disable-dirmngr |
|
68
|
|
|
|
|
|
|
), |
|
69
|
|
|
|
|
|
|
], |
|
70
|
|
|
|
|
|
|
GPG1 => [ |
|
71
|
|
|
|
|
|
|
qw( |
|
72
|
|
|
|
|
|
|
--verify |
|
73
|
|
|
|
|
|
|
--quiet --batch --no-tty |
|
74
|
|
|
|
|
|
|
--no-greeting --no-permission-warning |
|
75
|
|
|
|
|
|
|
--no-auto-key-retrieve --no-auto-check-trustdb |
|
76
|
|
|
|
|
|
|
--allow-weak-digest-algos |
|
77
|
|
|
|
|
|
|
), |
|
78
|
|
|
|
|
|
|
], |
|
79
|
|
|
|
|
|
|
); |
|
80
|
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
############################################################################## |
|
82
|
|
|
|
|
|
|
# Old global variables |
|
83
|
|
|
|
|
|
|
############################################################################## |
|
84
|
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
# These variables are part of the legacy PGP::Sign interface and are |
|
86
|
|
|
|
|
|
|
# maintained for backward compatibility. They are only used by the legacy |
|
87
|
|
|
|
|
|
|
# pgp_sign and pgp_verify functions, not by the new object-oriented API. |
|
88
|
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
# Whether or not to perform some standard whitespace munging to make other |
|
90
|
|
|
|
|
|
|
# signing and checking routines happy. |
|
91
|
|
|
|
|
|
|
our $MUNGE = 0; |
|
92
|
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
# The default path to PGP. PGPS is for signing, PGPV is for verifying. |
|
94
|
|
|
|
|
|
|
# (There's no reason to use separate commands any more, but with PGPv5 these |
|
95
|
|
|
|
|
|
|
# were two different commands, so this became part of the legacy API.) |
|
96
|
|
|
|
|
|
|
our $PGPS; |
|
97
|
|
|
|
|
|
|
our $PGPV; |
|
98
|
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
# The path to the directory containing the key ring. If not set, defaults to |
|
100
|
|
|
|
|
|
|
# $ENV{GNUPGHOME} or $HOME/.gnupg. |
|
101
|
|
|
|
|
|
|
our $PGPPATH; |
|
102
|
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
# What style of PGP invocation to use by default. If not set, defaults to the |
|
104
|
|
|
|
|
|
|
# default style for the object-oriented API. |
|
105
|
|
|
|
|
|
|
our $PGPSTYLE; |
|
106
|
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
# The directory in which temporary files should be created. If not set, |
|
108
|
|
|
|
|
|
|
# defaults to whatever File::Temp decides to use. |
|
109
|
|
|
|
|
|
|
our $TMPDIR; |
|
110
|
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
# Used by pgp_sign and pgp_verify to store errors returned by the |
|
112
|
|
|
|
|
|
|
# object-oriented API so that they can be returned via pgp_error. |
|
113
|
|
|
|
|
|
|
my @ERROR = (); |
|
114
|
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
############################################################################## |
|
116
|
|
|
|
|
|
|
# Utility functions |
|
117
|
|
|
|
|
|
|
############################################################################## |
|
118
|
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
# print with error checking and an explicit file handle. autodie |
|
120
|
|
|
|
|
|
|
# unfortunately can't help us with these because they can't be prototyped and |
|
121
|
|
|
|
|
|
|
# hence can't be overridden. |
|
122
|
|
|
|
|
|
|
# |
|
123
|
|
|
|
|
|
|
# $fh - Output file handle |
|
124
|
|
|
|
|
|
|
# @args - Remaining arguments to print |
|
125
|
|
|
|
|
|
|
# |
|
126
|
|
|
|
|
|
|
# Returns: undef |
|
127
|
|
|
|
|
|
|
# Throws: Text exception on output failure |
|
128
|
|
|
|
|
|
|
sub _print_fh { |
|
129
|
709
|
|
|
709
|
|
1379
|
my ($fh, @args) = @_; |
|
130
|
709
|
50
|
|
|
|
937
|
print {$fh} @args or croak("print failed: $!"); |
|
|
709
|
|
|
|
|
2075
|
|
|
131
|
709
|
|
|
|
|
1222
|
return; |
|
132
|
|
|
|
|
|
|
} |
|
133
|
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
############################################################################## |
|
135
|
|
|
|
|
|
|
# Object-oriented interface |
|
136
|
|
|
|
|
|
|
############################################################################## |
|
137
|
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
# Create a new PGP::Sign object encapsulating the configuration. |
|
139
|
|
|
|
|
|
|
# |
|
140
|
|
|
|
|
|
|
# $args_ref - Anonymous hash of arguments with the following keys: |
|
141
|
|
|
|
|
|
|
# home - Path to the GnuPG homedir containing keyrings |
|
142
|
|
|
|
|
|
|
# munge - Boolean indicating whether to munge whitespace |
|
143
|
|
|
|
|
|
|
# path - Path to the GnuPG binary to use |
|
144
|
|
|
|
|
|
|
# style - Style of OpenPGP backend to use |
|
145
|
|
|
|
|
|
|
# tmpdir - Directory to use for temporary files |
|
146
|
|
|
|
|
|
|
# |
|
147
|
|
|
|
|
|
|
# Returns: Newly created object |
|
148
|
|
|
|
|
|
|
# Throws: Text exception for an invalid OpenPGP backend style |
|
149
|
|
|
|
|
|
|
sub new { |
|
150
|
19
|
|
|
19
|
1
|
18928
|
my ($class, $args_ref) = @_; |
|
151
|
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
# Check the style argument. |
|
153
|
19
|
|
100
|
|
|
136
|
my $style = $args_ref->{style} || 'GPG'; |
|
154
|
19
|
100
|
100
|
|
|
296
|
if ($style ne 'GPG' && $style ne 'GPG1') { |
|
155
|
1
|
|
|
|
|
229
|
croak("Unknown OpenPGP backend style $style"); |
|
156
|
|
|
|
|
|
|
} |
|
157
|
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
# If path is not given, set a default based on the style. |
|
159
|
18
|
|
66
|
|
|
100
|
my $path = $args_ref->{path} // lc($style); |
|
160
|
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
# Create and return the object. |
|
162
|
|
|
|
|
|
|
my $self = { |
|
163
|
|
|
|
|
|
|
home => $args_ref->{home}, |
|
164
|
|
|
|
|
|
|
munge => $args_ref->{munge}, |
|
165
|
|
|
|
|
|
|
path => $path, |
|
166
|
|
|
|
|
|
|
style => $style, |
|
167
|
|
|
|
|
|
|
tmpdir => $args_ref->{tmpdir}, |
|
168
|
18
|
|
|
|
|
135
|
}; |
|
169
|
18
|
|
|
|
|
54
|
bless($self, $class); |
|
170
|
18
|
|
|
|
|
73
|
return $self; |
|
171
|
|
|
|
|
|
|
} |
|
172
|
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
# This function actually sends the data to a file handle. It's necessary to |
|
174
|
|
|
|
|
|
|
# implement munging (stripping trailing spaces on a line). |
|
175
|
|
|
|
|
|
|
# |
|
176
|
|
|
|
|
|
|
# $fh - The file handle to which to write the data |
|
177
|
|
|
|
|
|
|
# $string - The data to write |
|
178
|
|
|
|
|
|
|
sub _write_string { |
|
179
|
637
|
|
|
637
|
|
1159
|
my ($self, $fh, $string) = @_; |
|
180
|
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
# If there were any left-over spaces from the last invocation, prepend |
|
182
|
|
|
|
|
|
|
# them to the string and clear them. |
|
183
|
637
|
100
|
|
|
|
1294
|
if ($self->{spaces}) { |
|
184
|
2
|
|
|
|
|
11
|
$string = $self->{spaces} . $string; |
|
185
|
2
|
|
|
|
|
6
|
$self->{spaces} = q{}; |
|
186
|
|
|
|
|
|
|
} |
|
187
|
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
# If whitespace munging is enabled, strip any trailing whitespace from |
|
189
|
|
|
|
|
|
|
# each line of the string for which we've seen the newline. Then, remove |
|
190
|
|
|
|
|
|
|
# and store any spaces at the end of the string, since the newline may be |
|
191
|
|
|
|
|
|
|
# in the next chunk. |
|
192
|
|
|
|
|
|
|
# |
|
193
|
|
|
|
|
|
|
# If there turn out to be no further chunks, this removes any trailing |
|
194
|
|
|
|
|
|
|
# whitespace on the last line without a newline, which is still correct. |
|
195
|
637
|
100
|
|
|
|
1159
|
if ($self->{munge}) { |
|
196
|
70
|
|
|
|
|
377
|
$string =~ s{ [ ]+ \n }{\n}xmsg; |
|
197
|
70
|
100
|
|
|
|
375
|
if ($string =~ s{ ([ ]+) \Z }{}xms) { |
|
198
|
7
|
|
|
|
|
45
|
$self->{spaces} = $1; |
|
199
|
|
|
|
|
|
|
} |
|
200
|
|
|
|
|
|
|
} |
|
201
|
|
|
|
|
|
|
|
|
202
|
637
|
|
|
|
|
1530
|
_print_fh($fh, $string); |
|
203
|
637
|
|
|
|
|
1064
|
return; |
|
204
|
|
|
|
|
|
|
} |
|
205
|
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
# This is our generic "take this data and shove it" routine, used both for |
|
207
|
|
|
|
|
|
|
# signature generation and signature checking. Scalars, references to arrays, |
|
208
|
|
|
|
|
|
|
# references to IO::Handle objects, file globs, references to code, and |
|
209
|
|
|
|
|
|
|
# references to file globs are all supported as ways to get the data, and at |
|
210
|
|
|
|
|
|
|
# most one line at a time is read (cutting down on memory usage). |
|
211
|
|
|
|
|
|
|
# |
|
212
|
|
|
|
|
|
|
# References to code are an interesting subcase. A code reference is executed |
|
213
|
|
|
|
|
|
|
# repeatedly, passing whatever it returns to GnuPG, until it returns undef. |
|
214
|
|
|
|
|
|
|
# |
|
215
|
|
|
|
|
|
|
# $fh - The file handle to which to write the data |
|
216
|
|
|
|
|
|
|
# @sources - The data to write, in any of those formats |
|
217
|
|
|
|
|
|
|
sub _write_data { |
|
218
|
33
|
|
|
33
|
|
293
|
my ($self, $fh, @sources) = @_; |
|
219
|
33
|
|
|
|
|
179
|
$self->{spaces} = q{}; |
|
220
|
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
# Deal with all of our possible sources of input, one at a time. |
|
222
|
|
|
|
|
|
|
# |
|
223
|
|
|
|
|
|
|
# We can't do anything interesting or particularly "cool" with references |
|
224
|
|
|
|
|
|
|
# to references, so those we just print. (Perl allows circular |
|
225
|
|
|
|
|
|
|
# references, so we can't just dereference references to references until |
|
226
|
|
|
|
|
|
|
# we get something interesting.) |
|
227
|
33
|
|
|
|
|
221
|
for my $source (@sources) { |
|
228
|
515
|
100
|
33
|
|
|
2662
|
if (ref($source) eq 'ARRAY') { |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
229
|
3
|
|
|
|
|
38
|
for my $chunk (@$source) { |
|
230
|
65
|
|
|
|
|
167
|
$self->_write_string($fh, $chunk); |
|
231
|
|
|
|
|
|
|
} |
|
232
|
|
|
|
|
|
|
} elsif (ref($source) eq 'GLOB' || ref(\$source) eq 'GLOB') { |
|
233
|
0
|
|
|
|
|
0
|
while (defined(my $chunk = <$source>)) { |
|
234
|
0
|
|
|
|
|
0
|
$self->_write_string($fh, $chunk); |
|
235
|
|
|
|
|
|
|
} |
|
236
|
|
|
|
|
|
|
} elsif (ref($source) eq 'SCALAR') { |
|
237
|
0
|
|
|
|
|
0
|
$self->_write_string($fh, $$source); |
|
238
|
|
|
|
|
|
|
} elsif (ref($source) eq 'CODE') { |
|
239
|
1
|
|
|
|
|
25
|
while (defined(my $chunk = &$source())) { |
|
240
|
31
|
|
|
|
|
244
|
$self->_write_string($fh, $chunk); |
|
241
|
|
|
|
|
|
|
} |
|
242
|
|
|
|
|
|
|
} elsif (blessed($source)) { |
|
243
|
1
|
50
|
|
|
|
39
|
if ($source->isa('IO::Handle')) { |
|
244
|
1
|
|
|
|
|
28
|
while (defined(my $chunk = <$source>)) { |
|
245
|
31
|
|
|
|
|
58
|
$self->_write_string($fh, $chunk); |
|
246
|
|
|
|
|
|
|
} |
|
247
|
|
|
|
|
|
|
} else { |
|
248
|
0
|
|
|
|
|
0
|
$self->_write_string($fh, $source); |
|
249
|
|
|
|
|
|
|
} |
|
250
|
|
|
|
|
|
|
} else { |
|
251
|
510
|
|
|
|
|
995
|
$self->_write_string($fh, $source); |
|
252
|
|
|
|
|
|
|
} |
|
253
|
|
|
|
|
|
|
} |
|
254
|
33
|
|
|
|
|
113
|
return; |
|
255
|
|
|
|
|
|
|
} |
|
256
|
|
|
|
|
|
|
|
|
257
|
|
|
|
|
|
|
# Construct the command for signing. This will expect the passphrase on file |
|
258
|
|
|
|
|
|
|
# descriptor 3. |
|
259
|
|
|
|
|
|
|
# |
|
260
|
|
|
|
|
|
|
# $keyid - The OpenPGP key ID with which to sign |
|
261
|
|
|
|
|
|
|
# |
|
262
|
|
|
|
|
|
|
# Returns: List of the command and arguments. |
|
263
|
|
|
|
|
|
|
sub _build_sign_command { |
|
264
|
10
|
|
|
10
|
|
62
|
my ($self, $keyid) = @_; |
|
265
|
10
|
|
|
|
|
179
|
my @command = ($self->{path}, '-u', $keyid, qw(--passphrase-fd 3)); |
|
266
|
10
|
|
|
|
|
31
|
push(@command, @{ $SIGN_FLAGS{ $self->{style} } }); |
|
|
10
|
|
|
|
|
420
|
|
|
267
|
10
|
100
|
|
|
|
73
|
if ($self->{home}) { |
|
268
|
9
|
|
|
|
|
54
|
push(@command, '--homedir', $self->{home}); |
|
269
|
|
|
|
|
|
|
} |
|
270
|
10
|
|
|
|
|
73
|
return @command; |
|
271
|
|
|
|
|
|
|
} |
|
272
|
|
|
|
|
|
|
|
|
273
|
|
|
|
|
|
|
# Construct the command for verification. This will send all logging to |
|
274
|
|
|
|
|
|
|
# standard output and the status messages to file descriptor 3. |
|
275
|
|
|
|
|
|
|
# |
|
276
|
|
|
|
|
|
|
# $signature_file - Path to the file containing the signature |
|
277
|
|
|
|
|
|
|
# $data_file - Path to the file containing the signed data |
|
278
|
|
|
|
|
|
|
# |
|
279
|
|
|
|
|
|
|
# Returns: List of the command and arguments. |
|
280
|
|
|
|
|
|
|
sub _build_verify_command { |
|
281
|
24
|
|
|
24
|
|
400
|
my ($self, $signature_file, $data_file) = @_; |
|
282
|
24
|
|
|
|
|
165
|
my @command = ($self->{path}, qw(--status-fd 3 --logger-fd 1)); |
|
283
|
24
|
|
|
|
|
99
|
push(@command, @{ $VERIFY_FLAGS{ $self->{style} } }); |
|
|
24
|
|
|
|
|
308
|
|
|
284
|
24
|
100
|
|
|
|
107
|
if ($self->{home}) { |
|
285
|
23
|
|
|
|
|
104
|
push(@command, '--homedir', $self->{home}); |
|
286
|
|
|
|
|
|
|
} |
|
287
|
24
|
|
|
|
|
73
|
push(@command, $signature_file, $data_file); |
|
288
|
24
|
|
|
|
|
146
|
return @command; |
|
289
|
|
|
|
|
|
|
} |
|
290
|
|
|
|
|
|
|
|
|
291
|
|
|
|
|
|
|
# Create a detached signature for the given data. |
|
292
|
|
|
|
|
|
|
# |
|
293
|
|
|
|
|
|
|
# $keyid - GnuPG key ID to use to sign the data |
|
294
|
|
|
|
|
|
|
# $passphrase - Passphrase for the GnuPG key |
|
295
|
|
|
|
|
|
|
# @sources - The data to sign (see _write_data for more information) |
|
296
|
|
|
|
|
|
|
# |
|
297
|
|
|
|
|
|
|
# Returns: The signature as an ASCII-armored block with embedded newlines |
|
298
|
|
|
|
|
|
|
# Throws: Text exception on failure that includes the GnuPG output |
|
299
|
|
|
|
|
|
|
sub sign { |
|
300
|
10
|
|
|
10
|
1
|
9586
|
my ($self, $keyid, $passphrase, @sources) = @_; |
|
301
|
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
# Ignore SIGPIPE, since we're going to be talking to GnuPG. |
|
303
|
10
|
|
|
|
|
310
|
local $SIG{PIPE} = 'IGNORE'; |
|
304
|
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
# Build the command to run. |
|
306
|
10
|
|
|
|
|
108
|
my @command = $self->_build_sign_command($keyid); |
|
307
|
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
# Fork off a pgp process that we're going to be feeding data to, and tell |
|
309
|
|
|
|
|
|
|
# it to just generate a signature using the given key id and pass phrase. |
|
310
|
10
|
|
|
|
|
260
|
my $writefh = IO::Handle->new(); |
|
311
|
10
|
|
|
|
|
735
|
my ($signature, $errors); |
|
312
|
|
|
|
|
|
|
#<<< |
|
313
|
10
|
|
|
|
|
117
|
my $h = start( |
|
314
|
|
|
|
|
|
|
\@command, |
|
315
|
|
|
|
|
|
|
'3<', \$passphrase, |
|
316
|
|
|
|
|
|
|
'
|
|
317
|
|
|
|
|
|
|
'>', \$signature, |
|
318
|
|
|
|
|
|
|
'2>', \$errors, |
|
319
|
|
|
|
|
|
|
); |
|
320
|
|
|
|
|
|
|
#>>> |
|
321
|
9
|
|
|
|
|
78948
|
$self->_write_data($writefh, @sources); |
|
322
|
9
|
|
|
|
|
166
|
close($writefh); |
|
323
|
|
|
|
|
|
|
|
|
324
|
|
|
|
|
|
|
# Get the return status and raise an exception on failure. |
|
325
|
9
|
50
|
|
|
|
8221
|
if (!finish($h)) { |
|
326
|
0
|
|
|
|
|
0
|
my $status = $h->result(); |
|
327
|
0
|
|
|
|
|
0
|
$errors .= "Execution of $command[0] failed with status $status"; |
|
328
|
0
|
|
|
|
|
0
|
croak($errors); |
|
329
|
|
|
|
|
|
|
} |
|
330
|
|
|
|
|
|
|
|
|
331
|
|
|
|
|
|
|
# The resulting signature will look something like this: |
|
332
|
|
|
|
|
|
|
# |
|
333
|
|
|
|
|
|
|
# -----BEGIN PGP SIGNATURE----- |
|
334
|
|
|
|
|
|
|
# Version: GnuPG v0.9.2 (SunOS) |
|
335
|
|
|
|
|
|
|
# Comment: For info see http://www.gnupg.org |
|
336
|
|
|
|
|
|
|
# |
|
337
|
|
|
|
|
|
|
# iEYEARECAAYFAjbA/fsACgkQ+YXjQAr8dHYsMQCgpzOkRRopdW0nuiSNMB6Qx2Iw |
|
338
|
|
|
|
|
|
|
# bw0AoMl82UxQEkh4uIcLSZMdY31Z8gtL |
|
339
|
|
|
|
|
|
|
# =Dj7i |
|
340
|
|
|
|
|
|
|
# -----END PGP SIGNATURE----- |
|
341
|
|
|
|
|
|
|
# |
|
342
|
|
|
|
|
|
|
# Find and strip the marker line for the start of the signature. |
|
343
|
9
|
|
|
|
|
98892
|
my @signature = split(m{\n}xms, $signature); |
|
344
|
9
|
|
|
|
|
168
|
while ((shift @signature) !~ m{-----BEGIN [ ] PGP [ ] SIGNATURE-----}xms) { |
|
345
|
0
|
0
|
|
|
|
0
|
if (!@signature) { |
|
346
|
0
|
|
|
|
|
0
|
croak('No signature returned by GnuPG'); |
|
347
|
|
|
|
|
|
|
} |
|
348
|
|
|
|
|
|
|
} |
|
349
|
|
|
|
|
|
|
|
|
350
|
|
|
|
|
|
|
# Strip any headers off the signature. Thankfully all of the important |
|
351
|
|
|
|
|
|
|
# data is encoded into the signature itself, so the headers aren't needed. |
|
352
|
9
|
|
66
|
|
|
157
|
while (@signature && $signature[0] ne q{}) { |
|
353
|
9
|
|
|
|
|
63
|
shift(@signature); |
|
354
|
|
|
|
|
|
|
} |
|
355
|
9
|
|
|
|
|
26
|
shift(@signature); |
|
356
|
|
|
|
|
|
|
|
|
357
|
|
|
|
|
|
|
# Remove the trailing marker line. |
|
358
|
9
|
|
|
|
|
24
|
pop(@signature); |
|
359
|
|
|
|
|
|
|
|
|
360
|
|
|
|
|
|
|
# Everything else is the signature that we want. |
|
361
|
9
|
|
|
|
|
168
|
return join("\n", @signature); |
|
362
|
|
|
|
|
|
|
} |
|
363
|
|
|
|
|
|
|
|
|
364
|
|
|
|
|
|
|
# Check a detached signature for given data. |
|
365
|
|
|
|
|
|
|
# |
|
366
|
|
|
|
|
|
|
# $signature - The signature as an ASCII-armored string with embedded newlines |
|
367
|
|
|
|
|
|
|
# @sources - The data over which to check the signature |
|
368
|
|
|
|
|
|
|
# |
|
369
|
|
|
|
|
|
|
# Returns: The human-readable key ID of the signature, or an empty string if |
|
370
|
|
|
|
|
|
|
# the signature did not verify |
|
371
|
|
|
|
|
|
|
# Throws: Text exception on an error other than a bad signature |
|
372
|
|
|
|
|
|
|
sub verify { |
|
373
|
24
|
|
|
24
|
1
|
22757
|
my ($self, $signature, @sources) = @_; |
|
374
|
24
|
|
|
|
|
81
|
chomp($signature); |
|
375
|
|
|
|
|
|
|
|
|
376
|
|
|
|
|
|
|
# Ignore SIGPIPE, since we're going to be talking to PGP. |
|
377
|
24
|
|
|
|
|
419
|
local $SIG{PIPE} = 'IGNORE'; |
|
378
|
|
|
|
|
|
|
|
|
379
|
|
|
|
|
|
|
# To verify a detached signature, we need to save both the signature and |
|
380
|
|
|
|
|
|
|
# the data to files and then run GnuPG on the pair of files. There |
|
381
|
|
|
|
|
|
|
# doesn't appear to be a way to feed both the data and the signature in on |
|
382
|
|
|
|
|
|
|
# file descriptors. |
|
383
|
24
|
50
|
|
|
|
167
|
my @tmpdir = defined($self->{tmpdir}) ? (DIR => $self->{tmpdir}) : (); |
|
384
|
24
|
|
|
|
|
413
|
my $sigfh = File::Temp->new(@tmpdir, SUFFIX => '.asc'); |
|
385
|
24
|
|
|
|
|
18009
|
_print_fh($sigfh, "-----BEGIN PGP SIGNATURE-----\n"); |
|
386
|
24
|
|
|
|
|
83
|
_print_fh($sigfh, "\n", $signature); |
|
387
|
24
|
|
|
|
|
66
|
_print_fh($sigfh, "\n-----END PGP SIGNATURE-----\n"); |
|
388
|
24
|
|
|
|
|
232
|
close($sigfh); |
|
389
|
24
|
|
|
|
|
3727
|
my $datafh = File::Temp->new(@tmpdir); |
|
390
|
24
|
|
|
|
|
9502
|
$self->_write_data($datafh, @sources); |
|
391
|
24
|
|
|
|
|
106
|
close($datafh); |
|
392
|
|
|
|
|
|
|
|
|
393
|
|
|
|
|
|
|
# Build the command to run. |
|
394
|
|
|
|
|
|
|
my @command |
|
395
|
24
|
|
|
|
|
2008
|
= $self->_build_verify_command($sigfh->filename, $datafh->filename); |
|
396
|
|
|
|
|
|
|
|
|
397
|
|
|
|
|
|
|
# Call GnuPG to check the signature. |
|
398
|
24
|
|
|
|
|
62
|
my ($output, $results); |
|
399
|
24
|
|
|
|
|
168
|
run(\@command, '>&', \$output, '3>', \$results); |
|
400
|
24
|
|
|
|
|
317278
|
my $status = $?; |
|
401
|
|
|
|
|
|
|
|
|
402
|
|
|
|
|
|
|
# Check for the message that gives us the key status and return the |
|
403
|
|
|
|
|
|
|
# appropriate thing to our caller. |
|
404
|
|
|
|
|
|
|
# |
|
405
|
|
|
|
|
|
|
# GPG 1.4.23 |
|
406
|
|
|
|
|
|
|
# [GNUPG:] GOODSIG 7D80315C5736DE75 Russ Allbery |
|
407
|
|
|
|
|
|
|
# [GNUPG:] BADSIG 7D80315C5736DE75 Russ Allbery |
|
408
|
|
|
|
|
|
|
# |
|
409
|
|
|
|
|
|
|
# Note that this returns the human-readable key ID instead of the actual |
|
410
|
|
|
|
|
|
|
# key ID. This is a historical wart in the API; a future version will |
|
411
|
|
|
|
|
|
|
# hopefully add an option to return more accurate signer information. |
|
412
|
24
|
|
|
|
|
351
|
for my $line (split(m{\n}xms, $results)) { |
|
413
|
42
|
100
|
|
|
|
671
|
if ($line =~ m{ ^ \[GNUPG:\] \s+ GOODSIG \s+ \S+ \s+ (.*) }xms) { |
|
|
|
100
|
|
|
|
|
|
|
414
|
17
|
|
|
|
|
1026
|
return $1; |
|
415
|
|
|
|
|
|
|
} elsif ($line =~ m{ ^ \[GNUPG:\] \s+ BADSIG \s+ }xms) { |
|
416
|
5
|
|
|
|
|
315
|
return q{}; |
|
417
|
|
|
|
|
|
|
} |
|
418
|
|
|
|
|
|
|
} |
|
419
|
|
|
|
|
|
|
|
|
420
|
|
|
|
|
|
|
# Neither a good nor a bad signature seen. |
|
421
|
2
|
|
|
|
|
29
|
$output .= $results; |
|
422
|
2
|
50
|
|
|
|
38
|
if ($status != 0) { |
|
423
|
2
|
|
|
|
|
26
|
$output .= "Execution of $command[0] failed with status $status"; |
|
424
|
|
|
|
|
|
|
} |
|
425
|
2
|
|
|
|
|
907
|
croak($output); |
|
426
|
|
|
|
|
|
|
} |
|
427
|
|
|
|
|
|
|
|
|
428
|
|
|
|
|
|
|
############################################################################## |
|
429
|
|
|
|
|
|
|
# Legacy function API |
|
430
|
|
|
|
|
|
|
############################################################################## |
|
431
|
|
|
|
|
|
|
|
|
432
|
|
|
|
|
|
|
# This is the original API from 0.x versions of PGP::Sign. It is maintained |
|
433
|
|
|
|
|
|
|
# for backwards compatibility, but is now a wrapper around the object-oriented |
|
434
|
|
|
|
|
|
|
# API that uses the legacy global variables. The object-oriented API should |
|
435
|
|
|
|
|
|
|
# be preferred for all new code. |
|
436
|
|
|
|
|
|
|
|
|
437
|
|
|
|
|
|
|
# Create a detached signature for the given data. |
|
438
|
|
|
|
|
|
|
# |
|
439
|
|
|
|
|
|
|
# The original API returned the PGP implementation version from the signature |
|
440
|
|
|
|
|
|
|
# headers as the second element of the list returned in array context. This |
|
441
|
|
|
|
|
|
|
# information is pointless and unnecessary and GnuPG doesn't include that |
|
442
|
|
|
|
|
|
|
# header by default, so the fixed string "GnuPG" is now returned for backwards |
|
443
|
|
|
|
|
|
|
# compatibility. |
|
444
|
|
|
|
|
|
|
# |
|
445
|
|
|
|
|
|
|
# Errors are stored for return by pgp_error(), overwriting any previously |
|
446
|
|
|
|
|
|
|
# stored error. |
|
447
|
|
|
|
|
|
|
# |
|
448
|
|
|
|
|
|
|
# $keyid - GnuPG key ID to use to sign the data |
|
449
|
|
|
|
|
|
|
# $passphrase - Passphrase for the GnuPG key |
|
450
|
|
|
|
|
|
|
# @sources - The data to sign (see _write_data for more information) |
|
451
|
|
|
|
|
|
|
# |
|
452
|
|
|
|
|
|
|
# Returns: The signature as an ASCII-armored block in scalar context |
|
453
|
|
|
|
|
|
|
# The signature and the string "GnuPG" in list context |
|
454
|
|
|
|
|
|
|
# undef or the empty list on error |
|
455
|
|
|
|
|
|
|
sub pgp_sign { |
|
456
|
4
|
|
|
4
|
1
|
34321
|
my ($keyid, $passphrase, @sources) = @_; |
|
457
|
4
|
|
|
|
|
29
|
@ERROR = (); |
|
458
|
|
|
|
|
|
|
|
|
459
|
|
|
|
|
|
|
# Create the signer object. |
|
460
|
4
|
|
|
|
|
177
|
my $signer = PGP::Sign->new( |
|
461
|
|
|
|
|
|
|
{ |
|
462
|
|
|
|
|
|
|
home => $PGPPATH, |
|
463
|
|
|
|
|
|
|
munge => $MUNGE, |
|
464
|
|
|
|
|
|
|
path => $PGPS, |
|
465
|
|
|
|
|
|
|
style => $PGPSTYLE, |
|
466
|
|
|
|
|
|
|
tmpdir => $TMPDIR, |
|
467
|
|
|
|
|
|
|
}, |
|
468
|
|
|
|
|
|
|
); |
|
469
|
|
|
|
|
|
|
|
|
470
|
|
|
|
|
|
|
# Do the work, capturing any errors. |
|
471
|
4
|
|
|
|
|
21
|
my $signature = eval { $signer->sign($keyid, $passphrase, @sources) }; |
|
|
4
|
|
|
|
|
39
|
|
|
472
|
4
|
50
|
|
|
|
1094
|
if ($@) { |
|
473
|
0
|
|
|
|
|
0
|
@ERROR = split(m{\n}xms, $@); |
|
474
|
0
|
|
|
|
|
0
|
return; |
|
475
|
|
|
|
|
|
|
} |
|
476
|
|
|
|
|
|
|
|
|
477
|
|
|
|
|
|
|
# Return the results, including a dummy version if desired. |
|
478
|
|
|
|
|
|
|
## no critic (Freenode::Wantarray) |
|
479
|
4
|
100
|
|
|
|
176
|
return wantarray ? ($signature, 'GnuPG') : $signature; |
|
480
|
|
|
|
|
|
|
## use critic |
|
481
|
|
|
|
|
|
|
} |
|
482
|
|
|
|
|
|
|
|
|
483
|
|
|
|
|
|
|
# Check a detached signature for given data. |
|
484
|
|
|
|
|
|
|
# |
|
485
|
|
|
|
|
|
|
# $signature - The signature as an ASCII-armored string with embedded newlines |
|
486
|
|
|
|
|
|
|
# @sources - The data over which to check the signature |
|
487
|
|
|
|
|
|
|
# |
|
488
|
|
|
|
|
|
|
# Returns: The human-readable key ID of the signature |
|
489
|
|
|
|
|
|
|
# An empty string if the signature did not verify |
|
490
|
|
|
|
|
|
|
# undef on error |
|
491
|
|
|
|
|
|
|
sub pgp_verify { |
|
492
|
9
|
|
|
9
|
1
|
1365
|
my ($signature, $version, @sources) = @_; |
|
493
|
9
|
|
|
|
|
27
|
@ERROR = (); |
|
494
|
|
|
|
|
|
|
|
|
495
|
|
|
|
|
|
|
# Create the verifier object. |
|
496
|
9
|
|
|
|
|
165
|
my $verifier = PGP::Sign->new( |
|
497
|
|
|
|
|
|
|
{ |
|
498
|
|
|
|
|
|
|
home => $PGPPATH, |
|
499
|
|
|
|
|
|
|
munge => $MUNGE, |
|
500
|
|
|
|
|
|
|
path => $PGPV, |
|
501
|
|
|
|
|
|
|
style => $PGPSTYLE, |
|
502
|
|
|
|
|
|
|
tmpdir => $TMPDIR, |
|
503
|
|
|
|
|
|
|
}, |
|
504
|
|
|
|
|
|
|
); |
|
505
|
|
|
|
|
|
|
|
|
506
|
|
|
|
|
|
|
# Do the work, capturing any errors. |
|
507
|
9
|
|
|
|
|
33
|
my $signer = eval { $verifier->verify($signature, @sources) }; |
|
|
9
|
|
|
|
|
46
|
|
|
508
|
9
|
100
|
|
|
|
4598
|
if ($@) { |
|
509
|
1
|
|
|
|
|
23
|
@ERROR = split(m{\n}xms, $@); |
|
510
|
1
|
|
|
|
|
52
|
return; |
|
511
|
|
|
|
|
|
|
} |
|
512
|
|
|
|
|
|
|
|
|
513
|
|
|
|
|
|
|
# Return the results. |
|
514
|
8
|
|
|
|
|
533
|
return $signer; |
|
515
|
|
|
|
|
|
|
} |
|
516
|
|
|
|
|
|
|
|
|
517
|
|
|
|
|
|
|
# Retrieve errors from the previous pgp_sign() or pgp_verify() call. |
|
518
|
|
|
|
|
|
|
# |
|
519
|
|
|
|
|
|
|
# Historically the pgp_error() return value in list context had newlines at |
|
520
|
|
|
|
|
|
|
# the end of each line, so add them back in. |
|
521
|
|
|
|
|
|
|
# |
|
522
|
|
|
|
|
|
|
# Returns: A list of GnuPG output and error messages in list context |
|
523
|
|
|
|
|
|
|
# The block of GnuPG output and error message in scalar context |
|
524
|
|
|
|
|
|
|
## no critic (Freenode::Wantarray) |
|
525
|
|
|
|
|
|
|
sub pgp_error { |
|
526
|
11
|
|
|
11
|
1
|
3316
|
my @error_lines = map { "$_\n" } @ERROR; |
|
|
44
|
|
|
|
|
78
|
|
|
527
|
11
|
100
|
|
|
|
225
|
return wantarray ? @error_lines : join(q{}, @error_lines); |
|
528
|
|
|
|
|
|
|
} |
|
529
|
|
|
|
|
|
|
## use critic |
|
530
|
|
|
|
|
|
|
|
|
531
|
|
|
|
|
|
|
############################################################################## |
|
532
|
|
|
|
|
|
|
# Module return value and documentation |
|
533
|
|
|
|
|
|
|
############################################################################## |
|
534
|
|
|
|
|
|
|
|
|
535
|
|
|
|
|
|
|
# Make sure the module returns true. |
|
536
|
|
|
|
|
|
|
1; |
|
537
|
|
|
|
|
|
|
|
|
538
|
|
|
|
|
|
|
__DATA__ |