Crypt-EECDH

 view release on metacpan or  search on metacpan

lib/Crypt/EECDH.pm  view on Meta::CPAN

    }
  }

  my $random = Bytes::Random::Secure->new( Bits => 128 );
  my $private = curve25519_secret_key($random->bytes(32));
  my $public  = curve25519_public_key($private);
  my $shared  = curve25519_shared_secret($private, $arg{PublicKey});

  my ($encrypt_key, $sign_key) = unpack 'a16 a16', sha256($shared);
  my $iv     = substr sha256($public), 0, 16;
  my $cipher = Crypt::Rijndael->new($encrypt_key, Crypt::Rijndael::MODE_CBC);
  $cipher->set_iv($iv);

  my $pad_length = 16 - length($arg{Message}) % 16;
  my $padding = chr($pad_length) x $pad_length;

  my $ciphertext = $cipher->encrypt($arg{Message} . $padding);
  my $mac = hmac_sha256($iv . $ciphertext, $sign_key);
  return (pack ($format, '', $public, $mac, $ciphertext), $private);
}

sub decrypt {
  my ($self, %arg) = @_;

  my ($options, $public, $mac, $ciphertext) = unpack $format, $arg{Ciphertext};
  die 'Unknown options' if $options ne '';

  my $shared = curve25519_shared_secret($arg{Key}, $public);
  my ($encrypt_key, $sign_key) = unpack 'a16 a16', sha256($shared);
  my $iv     = substr sha256($public), 0, 16;
  die 'MAC is incorrect' if hmac_sha256($iv . $ciphertext, $sign_key) ne $mac;
  my $cipher = Crypt::Rijndael->new($encrypt_key, Crypt::Rijndael::MODE_CBC);
  $cipher->set_iv($iv);

  my $plaintext = $cipher->decrypt($ciphertext);
  my $pad_length = ord substr $plaintext, -1;
  substr($plaintext, -$pad_length, $pad_length, '') eq chr($pad_length) x $pad_length or die 'Incorrectly padded';
  return ($plaintext, $public);
}

sub keygen {
  my ($self, %arg) = @_;

lib/Crypt/EECDH.pm  view on Meta::CPAN

=head1 DESCRIPTION

A simple hybrid crypto system with ephemeral ECDH key agreement in
combination with the AES cipher.

=head1 TECHNICAL DETAILS

This modules uses Daniel J. Bernstein's curve25519 to perform a
Diffie-Hellman key agreement. A new keypair is generated for every
encryption operation. The shared key resulting from the key agreement
is hashed and used to encrypt the plaintext using AES in CBC mode
(with the IV deterministically derived from the public key). It also
adds a HMAC, with the key derived from the same shared secret as the
encryption key.

Some of the code in this module (and most of the text of the previous
paragraph) is from the L<Crypt::ECDH_ES> module, which provides
one-way communication functionality in an ephemeral-static mode, where
one side (the decoder or "server") uses a static key.

Crypt::EECDH provides full two-way encryption capability with



( run in 0.485 second using v1.01-cache-2.11-cpan-df04353d9ac )