DCIT / perl-CryptX

https://metacpan.org/pod/CryptX
Other
35 stars 23 forks source link

Crypt::PK::DH documentation issue/question #109

Closed demonfoo closed 1 month ago

demonfoo commented 2 months ago

After reading the documentation for the Crypt::PK::DH submodule, I like the concept, but... how does one access the computed key to encrypt/decrypt communication with the peer? I'd like to use this instead of Crypt::DH::GMP, but while I can mostly substitute it in, with Crypt::DH::GMP I can call compute_key_twoc() (or compute_key()) to get the computed key, but the docs don't indicate how this would be done, and I can't find any examples.

karel-m commented 1 month ago

Could you show be a piece of runnable perl sample code using Crypt::DH::GMP which you want to implement using Crypt::PK::DH?

demonfoo commented 1 month ago

For example (I haven't tested this, but it's a rough analogue):

#!/usr/bin/env perl

use strict;
use warnings;

my @p_bytes = (0xba, 0x28, 0x73, 0xdf, 0xb0, 0x60, 0x57, 0xd4, 0x3f, 0x20,
               0x24, 0x74, 0x4c, 0xee, 0xe7, 0x5b,);
my @g_bytes = (0x07);

my $one = Crypt::DH::GMP->new(
        p => '0x' . unpack(q{H*}, pack q{C*}, @p_bytes),
        g => '0x' . unpack q{H*}, pack q{C*}, @g_bytes);
$one->generate_keys();
my $pk_one = pack 'H*', $one->pub_key_twoc();

my $two = Crypt::DH::GMP->new(
        p => '0x' . unpack(q{H*}, pack q{C*}, @p_bytes),
        g => '0x' . unpack q{H*}, pack q{C*}, @g_bytes);
$two->generate_keys();
my $pk_two = pack 'H*', $two->pub_key_twoc();

my $shared_key = $two->compute_key_twoc('0x' . $pk_one);
# now use $shared_key to encrypt plaintext

The $shared_key is what I need; I then need to be able to feed that into a block cipher for encryption/decryption, and I don't see any way to get that value out of Crypt::PK::DH.

Edit: I am using Crypt::Mode::CBC for doing the encryption, but I do also need access to the bare key to support other features.

karel-m commented 1 month ago

If you mean something like this:

  use Crypt::DH::GMP;

  my $p = '0xba2873dfb06057d43f2024744ceee75b';
  my $g = '0x07';

  my $one = Crypt::DH::GMP->new(p => $p, g => $g);
  $one->generate_keys();
  my $pub_one = $one->pub_key();

  my $two = Crypt::DH::GMP->new(p => $p, g => $g);
  $two->generate_keys();
  my $pub_two = $two->pub_key();

  my $shared_key1 = $one->compute_secret($pub_two);
  my $shared_key2 = $two->compute_secret($pub_one);

  print "shared_key1=$shared_key1\n";
  print "shared_key2=$shared_key2\n";

You can do it like this:

  use Crypt::PK::DH;

  my $one = Crypt::PK::DH->new();
  $one->generate_key({ g => '07', p => 'ba2873dfb06057d43f2024744ceee75b' });
  my $pub_one = $one->export_key('public');

  my $two = Crypt::PK::DH->new();
  $two->generate_key({ g => '07', p => 'ba2873dfb06057d43f2024744ceee75b' });
  my $pub_two = $two->export_key('public');

  my $shared_secret1 = $one->shared_secret(Crypt::PK::DH->new(\$pub_two));
  my $shared_secret2 = $two->shared_secret(Crypt::PK::DH->new(\$pub_one));
  printf("shared_secret1.hex=%s\n", unpack("H*", $shared_secret1));
  printf("shared_secret2.hex=%s\n", unpack("H*", $shared_secret2));
demonfoo commented 1 month ago

Okay, so it's returned from the shared_secret() method. I had a partial implementation, but that's clearly the bit I was missing. I just tried it, and now it's working. Thank you! That said, maybe that should be made clearer in the docs?