dear all i made an application a client server the client send a
certificate request and server reply with the certificate and it creates a
encrypted shared key and some data and sign the digest of the shared key
and data
my problem is
1- in SignDigest() in EVP_DigestSignFinal(mdctx, NULL, signlen); function
return an error No source available for "EVP_PKEY_sign() at 0xb7ede098"
i don't know the reason for this error it should return the length of the
sign only????
then i reserve a location in memory with this size
please help me
--
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;
servertest.SetSharedKey();
servertest.EncryptSharedKey(cert);
unsigned char enckey[RSA_KEY_SIZE];
servertest.GetEncryptedKey(enckey,RSA_KEY_SIZE);
clientest.DecryptSharedKey(enckey);
servertest.SetData(DATA_SIZE);
servertest.SetDigestData();
servertest.CreateDigest();
servertest.SignDigest();
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::DecryptSharedKey(unsigned char encryptedkey[])
{
int padding = RSA_PKCS1_PADDING;
RSA_private_decrypt(RSA_KEY_SIZE,encryptedkey,m_DecryptedSharedKey,m_rsa_keyPair,padding);
cout<<" shared key after decryption is "<<endl;
for (int i = 0 ; i<SHARED_KEY_SIZE ; i++)
{
printf("0x%.2x ", m_DecryptedSharedKey[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;
}
*/
/*
* 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 DIGEST_SIZE 20
#define DATA_SIZE 13
#define SIGNED_DATA_SIZE 20
#include <stdlib.h>
#include <stdio.h>
#include <openssl/rsa.h>
#include <openssl/conf.h>
#include <openssl/x509.h>
#include <openssl/pem.h>
#include <openssl/sha.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 DecryptSharedKey (unsigned char encryptedkey []);
private:
X509_REQ *m_myCertReq;
X509 *m_myCert;
X509_NAME *m_name;
RSA *m_rsa_keyPair;
EVP_PKEY *m_puk;
unsigned char m_DecryptedSharedKey[SHARED_KEY_SIZE];
};
#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 */
);
}
void
Server::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
Server::EncryptSharedKey(X509 *clientcert)
{
int padding = RSA_PKCS1_PADDING;
RSA *m_clrsa_keyPair = NULL;
EVP_PKEY *pkey = NULL;
pkey = X509_get_pubkey(clientcert);
m_clrsa_keyPair = EVP_PKEY_get1_RSA(pkey);
RSA_public_encrypt(SHARED_KEY_SIZE,m_sharedKey,m_encryptedSharedKey,m_clrsa_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
Server::GetEncryptedKey(unsigned char encryptedkey[], int size)
{
for (int i = 0 ; i<size ; i++)
{
encryptedkey [i] = m_encryptedSharedKey [i];
}
}
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;
}
void
Server::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
Server::SetDigestData()
{
for (int i = 0; i<DATA_SIZE ; i++)
{
m_digestData[i] = m_Data[i];
}
for (int j = 0 ; j <RSA_KEY_SIZE ; j++ )
{
m_digestData[(DATA_SIZE+j)] = m_encryptedSharedKey[j];
}
cout <<"digest data is"<<endl;
for (int k = 0 ; k< (DATA_SIZE + RSA_KEY_SIZE ); k++)
{
printf("0x%.2x ", m_digestData[k]);
}
cout<<endl;
}
void
Server::CreateDigest()
{
OpenSSL_add_all_ciphers();
OpenSSL_add_all_digests();
SHA1(m_digestData, (DATA_SIZE + RSA_KEY_SIZE), m_digest);
cout<<"digest is "<<endl;
for (int i = 0; i < DIGEST_SIZE; i++)
{
printf("0x%.2x ", m_digest[i]);
}
cout<<endl;
}
void
Server::SignDigest()
{
OpenSSL_add_all_ciphers();
OpenSSL_add_all_digests();
//create private key
EVP_PKEY *priv_key = NULL;
priv_key = EVP_PKEY_new();
EVP_PKEY_set1_RSA(priv_key,m_caKeyPairs);
cout<<"i'm in sign digest"<<endl;
/*
BIO *sgerr = NULL;
const char szPath[MAX_FILE_NAME_SIZE] = "sgerr.pem";
sgerr = BIO_new_file(szPath,"wb");
cout<<"input digest is "<<endl;
for (int i = 0; i < DIGEST_SIZE; i++)
{
printf("0x%.2x ", m_digest[i]);
}
cout<<endl;
*/
size_t *signlen = NULL;
unsigned char *sign = NULL;
//create message digest context
EVP_MD_CTX *mdctx = NULL;
mdctx = EVP_MD_CTX_create();
//Initialize the DigestSign operation
EVP_DigestSignInit(mdctx, NULL, EVP_sha1(), NULL, priv_key);
//update with the message
EVP_DigestSignUpdate(mdctx, m_digestData,(DATA_SIZE + RSA_KEY_SIZE));
//Finalise the DigestSign operation
EVP_DigestSignFinal(mdctx, NULL, signlen);
sign = (unsigned char *)OPENSSL_malloc(signlen);
EVP_DigestSignFinal(mdctx, sign, signlen);
//cout<<"sign length is "<<(*signlen)<<endl;
//unsigned int *siglen = NULL;
//assert (1 == RSA_sign(NID_sha1,m_digest, DIGEST_SIZE,m_signedDigest,siglen,m_caKeyPairs));
// ERR_print_errors(sgerr);
//BIO_free(sgerr);
/*
//cout <<"sig len is "<<(*siglen)<<endl;
cout<<"signed digest is "<<endl;
for (int i = 0; i < RSA_KEY_SIZE; i++)
{
printf("0x%.2x ", m_signedDigest[i]);
}
cout<<endl;
*/
}
/*
* 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 <assert.h>
#include <openssl/asn1.h>
#include <openssl/ssl.h>
#include <openssl/rsa.h>
#include <openssl/conf.h>
#include <openssl/err.h>
#include "client.h"
#include <openssl/x509.h>
#include <openssl/x509_vfy.h>
using namespace std;
class Client;
class Server
{
public:
Server();
~Server();
X509 *CreateCertificate (X509_REQ *req);
void CreateMyCertificate();
void GenerateMyKeyPairs ( );
void SetPublicKey ();
void SetSharedKey();
void EncryptSharedKey(X509 *clientcert);
void GetEncryptedKey (unsigned char encryptedkey [],int size);
int CheckCert (X509 *clientcert);
void SetData(int size);
void SetDigestData();
void CreateDigest();
void SignDigest();
private:
X509 *m_myCert;
RSA *m_caKeyPairs;
EVP_PKEY *m_pukey;
X509_NAME *m_issuerName;
unsigned char m_encryptedSharedKey[RSA_KEY_SIZE];
unsigned char m_sharedKey[SHARED_KEY_SIZE];
unsigned char m_Data[DATA_SIZE];
unsigned char m_digestData[DATA_SIZE + RSA_KEY_SIZE];
unsigned char m_digest[DIGEST_SIZE ];
unsigned char m_signedDigest[RSA_KEY_SIZE];
};
#endif /* SERVER_H_ */