CTKlib
view release on metacpan or search on metacpan
lib/CTK/Crypt/GPG.pm view on Meta::CPAN
Copyright (C) 1998-2022 D&D Corporation. All Rights Reserved
=head1 LICENSE
This program is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.
See C<LICENSE> file and L<https://dev.perl.org/licenses/>
=cut
use vars qw/$VERSION/;
$VERSION = '1.01';
use Carp;
use CTK::Util qw(:API :FORMAT :UTIL :FILE );
use File::Temp qw();
use File::Spec;
use constant {
# GPG (GNUPG)
GPGBIN => 'gpg',
GPGCONF => 'gpg.conf',
GPGOPTS => ["verbose", "yes"],
GPGEXT => ".asc",
};
sub new {
my $class = shift;
my ($gpgbin, $gpghome, $gpgconf, $gpgopts, $pubkey, $seckey, $pass, $recipient) =
read_attributes([
['GPG','GPGBIN','BIN','CMD','COMMAND'],
['GPGHOME','GPGDIR','DIRGPG','HOMEGPG','HOMEDIR'],
['GPGCONF','CONFIG','CONF'],
['GPGOPTS','GPGOPTIONS','OPTIONS','OPTS'],
['PUBLIC','PUBLICKEY','PUP','PUBKEY','PUBRING'],
['PRIVATE','PRIV','PRIVATEKEY','SEC','SECKEY','SECRETKEY','PRIVKEY','PRIVRING','SECRING'],
['PASS','PASSWORD','PASSPHRASE','PASSW'],
['RECIPIENT','KEYID','ID','USER','KEYGRIP'],
], @_) if defined $_[0];
$gpgbin ||= which(GPGBIN);
my $tmpdir = File::Temp->newdir(TEMPLATE => 'gpgXXXXX', TMPDIR => 1) unless $gpghome;
if ($gpghome) {
preparedir($gpghome, 0700) or do {
carp(sprintf("Can't prepare dir: %s", $gpghome));
return undef;
};
} else {
$gpghome = $tmpdir->dirname;
}
$gpgconf ||= File::Spec->catfile($gpghome, GPGCONF);
$gpgopts ||= GPGOPTS;
my @opts = ('# Do not edit this file');
if (ref($gpgopts) eq 'ARRAY') { push @opts, @$gpgopts }
else { push @opts, $gpgopts }
fsave($gpgconf, join("\n", @opts)) or do {
carp(sprintf("Can't save GPG conffile: %s", $gpgconf));
return undef;
};
eval { chmod $gpgconf, 0600 };
# Get version
my @cmd = ();
push(@cmd, $gpgbin, "--homedir", $gpghome, "--options", $gpgconf, "--version");
my $err = "";
my $out = execute( [@cmd], undef, \$err, 1 );
my $version = $out && $out =~ /gpg.+?([0-9\.]+)\s*$/m ? $1 : 0;
if ($version) {
my $tv = pack("U*",split(/\./, $version));
unless ($tv gt pack("U*", 2, 0)) {
carp(sprintf("Incorrect GPG version v%vd. Require v2.0.0 and above", $tv));
return undef;
}
}
$out = "" if $version;
# Import keys
foreach my $key ($pubkey, $seckey) {
next unless $key;
next unless length($key);
next unless -e $key;
@cmd = ($gpgbin, "--homedir", $gpghome, "--options", $gpgconf);
push @cmd, "--pinentry-mode", "loopback", "--passphrase", $pass if $pass && length($pass);
push @cmd, "--import", $key;
$out = execute( [@cmd], undef, \$err, 1 );
unless ($recipient) {
foreach my $t ($out, $err) {
next unless $t;
$recipient = $1 if $t =~ /key\s+([a-z0-9]+)\:/im;
last if $recipient;
}
}
}
my $self = bless {
gpgbin => $gpgbin,
homedir => $gpghome,
tempdir => $tmpdir,
gpgconf => $gpgconf,
options => [@opts],
cmd => join(" ", @cmd),
stdout => $out,
stderr => $err,
version => $version,
pubkey => $pubkey,
seckey => $seckey,
password => $pass,
recipient => $recipient,
error => $recipient ? "" : "Incorrect recipient!",
}, $class;
return $self;
}
sub encrypt {
my $self = shift;
my ($inf, $outf, $armor) =
read_attributes([
['IN','FILEIN','INPUT','FILESRC','SRC','INFILE'],
['OUT','FILEOUT','OUTPUT','FILEDST','DST','OUTFILE'],
['ARMOR','ASCII'],
( run in 0.491 second using v1.01-cache-2.11-cpan-71847e10f99 )