Crypt-ECDH_ES
view release on metacpan or search on metacpan
lib/Crypt/ECDH_ES.pm view on Meta::CPAN
my $pad_length = 16 - length($data) % 16;
my $padding = chr($pad_length) x $pad_length;
my $ciphertext = $cipher->encrypt($data . $padding, $iv);
my $mac = hmac_sha256($iv . $ciphertext, $sign_key);
return pack $format_unauthenticated, '', $public, $mac, $ciphertext;
}
sub ecdhes_decrypt {
my ($private_key, $packed_data) = @_;
my ($options, $public, $mac, $ciphertext) = unpack $format_unauthenticated, $packed_data;
croak 'Unknown options' if $options ne '';
my $shared = curve25519_shared_secret($private_key, $public);
my ($encrypt_key, $sign_key) = unpack 'a16 a16', sha256($shared);
my $iv = substr sha256($public), 0, 16;
croak 'MAC is incorrect' if hmac_sha256($iv . $ciphertext, $sign_key) ne $mac;
my $cipher = Crypt::Rijndael->new($encrypt_key, Crypt::Rijndael::MODE_CBC);
my $plaintext = $cipher->decrypt($ciphertext, $iv);
my $pad_length = ord substr $plaintext, -1;
substr($plaintext, -$pad_length, $pad_length, '') eq chr($pad_length) x $pad_length or croak 'Incorrectly padded';
return $plaintext;
}
my $format_authenticated = 'C/a C/a C/a C/a N/a';
sub ecdhes_encrypt_authenticated {
my ($public_key_other, $private_key_self, $data) = @_;
my $public_key_self = curve25519_public_key($private_key_self);
my $private_ephemeral = curve25519_secret_key(random_bytes(32));
my $ephemeral_public = curve25519_public_key($private_ephemeral);
my $primary_shared = curve25519_shared_secret($private_ephemeral, $public_key_other);
my ($primary_encrypt_key, $primary_iv) = unpack 'a16 a16', sha256($primary_shared);
my $primary_cipher = Crypt::Rijndael->new($primary_encrypt_key, Crypt::Rijndael::MODE_CBC);
my $encrypted_public_key = $primary_cipher->encrypt($public_key_self, $primary_iv);
my $secondary_shared = $primary_shared . curve25519_shared_secret($private_key_self, $public_key_other);
my ($secondary_encrypt_key, $sign_key) = unpack 'a16 a16', sha256($secondary_shared);
my $cipher = Crypt::Rijndael->new($secondary_encrypt_key, Crypt::Rijndael::MODE_CBC);
my $iv = substr sha256($ephemeral_public), 0, 16;
my $pad_length = 16 - length($data) % 16;
my $padding = chr($pad_length) x $pad_length;
my $ciphertext = $cipher->encrypt($data . $padding, $iv);
my $mac = hmac_sha256($iv . $ciphertext, $sign_key);
return pack $format_authenticated, "\x{1}", $ephemeral_public, $encrypted_public_key, $mac, $ciphertext;
}
sub ecdhes_decrypt_authenticated {
my ($private_key, $packed_data) = @_;
my ($options, $ephemeral_public, $encrypted_public_key, $mac, $ciphertext) = unpack $format_authenticated, $packed_data;
croak 'Unknown options' if $options ne "\x{1}";
my $primary_shared = curve25519_shared_secret($private_key, $ephemeral_public);
my ($primary_encrypt_key, $primary_iv) = unpack 'a16 a16', sha256($primary_shared);
my $primary_cipher = Crypt::Rijndael->new($primary_encrypt_key, Crypt::Rijndael::MODE_CBC);
my $public_key = $primary_cipher->decrypt($encrypted_public_key, $primary_iv);
my $secondary_shared = $primary_shared . curve25519_shared_secret($private_key, $public_key);
my ($secondary_encrypt_key, $sign_key) = unpack 'a16 a16', sha256($secondary_shared);
my $cipher = Crypt::Rijndael->new($secondary_encrypt_key, Crypt::Rijndael::MODE_CBC);
my $iv = substr sha256($ephemeral_public), 0, 16;
croak 'MAC is incorrect' if hmac_sha256($iv . $ciphertext, $sign_key) ne $mac;
my $plaintext = $cipher->decrypt($ciphertext, $iv);
my $pad_length = ord substr $plaintext, -1;
substr($plaintext, -$pad_length, $pad_length, '') eq chr($pad_length) x $pad_length or croak 'Incorrectly padded';
return ($plaintext, $public_key);
lib/Crypt/ECDH_ES.pm view on Meta::CPAN
Crypt::ECDH_ES - A fast and small hybrid crypto system
=head1 VERSION
version 0.006
=head1 SYNOPSIS
my $ciphertext = ecdhes_encrypt($public_key, $data);
my $plaintext = ecdhes_decrypt($private_key, $ciphertext);
=head1 DESCRIPTION
This module uses elliptic curve cryptography in an ephemerical-static configuration combined with the AES cipher to achieve a hybrid cryptographical system. Both the public and the private key are simply 32 byte blobs.
=head2 Use-cases
You may want to use this module when storing sensive data in such a way that the encoding side can't read it afterwards, for example a website storing credit card data in a database that will be used by a separate back-end financial processor. When u...
=head2 Technical details
lib/Crypt/ECDH_ES.pm view on Meta::CPAN
=head1 FUNCTIONS
=head2 ecdhes_encrypt
my $ciphertext = ecdhes_encrypt($public_key, $plaintext)
This will encrypt C<$plaintext> using C<$public_key>. This is a non-deterministic encryption: the result will be different for every invocation.
=head2 ecdhes_decrypt
my $plaintext = ecdhes_decrypt($private_key, $ciphertext)
This will decrypt C<$ciphertext> (as encrypted using C<ecdhes_encrypt>) using C<$private_key> and return the plaintext.
=head2 ecdhes_encrypt_authenticated
my $ciphertext = ecdhes_encrypt_authenticated($receiver_public_key, $sender_private_key, $plaintext)
This will encrypt C<$plaintext> using C<$receiver_public_key> and C<$sender_private_key>. This is a non-deterministic encryption: the result will be different for every invocation.
=head2 ecdhes_decrypt_authenticated
my ($plaintext, $sender_public_key) = ecdhes_decrypt_authenticated($receiver_private_key, $ciphertext)
This will decrypt C<$ciphertext> (as encrypted using C<ecdhes_encrypt_authenticated>) using C<$receiver_private_key> and return the plaintext and the public key of the sender.
=head2 ecdhes_generate_key
my ($public_key, $private_key) = ecdhes_generate_key()
This function generates a new random curve25519 keypair.
=head1 SEE ALSO
=over 4
=item * L<ecdh_es|https://github.com/tomk3003/ecdh_es>
A compatible decoder written in C.
( run in 0.217 second using v1.01-cache-2.11-cpan-a5abf4f5562 )