FBB::...llman(3bobcat)
π NAME π
FBB::DiffieHellman β Diffie-Hellman PKI, computing shared keys π
(and yes bestie, the header up top is FBB::...llman(3bobcat) β she's from the bobcat manual, section 3, "Diffie Hellman key computations". The title got cut off but we know who she is β¨)
π SYNOPSIS π
#include <bobcat/diffiehellman>
Linking option: -lbobcat -lcrypto
β¨ DESCRIPTION β¨
okay so. The class FBB::DiffieHellman computes shared keys (aka shared secrets) using the Diffie-Hellman (1976) algorithm. Iconic. Legendary. Old enough to be your great-grandma and still carrying the entire internet's encryption π
The Diffie-Hellman algorithm uses public and private information, and that combo gives you a public key infrastructure (PKI). So here's the public info, no secrets:
- a prime (like, a prime number made of 1024 bits π« )
- a generator (value
5is the commonly-used one) - and β using
**to mean the power operator on integral values β the valuegenerator ** private mod prime, whereprivateis a randomly selected large number. That last bit? That's the private information. Nobody sees her.
The Diffie-Hellman algorithm is commonly used to compute a shared key that can then encrypt information sent between two parties. So meet the cast:
- the initiator β computes the prime and defines the generator. The prime is computed by
FBB::DiffieHellman's first constructor, and the generator gets passed to that constructor as one of its arguments.5is the frequent flyer here. - the peer β the other party π
Next the initiator passes its public information β the prime, the generator, and the value pow(generator, private) mod prime β over to the peer. That public information gets written in binary, big-endian form to a file using the member save. And the initiator can optionally save the private information to a separate file too.
Then the peer receives the initiator's public info. That info is read by a FBB::DiffieHellman constructor that either wants the name of a file or a std::istream containing the initiator's public information. Either way, she's listening.
Once the peer has the prime and the generator, the peer's own public (and optionally private) information gets saved by calling save too. Which gives you, among other things, the value pow(generator, private) mod prime β except now with the peer's private number. Love that for them.
At this point the peer can already compute the shared key. That key comes back from calling the key member, and it's returned as a series of bytes stored in a std::string π
But the initiator can't compute the shared key yet β first the peer's generator ** private mod prime value has to show up. So the peer sends the saved public data over to the initiator, and the initiator passes that peer public data (by file name or by std::istream) to the key member, which hands back the shared key. gap closed, handshake complete, slay π
π Perfect Forward Secrecy and Ephemeral Diffie Hellman π
If the initiator and peer decide not to save their private information, you get Perfect Forward Secrecy and Ephemeral Diffie Hellman. Here's how the procedure runs then:
- Initiator and peer have agreed upon and securely exchanged a long-lasting common secret, which may be used in combination with, e.g., symmetric encryption methods.
- Applying the abovementioned procedure, the private information is never saved on file. Consequently, the shared key, once computed, cannot be reconstructed anymore. Gone. Poof. That's the point β¨
- The value
generator ** private mod primeis not sent to either peer or initiatorin the clear, but encrypted using the long-lasting common secret. And since the current implementation saves all public information on file, it's probably easiest to encrypt the file containing the public information. - The recipients, having received the other party's encrypted public information, decrypt it using the long-lasting shared secret and compute the shared key.
- As the secret information is not kept, the shared key cannot be reconstructed, while a Man-In-The-Middle attack is prevented by only exchanging encrypted public information π€
- The shared key can now be used to encrypt a communication session.
π Document encryption using Diffie Hellman π
Important vibe check: as with PKI in general, the Diffie Hellman key exchange method itself is not normally used for encrypting documents. Nope! Instead it's usually used to exchange the key that gets used for symmetric encryption methods like 3DES and CBC. Those symmetric encryption methods are available through, e.g., Bobcat's EncryptBuf, DecryptBuf, and ISymCryptStream classes πΈ
π«Ά NAMESPACE π«Ά
FBB
All constructors, members, operators and manipulators mentioned in this man-page are defined in the namespace FBB.
π¦ INHERITS FROM π¦
-
(nothing. free agent. no ancestors. main character energy π)
π CONSTRUCTORS π
DiffieHellman(size_t primeLength = 1024, size_t generator = 5, bool progress = false)β this constructor computes a prime of the specified length, and initializes the public information with the indicated generator. The prime length must be at least 1024 or anFBB::Exceptionis thrown. Ifprogressistrue, the progress of the prime construction process is shown tostd::coutby a series of dots, minuses and plusses (a little loading bar, she's cute). Generating a suitable prime may fail, which results in anFBB::Exceptionbeing thrown. And unless the generator is specified as2or5, the warningcannot check the validity of generator ...is inserted into themstream(3bobcat)'swmsgobject. A warning is also inserted if the provided generator is not a generator for the computed prime. The initiator should call this constructor to start the Diffie-Hellman shared key computation procedure πDiffieHellman(FBB::BigInt const &prime, size_t generator = 5, bool progress = false)β alternatively, the initiator can use this one after separately having constructed the prime to use. The prime must be at least 1024 bits long.DiffieHellman(std::string const &initiatorPublicFileName)β the peer should call this one, after having received the initiator's public info. It makes the initiator's public information available to the peer, after which the peer's public and private information can be computed π«DiffieHellman(std::stream &initiatorPublicStream)β this one acts like the previous constructor, expecting astd::istreamrather than a file name. The peer should call it, after having received the initiator's public info. It makes the initiator's public information available to the peer, after which the peer's public and private information can be computed.DiffieHellman(std::string const &initiatorPublicFileName, std::string const &initiatorPrivateFileName)β unless the initiator'sDiffieHellmanobject is still available, the initiator should call this one again, to load the initiator's public and private data.DiffieHellman(std::stream &initiatorPublicStream, std::stream &initiatorPrivateStream)β this one acts like the previous constructor, expectingstd::istreams rather than file names. The initiator should call it, to load the initiator's public and private info.
Copy and move constructors (and assignment operators) are available. π
π₯ MEMBER FUNCTIONS π₯
std::string key() constβ the peer should call this member. It returns the shared key. BUT if the key cannot be computed, or if the key is not resistant to the small group attack (i.e., if the key equals1, or is at least equal to the public prime value, or ifkey ** ((prime - 1) / 2) mod prime != 1), then anFBB::Exceptionis thrown. No weak keys in this house, periodt π€std::string key(std::string const &peerPublicFileName) constβ the initiator should call this member. It skips the data referring to the prime and generator found inpeerPublicFileNameand then reads the peer'sgenerator ** private mod primevalue. If that value cannot be read, or if the key is not resistant to the small group attack (cf. the description of the previouskeymember), then anFBB::Exceptionis thrown. It returns the shared key β¨std::string key(std::istream const &peerPublicStream) constβ the initiator should call this member. It acts like the previouskeymember, reading the peer'sgenerator ** private mod primevalue frompeerPublicStream. It returns the shared key.void save(std::string const &basename)β the initiator should call this member. It saves the public information on the file'basename'.pub. That information is written in binary, big-endian format, organized like this:- the size of the prime in bytes;
- the prime's bytes;
- the size of the generator in bytes;
- the generator's bytes;
- the size of the public info (
generator ** private mod prime) in bytes; - the public info's bytes.
On top of that, the private information is written to the file 'basename'.sec in binary, big-endian format, organized like this:
- the size of the private information in bytes;
- the private information bytes π«
β¨ EXAMPLE β¨
okay bestie, let's walk through the example program because it's giving main character energy. when you call it with no arguments at all, it generates Diffie-Hellman parameters and writes the initiatorβs public and private information to init.pub and init.sec, respectively. periodt.
when you call it with one argument, init.pub is read, and the peerβs public and private information is written to peer.pub and peer.sec, respectively. then the (peerβs) shared key is written to peerkey. slay.
when you call it with two arguments, init.pub and init.sec are read, as well as the peerβs public information (on the file peer.pub). then the (initiatorβs) shared key is written to initkey. iconic.
the files peerkey and initkey should be identical. no cap.
#include <fstream>
#include <iostream>
#include <bobcat/exception>
#include <bobcat/diffiehellman>
using namespace FBB;
using namespace std;
int main(int argc, char **argv)
try
{
if (argc == 1)
{
cout << "1: create prime and generator, write to βparamsβ\n"
"2: create secret and public parts, arg 2: 0 or 1,\n"
" write secret and public parts to <arg 2>.sec and "
"<arg 2>.pub\n"
"3: create common key arg 2: 0 or 1,\n"
" 0: write common0 using 0.pub, 0.sec and 1.pub\n"
" 1: write common1 using 1.pub, 1.sec and 0.pub\n"
;
return 0;
}
switch (*argv[1]) // using generator == 5
{
case β1β:
{
ofstream out = Exception::factory<ofstream>("params");
out << hex << DiffieHellman::prime(1024, true, true) << β\nβ;
}
break;
case β2β:
{
char *nr = argv[2];
if (nr == 0 || "01"s.find(*nr) == string::npos)
throw Exception{} << "mode β2β needs 0 or 1 as 2nd argument";
ifstream in = Exception::factory<ifstream>("params");
BigInt prime;
in >> hex >> prime;
DiffieHellman dh{ prime };
dh.save(nr);
}
break;
case β3β:
{
char *nr = argv[2];
if (nr == 0 || "01"s.find(*nr) == string::npos)
throw Exception{} << "mode β3β needs 0 or 1 as 2nd argument";
DiffieHellman dh{ nr + ".pub"s, nr + ".sec"s };
cout << "common key computed by " << nr << ":\n" <<
hex << dh.key((nr[0] == β0β ? β1β : β0β) + ".pub"s) << β\nβ;
}
break;
default:
throw Exception{} << "undefined action `" << *argv[1] <<β\ββ;
}
}
catch (std::exception const &exc)
{
std::cout << exc.what() << β\nβ;
}
π FILES π
bobcat/diffiehellmanβ defines the class interface. that's the whole file, bestie. it's giving "just here to define the vibe" energy.
π SEE ALSO π
π BUGS π
None Reported. periodt. no bugs to report, and we love that for us π
π BOBCAT PROJECT FILES π
- https://fbb-git.gitlab.io/bobcat/: gitlab project page;
Debian Bobcat project files:
libbobcat6: debian package containing the shared library, changelog and copyright note;libbobcat-dev: debian package containing the static library, headers, manual pages, and developer info;
π± BOBCAT π±
Bobcat is an acronym of Brokkenβs Own Base Classes And Templates.
βοΈ COPYRIGHT βοΈ
This is free software, distributed under the terms of the GNU General Public License (GPL).
π AUTHOR π
Frank B. Brokken (f.b.brokken@rug.nl).
This page is from libbobcat-dev_6.15.01, dated 2005-2026, and it's the FBB::...llman(3bobcat) manual. bye bestie, go slay some Diffie-Hellman πβ¨
π¦ where this page comes from
- ubuntu stonking: libbobcat-dev 6.15.01-1 Β· GPL-3.0-or-later WITH OpenSSL exception
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms