line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package VOMS::Lite::PEMHelper; |
2
|
|
|
|
|
|
|
|
3
|
1
|
|
|
1
|
|
26
|
use 5.004; |
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
49
|
|
4
|
1
|
|
|
1
|
|
7
|
use strict; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
43
|
|
5
|
1
|
|
|
1
|
|
962
|
use MIME::Base64 qw(encode_base64 decode_base64); |
|
1
|
|
|
|
|
248818
|
|
|
1
|
|
|
|
|
148
|
|
6
|
1
|
|
|
1
|
|
1244
|
use File::Copy qw(move); |
|
1
|
|
|
|
|
3150
|
|
|
1
|
|
|
|
|
88
|
|
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
require Exporter; |
9
|
1
|
|
|
1
|
|
7
|
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS); |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
3096
|
|
10
|
|
|
|
|
|
|
@ISA = qw(Exporter); |
11
|
|
|
|
|
|
|
%EXPORT_TAGS = ( ); |
12
|
|
|
|
|
|
|
@EXPORT_OK = qw( encodeCert writeAC encodeAC readAC readCert decodeCert writeKey writeCert writeCertKey readPrivateKey ); |
13
|
|
|
|
|
|
|
@EXPORT = ( ); |
14
|
|
|
|
|
|
|
$VERSION = '0.20'; |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
################################################################ |
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
sub writeAC { #writes a PEM formatted AC |
19
|
|
|
|
|
|
|
# Two arguments (Path to store AC and AC data as a string of chars) |
20
|
1
|
|
|
1
|
0
|
215
|
my ($file,$data)=@_; |
21
|
|
|
|
|
|
|
# my $umasksave=umask(0022); #ACs are not private key material |
22
|
|
|
|
|
|
|
# if ( umask() != 0022 ) { die "Can't umask 0022\n"; } |
23
|
1
|
50
|
|
|
|
81
|
if ( -e $file ) { move($file,"$file.old"); } #move old file away |
|
1
|
|
|
|
|
12
|
|
24
|
1
|
50
|
|
|
|
321
|
open(AC,">$file") || die "Can't create AC file"; |
25
|
1
|
|
|
|
|
6
|
print AC &encodeAC($data); |
26
|
1
|
|
|
|
|
56
|
close(AC); |
27
|
|
|
|
|
|
|
# umask($umasksave); |
28
|
1
|
|
|
|
|
5
|
return; |
29
|
|
|
|
|
|
|
} |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
################################################################ |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
sub encodeAC { |
34
|
2
|
|
|
2
|
0
|
935
|
return encodeCert(@_,"ATTRIBUTE CERTIFICATE"); |
35
|
|
|
|
|
|
|
} |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
################################################################ |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
sub readAC { #Returns BER with AC in it |
40
|
0
|
|
|
0
|
0
|
0
|
my $file=shift; |
41
|
0
|
|
|
|
|
0
|
return readCert($file,"ATTRIBUTE CERTIFICATE"); |
42
|
|
|
|
|
|
|
} |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
################################################################ |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
sub readCert { #Returns BERs with CERTs in them |
47
|
|
|
|
|
|
|
# One arguement (path to cert file); |
48
|
2
|
|
|
2
|
0
|
6
|
my $file=shift; |
49
|
|
|
|
|
|
|
|
50
|
2
|
|
|
|
|
4
|
my $type=shift; |
51
|
2
|
50
|
|
|
|
7
|
if ( ! defined($type) ) { $type="CERTIFICATE"; } |
|
2
|
|
|
|
|
6
|
|
52
|
2
|
|
|
|
|
6
|
$type =~ y/a-z/A-Z/; |
53
|
2
|
|
|
|
|
9
|
$type =~ s/[^A-Z0-9 ]//g; |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
# Load and parse cert file |
56
|
2
|
|
|
|
|
6
|
my @myCertData=(); |
57
|
2
|
|
|
|
|
3
|
my $Certnum=-1; |
58
|
2
|
|
|
|
|
4
|
my $read=0; |
59
|
2
|
50
|
|
|
|
115
|
open(CERT,"<$file") || die "Can't access Public Key file: '$file'"; |
60
|
2
|
|
|
|
|
40
|
while () { |
61
|
29
|
|
|
|
|
45
|
my $line=$_; |
62
|
29
|
100
|
|
|
|
113
|
if ( $line =~ /^-----BEGIN $type-----\r?$/ ) {$read=1; $Certnum++; next;} |
|
2
|
|
|
|
|
79
|
|
|
2
|
|
|
|
|
2
|
|
|
2
|
|
|
|
|
11
|
|
63
|
27
|
50
|
|
|
|
105
|
if ( $line =~ /^-----END $type-----\r?$/ ) {$read=0; wantarray ? next : last; } |
|
2
|
100
|
|
|
|
4
|
|
|
2
|
|
|
|
|
8
|
|
64
|
25
|
50
|
|
|
|
57
|
if ( $read==1 ) { |
65
|
25
|
50
|
|
|
|
86
|
if ( $line =~ /^([A-Za-z0-9+\/=]+)\r?$/ ) {$myCertData[$Certnum].=$1;} |
|
25
|
|
|
|
|
105
|
|
66
|
|
|
|
|
|
|
} |
67
|
|
|
|
|
|
|
} |
68
|
2
|
|
|
|
|
25
|
close(CERT); |
69
|
|
|
|
|
|
|
|
70
|
2
|
50
|
|
|
|
10
|
if ( $myCertData[0] eq "" ) { die "I didn't understand the format of your $type file:\n$file";} |
|
0
|
|
|
|
|
0
|
|
71
|
2
|
|
|
|
|
6
|
my @decoded=(); |
72
|
2
|
|
|
|
|
5
|
foreach (@myCertData) { push(@decoded,decode_base64($_)); } |
|
2
|
|
|
|
|
22
|
|
73
|
2
|
50
|
|
|
|
14
|
return wantarray?@decoded:$decoded[0]; |
74
|
|
|
|
|
|
|
} |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
################################################################ |
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
sub decodeCert { |
79
|
0
|
|
|
0
|
0
|
0
|
my $type = pop; |
80
|
0
|
|
|
|
|
0
|
my $pems = join "\n",@_; |
81
|
0
|
|
|
|
|
0
|
my @ders; |
82
|
0
|
|
|
|
|
0
|
$pems =~ s|^-----BEGIN $type-----$([a-zA-Z0-9/+=\r\n]+)^-----END $type-----$|push @ders,decode_base64($1)|mge; |
|
0
|
|
|
|
|
0
|
|
83
|
0
|
|
|
|
|
0
|
return @ders; |
84
|
|
|
|
|
|
|
} |
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
################################################################ |
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
sub encodeCert { |
89
|
|
|
|
|
|
|
#my $certstr=shift; |
90
|
5
|
|
|
5
|
0
|
11
|
my $certstr=""; |
91
|
5
|
|
|
|
|
10
|
my $type="CERTIFICATE"; |
92
|
5
|
50
|
|
|
|
20
|
if ( $_[-1] !~ /^\x30/ ) { $type=pop; } |
|
5
|
|
|
|
|
8
|
|
93
|
|
|
|
|
|
|
|
94
|
5
|
|
|
|
|
11
|
$type =~ y/a-z/A-Z/; |
95
|
5
|
|
|
|
|
15
|
$type =~ s/[^A-Z0-9 ]//g; |
96
|
5
|
|
|
|
|
12
|
foreach (@_) { |
97
|
5
|
|
|
|
|
32
|
my $OpenSSLCompat=encode_base64($_,''); |
98
|
5
|
|
|
|
|
127
|
$OpenSSLCompat=~s/(.{1,64})/$&\n/g; |
99
|
5
|
|
|
|
|
52
|
$certstr .= "-----BEGIN $type-----\n".$OpenSSLCompat."-----END $type-----\n"; |
100
|
|
|
|
|
|
|
} |
101
|
5
|
|
|
|
|
72
|
return $certstr; |
102
|
|
|
|
|
|
|
} |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
################################################################ |
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
sub writeCertKey { |
107
|
|
|
|
|
|
|
# At least 3 arguements (file, public key, private key, [chain of signing certificates]); |
108
|
1
|
|
|
1
|
0
|
442
|
my $file=shift; |
109
|
1
|
|
|
|
|
2
|
my $pub=shift; |
110
|
1
|
|
|
|
|
3
|
my $pri=shift; |
111
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
# Place file |
113
|
1
|
|
|
|
|
5
|
my $umasksave=umask(0077); |
114
|
|
|
|
|
|
|
|
115
|
1
|
50
|
|
|
|
9
|
if ( umask() != 0077 ) { |
116
|
0
|
0
|
|
|
|
0
|
if ( $^O =~ /^MSWin/ ) { print STDERR "WARNING: Can't umask 0077 when writing $file\n"; } |
|
0
|
|
|
|
|
0
|
|
117
|
0
|
|
|
|
|
0
|
else { die "Can't umask 0077 when writing $file"; } |
118
|
|
|
|
|
|
|
} |
119
|
1
|
50
|
|
|
|
44
|
if ( -e $file ) { move($file,"$file.old"); } #move old file away |
|
1
|
|
|
|
|
8
|
|
120
|
|
|
|
|
|
|
|
121
|
1
|
50
|
|
|
|
299
|
open(CERTKEY,">$file") || die "Can't create file to save cert and key to."; |
122
|
1
|
|
|
|
|
6
|
print CERTKEY encodeCert($pub,"CERTIFICATE"); |
123
|
1
|
|
|
|
|
5
|
print CERTKEY encodeCert($pri,"RSA PRIVATE KEY"); |
124
|
1
|
|
|
|
|
3
|
foreach ( @_ ) { print CERTKEY encodeCert($_,"CERTIFICATE"); } |
|
1
|
|
|
|
|
4
|
|
125
|
1
|
|
|
|
|
51
|
close(CERTKEY); |
126
|
1
|
|
|
|
|
4
|
umask($umasksave); |
127
|
1
|
|
|
|
|
6
|
return; |
128
|
|
|
|
|
|
|
} |
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
################################################################ |
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
sub writeKey { |
133
|
|
|
|
|
|
|
# At least 3 arguements (file, public key, private key, [chain of signing certificates]); |
134
|
3
|
|
|
3
|
0
|
948
|
my $file=shift; |
135
|
3
|
|
|
|
|
9
|
my $pri=shift; |
136
|
3
|
|
|
|
|
6
|
my $passwd=shift; |
137
|
3
|
|
|
|
|
9
|
my $ENCRYPTION=""; |
138
|
|
|
|
|
|
|
|
139
|
3
|
50
|
|
|
|
11
|
if ( ! defined $passwd ) { |
140
|
|
|
|
|
|
|
# Prompt for password |
141
|
0
|
|
|
|
|
0
|
require Term::ReadKey; |
142
|
0
|
|
|
|
|
0
|
print "I need the passphrase used to encrypt the key in \n$file\nPassphrase: "; |
143
|
0
|
|
|
|
|
0
|
my $dummy=Term::ReadKey::ReadMode('noecho'); |
144
|
0
|
|
|
|
|
0
|
$passwd = Term::ReadKey::ReadLine(), |
145
|
|
|
|
|
|
|
$dummy=Term::ReadKey::ReadMode('normal'); |
146
|
0
|
|
|
|
|
0
|
chomp $passwd; |
147
|
0
|
|
|
|
|
0
|
print "\n"; |
148
|
|
|
|
|
|
|
} |
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
# To encrypt or not to encrypt |
151
|
3
|
100
|
|
|
|
12
|
if ( $passwd ne "" ) { |
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
# Spin up the Crypto stuff |
154
|
2
|
|
|
|
|
25
|
require Digest::MD5; |
155
|
2
|
|
|
|
|
834
|
require Crypt::DES_EDE3; |
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
# Make Initialisation vector |
158
|
2
|
|
|
|
|
2148
|
my $iv=""; |
159
|
2
|
|
|
|
|
10
|
while (length($iv)<8 ) {$iv.=chr((rand(255)+1));} |
|
16
|
|
|
|
|
84
|
|
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
# Construct DES Key from password (Munge) |
162
|
2
|
|
|
|
|
4
|
my $keysize=24; |
163
|
2
|
|
|
|
|
7
|
my $SALT=$iv; |
164
|
2
|
|
|
|
|
16
|
my $key=Digest::MD5::md5($passwd,$SALT); |
165
|
2
|
|
|
|
|
11
|
while (length($key) < $keysize) { $key .= Digest::MD5::md5($key, $passwd, $SALT);} |
|
2
|
|
|
|
|
11
|
|
166
|
2
|
|
|
|
|
7
|
$key=substr($key,0,$keysize); |
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
# DES Padding Data as per RFC 1423 (not 1851 which adds message payload info) |
169
|
2
|
|
|
|
|
7
|
my $pad = ( 8 - (length($pri)%8) ); |
170
|
2
|
|
|
|
|
8
|
my $padding=chr($pad) x $pad; |
171
|
2
|
|
|
|
|
6
|
$pri.=$padding; |
172
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
# Encode Data |
174
|
2
|
|
|
|
|
15
|
my $DES = Crypt::DES_EDE3->new($key); |
175
|
2
|
|
|
|
|
189
|
my $cyphertextout=""; |
176
|
2
|
|
|
|
|
11
|
while ( my $len=length($pri) ) { |
177
|
81
|
|
|
|
|
165
|
my $block=substr($pri,0,8); |
178
|
81
|
|
|
|
|
109
|
$pri=substr($pri,8); |
179
|
81
|
|
|
|
|
119
|
$block = $SALT ^ $block; |
180
|
81
|
|
|
|
|
203
|
my $cyphertext=$DES->encrypt($block); |
181
|
81
|
|
|
|
|
1732
|
$SALT=$cyphertext; |
182
|
81
|
|
|
|
|
226
|
$cyphertextout.=$cyphertext; |
183
|
|
|
|
|
|
|
} |
184
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
# Set PEM encryprion header |
186
|
2
|
|
|
|
|
12
|
$iv=unpack('H*',$iv); |
187
|
2
|
|
|
|
|
7
|
$iv =~ y/[a-f]/[A-F]/; |
188
|
2
|
|
|
|
|
6
|
$ENCRYPTION="Proc-Type: 4,ENCRYPTED\nDEK-Info: DES-EDE3-CBC,$iv\n\n"; |
189
|
2
|
|
|
|
|
23
|
$pri=$cyphertextout; |
190
|
|
|
|
|
|
|
} |
191
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
# Place file |
193
|
3
|
|
|
|
|
21
|
my $umasksave=umask(0077); |
194
|
|
|
|
|
|
|
|
195
|
3
|
50
|
|
|
|
21
|
if ( umask() != 0077 ) { |
196
|
0
|
0
|
|
|
|
0
|
if ( $^O =~ /^MSWin/ ) { print STDERR "WARNING: Can't umask 0077 when writing $file\n"; } |
|
0
|
|
|
|
|
0
|
|
197
|
0
|
|
|
|
|
0
|
else { die "Can't umask 0077 when writing $file"; } |
198
|
|
|
|
|
|
|
} |
199
|
3
|
50
|
|
|
|
93
|
if ( -e $file ) { move($file,"$file.old"); } #move old file away |
|
3
|
|
|
|
|
20
|
|
200
|
|
|
|
|
|
|
|
201
|
3
|
50
|
|
|
|
592
|
open(KEY,">$file") || die "Can't create file to save cert and key to."; |
202
|
3
|
|
|
|
|
20
|
my $OpenSSLCompat=encode_base64($pri,''); |
203
|
3
|
|
|
|
|
56
|
$OpenSSLCompat=~s/(.{1,64})/$&\n/g; |
204
|
3
|
|
|
|
|
34
|
print KEY "-----BEGIN RSA PRIVATE KEY-----\n$ENCRYPTION".$OpenSSLCompat."-----END RSA PRIVATE KEY-----\n"; |
205
|
3
|
|
|
|
|
125
|
close(KEY); |
206
|
3
|
|
|
|
|
9
|
umask($umasksave); |
207
|
3
|
|
|
|
|
15
|
return; |
208
|
|
|
|
|
|
|
} |
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
################################################################ |
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
sub writeCert { |
213
|
|
|
|
|
|
|
# At least 3 arguements (file, public key, private key, [chain of signing certificates]); |
214
|
3
|
|
|
3
|
0
|
1896
|
my $file=shift; |
215
|
3
|
|
|
|
|
9
|
my $pub=shift; |
216
|
3
|
|
|
|
|
7
|
my $type=shift; |
217
|
3
|
50
|
|
|
|
16
|
if ( ! defined($type) ) { $type="CERTIFICATE"; } |
|
3
|
|
|
|
|
8
|
|
218
|
3
|
|
|
|
|
10
|
$type =~ y/a-z/A-Z/; |
219
|
3
|
|
|
|
|
14
|
$type =~ s/[^A-Z0-9 ]//g; |
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
# Place file |
222
|
3
|
50
|
|
|
|
207
|
if ( -e $file ) { move($file,"$file.old"); } #move old file away |
|
3
|
|
|
|
|
22
|
|
223
|
3
|
50
|
|
|
|
1294860
|
open(CERT,">$file") || die "Can't create file to save cert and key to."; |
224
|
3
|
|
|
|
|
44
|
my $OpenSSLCompat=encode_base64($pub,''); |
225
|
3
|
|
|
|
|
110
|
$OpenSSLCompat=~s/(.{1,64})/$&\n/g; |
226
|
3
|
|
|
|
|
131
|
print CERT "-----BEGIN $type-----\n".$OpenSSLCompat."-----END $type-----\n"; |
227
|
3
|
|
|
|
|
215
|
close(CERT); |
228
|
3
|
|
|
|
|
18
|
return; |
229
|
|
|
|
|
|
|
} |
230
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
################################################################ |
233
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
sub readPrivateKey { #Returns BER with Private key in it |
235
|
|
|
|
|
|
|
# Two arguements (path to private key, and optional password); |
236
|
1
|
|
|
1
|
0
|
2
|
my $file=shift; |
237
|
1
|
|
|
|
|
1
|
my $passwd=shift; |
238
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
# Load and parse private key file |
240
|
1
|
|
|
|
|
5
|
my ($myKeyData,$PEMV,$PEMType,$PEMEnc,$SALT)=("","","","",""); |
241
|
1
|
|
|
|
|
4
|
my $read=0; |
242
|
1
|
50
|
|
|
|
36
|
open(KEY,"<$file") || die "Can't access Private Key file $file"; |
243
|
1
|
|
|
|
|
19
|
while () { |
244
|
9
|
|
|
|
|
14
|
my $line=$_; |
245
|
9
|
100
|
|
|
|
18
|
if ( $line =~ /^-----BEGIN RSA PRIVATE KEY-----$/ ) {$read=1; next;} |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
3
|
|
246
|
8
|
50
|
|
|
|
17
|
if ( $line =~ /^-----BEGIN PRIVATE KEY-----$/ ) {$read=2; next;} |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
247
|
8
|
100
|
|
|
|
14
|
if ( $line =~ /^-----END RSA PRIVATE KEY-----$/ ) {last;} |
|
1
|
|
|
|
|
4
|
|
248
|
7
|
50
|
|
|
|
14
|
if ( $line =~ /^-----END PRIVATE KEY-----$/ ) {last;} |
|
0
|
|
|
|
|
0
|
|
249
|
7
|
50
|
|
|
|
14
|
if ( $read==1 ) { |
250
|
7
|
50
|
|
|
|
31
|
if ( $line =~ /^Proc-Type: ([0-9]+),(ENCRYPTED)$/ ) {$PEMV=$1; $PEMType=$2} |
|
0
|
50
|
|
|
|
0
|
|
|
0
|
50
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
251
|
0
|
|
|
|
|
0
|
elsif ( $line =~ /^DEK-Info: (.*),(.*)$/ ) {$PEMEnc=$1; $SALT=$2} |
|
7
|
|
|
|
|
13
|
|
252
|
|
|
|
|
|
|
elsif ( $line =~ /^([A-Za-z0-9+\/=]+)$/ ) {$myKeyData.=$1;} |
253
|
|
|
|
|
|
|
} |
254
|
7
|
50
|
|
|
|
22
|
if ( $read==2 ) { |
255
|
0
|
0
|
|
|
|
0
|
if ( $line =~ /^([A-Za-z0-9+\/=]+)$/ ) {$myKeyData.=$1;} |
|
0
|
|
|
|
|
0
|
|
256
|
|
|
|
|
|
|
} |
257
|
|
|
|
|
|
|
} |
258
|
1
|
|
|
|
|
8
|
close(KEY); |
259
|
|
|
|
|
|
|
|
260
|
|
|
|
|
|
|
# Return data if it's not encrypted |
261
|
1
|
50
|
|
|
|
4
|
if ( $myKeyData eq "" ) { die "I didn't understand the format of your key file:\n$file";} |
|
0
|
|
|
|
|
0
|
|
262
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
# Obtain and check Encryption values |
264
|
1
|
|
|
|
|
5
|
my $cyphertext=decode_base64($myKeyData); |
265
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
# If "PRIVATE KEY" but not "RSA PRIVATE KEY" Parse into it |
267
|
1
|
50
|
|
|
|
6
|
if ( $read == 2 ) { # Unencrypted pkcs #8 |
268
|
0
|
|
|
|
|
0
|
die "I didn't understand the format of your key file:\n$file"; |
269
|
|
|
|
|
|
|
} |
270
|
|
|
|
|
|
|
|
271
|
1
|
50
|
|
|
|
7
|
return $cyphertext if ( $PEMType ne "ENCRYPTED" ); # Because actually it's not encrypted. |
272
|
0
|
0
|
|
|
|
|
if ( $PEMEnc ne "DES-EDE3-CBC" ) { die "I don't know how to unencrypt your key\n";} |
|
0
|
|
|
|
|
|
|
273
|
0
|
0
|
|
|
|
|
if ( $SALT !~ /^[a-fA-F0-9]{16}$/ ) { die "Bad Initilisation Vector (salt)'; I can't unencrypt your key!\n";} |
|
0
|
|
|
|
|
|
|
274
|
0
|
0
|
|
|
|
|
if ( $PEMV ne "4" ) { print STDERR "Warning: I was expecting a version 4 PEM encrypted file you gave me a Version $PEMV\nFunny things may happen!\n"; } |
|
0
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
# Check/get password |
278
|
0
|
0
|
0
|
|
|
|
if ( defined $passwd && $passwd eq "" ) { return undef; } #was expecting no password so abort |
|
0
|
0
|
|
|
|
|
|
279
|
|
|
|
|
|
|
elsif ( ! defined $passwd ) { |
280
|
0
|
|
|
|
|
|
require Term::ReadKey; |
281
|
0
|
|
|
|
|
|
require Digest::MD5; |
282
|
0
|
|
|
|
|
|
print "I need the passphrase used to encrypt the key in \n$file\nPassphrase: "; |
283
|
0
|
|
|
|
|
|
my $dummy=Term::ReadKey::ReadMode('noecho'); |
284
|
0
|
|
|
|
|
|
$passwd = Term::ReadKey::ReadLine(), |
285
|
|
|
|
|
|
|
$dummy=Term::ReadKey::ReadMode('normal'); |
286
|
0
|
|
|
|
|
|
chomp $passwd; |
287
|
0
|
|
|
|
|
|
print "\n"; |
288
|
|
|
|
|
|
|
} |
289
|
|
|
|
|
|
|
|
290
|
|
|
|
|
|
|
# Reconstruct DES Key from password (Munge) |
291
|
0
|
|
|
|
|
|
my $keysize=24; |
292
|
0
|
|
|
|
|
|
$SALT=pack('H*', $SALT); |
293
|
0
|
|
|
|
|
|
my $key=Digest::MD5::md5($passwd,$SALT); |
294
|
0
|
|
|
|
|
|
while (length($key) < $keysize) { $key .= Digest::MD5::md5($key, $passwd, $SALT);} |
|
0
|
|
|
|
|
|
|
295
|
0
|
|
|
|
|
|
$key=substr($key,0,$keysize); |
296
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
# Decode Data |
298
|
0
|
|
|
|
|
|
require Crypt::DES_EDE3; |
299
|
0
|
|
|
|
|
|
my $DES = Crypt::DES_EDE3->new($key); |
300
|
0
|
|
|
|
|
|
my $dataout=""; |
301
|
0
|
|
|
|
|
|
while ( my $len=length($cyphertext) ) { |
302
|
0
|
|
|
|
|
|
my $block=substr($cyphertext,0,8); |
303
|
0
|
|
|
|
|
|
$cyphertext=substr($cyphertext,8); |
304
|
0
|
|
|
|
|
|
my $data=$SALT ^ $DES->decrypt($block); |
305
|
0
|
|
|
|
|
|
$SALT=$block; |
306
|
0
|
|
|
|
|
|
$dataout.=$data; |
307
|
|
|
|
|
|
|
} |
308
|
|
|
|
|
|
|
|
309
|
|
|
|
|
|
|
# Remove DES Padding |
310
|
0
|
|
|
|
|
|
my $unpad=substr ($dataout,-1); |
311
|
0
|
0
|
|
|
|
|
if ( "$unpad" =~ /[\001-\010]/ ) { $dataout=substr($dataout,0,-ord($unpad));} |
|
0
|
|
|
|
|
|
|
312
|
0
|
|
|
|
|
|
else { die "Your passphrase didn't do it for me!\n";} |
313
|
|
|
|
|
|
|
|
314
|
0
|
|
|
|
|
|
return $dataout; |
315
|
|
|
|
|
|
|
} |
316
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
1; |
318
|
|
|
|
|
|
|
__END__ |