Hi there folks!
I was wondering if someone could help me out in creating an x509 cert and
self signing it.?
This is how I tried to do it:
--Made DSA
--Created key pair
--Created x509 cert
--stuffed pub key in the x509 cert
--stuffed misc. info into cert -- name, etc..
--signed the cert with its private key
--verified the cert with is public key  -- only it won't verify.  The
X509_verify() function returns a -1.
Anywho..I pasted my source code in and I'd *REALLY* appreciate if someone
could take a look at it and tell me where I went wrong. (oh I took out a lot
of my error checking to conserve space, as well as some overly "explainy"
comments -- so in my deleting of these items I may have killed a ";" or
two... )
Thanks so much in advance.  I look forward to hearing from you.
--Andrea
email: [EMAIL PROTECTED]

------------------------------------ CODE BELOW, PLEASE LOOK :)
-------------------------------------------
#include <stdlib.h>
#include <stdio.h>
#include <iostream.h> // for cin\cout
#include <fstream.h>  // for File I\O
#include <string.h>   // for strlen
#include "dsa.h"      // for DSA functions
#include "crypto.h"   // CRYTPO functions
#include "x509.h"     // for X509 functions
#include "sha.h"      // for SHA1 functions
#include "asn1.h"     // for ASN1 functions
#include "pem.h"      // for PEM functions
#include "ssl.h"      // for SSL functions
#include "err.h"      // for ERR functions
#include "evp.h"      // for EVP functions


void main()
{
      
    const int MAX = 50;                          // max length of a string 
                                                 // used for allocating
space
                                                 // for char*

    const int KEYLENGTH = 512;                   // length of a key.
511<KL<1025
    
    
    
    // ==============> GENERATE PARAMETERS
    
    DSA* dsa = NULL;                             // make a ptr to a DSA
structure
    dsa = DSA_new();                             // make a new dsa
    
    // GENERATE PARAMETERS
    int pBits = KEYLENGTH;         // bits in a key
    int seedLen = 20;        // starting seed for psuedo random generator

   
    dsa = DSA_generate_parameters(pBits, NULL, seedLen, NULL, NULL, NULL,
NULL);
    
       
    // GENERATE KEYS
    int done = 0;    
    done = DSA_generate_key(dsa);
          
    // checking to make sure that the keys now point to something, not NULL

    
    //  ==============> CREATE X509 CERTIFICATE
    X509* x509;                                    // pointer to an X509
    x509 = X509_new();                             // create a new one
   
    // Convert the dsa->pub_key into an EVP_KEY so that it can be used to
set
    // the cert's public key field using X509_set_pubkey().
    
    EVP_PKEY* pkey;                            // ptr to an EVP_PKEY
    pkey = EVP_PKEY_new();                     // make a new key
    
    int ok = 0;                            // generic var to hold the return
                                               // values of functions, i.e.
1 | 0
                                               // to see if they worked 
                                               // correctly. Unless
otherwise 
                                               // indicated, all functions
who's
                                               // return value is put into
"ok" 
                                               // has 1 returned if
successful 
                                               // and 0 returned otherwise.

                                               // This var will be used 
                                               // throughout the rest of the
code
    
    ok = EVP_PKEY_assign(pkey, EVP_PKEY_DSA, (char*)(dsa));  // call assign 
                                                             // function, 
                                                             // so pkey
                                                             // is now a
valid EVP_KEY
    
         ok = 0;                                        // set generic var
back to 0
     ok = X509_set_pubkey(x509, pkey);              // put pub key info into
cert
    
     // TIME TO FILL IN THE CERT!
    // Get user info (name, subj. etc) to make cert
    
    // ISSUER NAME
    unsigned char* organizationIssuerName = NULL;     // pts to the
organization 
                                                      // that the issuer
belongs
                                                      // to. i.e. the
Certificate                                                    
                                                      // Authority's (CA)
name
    
    organizationIssuerName = new unsigned char[MAX];  // make some space
    organizationIssuerName = (unsigned char*)("Good Cert Co.");  // generic
info
    
    int len = 0;                                    // another generic var.
                                                    // This will be used 
                                                    // thoughout the program
to 
                                                    // hold the length of
some 
                                                    // data string.
    
    len = strlen((char*)organizationIssuerName);    // get len of
organization
    
    int type = V_ASN1_PRINTABLESTRING; // so its a printable string. ASN1
has
                                       // tons of types that one can use
here.  
                                          
    X509_NAME_ENTRY* organizationIssuerNameEntry;  // the NAME ENTRY (NE)
that
                                                   // will be used to hold
the 
                                                   // ASN1 objects, etc,
that 
                                                   // will later be stuffed
into 
                                                   // an X509_NAME (N). 
    
    organizationIssuerNameEntry = X509_NAME_ENTRY_create_by_NID(NULL,
        NID_organizationName,
        type, 
        organizationIssuerName,
        len);
        
    unsigned char* countryIssuerName = NULL;             // to pt to the 
                                                         // Issuer's country
    
    countryIssuerName = new unsigned char[MAX];          // allocate space
    countryIssuerName = (unsigned char*)("Timbuktu");    // put in the info
    len = 0;                                             // set the len back
zero
    len = strlen((char*)countryIssuerName);              // get len of
string
    
       
    X509_NAME_ENTRY* countryIssuerNameEntry;        // the NE to hold the
country
    countryIssuerNameEntry = X509_NAME_ENTRY_create_by_NID(NULL, 
                                                  NID_countryName, type,
                                                          countryIssuerName,
                                                          len);
    
        ok = 0;
    X509_NAME* issuerName;            // ptr to an X509_NAME to hold the
issuer
                                      // NE's info. A NAME is made a stack
of 
                                      // NE's.
    
    issuerName = X509_NAME_new();     // allocate space
    
    int loc = -1;                     // it'll be reset to the number of
elements
                                      // on the stack, that way we don't
need to 
                                      // keep track of how many NE's have
been 
                                      // put on the stack
    
    int set = -1;                     // so that the NE gets appended to the

                                      // prev. stack
    
    // Add the NE's to the N stack
    ok = X509_NAME_add_entry(issuerName, organizationIssuerNameEntry, loc,
set);
    // Same thing, add another NE to the N stack.
    ok = 0;
    ok = X509_NAME_add_entry(issuerName, countryIssuerNameEntry, loc, set);
   
    // Stuff that N that we just created from a stack of NE's into the cert.

    ok = 0;
    ok = X509_set_issuer_name(x509, issuerName); // set issuer name
    
     // SUBJECT NAME -- i.e. the entity holding the private key that
corresponds
    // to the cert's public key
    unsigned char* commonName = NULL;                       // hold the
subjects 
                                                            // common name
i.e 
                                                            // Joe Shmoe
    
    commonName = new unsigned char[MAX];                    // allocate
space
    commonName = (unsigned char*)("Joe Shmoe");   // stuff generic info
    len = 0;                                                // set the len
back 
                                                            // to 0
    
    len = strlen((char*)commonName);                        // get len of
the 
                                                            // string
    
     // make a X509_NAME_ENTRY using the create_by_NID() function call
    X509_NAME_ENTRY* commonNameEntry;                // ptr to a name entry
    commonNameEntry = X509_NAME_ENTRY_create_by_NID(NULL,
                                                  NID_commonName, type, 
                                                          commonName, len);
    
    unsigned char* countryName = NULL;        // holds the subject's country
name
    countryName = new unsigned char[MAX];     // allocate space!
    countryName = (unsigned char*)("USA");    // stuff generic country info
    len = 0;                                  // set length back to zero
    len = strlen((char*)countryName);         // get the string len
    
        // make the X509_NAME_ENTRY to hold the country name
    X509_NAME_ENTRY* countryNameEntry;     // ptr to a country name entry
    countryNameEntry = X509_NAME_ENTRY_create_by_NID(NULL, NID_countryName,
type,
        countryName, len);
    
       unsigned char* organizationalUnitName = NULL; // the subjects
organizational
                                                  // unit name, i.e. IAL 
    organizationalUnitName = new unsigned char[MAX];  // allocate space
    organizationalUnitName = (unsigned char*)("Intel Architecture Lab"); //
info
    
    len = 0 ;                          // set the length of the string back
to 0
    len = strlen((char*)organizationalUnitName);  // get string len
    
       // make the X509_NAME_ENTRY to hold the organizational unit name
    X509_NAME_ENTRY* organizationalUnitNameEntry;
    organizationalUnitNameEntry = X509_NAME_ENTRY_create_by_NID(NULL, 
        NID_organizationalUnitName, 
        type, organizationalUnitName, 
        len);
   
    
    unsigned char* organizationName = NULL; // subject's organization's name
    organizationName = new unsigned char[MAX];          // allocate space
    organizationName = (unsigned char*)("CompanyY");       // stuff in some
info
    len = 0;                                            // set the len back
to 0
    len = strlen((char*)organizationName);              // get strlen
    
      // make the X509_NAME_ENTRY to hold the organization name
    X509_NAME_ENTRY* organizationNameEntry;
    
    
    organizationNameEntry = X509_NAME_ENTRY_create_by_NID(NULL, 
        
NID_organizationName,
                                                                type, 
 
organizationName, 
                                                                      len);

       // Now make an X509_NAME with those 4 NAME_ENTRYs: commonNameEntry,
    // countryNameEntry, organizationalUnitNameEntry, and
organizationNameEntry
    
    X509_NAME* subjectName;                        // ptr to subjects "name"
    subjectName = X509_NAME_new();                 // create a new NAME
    loc = -1;                                      // it'll be reset to the 
                                                   // number of elements on 
                                                   // the stack.

    set = 1;                                       // gets appended to prev.
set
    
    // add a NE (countryNameEntry) to the stack
    ok = 0;
    ok = X509_NAME_add_entry(subjectName, countryNameEntry, loc, set); 
    
      // add another NE (commonNameEntry) to the stack in the N
    ok = 0;
    
    ok = X509_NAME_add_entry(subjectName, commonNameEntry, loc, set);
       // keep on addin' NE's (add organizationUnitNameEntry this time)!
    ok = 0;
    
    ok = X509_NAME_add_entry(subjectName, organizationalUnitNameEntry, 
        loc, set);
    
        // add another NE (organizationNameEntry) to the stack of them in
the N
    ok = 0; 
    
    ok = X509_NAME_add_entry(subjectName, organizationNameEntry, loc, set);
    
        // set the subject's "name" on the cert, which really consists of
all those
    // NE's that we just stuffed into the N.
    
    ok = 0;
    
    ok = X509_set_subject_name(x509, subjectName);  // set issuer name
    
        // SET VERSION
    ok = 0;
    
    ok = X509_set_version(x509, NID_X509); // version set to X509
   
   
    // SET NOT BEFORE TIME
    ASN1_UTCTIME* UTCTIMEnotBefore;     // make a ptr to an ASN1_UTCTIME
object 
                                        // which is what we use to store
                                        // some time data..
    
    UTCTIMEnotBefore = ASN1_UTCTIME_new();  // make a new one i.e allocate
space
    char* timeNotBefore;                    // to hold the GMT as a string 
                                            // (Grenage Mean Time)
    
    // going to store a time 
    timeNotBefore = new char[MAX];    // allocate space
    timeNotBefore = "790311064508Z";  // put generic info in. 
    
    ok = 0;
    
    ok =  ASN1_UTCTIME_set_string(UTCTIMEnotBefore, timeNotBefore); // put
that
                                                                    // big
time char 
                                                                    //
string into the 
                                                                    // ASN1
object
       
    // stuff that time into the cert
    ok = 0;
    ok = X509_set_notBefore(x509, UTCTIMEnotBefore);
   
    // SET TIME NOT AFTER
    ASN1_UTCTIME* UTCTIMEnotAfter;
    UTCTIMEnotAfter = ASN1_UTCTIME_new();            // make a new one
    char* timeNotAfter;                              // to hold the GMT
string
    timeNotAfter = new char[MAX];                    // allocate space
    timeNotAfter = "990807053011Z";                      ok = 0;
    ok = ASN1_UTCTIME_set_string(UTCTIMEnotAfter, timeNotAfter); // stuff
that 
                                                                 // time
char string into the 
                                                                 // ASN1
object just created
   
    // stuff the TIME NOT AFTER into the cert
    ok = 0;
    ok = X509_set_notAfter(x509, UTCTIMEnotAfter);   // stuffing it in there
now
    
    
    // SET SERIAL NUMBER
    ASN1_INTEGER* ASN1serialNumber;              // make a ptr to an oject
that
                                                 // holds the serial number

    ASN1serialNumber = ASN1_INTEGER_new();       // make a new one
    long serialNumber = 12345678;                // generic info
    ok = 0;
    ok = ASN1_INTEGER_set(ASN1serialNumber, serialNumber);  // stuff that
long 
    // in the ASN1 obj.
   
    // Now stuff the serial number into the cert
    ok = 0;
    

    ok = X509_set_serialNumber(x509, ASN1serialNumber); // stuffing now!
   


    // SIGN THE CERT  ====>  I THINK SOMETHING IS WRONG AROUND HERE, SINCE
IT WON'T VERIFY.

    // use the pkey which is of type EVP_PKEY to be an object that is sent
along
    // to help sign a cert
   
    unsigned int sig_len = 0;                       // length of the
signature 
    
    // write DSA private key to a .pem file
    
    FILE* privateKeyFile;
    static char keyfile[] = "key.pem";              // has private key in
pem format 
    privateKeyFile = fopen(keyfile, "w+");          // open key.pem for
writing
    
    // PEM_write_DSAPrivateKey();
    PEM_write_DSAPrivateKey(privateKeyFile, dsa, 
        NULL, // don't need ENV_CIPHER fumction to encrypt
        NULL, // for requiring password
        KEYLENGTH,  // length of the key
        NULL);  // no call back function needed
    
    
    fclose(privateKeyFile);  // close the file
    
    // now extract key from file
    
    privateKeyFile = fopen(keyfile, "r");            // open file for
reading
    
    if(privateKeyFile == NULL) // error check
    {
        cerr<<"Error in making privateKeyFile the handle of the
keyfile"<<endl;
        cerr<<"Program is now exiting....."<<endl;
        exit(1);
    }
    
    EVP_PKEY* privateKey; 
   // read the private key from the pem file, convert it into an 
    // EVP_PKEY and store it in privateKey
    privateKey = (EVP_PKEY*)PEM_ASN1_read ((char *(*)())d2i_PrivateKey,
        PEM_STRING_EVP_PKEY,
        privateKeyFile,
        NULL, NULL);
    
    if(privateKeyFile==NULL) // error check
    {
        ERR_print_errors_fp(stderr);
        exit(1);
    }
    
     sig_len = X509_sign(x509, privateKey, EVP_dss1());
    cout<<"X509_sign reports sig_len = "<<sig_len<<endl;

    if(sig_len <= 0)  // error check
    {
        cout<<endl<<endl;
        cout<<"ERROR:  in signing cert X509_sign()"<<endl;
        cerr<<"Program is now EXITING!...."<<endl;
        exit(1);
    }  // end if file writing error, i.e. ok == 0

  

    // WRITE INFO TO A FILE TO SEE IF IT LOOKS RIGHT
    // We will now write the cert into a human-readable file using a
function
    // who's sole purpose in life is to do just that: X509_print_fp()
    // We do this for another way to error check, by making sure that all
the
    // info we stuffed into the cert actually got into the right place.  
    
// =====> WHEN I WRITE IT TO THE FILE, IT "looks" RIGHT

    FILE*  certFP;                                            // pointer to
the cert file
    certFP = fopen("cert_info", "w+");                        // open
"cert_info" for writing
    ok = 0;
    ok = X509_print_fp(certFP, x509);                         // write the
cert x509 to the file
    if(ok == 0)  // error check
    {
        cout<<endl<<endl;
        cout<<"ERROR:  in writing cert to file 'cert_info'"<<endl;
        cerr<<"Program is now EXITING!...."<<endl;
        exit(1);
    }  // end if file writing error, i.e. ok == 0
    fclose(certFP);                       // close the file
    
    
    // WRITE INFO TO A .PEM FILE
    // Now we will write the X509 to "blah.pem" --a file which has the form:
    // -----BEGIN CERTIFICATE-----
    // KLDJFKL;JDSKF;LJSD;OSFIU87349DF0985-8_&**U
    // DKJF;KL*&*FUD;LFJ 78Y7987&*^FLKJLF98Y98Y75
    // DLKFJD;LSKAJFOP*#EPOIJHPODHUPIOULKJ^^&#HKJ
    // -----END CERTIFICATE-----
    // The X509 cert is DER-encoded then base64-encoded and then stuffed
into
    // the .pem file.
    
    FILE* pemFP;                                               // pointer to
the .pem file
    static char certFile[] = "cert.pem";                       // file to
write the.pem info to
    
    
    pemFP = fopen(certFile, "w+");                             // open
"blah.pem" for writing
    ok = 0;
    ok = PEM_write_X509(pemFP, x509);                          // stuff the
x509 in pem form into
                                                               // the file
    if(ok == 0)  // error check
    {
        cout<<endl<<endl;
        cout<<"ERROR:  in wrting to .pem file"<<endl;
        cerr<<"Program is now EXITING!...."<<endl;
        exit(1);
    }  // end if file writing to .PEM error, i.e. ok == 0
    fclose(pemFP);                                             // close the
file
    cout<<"Pem file written!"<<endl;  //<<<<<<<<<<<<<<<<<<<<
      
    
    // VERIFY CERT SIGNING
    // read the public key by pulling the cert out of the cert file
    pemFP = fopen(certFile, "r");                              // open file
for reading
    
    if(pemFP == NULL)  // error check
    {
        cerr<<"ERROR:  handle for certFile, for reading, not made properly."
            <<endl;
        cerr<<"Program is now exiting....."<<endl;
        exit(1);
    } // end if pemFP ==  NULL
    
    X509* x509CheckingCert;
    x509CheckingCert = (X509*)PEM_ASN1_read ((char *(*)())d2i_X509,
        PEM_STRING_X509,
        pemFP, NULL, NULL);

    if(x509CheckingCert == NULL) // error check
    {
        ERR_print_errors_fp(stderr);
        exit(1);
    } // end if x509CheckingCert == NULL
    fclose(pemFP); // close the file
    
    // Get public key
    EVP_PKEY* publicKey;
    publicKey = X509_get_pubkey(x509);
    
    if(publicKey == NULL) // error check
    {
        ERR_print_errors_fp(stderr);
        exit(1);
    } // end if publicKey == NULL
    
    // now verify the signature
    cout<<"now I am here"<<endl;
    ok = 0;
    
    ok = X509_verify(x509CheckingCert, publicKey);  // <============= THIS
RETURNS -1
    
    
    if(ok != 1) // error check
    {
        cerr<<"ERROR: X509_verify() did not return 1"<<endl;
        ERR_print_errors_fp(stderr);
        cerr<<"Program is now EXITING!!"<<endl;
        exit(1);  // <============================== SINCE OK = -1, IT DIES
HERE!
    } // end if err != 1
    
    cout<<"Signature Verified! Thank Goodness!"<<endl;
              
    cout<<"Press any key to continue"<<endl;
    char blah;
    cin>>blah;

    cout<<endl<<"-----DONE-----"<<endl<<endl;
    
    
    // just so we know where we are ;)
    cout<<endl<<"-----DONE-----"<<endl<<endl;   
    
    
} // end main





















______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
Development Mailing List                       [EMAIL PROTECTED]
Automated List Manager                           [EMAIL PROTECTED]

Reply via email to