| 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__ |