4

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! :)

4
  • 1
    Are you sure you cannot use RSA or ECDSA? DSA is not used that much anymore for signatures. Commented Nov 18, 2013 at 22:43
  • I don't know i just want to generate the keys using functions from C. Can you help me please? Commented Nov 18, 2013 at 23:07
  • Which kind of key do you need? Algorithm? Length? Commented Nov 19, 2013 at 1:59
  • I need to generate a pair of keys (private and public) with DSA or RSA Commented Nov 20, 2013 at 11:04

2 Answers 2

6

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.
Sign up to request clarification or add additional context in comments.

Comments

3

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 

2 Comments

Yes that's it. But how can i read the private or the public key from the key generated?. Thank you
Use BCryptExportKey and examine the blob

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.