Mail-Make

 view release on metacpan or  search on metacpan

lib/Mail/Make/SMIME.pm  view on Meta::CPAN

Mail::Make::SMIME - S/MIME signing and encryption for Mail::Make (RFC 5751)

=head1 SYNOPSIS

    use Mail::Make;

    my $mail = Mail::Make->new;
    $mail->from( 'jacques@example.com' );
    $mail->to( 'recipient@example.com' );
    $mail->subject( 'Signed message' );
    $mail->plain( 'This message is signed.' );

    # Sign only
    my $signed = $mail->smime_sign(
        Cert => '/path/to/my.cert.pem',
        Key  => '/path/to/my.key.pem',
    ) || die( $mail->error );
    $signed->smtpsend( Host => 'smtp.example.com' );

    # Encrypt only
    my $encrypted = $mail->smime_encrypt(
        RecipientCert => '/path/to/recipient.cert.pem',
    ) || die( $mail->error );

    # Sign then encrypt
    my $protected = $mail->smime_sign_encrypt(
        Cert          => '/path/to/my.cert.pem',
        Key           => '/path/to/my.key.pem',
        RecipientCert => '/path/to/recipient.cert.pem',
    ) || die( $mail->error );

    # Using the Mail::Make::SMIME object directly
    use Mail::Make::SMIME;
    my $smime = Mail::Make::SMIME->new(
        cert => '/path/to/my.cert.pem',
        key  => '/path/to/my.key.pem',
    ) || die( Mail::Make::SMIME->error );

    my $signed = $smime->sign( entity => $mail ) || die( $smime->error );

=head1 VERSION

    v0.1.3

=head1 DESCRIPTION

C<Mail::Make::SMIME> provides S/MIME signing, encryption, and combined sign-then-encrypt operations for L<Mail::Make> objects, following RFC 5751 (S/MIME Version 3.2).

It delegates cryptographic operations to L<Crypt::SMIME>, which wraps the OpenSSL C<libcrypto> library. All certificates and keys must be supplied in PEM format, either as strings or as file paths.

=head1 MEMORY USAGE AND LIMITATIONS

=head2 In-memory processing

All cryptographic operations performed by this module load the complete serialised message into memory before signing or encrypting it. This is a consequence of two factors:

=over 4

=item 1. C<Crypt::SMIME> API

L<Crypt::SMIME> accepts and returns plain Perl strings. It does not expose a streaming or filehandle-based interface.

=item 2. Protocol constraints

B<Signing> requires computing a cryptographic hash (e.g. SHA-256) over the entire content to be signed. Although the hash algorithm itself is sequential and could theoretically operate on a stream, the resulting C<multipart/signed> structure must car...

B<Encryption> uses a symmetric cipher (AES by default) operating on PKCS#7 C<EnvelopedData>. The ASN.1 DER encoding of C<EnvelopedData> declares the total length of the encrypted payload in the structure header, which must be known before the first b...

=back

=head2 Practical impact

For typical email messages, such as plain text, HTML, and modest attachments, memory consumption is not a concern. Problems may arise with very large attachments (tens of megabytes or more).

=head2 Future work

A future C<v0.2.0> of C<Mail::Make::SMIME> may optionally delegate to the C<openssl smime> command-line tool via L<IPC::Run>, using temporary files, to support large messages without holding them in memory. This mirrors the approach already used by L...

If in-memory processing is a concern for your use case, consider using L<Mail::Make::GPG> instead: OpenPGP uses I<partial body packets> (RFC 4880 §4.2.2) which allow true streaming without knowing the total message size in advance.

=head1 CONSTRUCTOR

=head2 new( %opts )

    my $smime = Mail::Make::SMIME->new(
        cert         => '/path/to/cert.pem',
        key          => '/path/to/key.pem',
        key_password => 'secret',    # or CODE ref
        ca_cert      => '/path/to/ca.pem',
    );

All options are optional at construction time and can be overridden per method call.

=head1 METHODS

=head2 ca_cert( [$pem_or_path] )

Gets or sets the CA certificate used for signature verification.

=head2 cert( [$pem_or_path] )

Gets or sets the signer certificate.

=head2 encrypt( entity => $mail, RecipientCert => $cert [, %opts] )

Encrypts C<$mail> for one or more recipients. Returns a new L<Mail::Make> object whose entity is a C<application/pkcs7-mime; smime-type=enveloped-data> message.

C<RecipientCert> may be a PEM string, a file path, or an array reference of either, for multi-recipient encryption.

=head2 key( [$pem_or_path] )

Gets or sets the private key.

=head2 key_password( [$string_or_coderef] )

Gets or sets the private key passphrase.

=head2 sign( entity => $mail [, %opts] )

Signs C<$mail> with a detached S/MIME signature and returns a new L<Mail::Make> object whose entity is a C<multipart/signed> message.

The signature is always detached (C<smime-type=signed-data> with C<Content-Type: multipart/signed>), which allows non-S/MIME-aware clients to read the message body.

Options (all override constructor defaults):

=over 4

=item Cert => $pem_string_or_path

Signer certificate in PEM format.

=item Key => $pem_string_or_path

Private key in PEM format.

=item KeyPassword => $string_or_coderef

Passphrase for an encrypted private key, or a CODE ref that returns one.



( run in 0.566 second using v1.01-cache-2.11-cpan-2398b32b56e )