X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Fgroupsecret;a=blobdiff_plain;f=lib%2FApp%2FGroupSecret%2FCrypt.pm;h=20242189b3474626afa3e33dda851143ca255a7e;hp=f5360bec464bf120148b056248042db86365bfe5;hb=ac76dab2d994d3de86fb59c1ffac0a01bcebbac8;hpb=93527579d68b0ccdd5dab72d88764a53fef43b88 diff --git a/lib/App/GroupSecret/Crypt.pm b/lib/App/GroupSecret/Crypt.pm index f5360be..2024218 100644 --- a/lib/App/GroupSecret/Crypt.pm +++ b/lib/App/GroupSecret/Crypt.pm @@ -9,6 +9,8 @@ our $VERSION = '9999.999'; # VERSION use Exporter qw(import); use File::Temp; use IPC::Open2; +use IPC::Open3; +use Symbol qw(gensym); use namespace::clean -except => [qw(import)]; our @EXPORT_OK = qw( @@ -21,6 +23,9 @@ our @EXPORT_OK = qw( encrypt_aes_256_cbc ); +our $OPENSSL = 'openssl'; +our $SSH_KEYGEN = 'ssh-keygen'; + sub _croak { require Carp; Carp::croak(@_) } sub _usage { _croak("Usage: @_\n") } @@ -35,12 +40,11 @@ Get a certain number of secure random bytes. sub generate_secure_random_bytes { my $size = shift or _usage(q{generate_secure_random_bytes($num_bytes)}); - my @cmd = (qw{openssl rand}, $size); + my @cmd = ($OPENSSL, 'rand', $size); - my ($in, $out); - my $pid = open2($out, $in, @cmd); + my $out; + my $pid = open2($out, undef, @cmd); - close($in); waitpid($pid, 0); my $status = $?; @@ -61,12 +65,10 @@ Read a RFC4716 (SSH2) public key from a file, converting it to PKCS8 (PEM). sub read_openssh_public_key { my $filepath = shift or _usage(q{read_openssh_public_key($filepath)}); - my @cmd = (qw{ssh-keygen -e -m PKCS8 -f}, $filepath); + my @cmd = ($SSH_KEYGEN, qw{-e -m PKCS8 -f}, $filepath); - my ($in, $out); - my $pid = open2($out, $in, @cmd); - - close($in); + my $out; + my $pid = open2($out, undef, @cmd); waitpid($pid, 0); my $status = $?; @@ -88,21 +90,37 @@ Get the fingerprint of an OpenSSH private or public key. sub read_openssh_key_fingerprint { my $filepath = shift or _usage(q{read_openssh_key_fingerprint($filepath)}); - my @cmd = (qw{ssh-keygen -l -E md5 -f}, $filepath); + # try with the -E flag first + my @cmd = ($SSH_KEYGEN, qw{-l -E md5 -f}, $filepath); my $out; - my $pid = open2($out, undef, @cmd); + my $err = gensym; + my $pid = open3(undef, $out, $err, @cmd); waitpid($pid, 0); my $status = $?; my $exit_code = $status >> 8; - _croak 'Failed to read SSH2 key fingerprint' if $exit_code != 0; + if ($exit_code != 0) { + my $error_str = do { local $/; <$err> }; + _croak 'Failed to read SSH2 key fingerprint' if $error_str !~ /unknown option -- E/s; + + @cmd = ($SSH_KEYGEN, qw{-l -f}, $filepath); + + undef $out; + $pid = open2($out, undef, @cmd); + + waitpid($pid, 0); + $status = $?; + + $exit_code = $status >> 8; + _croak 'Failed to read SSH2 key fingerprint' if $exit_code != 0; + } my $line = do { local $/; <$out> }; chomp $line; - my ($bits, $fingerprint, $comment, $type) = $line =~ m!^(\d+) MD5:([^ ]+) (.*) \(([^\)]+)\)$!; + my ($bits, $fingerprint, $comment, $type) = $line =~ m!^(\d+) (?:MD5:)?([^ ]+) (.*) \(([^\)]+)\)$!; $fingerprint =~ s/://g; @@ -138,13 +156,11 @@ sub decrypt_rsa { $filepath = $temp->filename; } - my @cmd = (qw{openssl rsautl -decrypt -oaep -in}, $filepath, '-inkey', $privkey); + my @cmd = ($OPENSSL, qw{rsautl -decrypt -oaep -in}, $filepath, '-inkey', $privkey); push @cmd, ('-out', $outfile) if $outfile; - my ($in, $out); - my $pid = open2($out, $in, @cmd); - - close($in); + my $out; + my $pid = open2($out, undef, @cmd); waitpid($pid, 0); my $status = $?; @@ -186,13 +202,11 @@ sub encrypt_rsa { close $temp2; my $keypath = $temp2->filename; - my @cmd = (qw{openssl rsautl -encrypt -oaep -pubin -inkey}, $keypath, '-in', $filepath); + my @cmd = ($OPENSSL, qw{rsautl -encrypt -oaep -pubin -inkey}, $keypath, '-in', $filepath); push @cmd, ('-out', $outfile) if $outfile; - my ($in, $out); - my $pid = open2($out, $in, @cmd); - - close($in); + my $out; + my $pid = open2($out, undef, @cmd); waitpid($pid, 0); my $status = $?; @@ -227,7 +241,7 @@ sub decrypt_aes_256_cbc { $filepath = $temp->filename; } - my @cmd = (qw{openssl aes-256-cbc -d -pass stdin -in}, $filepath); + my @cmd = ($OPENSSL, qw{aes-256-cbc -d -pass stdin -md sha256 -in}, $filepath); push @cmd, ('-out', $outfile) if $outfile; my ($in, $out); @@ -269,7 +283,7 @@ sub encrypt_aes_256_cbc { $filepath = $temp->filename; } - my @cmd = (qw{openssl aes-256-cbc -pass stdin -in}, $filepath); + my @cmd = ($OPENSSL, qw{aes-256-cbc -pass stdin -md sha256 -in}, $filepath); push @cmd, ('-out', $outfile) if $outfile; my ($in, $out);