2014-10-30 121 views
0

我正在爲服務器客戶端執行代碼,服務器是CA,客戶端向服務器發送簽名請求,服務器創建簽名證書,然後客戶端向服務器發送證書。服務器首先驗證證書。同時客戶端提取證書的序列號 我有一些問題在這裏 1-驗證過程失敗 verifiy失敗 證書籤名失敗 2-序列號總是返回一個固定數量的3我不知道爲什麼用於終止X509證書並驗證它的C++代碼

THX配發對我的幫助

certificate.cpp

#include <iostream> 
#include "server.h" 
#include "client.h" 
using namespace std; 
int main() 
{ 
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; 
return 0; 
} 

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> 
using namespace std; 
class Server 
{ 
public: 
Server(); 
~Server(); 
X509 *CreateCertificate (X509_REQ *req); 
void CreateMyCertificate(); 
void GenerateMyKeyPairs (); 
void SetPublicKey(); 
int CheckCert (X509 *clientcert); 
private: 
X509  *m_myCert; 
RSA  *m_caKeyPairs; 
EVP_PKEY *m_pukey; 
X509_NAME *m_issuerName; 
}; 
#endif /* SERVER_H_ */ 

server.cc

#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(); 
    //SetPublicKey(); 
} 
Server::~Server() 
{ 
    X509_free(m_myCert); 
    RSA_free(m_caKeyPairs); 
    X509_NAME_free(m_issuerName); 
    } 
    X509* 
    Server::CreateCertificate(X509_REQ* req) 
    { 
    cout<<"hello i began"<<endl; 
    X509 *m_req_reply; 
    m_req_reply = X509_new(); 
    X509_NAME *subject = NULL; 
    EVP_PKEY *pkey = NULL; 
    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); 
    pkey = X509_REQ_get_pubkey(req); 
    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); 
    cout << "cert subject name:" << X509_get_subject_name(m_req_reply) << endl; 
    if(1 == X509_sign(m_req_reply, m_pukey, EVP_sha1())) 
    cout << "client cert ok\n"; 
    else 
    cout << "client cert error\n"; 
    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 
if(1 == X509_sign(m_myCert, m_pukey, EVP_sha1())) 
    cout << "self cert signed ok\n"; 
else 
    cout << "self cert sign error\n"; 
FILE * fcert; 
fcert = fopen("cert.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(2048,RSA_F4 , NULL , NULL); 
} 
void 
Server::SetPublicKey() 
{ 
if(1 == EVP_PKEY_assign_RSA(m_pukey,m_caKeyPairs)) 
    cout << "key assigned OK\n"; 
else 
    cout << "key assign error\n"; 
BIO *out = NULL; 
const char szPath[10] = "key2.pem"; 
out = BIO_new_file(szPath,"wb"); 
EVP_PKEY_print_private(out, m_pukey, 
           0, NULL); 
BIO_free(out); 
out = BIO_new_file("key.pem","wb"); 
//print the self signed certificate 
//FILE * fkey; 
//fkey = fopen("key.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(); 
//void X509_STORE_CTX_cleanup(X509_STORE_CTX *ctx); 
//void X509_STORE_CTX_free(X509_STORE_CTX *ctx); 
//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); 
//status = X509_verify(clientcert, m_pukey); 
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; 
} 

client.h

#ifndef CLIENT_H_ 
#define CLIENT_H_ 
#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(); 
private: 
X509_REQ *m_myCertReq; 
X509  *m_myCert; 
X509_NAME *m_name; 
RSA  *m_rsa_keyPair; 
EVP_PKEY *m_puk; 
}; 
#endif /* CLIENT_H_ */ 

client.cc

#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(); 
// SetPublicKey(); 
} 
Client :: ~Client() 
{ 
    X509_REQ_free(m_myCertReq); 
    X509_free(m_myCert); 
    //X509_NAME_free(m_name); 
    RSA_free(m_rsa_keyPair); 
    //EVP_PKEY_free(m_puk); 
} 
void 
Client :: GenerateRSAKeyPair () 
{ 
m_rsa_keyPair = RSA_generate_key(2048,RSA_F4,NULL,NULL); 
BIO *pubout = NULL; 
const char szPath[10] = "clrsa.pem"; 
pubout = BIO_new_file(szPath,"wb"); 
PEM_write_bio_RSAPublicKey (pubout , m_rsa_keyPair); 
} 
void 
Client::SetPublicKey() 
{ 
EVP_PKEY_assign_RSA(m_puk,m_rsa_keyPair); 
BIO *out = NULL; 
const char szPath[10] = "cpuky.pem"; 
out = BIO_new_file(szPath,"wb"); 
PEM_write_bio_PUBKEY(out,m_puk); 
} 
X509_REQ* 
Client::MakeSignedCertReq() 
{ 
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[10] = "req.pem"; 
out = BIO_new_file(szPath,"wb"); 
PEM_write_bio_X509_REQ(out,m_myCertReq); 
return m_myCertReq; 
} 
void 
Client::SetCert(X509 *cert) 
{ 
cout << "writing certificate\n"; 
BIO *out = NULL; 
const char szPath[10] = "x509.pem"; 
out = BIO_new_file(szPath,"wb"); 
m_myCert = cert; 
int len; 
unsigned char *buf, *p; 
len = i2d_X509(cert, NULL); 
cout << "cert length =" << len << endl; 
buf = (unsigned char *)OPENSSL_malloc(len); 
p = buf; 
i2d_X509(cert, &p); 
cout << "cert= "<<endl; 
for(int i=0; i<len; i++) 
    cout << buf[i]; 
cout << endl; 
if(!PEM_write_bio_X509 (out , cert)) 
    cout << "error writing certificate\n"; 
    } 
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 << "converted client cert is"<<endl; 
for (int j = 0 ; j<len ; j++) 
{ 
    cout << certarray[j]; 
} 
cout<<endl; 
/* 
X509 *certtest = NULL; 
certtest = d2i_X509(NULL, certarray , len); 
cout<<"write the array to file"<<endl; 
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); 
} 

希望任何人能幫助我儘快解決我的問題

注意我已經創建了自簽名證書以及在cert.pem文件也x509.pem(爲客戶端)創建好,但是當我驗證它我得到一個錯誤所有的時間沒有驗證,因爲證書籤名失敗時,我得到錯誤處理程序X509_verify_cert_error_string(X509_STORE_CTX_get_error(ctx) )也序列號總是恆定3

回答

0

我發現,在請求中應該添加

 //adds all digest algorithms to the table 
    OpenSSL_add_all_digests(); 

沒有該行的證書將不會被正確驗證