summaryrefslogtreecommitdiff
path: root/lib/Crypt/AuthEnc/ChaCha20Poly1305.pm
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Crypt/AuthEnc/ChaCha20Poly1305.pm')
-rw-r--r--lib/Crypt/AuthEnc/ChaCha20Poly1305.pm164
1 files changed, 164 insertions, 0 deletions
diff --git a/lib/Crypt/AuthEnc/ChaCha20Poly1305.pm b/lib/Crypt/AuthEnc/ChaCha20Poly1305.pm
new file mode 100644
index 00000000..c134a545
--- /dev/null
+++ b/lib/Crypt/AuthEnc/ChaCha20Poly1305.pm
@@ -0,0 +1,164 @@
+package Crypt::AuthEnc::ChaCha20Poly1305;
+
+use strict;
+use warnings;
+our $VERSION = '0.048';
+
+use base qw(Crypt::AuthEnc Exporter);
+our %EXPORT_TAGS = ( all => [qw( chacha20poly1305_encrypt_authenticate chacha20poly1305_decrypt_verify )] );
+our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
+our @EXPORT = qw();
+
+use CryptX;
+
+sub new { my $class = shift; _new(@_) }
+
+sub chacha20poly1305_encrypt_authenticate {
+ my $key = shift;
+ my $iv = shift;
+ my $adata = shift;
+ my $plaintext = shift;
+
+ my $m = Crypt::AuthEnc::ChaCha20Poly1305->new($key, $iv);
+ $m->adata_add(defined $adata ? $adata : ''); #XXX-TODO if no aad we have to pass empty string
+ my $ct = $m->encrypt_add($plaintext);
+ my $tag = $m->encrypt_done;
+ return ($ct, $tag);
+}
+
+sub chacha20poly1305_decrypt_verify {
+ my $key = shift;
+ my $iv = shift;
+ my $adata = shift;
+ my $ciphertext = shift;
+ my $tag = shift;
+
+ my $m = Crypt::AuthEnc::ChaCha20Poly1305->new($key, $iv);
+ $m->adata_add(defined $adata ? $adata : ''); #XXX-TODO if no aad we have to pass empty string
+ my $ct = $m->decrypt_add($ciphertext);
+ return $m->decrypt_done($tag) ? $ct : undef;
+}
+
+1;
+
+=pod
+
+=head1 NAME
+
+Crypt::AuthEnc::ChaCha20Poly1305 - Authenticated encryption in ChaCha20Poly1305 mode
+
+=head1 SYNOPSIS
+
+ ### OO interface
+ use Crypt::AuthEnc::ChaCha20Poly1305;
+
+ # encrypt and authenticate
+ my $ae = Crypt::AuthEnc::ChaCha20Poly1305->new($key, $iv);
+ $ae->aad_add('additional_authenticated_data1');
+ $ae->aad_add('additional_authenticated_data2');
+ $ct = $ae->encrypt_add('data1');
+ $ct = $ae->encrypt_add('data2');
+ $ct = $ae->encrypt_add('data3');
+ $tag = $ae->encrypt_done();
+
+ # decrypt and verify
+ my $ae = Crypt::AuthEnc::ChaCha20Poly1305->new($key, $iv);
+ $ae->aad_add('additional_authenticated_data1');
+ $ae->aad_add('additional_authenticated_data2');
+ $pt = $ae->decrypt_add('ciphertext1');
+ $pt = $ae->decrypt_add('ciphertext2');
+ $pt = $ae->decrypt_add('ciphertext3');
+ $tag = $ae->decrypt_done();
+ die "decrypt failed" unless $tag eq $expected_tag;
+
+ #or
+ my $result = $ae->decrypt_done($expected_tag) die "decrypt failed";
+
+ ### functional interface
+ use Crypt::AuthEnc::ChaCha20Poly1305 qw(chacha20poly1305_encrypt_authenticate chacha20poly1305_decrypt_verify);
+
+ my ($ciphertext, $tag) = chacha20poly1305_encrypt_authenticate($key, $iv, $adata, $plaintext);
+ my $plaintext = chacha20poly1305_decrypt_verify($key, $iv, $adata, $ciphertext, $tag);
+
+=head1 DESCRIPTION
+
+Provides encryption and authentication based on ChaCha20 + Poly1305 as defined in RFC 7539 - L<https://tools.ietf.org/html/rfc7539>
+
+=head1 EXPORT
+
+Nothing is exported by default.
+
+You can export selected functions:
+
+ use Crypt::AuthEnc::ChaCha20Poly1305 qw(chacha20poly1305_encrypt_authenticate chacha20poly1305_decrypt_verify);
+
+=head1 FUNCTIONS
+
+=head2 chacha20poly1305_encrypt_authenticate
+
+ my ($ciphertext, $tag) = chacha20poly1305_encrypt_authenticate($key, $iv, $adata, $plaintext);
+
+ # $key ..... key of proper length (128 or 256 bits / 16 or 32 bytes)
+ # $iv ...... initialization vector (64 or 96 bits / 8 or 12 bytes)
+ # $adata ... additional authenticated data (optional)
+
+=head2 chacha20poly1305_decrypt_verify
+
+ my $plaintext = chacha20poly1305_decrypt_verify($key, $iv, $adata, $ciphertext, $tag);
+
+ # on error returns undef
+
+=head1 METHODS
+
+=head2 new
+
+ my $ae = Crypt::AuthEnc::ChaCha20Poly1305->new($key, $iv);
+
+ # $key ..... encryption key of proper length (128 or 256 bits / 16 or 32 bytes)
+ # $iv ...... initialization vector (64 or 96 bits / 8 or 12 bytes)
+
+=head2 aad_add
+
+Can be called before the first C<encrypt_add> or C<decrypt_add>;
+
+ $ae->aad_add($aad_data); #can be called multiple times
+
+=head2 encrypt_add
+
+ $ciphertext = $ae->encrypt_add($data); #can be called multiple times
+
+=head2 encrypt_done
+
+ $tag = $ae->encrypt_done();
+
+=head2 decrypt_add
+
+ $plaintext = $ae->decrypt_add($ciphertext); #can be called multiple times
+
+=head2 decrypt_done
+
+ my $result = $ae->decrypt_done($tag); # returns 1 (success) or 0 (failure)
+ #or
+ my $tag = $ae->decrypt_done; # returns $tag value
+
+=head2 clone
+
+ my $ae_new = $ae->clone;
+
+=head2 set_iv
+
+ $ae->set_iv($iv);
+
+=head2 set_iv_rfc7905
+
+ $ae->set_iv_rfc7905($iv, $seqnum);
+
+=head1 SEE ALSO
+
+=over
+
+=item * L<CryptX|CryptX>, L<Crypt::AuthEnc::GCM|Crypt::AuthEnc::GCM>, L<Crypt::AuthEnc::CCM|Crypt::AuthEnc::CCM>, L<Crypt::AuthEnc::EAX|Crypt::AuthEnc::EAX>, L<Crypt::AuthEnc::OCB|Crypt::AuthEnc::OCB>
+
+=item * L<https://tools.ietf.org/html/rfc7539>
+
+=back