#!/usr/bin/perl # # Quick hack to make SHA256 files and create gpg detached signatures # for all packages and SHA256 files. use warnings; use File::Find; use Digest::SHA; umask(022); my @signfiles = (); my $startdir = $ARGV[0]; die "usage: $0 start_dir\n" unless defined($startdir); $| = 1; # unbuffered stdout print "Computing checksums and checking signatures"; find(\&wanted, $startdir); print "\n"; # Now sign the files but only read the passphrase once if (scalar(@signfiles)) { system("stty -echo"); print "Enter passphrase: "; chomp(my $pass = ); system("stty echo"); foreach (@signfiles) { # XXX - catch errors and reprompt if passphrase bad open(GPG, "|gpg --yes --passphrase-fd 0 -b $_"); print GPG $pass; close(GPG); } $pass =~ s/./x/g; # probably not effective } else { print "No changes needed\n"; } exit(0); # XXX - return an error if warranted sub wanted { if (-d && opendir(DIR, $_)) { my @files = (); while (defined(my $file = readdir(DIR))) { next unless $file =~ /\.(gz|deb|rpm|pkg)$/; push(@files, $file); } if (int(@files)) { print "."; if (write_sha($_, @files)) { foreach (@files, 'SHA256') { # Only need to sign if no valid existing signature my $file = $File::Find::name . "/$_"; my $sign_it = 1; if (-f "$file.sig") { system("gpg -quiet --no-tty --verify $file.sig $file >/dev/null 2>&1"); $sign_it = $? >> 8; } push(@signfiles, $file) if $sign_it; } } } closedir(DIR); } } sub write_sha { my ($dir, @files) = @_; # Calculate SHA256 digest of all the files in the dir my $sha = Digest::SHA->new(256); my %digests; foreach my $file (@files) { if (open(FILE, '<', "$dir/$file")) { $sha->addfile(*FILE); $digests{$file} = $sha->hexdigest; close(FILE); $sha->reset; } else { warn "$dir/$file: $!\n"; } } if (scalar(keys %digests)) { my $modified = 1; if (open(SHA256, '<', "$dir/SHA256")) { my %old_digests; while () { chomp; my ($digest, $file) = split; $old_digests{$file} = $digest; } close(SHA256); # Check existing digest file for modifications if (scalar(keys %old_digests) == scalar(keys %digests)) { $modified = 0; foreach my $file (sort keys %digests) { if ($old_digests{$file} ne $digests{$file}) { $modified = 1; last; } } } } if ($modified) { if (open(SHA256, '>', "$dir/SHA256")) { # Digest file missing or changed, write a new one foreach my $file (sort keys %digests) { print SHA256 "$digests{$file} $file\n"; } close(SHA256); return 1; } else { warn "$dir/SHA256: $!\n"; } } } return 0; }