]> Dogcows Code - chaz/groupsecret/blobdiff - lib/App/GroupSecret/Crypt.pm
add support for ssh-keygen without -E flag
[chaz/groupsecret] / lib / App / GroupSecret / Crypt.pm
index f5360bec464bf120148b056248042db86365bfe5..20242189b3474626afa3e33dda851143ca255a7e 100644 (file)
@@ -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);
This page took 0.021426 seconds and 4 git commands to generate.