From 2f9e679a099ab2e59aed109e1d5e3555b5c23b57 Mon Sep 17 00:00:00 2001 From: Marius Gavrilescu Date: Sun, 6 Jul 2014 09:52:45 +0300 Subject: [PATCH] Initial commit --- Changes | 4 + MANIFEST | 24 ++++ Makefile.PL | 29 ++++ README | 37 +++++ edwardng | 113 +++++++++++++++ lib/App/EdwardNG.pm | 244 +++++++++++++++++++++++++++++++++ t/App-EdwardNG.t | 43 ++++++ t/data/inline-encrypted | 21 +++ t/data/inline-signed | 26 ++++ t/data/inline-signed-encrypted | 27 ++++ t/data/mime-encrypted | 31 +++++ t/data/mime-signed | 32 +++++ t/data/mime-signed-encrypted | 39 ++++++ t/keydir/pubring.gpg | Bin 0 -> 1213 bytes t/keydir/secring.gpg | Bin 0 -> 2515 bytes t/keydir/trustdb.gpg | Bin 0 -> 1200 bytes tmpl/en/encrypt | 7 + tmpl/en/encrypt_error | 1 + tmpl/en/error | 1 + tmpl/en/plain | 1 + tmpl/en/sign | 4 + tmpl/en/sign_error | 1 + tmpl/en/signencrypt | 7 + tmpl/en/subject | 1 + 24 files changed, 693 insertions(+) create mode 100644 Changes create mode 100644 MANIFEST create mode 100644 Makefile.PL create mode 100644 README create mode 100755 edwardng create mode 100644 lib/App/EdwardNG.pm create mode 100644 t/App-EdwardNG.t create mode 100644 t/data/inline-encrypted create mode 100644 t/data/inline-signed create mode 100644 t/data/inline-signed-encrypted create mode 100644 t/data/mime-encrypted create mode 100644 t/data/mime-signed create mode 100644 t/data/mime-signed-encrypted create mode 100644 t/keydir/pubring.gpg create mode 100644 t/keydir/secring.gpg create mode 100644 t/keydir/trustdb.gpg create mode 100644 tmpl/en/encrypt create mode 100644 tmpl/en/encrypt_error create mode 100644 tmpl/en/error create mode 100644 tmpl/en/plain create mode 100644 tmpl/en/sign create mode 100644 tmpl/en/sign_error create mode 100644 tmpl/en/signencrypt create mode 100644 tmpl/en/subject diff --git a/Changes b/Changes new file mode 100644 index 0000000..08d38a8 --- /dev/null +++ b/Changes @@ -0,0 +1,4 @@ +Revision history for Perl extension App::EdwardNG. + +0.001 Not Released + - Initial release diff --git a/MANIFEST b/MANIFEST new file mode 100644 index 0000000..405cd62 --- /dev/null +++ b/MANIFEST @@ -0,0 +1,24 @@ +Changes +edwardng +lib/App/EdwardNG.pm +Makefile.PL +MANIFEST +README +t/App-EdwardNG.t +t/data/inline-encrypted +t/data/inline-signed +t/data/inline-signed-encrypted +t/data/mime-encrypted +t/data/mime-signed +t/data/mime-signed-encrypted +t/keydir/pubring.gpg +t/keydir/secring.gpg +t/keydir/trustdb.gpg +tmpl/en/encrypt +tmpl/en/encrypt_error +tmpl/en/error +tmpl/en/plain +tmpl/en/sign +tmpl/en/sign_error +tmpl/en/signencrypt +tmpl/en/subject diff --git a/Makefile.PL b/Makefile.PL new file mode 100644 index 0000000..99e91db --- /dev/null +++ b/Makefile.PL @@ -0,0 +1,29 @@ +use 5.014000; +use ExtUtils::MakeMaker; + +WriteMakefile( + NAME => 'App::EdwardNG', + VERSION_FROM => 'lib/App/EdwardNG.pm', + ABSTRACT_FROM => 'lib/App/EdwardNG.pm', + AUTHOR => 'Marius Gavrilescu ', + MIN_PERL_VERSION => '5.14.0', + LICENSE => 'perl', + SIGN => 1, + PREREQ_PM => { + qw/Email::Sender::Simple 0 + File::Slurp 0 + Getopt::Long 0 + MIME::Entity 5.419 + MIME::Parser 5.419 + Mail::GnuPG 0 + PerlX::Maybe 0 + Template 0 + Try::Tiny 0/ + }, + META_MERGE => { + dynamic_config => 0, + resources => { + repository => 'https://git.ieval.ro/?p=app-edwardng.git', + } + } +); diff --git a/README b/README new file mode 100644 index 0000000..84a06d3 --- /dev/null +++ b/README @@ -0,0 +1,37 @@ +App-EdwardNG version 0.001 +========================== + +EdwardNG is a reimplementation of the Edward reply bot referenced in https://emailselfdefense.fsf.org/. + +It takes mail messages, checks them for PGP signatures and encryption, then replies appropriately. + +INSTALLATION + +To install this module type the following: + + perl Makefile.PL + make + make test + make install + +DEPENDENCIES + +This module requires these other modules and libraries: + + * Email::Sender + * File::Slurp + * MIME-Tools + * Mail::GnuPG + * PerlX::Maybe + * Template-Toolkit + * Try::Tiny + +COPYRIGHT AND LICENCE + +Copyright (C) 2014 by Marius Gavrilescu + +This library is free software; you can redistribute it and/or modify +it under the same terms as Perl itself, either Perl version 5.18.2 or, +at your option, any later version of Perl 5 you may have available. + + diff --git a/edwardng b/edwardng new file mode 100755 index 0000000..e111f70 --- /dev/null +++ b/edwardng @@ -0,0 +1,113 @@ +#!/usr/bin/perl -w +use v5.14; +use App::EdwardNG; + +App::EdwardNG->run; + +__END__ + +=encoding utf-8 + +=head1 NAME + +edwardng - GnuPG email sign/encrypt testing bot + +=head1 SYNOPSIS + +edwardng -- + + +=head1 DESCRIPTION + +EdwardNG is a reimplementation of the Edward reply bot referenced in L. + +It takes mail messages, checks them for PGP signatures and encryption, then replies appropriately. + +=head1 OPTIONS + +=over + +=item B<--always-trust>, B<--no-always-trust> + +If B<--always-trust>, skip key validation and assume that used keys are always fully trusted. See the gpg(1) manpage, option C<--trust-model always> for more information. Defaults to B<--no-always-trust>. + +=item B<--debug>, B<--no-debug> + +If B<--debug>, output some debugging information on STDERR. Defaults to B<--no-debug> + +=item B<--from>=I
+ +Mail address to send messages from. + +=item B<--key>=I + +ID of key used for encrypting replies. + +=item B<--keydir>=I + +Path to GnuPG homedir. + +=item B<--passphrase>=I + +Private key passphrase. + +=item B<--use-agent>, B<--no-use-agent> + +If B<--use-agent>, use L. Defaults to B<--no-gpg-agent>. + +=back + +=head1 ENVIRONMENT + +Configuration can also be done via the environment. Use 1 for true and 0 for false. Command-line options override environment variables. + +=over + +=item EDWARDNG_ALWAYS_TRUST + +Corresponds to B<--always-trust> (if true) and B<--no-always-trust> (if false). + +=item EDWARDNG_DEBUG + +Corresponds to B<--debug> (if true) and B<--no-debug> (if false). + +=item EDWARDNG_FROM + +Corresponds to B<--from>. + +=item EDWARDNG_KEY + +Corresponds to B<--key>. + +=item EDWARDNG_KEYDIR + +Corresponds to B<--keydir>. + +=item EDWARDNG_PASSPHRASE + +Corresponds to B<--passphrase>. + +=item EDWARDNG_USE_AGENT + +Corresponds to B<--use-agent> (if true) and B<--no-use-agent> (if false). + +=back + +=head1 SEE ALSO + +L + +=head1 AUTHOR + +Marius Gavrilescu, Emarius@ieval.roE + +=head1 COPYRIGHT AND LICENSE + +Copyright (C) 2014 by Marius Gavrilescu + +This library is free software; you can redistribute it and/or modify +it under the same terms as Perl itself, either Perl version 5.18.2 or, +at your option, any later version of Perl 5 you may have available. + + +=cut diff --git a/lib/App/EdwardNG.pm b/lib/App/EdwardNG.pm new file mode 100644 index 0000000..6ccc059 --- /dev/null +++ b/lib/App/EdwardNG.pm @@ -0,0 +1,244 @@ +package App::EdwardNG; + +use 5.014000; +use strict; +use warnings; +use parent qw/Exporter/; +our $VERSION = '0.001'; +our @EXPORT = qw/process_message/; + +use Email::Sender::Simple qw/sendmail/; +use File::Slurp qw/read_file/; +use Getopt::Long; +use MIME::Entity; +use MIME::Parser; +use Mail::GnuPG; +use PerlX::Maybe; +use Template; +use Try::Tiny; + +sub debug { say STDERR @_ if $ENV{EDWARDNG_DEBUG} } +sub stringify ($) { join '', map {; '>', $_ } @{$_[0]} } +sub mg { + Mail::GnuPG->new( + key => $ENV{EDWARDNG_KEY}, + maybe always_trust => $ENV{EDWARDNG_ALWAYS_TRUST}, + maybe keydir => $ENV{EDWARDNG_KEYDIR}, + maybe passphrase => $ENV{EDWARDNG_PASSPHRASE}, + maybe use_agent => $ENV{EDWARDNG_USE_AGENT}, + @_); +} + +sub first_part{ + my ($ent) = @_; + return first_part $ent->parts(0) if $ent->parts; + $ent->bodyhandle->as_string +} + +sub process_message { + my ($msg) = @_; + my $parser = MIME::Parser->new; + $parser->decode_bodies(0); + $parser->output_to_core(1); + + if (ref $msg eq 'MIME::Entity') { + debug 'Got MIME::Entity'; + } elsif (ref $msg eq 'IO') { + debug 'Parsing from filehandle'; + $msg = $parser->parse($msg) + } elsif (ref $msg eq 'SCALAR') { + debug 'Parsing from string'; + $msg = $parser->parse_data($$msg) + } elsif (!ref $msg) { + debug "Parsing from file $msg"; + $msg = $parser->parse_open($msg) + } else { + die "Don't know how to parse $msg" + } + + if ($msg->mime_type ne 'multipart/signed' && $msg->mime_type ne 'multipart/encrypted') { + # PGP/Inline requires decoding + $parser->decode_bodies(1); + $msg = $parser->parse_data($msg->stringify) + } + + my $gpg = mg; + if ($gpg->is_signed($msg)) { + debug 'This mail looks signed'; + my ($code, $keyid, $email) = $gpg->verify($msg); + return sign_error => ( + message => stringify $gpg->{last_message}) if $code; + return sign => ( + keyid => $keyid, + email => $email, + message => stringify $gpg->{last_message}); + } + + if ($gpg->is_encrypted($msg)) { + debug 'This mail looks encrypted'; + my ($code, $keyid, $email) = $gpg->decrypt($msg); + return encrypt_error => ( + message => stringify $gpg->{last_message}) if $code; + return encrypt => ( + plaintext => stringify $gpg->{plaintext}, + decrypted => $gpg->{decrypted}, + message => stringify $gpg->{last_message}) unless defined $keyid; + return signencrypt => ( + keyid => $keyid, + email => $email, + plaintext => stringify $gpg->{plaintext}, + decrypted => $gpg->{decrypted}, + message => stringify $gpg->{last_message}); + } + + debug 'This mail doesn\'t seem to be signed or encrypted'; + return 'plain' +} + +sub run { + GetOptions( + 'always-trust!' => \$ENV{EDWARDNG_ALWAYS_TRUST}, + 'debug!' => \$ENV{EDWARDNG_DEBUG}, + 'from=s' => \$ENV{EDWARDNG_FROM}, + 'key=s' => \$ENV{EDWARDNG_KEY}, + 'keydir=s' => \$ENV{EDWARDNG_KEYDIR}, + 'passphrase=s' => \$ENV{EDWARDNG_PASSPHRASE}, + 'use-agent!' => \$ENV{EDWARDNG_USE_AGENT}, + ); + + my $parser = MIME::Parser->new; + $parser->decode_bodies(0); + $parser->output_to_core(1); + my $in = $parser->parse(\*STDIN); + + my ($tmpl, %params); + try { + ($tmpl, %params) = process_message $in + } catch { + ($tmpl, %params) = (error => message => $_) + }; + + $params{plaintext} = first_part $params{decrypted} if $params{decrypted}; + + my $tt = Template->new(INCLUDE_PATH => 'tmpl/en'); + my ($data, $subject); + $tt->process($tmpl, \%params, \$data); + $tt->process('subject', undef, \$subject); + my $email = MIME::Entity->build( + From => $ENV{EDWARDNG_FROM}, + To => $in->get('From'), + Subject => $subject, + Data => $data); + + my $mg = mg always_trust => 1; + $mg->mime_signencrypt($email, $in->get('From') =~ /<(.*)>/) and debug 'Could not encrypt message. GnuPG said ', stringify $mg->{last_message}; + sendmail $email +} + +1; +__END__ + +=encoding utf-8 + +=head1 NAME + +App::EdwardNG - GnuPG email sign/encrypt testing bot + +=head1 SYNOPSIS + + use App::EdwardNG; + my ($status, %params) = process_message '/path/to/message'; + if ($status eq 'signencrypt') { + say 'This message is encrypted and signed with key ', $params{keyid}, ' from ', $params{email}; + say 'Its contents are: ', $params{plaintext}; + } elsif ($status eq 'encrypt') { + say 'This message is encrypted but not signed'; + say 'Its contents are: ', $params{plaintext}; + } elsif ($status eq 'encrypt_error') { + say 'This message is encrypted but I was unable to decrypt it. GnuPG output: ', $params{message}; + } elsif ($status eq 'sign') { + say 'This message is signed with key ', $params{keyid}, ' from ', $params{email}; + } elsif ($status eq 'sign_error') { + say 'This message is signed but I was unable to verify the signature. GnuPG output: ', $params{message}; + } elsif ($status eq 'plain') { + say 'This message is neither signed nor encrypted'; + } elsif ($status eq 'error') { + say 'There was an error processing the message: ', $params{message}; + } + +=head1 DESCRIPTION + +EdwardNG is a reimplementation of the Edward reply bot referenced in L. + +It takes mail messages, checks them for PGP signatures and encryption, then replies appropriately. + +This module exports a single function, B, which takes a single parameter representing the message. This parameter can be: + +=over + +=item A filehandle reference, e.g. C<\*STDIN>. + +=item A reference to a scalar which holds the message contents. + +=item A scalar which represents a path to a message. + +=item A L object + +=back + +The function returns a status followed by a hash. Possible results: + +=over + +=item plain + +The message is neither signed nor encrypted. + +=item sign_error, message => $message + +The message is signed but the signature could not be verified. GnuPG output is $message. + +=item sign, keyid => $keyid, email => $email, message => $message + +The message is signed with key $keyid from $email. GnuPG output is $message. + +=item encrypt_error, message => $message + +The message is encrypted and unable to be decrypted. GnuPG output is $message. + +=item encrypt, plaintext => $plaintext, decrypted => $decrypted, message => $message + +The message is encrypted and unsigned. $plaintext is the decrypted message as plain text, while $decrypted is a MIME::Entity representing the decrypted message. GnuPG output is $message. + +=item signencrypt, plaintext => $plaintext, decrypted => $decrypted, keyid => $keyid, email => $email, message => $message + +The message is encrypted and signed with key $keyid from $email. $plaintext is the decrypted message as plain text, while $decrypted is a MIME::Entity representing the decrypted message. GnuPG output is $message. + +=item error, message => $message + +There was an error while processing the message. The error can be found in $message. + +=back + +=head1 ENVIRONMENT + +This module is configured via the %ENV hash. See the L manpage for more information. + +=head1 SEE ALSO + +L + +=head1 AUTHOR + +Marius Gavrilescu, Emarius@ieval.roE + +=head1 COPYRIGHT AND LICENSE + +Copyright (C) 2014 by Marius Gavrilescu + +This library is free software; you can redistribute it and/or modify +it under the same terms as Perl itself, either Perl version 5.18.2 or, +at your option, any later version of Perl 5 you may have available. + + +=cut diff --git a/t/App-EdwardNG.t b/t/App-EdwardNG.t new file mode 100644 index 0000000..4b4550e --- /dev/null +++ b/t/App-EdwardNG.t @@ -0,0 +1,43 @@ +#!/usr/bin/perl -w +use strict; +use warnings; + +use constant KEYID => '34B22806'; +use constant EMAIL => 'EdwardNG (Key for testing EdwardNG) '; + +use Test::More tests => 19; +BEGIN { use_ok('App::EdwardNG') }; +$ENV{EDWARDNG_DEBUG} = $ENV{TEST_VERBOSE}; +$ENV{EDWARDNG_KEYDIR} = 't/keydir'; + +my ($tmpl, %params); + +sub process { + my ($name, $expected) = @_; + ($tmpl, %params) = App::EdwardNG::process_message("t/data/$name"); + is $tmpl, $expected, "Result for $name is $expected" or diag "GnuPG said: $params{message}" +} + +process 'mime-signed', 'sign'; +is $params{keyid}, KEYID, 'mime-signed keyid'; +is $params{email}, EMAIL, 'mime-signed email'; + +process 'mime-encrypted', 'encrypt'; +like $params{plaintext}, qr/MIME encrypted/, 'mime-signed plaintext'; + +process 'mime-signed-encrypted', 'signencrypt'; +is $params{keyid}, KEYID, 'mime-signed-encrypted keyid'; +is $params{email}, EMAIL, 'mime-signed-encrypted email'; +like $params{plaintext}, qr/MIME signed & encrypted/, 'mime-signed-encrypted plaintext'; + +process 'inline-signed', 'sign'; +is $params{keyid}, KEYID, 'inline-signed keyid'; +is $params{email}, EMAIL, 'inline-signed email'; + +process 'inline-encrypted', 'encrypt'; +like $params{plaintext}, qr/Inline encrypted/, 'inline-signed plaintext'; + +process 'inline-signed-encrypted', 'signencrypt'; +is $params{keyid}, KEYID, 'inline-signed-encrypted keyid'; +is $params{email}, EMAIL, 'inline-signed-encrypted email'; +like $params{plaintext}, qr/Inline signed & encrypted/, 'inline-signed-encrypted plaintext'; diff --git a/t/data/inline-encrypted b/t/data/inline-encrypted new file mode 100644 index 0000000..4f17c00 --- /dev/null +++ b/t/data/inline-encrypted @@ -0,0 +1,21 @@ +From: EdwardNG +To: EdwardNG +Subject: Inline Encrypted +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii + +-----BEGIN PGP MESSAGE----- +Version: GnuPG v1 + +hQEMAzLKYfkz3zGcAQgAujmOHpwpHD8nlYcwSlF2peRV98+JFZd78gfikpS7lq01 +C5xFK7u/GkbNwb3Y7YLFGlectQIzpIkRSnPtTqO9nkVZ0vk9sSP5nztuc6pWZztU +zre0yFedLFgSSUeIpSwMAfluB4cUWBBJkP/LryMWpvetJ6kqBFAciffz/5apf8Ol +Fij5/4zkA/5NKNmy+jlDVtmaSI+cuGp5LCNqWHTcpNqRFFXh1GBWAVahmc0fwpzU +R0PWgfE+X9IpxnqvHSLUW8vcevdd/vuChd0e6vn+k6DEFvsSm8E3qIpv1KvAzvPZ +A/RbgBM8XzpD1JQQy+NekTJO1Xe1BiFizZbYlMRpndJ8AXle3rZFhYhtty8mGLVZ +xGt41ptvQPjF7iVJxIMjgrpg212ZZWUfiFn0Ao67WFYvlfCUIymalf34tynPMop/ +F3S5qmAhLAuGf0VauMQqDjneAsfmMG9TrBIC0eu7pSRY+JkDVxavI9ABjqkPi/oy +Zn9pulUxMMRlMoi53Q== +=5snb +-----END PGP MESSAGE----- + diff --git a/t/data/inline-signed b/t/data/inline-signed new file mode 100644 index 0000000..408ba7e --- /dev/null +++ b/t/data/inline-signed @@ -0,0 +1,26 @@ +From: EdwardNG +To: EdwardNG +Subject: Inline Signed +MIME-Version: 1.0 +Content-Type: text/plain +Content-Transfer-Encoding: quoted-printable + +=2D----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA512 + + +This is a PGP/Inline signed message. +=2D --=20 +Marius Gavrilescu +=2D----BEGIN PGP SIGNATURE----- +Version: GnuPG v1 + +iQEcBAEBCgAGBQJTuFUmAAoJEPduLdg0sigG5mcH/0Iu5/1bcj2FHcHF/7rBTsqZ +ptSQVTG4nPhsDOU/7MZOoCrjBpWMoMALc6IfYuv2GwV2Aq5uUt/3H9EwRDNLLz8U +KiZj1XNmHWDXa9Pb0EVEEiQXqnxFeGPmU6f/yKOnK0FTPBqkwfShtinuyBznLGMH +Ron3gzInBvTAHF2bzh9rG7rt74nRTt+I7IlI+ZQkunl6x6p7olTPtF2i0YvuV47Y +EGmbd6cnhELVm69JFo06TVPG5sw8zfwVo4D83pMEd4nrFcDwjeNfIfiiY6ZXrjrf +sfc4ghMRJHJxccuLVOnM/UP5vq57egN45aUgP+iSOEoqEJdzvV5fUlqP1UQavsI=3D +=3DjJ5U +=2D----END PGP SIGNATURE----- + diff --git a/t/data/inline-signed-encrypted b/t/data/inline-signed-encrypted new file mode 100644 index 0000000..16ec127 --- /dev/null +++ b/t/data/inline-signed-encrypted @@ -0,0 +1,27 @@ +From: EdwardNG +To: EdwardNG +Subject: Inline Signed & Encrypted +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii + +-----BEGIN PGP MESSAGE----- +Version: GnuPG v1 + +hQEMAzLKYfkz3zGcAQf9HtMPNgaPA1BGlXaA18ADFFzRQxhWoUk18Ce/IGP1AHmL +FY3vhzQpamowDjAu+JgWiohuP4lB1eP6e2rxgsTrrx+O+Yffy+Kl36xAtgs+pl3t +EXz1BOeAZNrFRr/3RjRzMzZZlhBnYg/uq3fJceDsHZG+FchbtAXavQ7hgXfLXBWJ +XWDjQDK5dXqtNPEwq2cWRfjQx1M1W/NNj2DXWanLacb/tuvjYMRfYyeLKZ1BVwvB +YtTC8lHtwCGMkSpf96e6+LniiNqmFVwlD7VH99UcIR6v+7ZoWm+mnZsoH8lVRXfz +OO0uLxCa2M7kvPwAg4VJDvjFwbFfl/L445onZuNhetLA+AHJ/BGRMRwg1ZU1oVrR +8kCx6LzsrKDVFs9tUbC1qzIekdUY64FhZrfFnE1QqYMHz6kPjeDtG8JfwKWntb6O +kc8mLZeZHt9Gr4KAviiQq7pE37JF2F7X6OFhgbG90foJfVCB58X8h4Ulc7TpHT1z +rpRynJVwqye3SeJ5vk7J3zifRTKWkngU07Ni5zcsqxOg6e+bIbrZA9DK9EYqrwpq +bbQkRWGWT5hX64k1oO+Nr5x7n+sLog6Okph+cdX7uN27sMC6fOcOIqM/TJUkdDKU +hOsMcBKigq0o4xth1YgOhBwoWHj29JVXluApkPXL8QUPR4EhbqTGwGGAO5P55b/d +gS4k7vlQFnezSSS5COs7OTN/AgrkGi3xF+goXsHCJ5laCxKpvD8YDkG+sGCiq1L1 +2BI2TVVAQ/352vAwQC4csZ8iSLPaJOOXPKlzJ3SXw8ks08OqjOR2FVvwIOHOSxFt +jPoFtP2PWMFWxqx4Mvvcs3A6FUS3jBSlhpNC3mv/4CSWZydQwpM7G33xofkMlvFu +kwZi5Ziz1TnvutlwM6Nr2H8ahLZWPMEp2LIKH9Gl3njxG8pV0BYPxbR0 +=1Ls6 +-----END PGP MESSAGE----- + diff --git a/t/data/mime-encrypted b/t/data/mime-encrypted new file mode 100644 index 0000000..760e3a4 --- /dev/null +++ b/t/data/mime-encrypted @@ -0,0 +1,31 @@ +From: EdwardNG +To: EdwardNG +Subject: MIME Encrypted +MIME-Version: 1.0 +Content-Type: multipart/encrypted; boundary="=-=-="; + protocol="application/pgp-encrypted" + +--=-=-= +Content-Type: application/pgp-encrypted + +Version: 1 + +--=-=-= +Content-Type: application/octet-stream + +-----BEGIN PGP MESSAGE----- +Version: GnuPG v1 + +hQEMAzLKYfkz3zGcAQf+M6wBMuL7OYJjNgGrdGUFnNWockCdoto+uM9k+dLO0dBE +mL+oOtf8mdQ2D2G1VbvdLu9QyoW87BnlcukjUt1pV/TOnBfZtYgwYXQdWL2hr/yv +IoY1LO3CEPbDlK0X01RGf7V8zRh4Xz0qQuKf7x+TyqZQt0DKobSGctM8IsqqexWy +4UUQLh2yZvaZexa6vXt3RGnXdD7348lZKS7SV8TR2WpFkliihp0DIO2tme4o+aog +O/09i/HrFuleZoTnaWI7pScZ+gJgsc/qLOlH7cmH/fdbp6JD98Ths4CbmirIeCmb +YosPJQUa8kv/tjFGLu7I6TrKXgoyOpZKNip/Amt/aNKUAa+6GdQGPj1ddfoYtJqo +s40+/ZwY5v8t/qTShNKTg8WShCZ1GNriN4NALQMBopjYg7Qy2zN+VpxZIR4fJ409 +MLlqt2dOHVI3hrtL0QBt7OaMO+vXJ04jt4kPO0VpUgJqcU6pAW/8PL+zeoeEajSp +hUtbrcvSu6ECwzIarBEzQe5AGkanjDXGcaAcMWra8aj9ixdiPw== +=o50Z +-----END PGP MESSAGE----- +--=-=-=-- + diff --git a/t/data/mime-signed b/t/data/mime-signed new file mode 100644 index 0000000..b1cc590 --- /dev/null +++ b/t/data/mime-signed @@ -0,0 +1,32 @@ +From: EdwardNG +To: EdwardNG +Subject: MIME Signed +MIME-Version: 1.0 +Content-Type: multipart/signed; boundary="=-=-="; + micalg=pgp-sha512; protocol="application/pgp-signature" + +--=-=-= +Content-Type: text/plain +Content-Transfer-Encoding: quoted-printable + + +This is a PGP/MIME signed message. +=2D-=20 +Marius Gavrilescu + +--=-=-= +Content-Type: application/pgp-signature + +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v1 + +iQEcBAEBCgAGBQJTuFSGAAoJEPduLdg0sigGl/AH+wf5+jPP+v5LEYnKzSCLpvCF +/CMEH/XK0XEkxzGYi52pQjGFyX5gO3NSBP/bqx7OqXfv6rV4SImxExl5HHKqqZkc +cDXjN1nU88r8q2K+apRAaU4g9ukmusoyPQQahEb1kOyzK2uplartYxnWB4PWhxpM +MIWVaKfINGpZ2e2mTAAelaj36LUATeCwB8A5U68NudRLVvd26tUfKphHbV2msJaW +1ZV5GgLp7kXPZm0F7GbY9b+3i0vCwNO3UJ5Nht5RnOMrnxqdT5ehbRPxfmH16PdA +ebTLh23sPEgmXjzIi0oN5LxfWj+26mViTp/7jsAsj8whmVrSfBKPF2pMWsIrB88= +=BvqQ +-----END PGP SIGNATURE----- +--=-=-=-- + diff --git a/t/data/mime-signed-encrypted b/t/data/mime-signed-encrypted new file mode 100644 index 0000000..9cb82c3 --- /dev/null +++ b/t/data/mime-signed-encrypted @@ -0,0 +1,39 @@ +From: EdwardNG +To: EdwardNG +Subject: MIME Signed & Encrypted +MIME-Version: 1.0 +Content-Type: multipart/encrypted; boundary="=-=-="; + protocol="application/pgp-encrypted" + +--=-=-= +Content-Type: application/pgp-encrypted + +Version: 1 + +--=-=-= +Content-Type: application/octet-stream + +-----BEGIN PGP MESSAGE----- +Version: GnuPG v1 + +hQEMAzLKYfkz3zGcAQgA1q4eoIqc/soA8vczuNvwdlEitJ+bIvpbp6UCegPr8nJi +4k3faParZu2EMGuQBfzDPYSXZN7CVztwARoKpxy17ZvT4tZFEiJRGAQyU5fz3NOL +rrf/MKIkcxA38+FokbdNIf9XKI2piDl2REeK48yqzBscTeYYFZpTKIYdvJheyLHv +YyT8vqzmzmOCzl7fZc/wJM9mKTZ9/+DD1H4UoBpRx7HmpXE8m0bfLzJnperZh5KF +4rq4rXlXau0KtDxQ2g8gXXVKTMgu2lZqFTWya/eNZUS3RWRvfu1tJSsdoSXOqt8f +z3CQgoQ23uRlnT3cE785PYGcnJyDcvhKbLgHbYje4tLBOwHx4EKeXQkXDeWxW5Or +s3vPDjV6lyfoohyrl7+mb84A6+2ZBSJHBMxPb9MQUZfEoB7XKy8LpjF1IvX6ZXYk +ASb1j60HGAimVORI0ifod+Adw39wfFDI2EH+e8BzQnocKuqDJhd3kyLUxDCeNIl+ +wo8w5rU+hHGiBsqA0XnbziIXYP2uVfM7HuX6SsaB6FWGSv/evHoAJwvqwWaAGpbK +gfWHz4kgwOQvcoEECGMGxxtz+WoR7TsGRwOOgIt5ZE2FXBm6NQj9Coe06Qxi5cQL +K/LOql/XGGWc4IdF6R+ERTDiKX6fjNh4Bq7AnLaoxlOPisJ8bIpWnZr7lncgHnk4 +SmLMZd4SRA5r3/Teth55x26Fraht5VEGdPGeuQNpkONdxN+Vju+1Mgurxi0FghPc +1MLt0zpIh4Ng7N/wtvlW2sSV0dFXoXypkk4DDBUumeh3YTPhhJ6hyViAa0ci4TFY ++LEc2TlQawqeTxaWrYbXL5p+yYWE6iBafF//+HB6IwV/z4it/nCnwskDOsYtjL3C +gpR9Y5U3TugCUY1NJ/5hj39eOJ6UO0sXXMUBxIrsq4nrD4HGdbUqwDEiSmMFPGCk +7xjKo2LpgpxT9mDyY2DIUwupgaB4IMWC9iySZ466N1yxTopm5xzXq5PinVUuIZyY +2Xf3kWxMQOGkQlf4Wg== +=4jVV +-----END PGP MESSAGE----- +--=-=-=-- + diff --git a/t/keydir/pubring.gpg b/t/keydir/pubring.gpg new file mode 100644 index 0000000000000000000000000000000000000000..47a73f9ee86fbc9dce5cfa1bb2a1729839f1a0df GIT binary patch literal 1213 zcmV;u1Va0n0SyFGxKUXF2mq&TJ{wy}d1Cq5o5RbPtA9ykxSfGcHk3xyI?f&Zk#=Qe zU1P8%Vuj7L@&Cs?s7kG0{km%FHr266DogT7y9YF^m~f?Z-cL0O1@#Hmc+ak~fh0LK z-ofN49Rx6l-Nh&2PVU3-cUjW+kC?h^^X(o-eG%v}VjK*+RpgYsc@lP7wJtsI;u!HGs5GYI?Bn5?U7M4Wb{{UYdY) zeFkGGdw8)4U*nywdS$e3gzBj1XHBo zbm7lonHdzi*xwrjTI&E20RRECH$`N3VRB?nM<6ImWqBZGZ*m}XWpi|CZf77xWOre5 zWKKsZAUtJccVTj5Zf8JgWp-g~E^==^i2*kR69EbUAq4_cxKUXG8v_Lk2?z%R1r-Vj z2nz)k0s{d60v-VZ7k~f?2@v;gE!Z@&CF6K-(jlKO994@mG}g$SBRH^Q zArA3t2V;lKowdAFm(4Q_keQ`nZDoE-K24AJyZw{bvn@H{)EUmC{$x~l?wEDy`FJ@! zevosQ#6b_PKTRQ`Ypk>)VL5Mnw*;T2@M3>Tx|H&cc>#2wkhiLG=YB~uzoxq2t6cNW zxp_A5WlLhecp%#-csoJ)Yz*ZeFPgk!4{)#o00X%J4FprTQCR^90N#S-w4ApylgLS+ z7wf@#irck6hkhc8=t>mo^*`7WxUck{`oA$Uac$S*^v%T(Q?#{lf_V#uISR}-zZOg> zhvJ#O+WVE84$<#PY|)r2P)HU;#&kSn+kLB8IOVj6_2iikd-^a^uwP5U#sn{K^5YGD z`!4D@2RTgOb}b`qc#Gmlo#(3^mlccs8Q}dOT4d?M*{Cg#G;CD<8WI8oUVDYSBf%%fdCN!00D^s9|RZy3IGWO z0#mqASppjj0162Z_iioNG_oiL8(ateE^eb9e-TdI@=%^k;XZD+94RosUYk(#mKUzq zQ-;yK;n0^ZzjuNY*+Rz^`ck(1E3CvJ>67x1)4fFqwYaR}Vr{TZJZy2h_y3sr90u0g zg_J4cli9@>I$7HszAxqNBPd9p-Hn#~8wQrjaU&6CwO7V=XajyGAHBFzVw*@O;_X>YB>OCj~+EvkY zPQi?KmulbtOpejnB*3KW`iql6!nd!4rS?mxF7E&A@W5q81iIeK5;4Ec3*Vc=i5kX0 b%SO;ER-qMDi|jc@lP7wJtsI;u!HGs5GYI?Bn5?U7M4Wb{{UYdY) zeFkGGdw8)4U*nywdS$e3gzBj1XHBo zbm7lonHdzi*xwrjTI&E20RRC22mexMaw-JGB>Iv5h^y6!PTyBRJDo}gG}XojEb2wr z3BWujr_X5O{hHmRF?X_=q-flQCjklf&gat6+{;biPe6CTI;;^2CT49aQ_s6Zf zj`z)T$i8(4p<1wR!-pN!Bzg^@6!xP@WmD65fY1u{k;DghkK^vPc}ObggI;~_Hp|n1 zQoVELjm!E6Bpz9_X|wN8L6Wi8i$f8H2jZ$yuMaGNUXaDfHw{qj&cHQOpk`PhS)NKO zLVlEG9u!QWvQGEIkc~hY5CH@L%~PeS0nIKD8vS)xwEo58$C~y*r@Ybq+N3xED3N)2 z=tVshgmhv*%&+KJ6g(M{Ljp&H(&~g|@F6CPdUz0lDPpugbL=(IPUlD`48toVCrrLX z_ae|XNQw~}Oa9Yw(BME=dC42Zrea2p6_t6S_CA`PbOJDleb0PZcgBb%1OU*#8;qn# zvR%yALQ1n@d4mMVA^zCx5hJ?~*n{-E(sbhLK`R^4Q7nvQ{V%^o9wdtO8q0a;Wykuw7nP5?F*)&X2pgP*qkp%Aj}jfyKh3l^MPzqj za%4_NASg>^c_3zQav*eNb98BLXCOsncVTj5PDd#qJY{5eVRB?{XFzFXc42HTa&JC~ z0XGB_0SW*i1p-sJQCR{T0|g5S2nPcN6$%Lm3k4Pe0|5X69svRufB*^!5ch5^*fg>z z1{{kA{0lny!gbduQ=P`I#LCsdgm+_O+d$fQ4ZAG(Y$19*0(rHi!|&K4^jM?iMw?JL z3^f|sBIXA*kJ;M;FiM!kq)?y$fx}LR!cTbIXL&$w9LAkH57&B&m+5*c2kxGCaZ|Po z%#xsKjLkdg=pX;mA)hZCRf{t;*2tYBIIv?O4)JRTV~5P0wY*f9%`*&;nWbTEWqwOO zO^^4x{gc%n@8+qFN3ejbxNESrKbUb9+ zeXCeF<+OQQSdh^&RNO1r1F7_hc~P1&bkna(*f~*2#(2B# zx>BSd?!&43e!+J|5^MdSV@*yqVf@PPfw~M`wDhuL0VxY@3?9&|6~nFu60HTVkyl75 zVT5b_{ z!8(h+RX$O_43a_J-ribC5R!aV%eHfNaJhd-fR3h|{^o8QSB`!?QiN1X0meH1L#@7} z*&0^6%!lz^6RZv zww;Lo_6~p+W-ftys-RbwO`lX-0iy#oqNyU4uTOO`d?g3PKzWNdP)L?P!)p%ptr+&C z1=^y8s^G_%X1jF6{yc9%-i2)x37y$|Z z2?YXExKUXG8w>yn2@v;gE!Z@&CNlR?6_uY{%cOQ