File Coverage

blib/lib/Net/SSH/Perl/Util/Authfile.pm
Criterion Covered Total %
statement 21 88 23.8
branch 0 22 0.0
condition 0 9 0.0
subroutine 7 10 70.0
pod n/a
total 28 129 21.7


line stmt bran cond sub pod time code
1             package Net::SSH::Perl::Util::Authfile;
2 1     1   7 use strict;
  1         2  
  1         29  
3 1     1   5 use warnings;
  1         2  
  1         22  
4              
5 1     1   4 use Net::SSH::Perl::Buffer;
  1         2  
  1         21  
6 1     1   4 use Net::SSH::Perl::Constants qw( PRIVATE_KEY_ID_STRING );
  1         4  
  1         15  
7 1     1   6 use Net::SSH::Perl::Cipher;
  1         2  
  1         26  
8 1     1   506 use Net::SSH::Perl::Key;
  1         3  
  1         32  
9              
10 1     1   6 use Carp qw( croak );
  1         2  
  1         822  
11              
12             sub _load_public_key {
13 0     0     _load_private_key($_[0], '', 1);
14             }
15              
16             sub _load_private_key {
17 0     0     my($key_file, $passphrase, $want_public) = @_;
18 0   0       $passphrase ||= '';
19              
20 0 0         open my $fh, '<', $key_file or croak "Can't open $key_file: $!";
21 0           my $c = do { local $/; <$fh> };
  0            
  0            
22 0 0         close $fh or die "Can't close $key_file: $!";
23 0           ($c) = $c =~ /(.*)/s; ## Untaint data. Anything is allowed.
24              
25 0           my $buffer = Net::SSH::Perl::Buffer->new( MP => 'SSH1' );
26 0           $buffer->append($c);
27              
28 0           my $id = $buffer->bytes(0, length(PRIVATE_KEY_ID_STRING), "");
29 0 0         croak "Bad key file $key_file." unless $id eq PRIVATE_KEY_ID_STRING;
30 0           $buffer->bytes(0, 1, "");
31              
32 0           my $cipher_type = $buffer->get_int8;
33 0           $buffer->get_int32; ## Reserved data.
34              
35 0           my $key = Net::SSH::Perl::Key->new('RSA1');
36 0           $key->{rsa}{bits} = $buffer->get_int32;
37 0           $key->{rsa}{n} = $buffer->get_mp_int;
38 0           $key->{rsa}{e} = $buffer->get_mp_int;
39              
40 0           my $comment = $buffer->get_str;
41              
42 0 0         if ($want_public) {
43 0 0         return wantarray ? ($key, $comment) : ($key);
44             }
45              
46 0           my $cipher_name = Net::SSH::Perl::Cipher::name($cipher_type);
47 0 0         unless (Net::SSH::Perl::Cipher::supported($cipher_type)) {
48 0           croak sprintf "Unsupported cipher '%s' used in key file '%s'",
49             $cipher_name, $key_file;
50             }
51              
52 0           my $ciph =
53             Net::SSH::Perl::Cipher->new_from_key_str($cipher_name, $passphrase);
54 0           my $decrypted = $ciph->decrypt($buffer->bytes($buffer->offset));
55 0           $buffer->empty;
56 0           $buffer->append($decrypted);
57              
58 0           my $check1 = ord $buffer->get_char;
59 0           my $check2 = ord $buffer->get_char;
60 0 0 0       if ($check1 != ord($buffer->get_char) ||
61             $check2 != ord($buffer->get_char)) {
62 0           croak "Bad passphrase supplied for key file $key_file";
63             }
64              
65 0           $key->{rsa}{d} = $buffer->get_mp_int;
66 0           $key->{rsa}{u} = $buffer->get_mp_int;
67 0           $key->{rsa}{p} = $buffer->get_mp_int;
68 0           $key->{rsa}{q} = $buffer->get_mp_int;
69              
70 0 0         wantarray ? ($key, $comment) : $key;
71             }
72              
73             sub _save_private_key {
74 0     0     my($key_file, $key, $passphrase, $comment) = @_;
75 0   0       $passphrase ||= '';
76              
77 0 0         my $cipher_type = $passphrase eq '' ? 'None' : 'DES3';
78              
79 0           my $buffer = Net::SSH::Perl::Buffer->new( MP => 'SSH1' );
80 0           my($check1, $check2);
81 0           $buffer->put_int8($check1 = int rand 255);
82 0           $buffer->put_int8($check2 = int rand 255);
83 0           $buffer->put_int8($check1);
84 0           $buffer->put_int8($check2);
85              
86 0           $buffer->put_mp_int($key->{rsa}{d});
87 0           $buffer->put_mp_int($key->{rsa}{u});
88 0           $buffer->put_mp_int($key->{rsa}{p});
89 0           $buffer->put_mp_int($key->{rsa}{q});
90              
91 0           $buffer->put_int8(0)
92             while $buffer->length % 8;
93              
94 0           my $encrypted = Net::SSH::Perl::Buffer->new( MP => 'SSH1' );
95 0           $encrypted->put_chars(PRIVATE_KEY_ID_STRING);
96 0           $encrypted->put_int8(0);
97 0           $encrypted->put_int8(Net::SSH::Perl::Cipher::id($cipher_type));
98 0           $encrypted->put_int32(0);
99              
100 0           $encrypted->put_int32($key->{rsa}{bits});
101 0           $encrypted->put_mp_int($key->{rsa}{n});
102 0           $encrypted->put_mp_int($key->{rsa}{e});
103 0   0       $encrypted->put_str($comment || '');
104              
105 0           my $cipher =
106             Net::SSH::Perl::Cipher->new_from_key_str($cipher_type, $passphrase);
107 0           $encrypted->append( $cipher->encrypt($buffer->bytes) );
108              
109 0 0         open my $fh, '>', $key_file or croak "Can't open $key_file: $!";
110 0           print $fh $encrypted->bytes;
111 0 0         close $fh or croak "Can't close $key_file: $!";
112             }
113              
114             1;