Module-Signature

 view release on metacpan or  search on metacpan

Changes  view on Meta::CPAN

[Changes for 0.71 - Tue Jun  4 18:24:10 CST 2013]

* Constrain the user-specified digest name to /^\w+\d+$/.

* Avoid loading Digest::* from relative paths in @INC.

  Contributed by: Florian Weimer (CVE-2013-2145)

[Changes for 0.70 - Thu Nov 29 01:45:54 CST 2012]

* Don't check gpg version if gpg does not exist.

  This avoids unnecessary warnings during installation
  when gpg executable is not installed.

  Contributed by: Kenichi Ishigaki

[Changes for 0.69 - Fri Nov  2 23:04:19 CST 2012]

* Support for gpg under these alternate names:

    gpg gpg2 gnupg gnupg2

  Contributed by: Michael Schwern

[Changes for 0.68 - Fri, 13 May 2011 11:51:50 +0200]

* Fix breakage introduced by 0.67 (Andreas König).

[Changes for 0.67 - Sun, 17 Apr 2011 16:29:23 +0200]

* Better handling of \r (Andreas König, Zefram) (Closes RT#46339).

Changes  view on Meta::CPAN

* Don't ask user to install Crypt::OpenPGP if she does not have a
  C compiler anyway.

* ExtUtils::Manifest 1.38 does not support good enough skips even
  for Makefile.PL, sigh.

[Changes for 0.33 - 2003-08-12]

* William Wentworth-Sheilds points out that META.yml is dynamic,
  which makes SIGNATURE incorrect for people without either "diff"
  or "gpg".  Fixed.

[Changes for 0.32 - 2003-08-11]

* Take Schwern's patch to only set _maniskip for legacy EU::Manifest.

* Remove ::TieOut since we are not using it anymore.

* Reduce noise for untrusted signatures to two lines.

[Changes for 0.31 - 2003-08-10]

Changes  view on Meta::CPAN

* Ken Williams noted that M::B now works on 5.005.

[Changes for 0.22 - 2003-05-15]

* Move Signature.pm to lib/Module/Signature.pm.

* Switch to the Module::Install framework.

* Updates TODO to reflect correspondence with andk.

* Matt Southall mentioned that, if somebody has never run gpg before,
  we need to initialize it once before running test.

* Warn about potential 'Makefile' exploit as pointed out by Tels.
  Document pending.

* Bugfix for incorrect 'MALFORMED' response to signatures made from
  older versions of GnuPG, as reported by Tels.

[Changes for 0.18 - 2002-11-04]

Makefile.PL  view on Meta::CPAN

       if ( can_cc() ) {
               $requires{'Digest::SHA'} = 0;
       } else {
               $requires{'Digest::SHA::PurePerl'} = 0;
       }
}

# Is openpgp currently installed
if ( can_use ('Crypt::OpenPGP') ) {
       # Crypt::OpenPGP installed/available, continue on...
} elsif ( my $gpg = locate_gpg() ) {
       # We SHOULD have gpg, double-check formally
       requires_external_bin ($gpg);
} elsif ( can_cc() and $ENV{AUTOMATED_TESTING} ) {
       # Dive headlong into a full Crypt::OpenPGP install.
       $requires{'Crypt::OpenPGP'} = 0;
} else {
       # Ask the user what to do
       ask_user();
}

unless ( can_run('diff') ) {
       # We know Text::Diff fails on Cygwin (for now)
       if ( $^O ne 'Cygwin' ) {
               $requires{'Algorithm::Diff'} = 0;
               $requires{'Text::Diff'} = 0;
       }
   }

#####################################################################
# Support Functions

sub locate_gpg {
       print "Looking for GNU Privacy Guard (gpg), a cryptographic signature tool...\n";

       my ($gpg, $gpg_path);
       for my $gpg_bin ('gpg', 'gpg2', 'gnupg', 'gnupg2') {
               $gpg_path = can_run($gpg_bin);
               next unless $gpg_path;
               next unless `$gpg_bin --version` =~ /GnuPG/;
               next unless defined `$gpg_bin --list-public-keys`;

               $gpg = $gpg_bin;
               last;
       }
       unless ( $gpg ) {
               print "gpg not found.\n";
               return;
       }

       print "GnuPG found ($gpg_path).\n";

       return 1 if grep { /^--installdeps/} @ARGV;

       if ( prompt("Import PAUSE and author keys to GnuPG?", 'y' ) =~ /^y/i) {
               print 'Importing... ';
               system $gpg, '--quiet', '--import', qw[ AUDREYT2018.pub ANDK2020.pub PAUSE2022.pub NIKLASHOLM2018.pub TIMLEGGE2024.pub ];
               print "done.\n";
       }

       return $gpg;
}

sub ask_user {

    # Defined the prompt messages
    my $message1 = <<'END_MESSAGE';

Could not auto-detect a signature utility on your system.

What do you want me to do?

Makefile.PL  view on Meta::CPAN

END_MESSAGE

       my $choice;
       foreach ( 1 .. 3 ) {
               $choice = prompt("Your choice:", 3) || 3;
               last if $choice =~ /^[123]$/;
               print "Sorry, I cannot understand '$choice'.\n"
       }

       if ( $choice == 1 ) {
               # They claim to have installed gpg
               requires_external_bin ('gpg');
       } elsif ( $choice == 2 and $option3 == 3 ) {
               # They want to install Crypt::OpenPGP
               $requires{'Crypt::OpenPGP'} = 0;
       } else {
               # Forget about it...
               print "Module::Signature is not wanted on this host.\n";
               exit(0);
       }
}

PAUSE2022.pub  view on Meta::CPAN

gpg --export --armor 450F89EC
-----BEGIN PGP PUBLIC KEY BLOCK-----

mQGiBD4+cJARBACxOByY0SJBBuJoFrH2hoqRFny423gY6V3jq1uTgGY/PPaxP+Sq
r3RzxPct4vJcsoo48pwBsMHLrWfORq26zb6eKgmMq/CQo2gzaRbeRxCi3ke4KBmu
aREi6RjaZSU94yABtDmspUBrpYV8zfZMv5ZIQlg9W1Tu66BFOUrrNeDpKwCgosCp
9dtNAMhHkzxs8UJH5i3Uzb0D/0VLoAE8sOfUXqjc38rxiHuGBFSNC70Ih4mzGUCJ
MGT4z1X3K6uUawnXMoc8XqPaYnEgOzztMymydtr+urjUwcGnuXDSpV6nulE5irxh
zlikSTJy/42QzTMcrdRynffmJo9PRgymMI8GgWaYG5g3zzGAhi5BA6G8JKfC93IV
xiRPBACXJpLBYQljqJY9UDNJuq8nHhKiWHBXdZzrC3LM0FSF3PKuP/ugc+KBIKXm
clNPNFKla/SRbH6dMHsGIy8wnGPI5AtTS0roNQrttv3/ghRT7+OKXrGmBxZ/KHVr

lib/Module/Signature.pm  view on Meta::CPAN

            my $sock = IO::Socket::INET->new(
                Timeout => $Timeout,
                PeerAddr => "$KeyServer:$KeyServerPort",
            );
            $CanKeyRetrieve = ($sock ? 1 : 0);
            $sock->shutdown(2) if $sock;
        }
        $AutoKeyRetrieve = $CanKeyRetrieve;
    }

    if (my $version = _has_gpg()) {
        return _verify_gpg($sigtext, $plaintext, $version);
    }
    elsif (eval {require Crypt::OpenPGP; 1}) {
        return _verify_crypt_openpgp($sigtext, $plaintext);
    }
    else {
        warn "Cannot use GnuPG or Crypt::OpenPGP, please install either one first!\n";
        return _compare($sigtext, $plaintext, CANNOT_VERIFY);
    }
}

sub _has_gpg {
    my $gpg = _which_gpg() or return;
    `$gpg --version` =~ /GnuPG.*?(\S+)\s*$/m or return;
    return $1;
}

sub _fullcheck {
    my $skip = shift;
    my @extra;

    local $^W;
    local $ExtUtils::Manifest::Quiet = 1;

lib/Module/Signature.pm  view on Meta::CPAN

sub _default_skip {
    local $_ = shift;
    return 1 if /\bRCS\b/ or /\bCVS\b/ or /\B\.svn\b/ or /,v$/
             or /^MANIFEST\.bak/ or /^Makefile$/ or /^blib\//
             or /^MakeMaker-\d/ or /^pm_to_blib/ or /^blibdirs/
             or /^_build\// or /^Build$/ or /^pmfiles\.dat/
             or /^MYMETA\./
             or /~$/ or /\.old$/ or /\#$/ or /^\.#/;
}

my $which_gpg;
sub _which_gpg {
    # Cache it so we don't need to keep checking.
    return $which_gpg if $which_gpg;

    for my $gpg_bin ('gpg', 'gpg2', 'gnupg', 'gnupg2') {
        my $version = `$gpg_bin --version 2>&1`;
        if( $version && $version =~ /GnuPG/ ) {
            $which_gpg = $gpg_bin;
            return $which_gpg;
        }
    }
}

sub _verify_gpg {
    my ($sigtext, $plaintext, $version) = @_;

    local $SIGNATURE = Win32::GetShortPathName($SIGNATURE)
        if defined &Win32::GetShortPathName and $SIGNATURE =~ /[^-\w.:~\\\/]/;

    my $keyserver = _keyserver($version);

    require File::Temp;
    my $fh = File::Temp->new();
    print $fh $sigtext || _read_sigfile($SIGNATURE);
    close $fh;

    my $gpg = _which_gpg();
    my @quiet = $Verbose ? () : qw(-q --logger-fd=1);
    my @cmd = (
        $gpg, qw(--verify --batch --no-tty), @quiet, ($KeyServer ? (
            "--keyserver=$keyserver",
            ($AutoKeyRetrieve and $version ge '1.0.7')
                ? '--keyserver-options=auto-key-retrieve'
                : ()
        ) : ()), $fh->filename
    );

    my $output = '';
    if( $Verbose ) {
        warn "Executing @cmd\n";

lib/Module/Signature.pm  view on Meta::CPAN

        warn "==> MISMATCHED content between MANIFEST and the distribution! <==\n";
        warn "==> Please correct your MANIFEST file and/or delete extra files. <==\n";
    }

    if (!$overwrite and -e $SIGNATURE and IO::Interactive::is_interactive()) {
        local $/ = "\n";
        print "$SIGNATURE already exists; overwrite [y/N]? ";
        return unless <STDIN> =~ /[Yy]/;
    }

    if (my $version = _has_gpg()) {
        _sign_gpg($SIGNATURE, $plaintext, $version);
    }
    elsif (eval {require Crypt::OpenPGP; 1}) {
        _sign_crypt_openpgp($SIGNATURE, $plaintext);
    }
    else {
        die 'Cannot use GnuPG or Crypt::OpenPGP, please install either one first!';
    }

    warn "==> SIGNATURE file created successfully. <==\n";
    return SIGNATURE_OK;
}

sub _sign_gpg {
    my ($sigfile, $plaintext, $version) = @_;

    die "Could not write to $sigfile"
        if -e $sigfile and (-d $sigfile or not -w $sigfile);

    my $gpg = _which_gpg();

    my $gpg_fh;
    my $set_key = '';
    $set_key = qq{--default-key "$AUTHOR"} if($AUTHOR);
    open ($gpg_fh, '|-', "$gpg $set_key --clearsign --openpgp --personal-digest-preferences RIPEMD160 >> $sigfile.tmp")
        or die "Could not call $gpg: $!";
    print $gpg_fh $plaintext;
    close $gpg_fh;

    (-e "$sigfile.tmp" and -s "$sigfile.tmp") or do {
        unlink "$sigfile.tmp";
        die "Cannot find $sigfile.tmp, signing aborted.\n";
    };

    my $sigfile_tmp_fh;
    open ($sigfile_tmp_fh, '<', "$sigfile.tmp") or die "Cannot open $sigfile.tmp: $!";

    my $sigfile_fh;

lib/Module/Signature.pm  view on Meta::CPAN

    print $sigfile_fh $Preamble;
    print $sigfile_fh (<$sigfile_tmp_fh>);

    close $sigfile_fh;
    close $sigfile_tmp_fh;

    unlink("$sigfile.tmp");

    my $key_id;
    my $key_name;
    my @verify = `$gpg --batch --logger-fd 1 --verify $SIGNATURE`;
    foreach (@verify) {
        if (/key(?: ID)? ([0-9A-F]+)$/) {
            $key_id = $1;
        } elsif (/signature from "(.+)"(?: \[[a-z]+\])?$/) {
            $key_name = $1;
        }
    }
    my $found_name;
    my $found_key;
    if (defined $key_id && defined $key_name) {
        my $keyserver = _keyserver($version);
        foreach (`$gpg --output - --keyserver=$keyserver --recv-key '$key_id' 2>&1`) {
            if (/^\(\d+\)/) {
                $found_name = 0;
            } elsif ($key_id) {
                my $short_key_id = substr($key_id, (length($key_id) - 16));
                if (/key \Q$short_key_id\E/) {
                    $found_key = 1;
                    last;
                }
            }

lib/Module/Signature.pm  view on Meta::CPAN


=head1 VARIABLES

No package variables are exported by default.

=over 4

=item $Verbose

If true, Module::Signature will give information during processing including
gpg output.  If false, Module::Signature will be as quiet as possible as
long as everything is working ok.  Defaults to false.

=item $SIGNATURE

The filename for a distribution's signature file.  Defaults to
C<SIGNATURE>.

=item $AUTHOR

The key ID used for signature. If empty/null/0, C<gpg>'s configured default ID,
or the most recently added key within the secret keyring for C<Crypt::OpenPGP>,
will be used for the signature.

=item $KeyServer

The OpenPGP key server for fetching the author's public key
(currently only implemented on C<gpg>, not C<Crypt::OpenPGP>).
May be set to a false value to prevent this module from
fetching public keys.

=item $KeyServerPort

The OpenPGP key server port, defaults to C<11371>.

=item $Timeout

Maximum time to wait to try to establish a link to the key server.

maint/Makefile_header.PL  view on Meta::CPAN

       if ( can_cc() ) {
               $requires{'Digest::SHA'} = 0;
       } else {
               $requires{'Digest::SHA::PurePerl'} = 0;
       }
}

# Is openpgp currently installed
if ( can_use ('Crypt::OpenPGP') ) {
       # Crypt::OpenPGP installed/available, continue on...
} elsif ( my $gpg = locate_gpg() ) {
       # We SHOULD have gpg, double-check formally
       requires_external_bin ($gpg);
} elsif ( can_cc() and $ENV{AUTOMATED_TESTING} ) {
       # Dive headlong into a full Crypt::OpenPGP install.
       $requires{'Crypt::OpenPGP'} = 0;
} else {
       # Ask the user what to do
       ask_user();
}

unless ( can_run('diff') ) {
       # We know Text::Diff fails on Cygwin (for now)
       if ( $^O ne 'Cygwin' ) {
               $requires{'Algorithm::Diff'} = 0;
               $requires{'Text::Diff'} = 0;
       }
   }

#####################################################################
# Support Functions

sub locate_gpg {
       print "Looking for GNU Privacy Guard (gpg), a cryptographic signature tool...\n";

       my ($gpg, $gpg_path);
       for my $gpg_bin ('gpg', 'gpg2', 'gnupg', 'gnupg2') {
               $gpg_path = can_run($gpg_bin);
               next unless $gpg_path;
               next unless `$gpg_bin --version` =~ /GnuPG/;
               next unless defined `$gpg_bin --list-public-keys`;

               $gpg = $gpg_bin;
               last;
       }
       unless ( $gpg ) {
               print "gpg not found.\n";
               return;
       }

       print "GnuPG found ($gpg_path).\n";

       return 1 if grep { /^--installdeps/} @ARGV;

       if ( prompt("Import PAUSE and author keys to GnuPG?", 'y' ) =~ /^y/i) {
               print 'Importing... ';
               system $gpg, '--quiet', '--import', qw[ AUDREYT2018.pub ANDK2020.pub PAUSE2022.pub NIKLASHOLM2018.pub TIMLEGGE2024.pub ];
               print "done.\n";
       }

       return $gpg;
}

sub ask_user {

    # Defined the prompt messages
    my $message1 = <<'END_MESSAGE';

Could not auto-detect a signature utility on your system.

What do you want me to do?

maint/Makefile_header.PL  view on Meta::CPAN

END_MESSAGE

       my $choice;
       foreach ( 1 .. 3 ) {
               $choice = prompt("Your choice:", 3) || 3;
               last if $choice =~ /^[123]$/;
               print "Sorry, I cannot understand '$choice'.\n"
       }

       if ( $choice == 1 ) {
               # They claim to have installed gpg
               requires_external_bin ('gpg');
       } elsif ( $choice == 2 and $option3 == 3 ) {
               # They want to install Crypt::OpenPGP
               $requires{'Crypt::OpenPGP'} = 0;
       } else {
               # Forget about it...
               print "Module::Signature is not wanted on this host.\n";
               exit(0);
       }
}

t/2-cygwin.t  view on Meta::CPAN


use Module::Signature;
use Test::More;

if ($^O ne 'cygwin') {
    plan skip_all => "Cygwin only tests";
}
elsif (! $ENV{TEST_CYGWIN_GNUPG} ) {
    plan skip_all => 'Set the environment variable TEST_CYGWIN_GNUPG to enable this test';
}
elsif (! -x '/usr/local/bin/gpg') {
    plan skip_all => '/usr/local/bin/gpg not found';
}

plan tests => 1;

my $version = Module::Signature::_has_gpg();

like($version, qr/^\d+\.\d+\.\d+$/, "gpg version detected");



( run in 1.512 second using v1.01-cache-2.11-cpan-df04353d9ac )