我正在为服务器客户端执行代码,服务器是CA,客户端向服务器发送签名请求,服务器创建签名证书,然后客户端向服务器发送其证书。服务器首先验证证书。客户端也提取证书的序列号 我在这里遇到一些问题 1-验证过程失败 验证失败 证书签名失败 2-序列号总是返回一个常数3我不知道为什么
分享给我帮助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 :(得分:1)
我发现在请求中应该添加
//adds all digest algorithms to the table
OpenSSL_add_all_digests();
没有此行,证书永远无法正确验证
答案 1 :(得分:0)
CreateCertificate(X509_REQ* req){...}
中,您有
ASN1_INTEGER_set(X509_get_serialNumber(m_req_reply), 2);
所以你
将始终将序列号设置为2(3)。CreateCertificate(X509_REQ* req){...}
中,您也有if(1 == X509_sign(m_req_reply, m_pukey, EVP_sha1()))
,但是X509_sign(...)
将返回签名的大小,如果成功则返回1。