I'm trying to do the following:
I'm stuck at the last step, from the Documentation is seems like I have to use ECDH<ECP>::Domain
but nowhere is it explained how to convert the keys into the required SecByteBlock
objects, how can I do this? Pseudocode follows.
std::string x = ...
std::string y = ...
auto make_curve = []{ return ASN1::secp256r1(); };
// Public key
ECDSA<ECP, SHA256>::PublicKey g_a;
g_a.Initialize(make_curve(),
ECP::Point {
Integer { x.data() },
Integer { y.data() }
});
// Private key
ECDSA<ECP, SHA256>::PrivateKey g_b;
g_b.Initialize(RANDOM_POOL, make_curve());
// Compute shared secret
ECDH<ECP>::Domain agreement { make_curve() };
SecByteBlock shared_secret_buf { agreement.AgreedValueLength() };
agreement.Agree(shared_secret_buf, ???, ???);
The Wikipedia page shows you show to do this:
So first create a new key pair (you never generate just one private key):
ECDH < ECP >::Domain dhB( CURVE );
SecByteBlock privB(dhB.PrivateKeyLength()), pubB(dhB.PublicKeyLength());
dhB.GenerateKeyPair(rng, privB, pubB);
and then you can perform the key agreement like this:
if(!dhB.Agree(shared_secret_buf, privB, pubA))
throw runtime_error("Failed to reach shared secret (B)");
OK, so now you are left with one issue: encoding the public point. Fortunately that has been explained in the Wiki as well, here, basically you should just be able to use:
void ECP::EncodePoint(BufferedTransformation &bt, const Point &P, bool compressed)
Where your pubA
buffer is put in &bt
(I hope the input for &P
is clear, use false
for compressed).
Basically this returns a byte 04
, then the concatenation of X and Y encoded with the size of the field (big endian).
Note that this just requires an ECP::Point
and as the key pair generation also doesn't use ECDSA, that part of the code can be stripped out entirely. That's good, because ECDH is a different algorithm and using ECDSA could make the code less portable, e.g. when using the X25519 curve.