#!/usr/bin/perl use IPC::Open3; use MIME::Base64; use File::Temp qw/ :POSIX /; use Getopt::Long; use Pod::Usage; my $initsign = ""; my $key = "pubkey.pem"; my $initfile = undef; my $help = 0; my $input = undef; my $fd = \*STDIN; GetOptions ("file=s" => \$input, "key=s" => \$key, "lastsig=s" => \$initsign, "initfile=s" => \$initfile, "help" => \$help, ); pod2usage(1) if($help); if(defined $input) { open($fd, "<$input") or die ("Can't read from $input\n"); } if($initsign ne "") { $initsign .= "\n"; } if(defined $initfile) { $initsign = `tail -n1 $initfile`; } if($initsign eq "") { print "No initial signature, chaining is not proven\n"; } my $tempfile = tmpnam(); my $buffer = ""; my $lastsign = $initsign; while(my $line=<$fd>) { if($line =~ m|--- DGST/SHA512/base64 --- (.*)|) { $signature = $1; check($lastsign, $buffer, $signature); $lastsign = $line; $buffer = ""; } else { $buffer .= $line; print $line; } } unlink($tempfile); sub check { my ($lastsign, $buffer, $signature) = @_; my $binsign = decode_base64($signature); open(my $signpipe, ">$tempfile") or die ("can't write $tempfile\n"); print $signpipe $binsign; close($signpipe); my ($stdin, $stdout, $stderr); my $pid = open3($stdin, $stdout, $stderr, "openssl dgst -sha512 -verify $key -signature $tempfile"); print $stdin $lastsign; print $stdin $buffer; close($stdin); local $/; my $message = <$stdout>; my $error = <$stderr>; waitpid( $pid, 0 ); my $status = $?; print "--- DGST/Check --- $error($status) $message"; } __END__ =head1 NAME signvalidator - verify signed logs =head1 SYNOPSIS signvalidator [options] Options --key|-k keyfile Use public key for validation (PEM encoded) --file|-f file Read file instead of stdin --lastsig|-l line Use line as last signature (used for chaining) --initfile|-i file Use last line of file as last signature (used for chaining) --help|-h This help =head1 DESCRIPTION This program will read one line at a time and write it to stdout. Each time a signature line is detected, the last content block is checked against this signature. Each signature line is replaced by the result of validation. Every time a valid block is found here is the line printed : --- DGST/Check --- (0) Verified OK =head1 SEE ALSO B Author: Benoit Peccatte (http://linux-attitude.fr) License : GPLv2 =cut