Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using openssl to generate a DSA key pair

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

like image 756
HaTiMuX Avatar asked Jan 12 '23 21:01

HaTiMuX


2 Answers

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.
like image 113
jww Avatar answered Jan 23 '23 13:01

jww


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 
like image 27
onemouth Avatar answered Jan 23 '23 15:01

onemouth