dear all
i'm a Msc student that uses NS3 simulator to do some researches. my target
for right now is to make a sample code for a client and a server then add
it to the simulator
as a brief
1-the client send a certificate request and the server send the certificate
to the client
2- the client create a shared key and encrypt it using function
RSA_public_encrypt and create some data and sign the data and encrypted
shared key and send (client certificate and the data and the encrypted
shared key and the sign (of both encrypted shared key and the data)) to the
server side
3- the server will verify the certificate and decrypt the encrypted shared
key using its private key. and verify the sign using the public key
extracted from the client certificate

i have created the certificate and its working well and verified and the
encrypted shared key is done

 my problem is
1- how to sign both the data and encrypted shared key with the private key
of the client even i have only RSA structure

2- the encrypted shared key should be encrypted by the public key of the
server which can be extracted from the server certificate but the method it
self RSA_public_encrypt got RSA structure as an argument

3-how can i verify the sign

 do i need to make all of the data and encrypted shared key to digest then
sign it ???? even i don't separated private and public key i have only RSA
structure and how to do that

thanks allot for help

-- 
Warmest regards and best wishes for a good health,*urs sincerely *
*mero*
//============================================================================
// Name        : certificate.cpp
// Author      : Amir
// Version     :
// Copyright   : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================

#include <iostream>
#include "server.h"
#include "client.h"
using namespace std;

int main()
{
	clock_t start, end;
	double msecs;

	start = clock();

	Client clientest;
    Server servertest;

    X509 *cert;
    cert = servertest.CreateCertificate(clientest.MakeSignedCertReq());

    clientest.SetCert(cert);
    clientest.CertConverter();
    X509 *test;
    test = clientest.GetCert();
    servertest.CheckCert(cert);
    int serial = 0;
    serial = clientest.ExtractCertSerial();
    cout<<"client serial is "<<serial<<endl;

    clientest.SetSharedKey();
    clientest.EncryptSharedKey();

    clientest.SetData(DATA_SIZE);
    clientest.SignData();

    clientest.SetDigestData(DATA_SIZE,RSA_KEY_SIZE);

    X509 *certtest = NULL;
    unsigned char data[DATA_SIZE];
    unsigned char signeddata[RSA_KEY_SIZE];

    servertest.client->GetData(certtest,data,DATA_SIZE,signeddata,RSA_KEY_SIZE);

    //int serverserial = 0;
    //serverserial = servertest.ExtractCertSerial();
    //cout<<"server serial is "<<serverserial<<endl;

	end = clock();
	msecs = ((double) (end - start)) * 1000 / CLOCKS_PER_SEC;
	cout<<"time is "<<msecs<<"msec"<<endl;

	return 0;
}
/*
 * client.cc
 *
 *  Created on: Sep 17, 2014
 *      Author: amirale32
 */

#include "client.h"

 Client :: Client()
 {
	  m_myCertReq = X509_REQ_new();
	  m_myCert = X509_new();
	  m_name = X509_NAME_new();
	  m_rsa_keyPair = RSA_new();
	  m_puk  = EVP_PKEY_new();
	  GenerateRSAKeyPair();
 }

 Client :: ~Client()
 {
	  X509_REQ_free(m_myCertReq);
	  X509_free(m_myCert);
	  RSA_free(m_rsa_keyPair);
 }

 void
 Client :: GenerateRSAKeyPair ( )
 {
     m_rsa_keyPair = RSA_generate_key((8*RSA_KEY_SIZE),RSA_F4,NULL,NULL);
     BIO *pubout = NULL;
     const char szPath[MAX_FILE_NAME_SIZE] = "clrsa.pem";
     pubout = BIO_new_file(szPath,"wb");
     PEM_write_bio_RSAPublicKey (pubout , m_rsa_keyPair);
     BIO_free(pubout);

}

 void
 Client::SetPublicKey()
 {
	 EVP_PKEY_assign_RSA(m_puk,m_rsa_keyPair);
     BIO *out = NULL;
     const char szPath[MAX_FILE_NAME_SIZE] = "cpuky.pem";
     out = BIO_new_file(szPath,"wb");
     PEM_write_bio_PUBKEY(out,m_puk);
 }

 X509_REQ*
 Client::MakeSignedCertReq()
 {
	 //adds all digest algorithms to the table
	 OpenSSL_add_all_digests();
	 SetPublicKey();
	 //include the public key in the req
	 X509_REQ_set_pubkey(m_myCertReq,m_puk);
	 //set the subject name of the request
	 m_name=X509_REQ_get_subject_name(m_myCertReq);
	 //set the request
	 X509_NAME_add_entry_by_txt(m_name,"C",MBSTRING_ASC, (const unsigned char *)"UK", -1, -1, 0);
	 X509_NAME_add_entry_by_txt(m_name,"CN",MBSTRING_ASC, (const unsigned char *)"OpenSSL Group", -1, -1, 0);
	 //sign the req
	 X509_REQ_sign(m_myCertReq,m_puk,EVP_sha1());
	 BIO *out = NULL;
	 const char szPath[MAX_FILE_NAME_SIZE] = "req.pem";
	 out = BIO_new_file(szPath,"wb");
	 PEM_write_bio_X509_REQ(out,m_myCertReq);
	 BIO_free(out);
	 return m_myCertReq;
}

 void
 Client::SetCert(X509 *cert)
 {
	 m_myCert =  cert;
	 BIO *out = NULL;
	 const char szPath[MAX_FILE_NAME_SIZE] = "clcrt.pem";
	 out = BIO_new_file(szPath,"wb");
	 PEM_write_bio_X509 (out , cert);
}

 int
 Client::CertConverter()
 {
	 int len = i2d_X509(m_myCert, NULL);
	 unsigned char *buf, *p;
	 buf = (unsigned char *)OPENSSL_malloc(len);
	 p = buf;
	 i2d_X509(m_myCert, &p);
	 unsigned char certarray[len];
	 for (int i = 0 ; i<len ; i++)
	 {
		 certarray[i] = *(p-len+i);
	 }
	 cout<<"cert len is "<<len<<endl;
	 cout << "converted client cert is"<<endl;
	 for (int j = 0 ; j<len ; j++)
	 {
	     	printf("0x%.2x ", certarray[j]);
	 }
	 cout<<endl;

	 X509 *certtest;
	 unsigned char *buf1;
	 buf1 = certarray;
	 const unsigned char *p1 = buf1;
	 p1 = buf1;
	 certtest = d2i_X509(NULL, &p1, CERT_SIZE);

	 FILE * fcert;
	 fcert = fopen("certarray.pem", "wb");
	 PEM_write_X509(
	     fcert,    //write the certificate to the file we've opened
	     certtest  //our certificate
	 );
	 return 0;
}

 X509*
 Client::GetCert()
 {
	 return m_myCert;
}

 int
 Client::ExtractCertSerial()
 {
	 int serial = 0;
	 unsigned char **out = NULL;
	 ASN1_INTEGER *asn1_serial = NULL;

	 asn1_serial = X509_get_serialNumber(m_myCert);
	 serial = i2d_ASN1_INTEGER(asn1_serial, out);
	 return (serial);
}

 void
 Client::SetDigestData(int datasize, int keysize)
 {
	 for (int i = 0; i<datasize ; i++)
	 {
		 m_digestData[i] = m_Data[i];
	 }
	 for (int j = 0 ; j <keysize ; j++ )
	 {
		 m_digestData[(datasize+j)] = m_encryptedSharedKey[j];
	 }
	 cout <<"digest data is"<<endl;
	 for (int k = 0 ; k< (datasize + keysize ); k++)
	 {
	     	printf("0x%.2x ", m_digestData[k]);
	 }
	 cout<<endl;
 }
 void
 Client::CreateDigest()
 {

 }

void
Client::SetData(int size)
{
	cout<<"data is "<<endl;
	for (int i = 0 ; i<size ; i++)
	{
		m_Data[i]=i;
    	printf("0x%.2x ", m_Data[i]);
	}
	cout<<endl;
}

void
Client::SignData()
{
	int padding = RSA_PKCS1_PADDING;
	RSA_private_encrypt(DATA_SIZE, m_Data, m_signedData, m_rsa_keyPair , padding);
    cout<<"sign data is "<<endl;

    for (int i = 0 ; i <RSA_KEY_SIZE;i++)
    {
    	printf("0x%.2x ", m_signedData[i]);
    }
    cout<<endl;
}

void
Client::SetSharedKey()
{
	cout<<"shared key is "<<endl;
	for (int i = 0; i<SHARED_KEY_SIZE ; i++)
	{
	m_sharedKey[i] = i;
	printf("0x%.2x ", m_sharedKey[i]);
	}
	cout<<endl;
}

void
Client::EncryptSharedKey()
{
	int padding = RSA_PKCS1_PADDING;
	RSA_public_encrypt(SHARED_KEY_SIZE,m_sharedKey,m_encryptedSharedKey,m_rsa_keyPair,padding);
    cout<<"encrypted shared key is "<<endl;
    for (int i = 0 ; i<RSA_KEY_SIZE ; i++)
    {
    	printf("0x%.2x ", m_encryptedSharedKey[i]);
    }
    cout<<endl;
}

void
Client::GetData(X509* cert, unsigned char data[], int datasize,unsigned char signeddata[], int signsize)
{
	cert = GetCert();

	for(int i = 0 ; i< datasize ; i++)
	{
		data [i] =  m_Data[i];
	}
	for (int j = 0 ; j<signsize ; j++)
	{
		signeddata[j] = m_signedData[j];
	}
}
/*
 * client.h
 *
 *  Created on: Sep 17, 2014
 *      Author: amirale32
 */

#ifndef CLIENT_H_
#define CLIENT_H_

#define MAX_FILE_NAME_SIZE 20
#define RSA_KEY_SIZE 256 //bytes
#define CERT_SIZE 727
#define SHARED_KEY_SIZE 32 //bytes
#define DATA_SIZE    13

#include <stdlib.h>
#include <stdio.h>
 #include <openssl/rsa.h>
 #include <openssl/conf.h>
 #include <openssl/x509.h>
 #include <openssl/pem.h>
#include "server.h"

 class Client
 {
   public:

   Client();
   ~Client();

   void GenerateRSAKeyPair ();
   void SetPublicKey ();

   X509_REQ *MakeSignedCertReq();
   void SetCert (X509 *cert);
   X509 *GetCert();
   int CertConverter ();
   int ExtractCertSerial ();

   void SetSharedKey();
   void EncryptSharedKey();

   void SetDigestData(int datasize,int keysize);
   void CreateDigest();

   void SetData(int size);
   void SignData();

   void GetData(X509 *cert,unsigned char data[],int datasize, unsigned char signeddata[],int signsize );


   private:

   X509_REQ         *m_myCertReq;
   X509             *m_myCert;
   X509_NAME        *m_name;
   RSA              *m_rsa_keyPair;
   EVP_PKEY         *m_puk;
   unsigned char     m_Data[DATA_SIZE];
   unsigned char     m_signedData[RSA_KEY_SIZE ];
   unsigned char     m_encryptedSharedKey[RSA_KEY_SIZE];
   unsigned char     m_sharedKey[SHARED_KEY_SIZE];
   unsigned char     m_digestData[DATA_SIZE+RSA_KEY_SIZE];
   unsigned char     m_digestOutput[256];

 };



#endif /* CLIENT_H_ */
#include "server.h"

 Server::Server()
 {
	  m_myCert = X509_new();
	  m_caKeyPairs = RSA_new();
	  m_pukey  = EVP_PKEY_new();
	  m_issuerName = X509_NAME_new();
	  GenerateMyKeyPairs();
	  CreateMyCertificate();
 }

 Server::~Server()
 {
	  X509_free(m_myCert);
	  RSA_free(m_caKeyPairs);
	  X509_NAME_free(m_issuerName);
 }

 X509*
 Server::CreateCertificate(X509_REQ* req)
 {
	 X509 *m_req_reply;
	 m_req_reply = X509_new();
	 X509_NAME *subject = NULL;
	 EVP_PKEY *pkey = NULL;
	 //check Request signature matches the certificate request
	 pkey = X509_REQ_get_pubkey(req);

	 ASN1_INTEGER_set(X509_get_serialNumber(m_req_reply), 2);

	 X509_gmtime_adj(X509_get_notBefore(m_req_reply), 0);
	 X509_gmtime_adj(X509_get_notAfter(m_req_reply), 31536000L);

	 X509_set_pubkey(m_req_reply, pkey);

	 X509_NAME *issuerSubject = X509_get_subject_name(m_myCert);

	 X509_set_issuer_name(m_req_reply, issuerSubject);

	 //extract the subject of the request
	 subject = X509_REQ_get_subject_name(req);
	 X509_set_subject_name(m_req_reply, subject);

	 X509_get_subject_name(m_req_reply);

	 X509_sign(m_req_reply, m_pukey, EVP_sha1());
	 return m_req_reply;
 }

 void
 Server::CreateMyCertificate()
 {
     // we use rsa pairs and assign it into evp_key
	 SetPublicKey();
	 // properties of the certificate
	 //set the serial number
	 ASN1_INTEGER_set(X509_get_serialNumber(m_myCert), 1);
	 //set the time validity
	 X509_gmtime_adj(X509_get_notBefore(m_myCert), 0);
	 X509_gmtime_adj(X509_get_notAfter(m_myCert), 31536000L);
	 //set the public key of the cert to be signed
	 X509_set_pubkey(m_myCert, m_pukey);
     //this is a self-signed certificate, we set the name of the issuer to the name of the subject
	 m_issuerName = X509_get_subject_name(m_myCert);

	 X509_NAME_add_entry_by_txt(m_issuerName, "C",  MBSTRING_ASC,
	                            (unsigned char *)"CA", -1, -1, 0);
	 X509_NAME_add_entry_by_txt(m_issuerName, "O",  MBSTRING_ASC,
	                            (unsigned char *)"MyCompany Inc.", -1, -1, 0);
	 X509_NAME_add_entry_by_txt(m_issuerName, "CN", MBSTRING_ASC,
	                            (unsigned char *)"localhost", -1, -1, 0);

     //set the issuer name
	 X509_set_issuer_name(m_myCert, m_issuerName);
	 //sign the cert
	 X509_sign(m_myCert, m_pukey, EVP_sha1());

	 FILE * fcert;
	 fcert = fopen("cacert.pem", "wb");
	 PEM_write_X509(
	     fcert,   /* write the certificate to the file we've opened */
	     m_myCert /* our certificate */
	 );
 }

 void
 Server::GenerateMyKeyPairs()
 {
	 m_caKeyPairs = RSA_generate_key((8*RSA_KEY_SIZE),RSA_F4 , NULL , NULL);
     BIO *pubout = NULL;
     const char szPath[MAX_FILE_NAME_SIZE] = "carsa.pem";
     pubout = BIO_new_file(szPath,"wb");
     PEM_write_bio_RSAPublicKey (pubout , m_caKeyPairs);
     BIO_free(pubout);
}

 void
 Server::SetPublicKey()
 {
	 EVP_PKEY_assign_RSA(m_pukey,m_caKeyPairs);

	 BIO *out = NULL;
	 const char szPath[MAX_FILE_NAME_SIZE] = "caevp.pem";
	 out = BIO_new_file(szPath,"wb");

	 EVP_PKEY_print_private(out, m_pukey,
	                                0, NULL);
	 BIO_free(out);
	 out = BIO_new_file("prkey.pem","wb");

	 PEM_write_bio_PrivateKey(
	     out,                  /* write the key to the file we've opened */
		 m_pukey,               /* our key from earlier */
	     EVP_des_ede3_cbc(), /* default cipher for encrypting the key on disk */
	     (unsigned char *)"replace_me",       /* passphrase required for decrypting the key on disk */
	     10,                 /* length of the passphrase string */
	     NULL,               /* callback for requesting a password */
	     NULL                /* data to pass to the callback */
	 );

 }

 int
 Server::CheckCert(X509* clientcert)
 {

	 int status = 0;
	 X509_STORE_CTX *ctx = X509_STORE_CTX_new();

     //store the trusted cert into ctx
	 X509_STORE *store = X509_STORE_new();
	 X509_STORE_add_cert(store, m_myCert);

     //put the trusted cert and cert then verify it
	 X509_STORE_CTX_init(ctx,store, clientcert, NULL);
	 status  = X509_verify_cert(ctx);

	 if (status == 1)
	 {
		 cout<<"verified succesfully"<<endl;
	 }
	 else
	 {
		 cout<<"verifiy fail"<<endl;
		 cout << X509_verify_cert_error_string(X509_STORE_CTX_get_error(ctx));
	 }
	 return status;
}

bool
Server::CheckData(X509 *clientcert,unsigned char data[],int datasize, unsigned char signeddata[],int signsize)
{
	bool certstatus;
	bool signstatus;

	if (CheckCert(clientcert) == 1)
	{
		certstatus = true;
	}
	else
	{
		certstatus = false;
	}

	if ((certstatus && signstatus) == true)
	{
		return true;
	}
	return false;
}
/*
 * server.cc
 *
 *  Created on: Sep 17, 2014
 *      Author: amirale32
 */




/*
 * server.h
 *
 *  Created on: Sep 17, 2014
 *      Author: amirale32
 */

#ifndef SERVER_H_
#define SERVER_H_

 #include <stdlib.h>
 #include <iostream>
 #include <stdio.h>
 #include <openssl/asn1.h>
 #include <openssl/ssl.h>
 #include <openssl/rsa.h>
 #include <openssl/conf.h>
#include  "client.h"
#include <openssl/x509.h>
#include <openssl/x509_vfy.h>

#define MAX_FILE_NAME_SIZE 20
#define RSA_KEY_SIZE 256 //bytes
#define CERT_SIZE 727

#define DATA_SIZE    13

using namespace std;
class Client;
 class Server
 {
 public:

	 Server();
	 ~Server();

	 X509 *CreateCertificate (X509_REQ *req);
	 void CreateMyCertificate();

	 void GenerateMyKeyPairs ( );
	 void SetPublicKey ();

	 int CheckCert (X509 *clientcert);
	 bool CheckData(X509 *cert,unsigned char data[],int datasize, unsigned char signeddata[],int signsize);

	 Client           *client;

 private:

	 X509             *m_myCert;
	 RSA              *m_caKeyPairs;
	 EVP_PKEY         *m_pukey;
	 X509_NAME        *m_issuerName;
 };



#endif /* SERVER_H_ */

Reply via email to