dear all i have a client server client application the server should created an encrypted shared key and some data and make digest of both of them (data and encrypted shared key) as an input to SHA1 then the server should sign the output of the hash with function SignDigest() which include function RSA_sign to sign the digest my problem is 1- the code give an error No source available for "RSA_sign() at 0xb7ea85e5"
2- i have tried to know what is the error so i added error = ERR_get_error(); but i got nothing can you tell me what i did wrong thanks allot for your reply -- 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 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() { 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(); cout<<"i'm in sign digest"<<endl; unsigned int *siglen = NULL; unsigned long error; RSA_sign(NID_sha1,m_digest, DIGEST_SIZE,m_signedDigest,siglen,m_caKeyPairs); error = ERR_get_error(); cout<<"error is "<<error<<endl; 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 <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> #define MAX_FILE_NAME_SIZE 20 #define RSA_KEY_SIZE 256 //bytes #define CERT_SIZE 727 #define DIGEST_SIZE 20 #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 (); 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_ */