I want to generate a private and public key using C to use them in an authentication process.
Can you please give me a basic example to generate the keys in C?
I've found these functions but i don't how to use them:
DSA * DSA_generate_parameters(int bits,
unsigned char *seed,
int seed_len,
int *counter_ret,
unsigned long *h_ret,
void (*callback)(int, int, void *),
void *cb_arg);
int DSA_generate_key(DSA *dsa);
Help me please!
Thank you! :)
Can you please give me a basic example to generate the keys in C?
Here's the C++ example for those visitors who search using the C++ tag. The example includes writing the key in PEM format and ASN.1/DER format. C++ is much easier to work with.
#include <iostream>
#include <memory>
#include <string>
using std::cout;
using std::cerr;
using std::endl;
using std::string;
using std::unique_ptr;
#include <openssl/bio.h>
#include <openssl/dsa.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/rand.h>
using DSA_ptr = std::unique_ptr<DSA, decltype(&::DSA_free)>;
using BIO_MEM_ptr = std::unique_ptr<BIO, decltype(&::BIO_free)>;
using BIO_FILE_ptr = std::unique_ptr<BIO, decltype(&::BIO_free)>;
using EVP_PKEY_ptr = std::unique_ptr<EVP_PKEY, decltype(&::EVP_PKEY_free)>;
int main(int argc, char* argv[])
{
int rc = 0;
unsigned long err = 0;
DSA_ptr key(DSA_new(), ::DSA_free);
err = ERR_get_error();
unsigned char buffer[32];
rc = RAND_bytes(buffer, sizeof(buffer));
if (rc != 1)
{
cerr << "RAND_bytes failed, error " << err << ", " << std::hex;
cerr << "0x" << err << endl;
exit(1);
}
rc = DSA_generate_parameters_ex(key.get(), 2048 /*bits*/, buffer, sizeof(buffer), NULL, NULL,
NULL);
err = ERR_get_error();
if (rc != 1)
{
cerr << "DSA_generate_parameters_ex failed, error " << err << ", " << std::hex;
cerr << "0x" << err << endl;
exit(2);
}
rc = DSA_generate_key(key.get());
err = ERR_get_error();
if (rc != 1)
{
cerr << "DSA_generate_key failed, error " << err << ", " << std::hex;
cerr << "0x" << err << endl;
exit(3);
}
EVP_PKEY_ptr pkey(EVP_PKEY_new(), ::EVP_PKEY_free);
/* set1 bumps the reference count; no double free */
rc = EVP_PKEY_set1_DSA(pkey.get(), key.get());
err = ERR_get_error();
if (rc != 1)
{
cerr << "EVP_PKEY_assign_DSA failed, error " << err << ", " << std::hex;
cerr << "0x" << err << endl;
exit(4);
}
BIO_MEM_ptr bio1(BIO_new(BIO_s_mem()), ::BIO_free);
rc = PEM_write_bio_PKCS8PrivateKey(bio1.get(), pkey.get(), NULL, NULL, 0, NULL, NULL);
err = ERR_get_error();
if (rc != 1)
{
cerr << "PEM_write_bio_PKCS8PrivateKey, error " << err << ", " << std::hex;
cerr << "0x" << err << endl;
exit(5);
}
BUF_MEM *mem = NULL;
BIO_get_mem_ptr(bio1.get(), &mem);
err = ERR_get_error();
if (!mem || !mem->data || !mem->length)
{
cerr << "BIO_get_mem_ptr failed, error " << err << ", ";
cerr << std::hex << "0x" << err;
exit(6);
}
string pem(static_cast<const char*>(mem->data), static_cast<size_t>(mem->length));
cout << pem;
BIO_FILE_ptr bio2(BIO_new_file("dsa-private.der", "w"), ::BIO_free);
/* Uses the DSA key, and not the PKEY */
rc = i2d_DSAPrivateKey_bio(bio2.get(), key.get());
err = ERR_get_error();
if (rc != 1)
{
cerr << "i2d_DSAPrivateKey_bio, error " << err << ", " << std::hex;
cerr << "0x" << err << endl;
exit(7);
}
return 0;
}
Compile with something similar to the following. -stdlib=libc++
is needed for OS X.
g++ -g3 -Os -DNDEBUG -std=c++11 -stdlib=libc++ t-dsa.cpp -o t-dsa.exe \
-I/usr/local/ssl/macosx-x64/include /usr/local/ssl/macosx-x64/lib/libcrypto.a -ldl
A typical output is:
$ ./t-dsa.exe
-----BEGIN PRIVATE KEY-----
MIICZQIBADCCAjkGByqGSM44BAEwggIsAoIBAQCgxSeFSRNWTdYyHuPdTxAI2IDN
D6kMFJaYTskneciAolqLszf1xDrJI0+k3J2z4IObBBd6vyFpDzXDHqqr2a2DfF2R
GF5BVGO+x8lXEpMTqViHpBpUpocw04eB6scJ2BEw/OLFA9+09Mhe70m9vcVk72jl
WdnGql55aPrTDZ4xoDNjWKPF2M9bb7JPko9LaPkIHnxdEINspQIl9+i2wk7Vw8UH
ekdOlESxmEvbXTGE25vyggU1x11iHKFz5yfVlG9owUGfn6oCoGqFg6d4bcCd4Dj7
/a3nuVF0b15L//RUFYpkXNJf+Od8ke5m4TNOpx52mja/je+RbsPjHoDHFnUJAiEA
uWApPAEMNBRGu42qSgrI2jFPjY1G6R2etuHEwWjXmQ0CggEANPB/Oi4gi5vtfbXG
+jYSCJs7sA6FzkpH8JFe1vYMbtkTkedAs5kYYwKSs4OqlRCljRTvdDFMcOtVcWcF
VMicYgYmy2Bz7QFNsXFA2iQ1eVBLZ6C12ClvLX4CmHOvIVu47wh3Chn3fdT0fUnc
cgCX8E9+a6483w1IfHAjkprh5atPrRvmCLeZDnOZVuF798dii00/GIDEIZNg6VjV
8ZSE0aTimtuwJyfKbo0bO21Sp4GsVM5X0PYvpimLXkvBUjb/bfmgFm6e4OKvsM5y
TdUag+bqKJRiVUIhDqgbSDhOKVRJJyOMLt9vsR6bql31GzdvhfLRq4qykwfcsSFa
g4m0GgQjAiEAm60m4khLftmgnsZvt5kg1xn5/N7WYYq6tHXPd79M7cc=
-----END PRIVATE KEY-----
The above code use PEM_write_bio_PKCS8PrivateKey
to write out the private key in PEM encoding. The code also uses i2d_DSAPrivateKey_bio
to write it out in ASN.1/DER encoding.
In ASN.1/DER, you would use a tool like Guttman's dumpasn1
to dump it:
$ dumpasn1 dsa-private.der
0 854: SEQUENCE {
4 1: INTEGER 0
7 257: INTEGER
: 00 A0 C5 27 85 49 13 56 4D D6 32 1E E3 DD 4F 10
: 08 D8 80 CD 0F A9 0C 14 96 98 4E C9 27 79 C8 80
: A2 5A 8B B3 37 F5 C4 3A C9 23 4F A4 DC 9D B3 E0
: 83 9B 04 17 7A BF 21 69 0F 35 C3 1E AA AB D9 AD
: 83 7C 5D 91 18 5E 41 54 63 BE C7 C9 57 12 93 13
: A9 58 87 A4 1A 54 A6 87 30 D3 87 81 EA C7 09 D8
: 11 30 FC E2 C5 03 DF B4 F4 C8 5E EF 49 BD BD C5
: 64 EF 68 E5 59 D9 C6 AA 5E 79 68 FA D3 0D 9E 31
: [ Another 129 bytes skipped ]
268 33: INTEGER
: 00 B9 60 29 3C 01 0C 34 14 46 BB 8D AA 4A 0A C8
: DA 31 4F 8D 8D 46 E9 1D 9E B6 E1 C4 C1 68 D7 99
: 0D
...
823 33: INTEGER
: 00 9B AD 26 E2 48 4B 7E D9 A0 9E C6 6F B7 99 20
: D7 19 F9 FC DE D6 61 8A BA B4 75 CF 77 BF 4C ED
: C7
: }
0 warnings, 0 errors.
Suppose you want to generate DSA key pairs.
DSA* dsa = DSA_new();
DSA_generate_parameters_ex(dsa,2048,NULL,0,NULL,NULL, NULL);
DSA_generate_key(dsa);
Or use command line:
openssl dsaparam -genkey 2048
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With