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_ */