C++使用OpenSSL证书API

来源:互联网 发布:js addeventlistener 编辑:程序博客网 时间:2024/05/20 11:37

本文主要介绍如果在C++中使用OpenSSL的证书相关API。(基于OpenSSL 1.0.2k版本,不同版本可能API会有一些差异,但大体应该类似)


使用下面方法前,需要全局调用一次(无需多次调用)

OpenSSL_add_all_algorithms();



1、生成公私钥对

    BIGNUM *bne = NULL;    int bits = RSAKeyBits;    unsigned long   e = RSA_F4;    int ret = 0;    bne = BN_new();    int r = BN_set_word(bne,e);    if(r != 1){        goto free_all;    }    if(m_rsa)    {        RSA_free(m_rsa);        m_rsa = NULL;    }    // m_rsa是成员变量,用于存储公私钥对    m_rsa = RSA_new();        r = RSA_generate_key_ex(m_rsa, bits, bne, NULL);    if(r != 1){        goto free_all;    }free_all:    BN_free(bne);


2、生成CSR

    X509 *x509 = NULL;    X509_NAME *subject = NULL;    BIO *bio = NULL;    X509_REQ *x509Req = NULL;    char *szCSR = NULL;    // 提取私钥    EVP_PKEY_assign_RSA(m_pKey, m_rsa);    x509 = X509_new();    X509_set_pubkey(x509, m_pKey);    // 设置属性    subject = X509_get_subject_name(x509);    // 国家    X509_NAME_add_entry_by_txt(subject, SN_countryName,  MBSTRING_ASC,                               (unsigned char *)"CN", -1, -1, 0);    // 省份    X509_NAME_add_entry_by_txt(subject, SN_stateOrProvinceName,  MBSTRING_ASC,                               (unsigned char *)"GuangDong", -1, -1, 0);    // 城市    X509_NAME_add_entry_by_txt(subject, SN_localityName,  MBSTRING_ASC,                               (unsigned char *)"ShenZhen", -1, -1, 0);    X509_set_subject_name(x509, subject);    x509Req = X509_to_X509_REQ(x509, m_pKey, ShaFunc);    if(!x509Req)    {        goto free_all;    }    // 可视化输出    bio = BIO_new(BIO_s_mem());    PEM_write_bio_X509_REQ(bio, x509Req);    if(bio->num_write == 0)    {        goto free_all;    }    szCSR = (char*)malloc(bio->num_write+1);    if(!szCSR)    {        goto free_all;    }    memset(szCSR, 0, bio->num_write+1);    BIO_read(bio, szCSR, bio->num_write);free_all:    if(x509)        X509_free(x509);    if(x509Req)        X509_REQ_free(x509Req);    if(bio)        BIO_free(bio);    if(szCSR)        free(szCSR);

3、生成证书

void x509FromCertString(string cert, X509 **pX509){    if(cert.length() == 0)        return;        handleCertLineBreak(cert);        BIO *bio = NULL;    X509 *x509 = NULL;        const char *certData = cert.c_str();        bio = BIO_new(BIO_s_mem());    BIO_puts(bio, certData);    x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);        *pX509 = x509;        BIO_free(bio);}bool checkX509Data(X509 *x509){    // 校验密钥和证书是否匹配    if(!X509_check_private_key(x509, m_pKey))    {        return false;    }        // 根证书校验    if(m_rootCert == NULL)    {        BIO *bio = BIO_new_file("cert/RootCA.cer","r");        if(!bio)        {            return false;        }                PEM_read_bio_X509(bio, &m_rootCert, NULL, NULL);                BIO_free(bio);                if(m_rootCert == NULL)        {            return false;        }    }        EVP_PKEY *pubKey = X509_get_pubkey(m_rootCert);    if(X509_verify(x509, pubKey) != 1)    {        return false;    }        return true;}// p12void importCert(string cert, string pass, string path){    if(cert.length() == 0 || path.length() == 0)        return;        int ret = 0;    BIO *bio = NULL;    X509 *x509 = NULL;    PKCS12 *p12 = NULL;    BIO *bioW = NULL;        const char *certData = cert.c_str();        bio = BIO_new(BIO_s_mem());    BIO_puts(bio, certData);    x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);        // 校验数据    ret = checkX509Data(x509);    if(ret)    {        goto free_all;    }        p12 = PKCS12_create((char*)pass.c_str(), CertAlias, m_pKey, x509, NULL, 0, 0, 0, 0, 0);        if(!p12)    {        goto free_all;    }        bioW = BIO_new_file(path.c_str(),"wb");    if(!bioW)    {        goto free_all;    }        // 写入文件    if ( i2d_PKCS12_bio(bioW,p12) != 1)    {        goto free_all;    }        free_all:    if(x509)        X509_free(x509);    if(p12)        PKCS12_free(p12);    if(bioW)        BIO_free(bioW);}// crtvoid importCert(string cert, string path){    if(cert.length() == 0 || path.length() == 0)        return;        int ret = 0;    X509 *x509 = NULL;    BIO *bioW = NULL;        ret = x509FromCertString(cert, &x509);    if(ret)    {        goto free_all;    }        ret = checkX509Data(x509, false);    if(ret)    {        goto free_all;    }        bioW = BIO_new_file(path.c_str(),"wb");    if(!bioW)    {        goto free_all;    }        // 写入文件    if ( i2d_X509_bio(bioW,x509) != 1)    {        goto free_all;    }        free_all:    if(x509)        X509_free(x509);    if(bioW)        BIO_free(bioW);    }

4、展示证书信息

// p12void getCertInfo(string path, string pass, string &info){    BIO *bio = NULL;    PKCS12 *p12 = NULL;    EVP_PKEY *pKey = NULL;    X509 *x509 = NULL;    BIO *x509Bio = NULL;    char *szCertInfo = NULL;    bio = BIO_new_file(path.c_str(),"r");    if(!bio)    {        goto free_all;    }    p12 = d2i_PKCS12_bio(bio, NULL);    if(!p12)    {        goto free_all;    }    if(PKCS12_parse(p12, pass.c_str(), &pKey, &x509, NULL) != 1)    {        goto free_all;    }    x509Bio = BIO_new(BIO_s_mem());    X509_print(x509Bio, x509);    if(x509Bio->num_write == 0)    {        goto free_all;    }    szCertInfo = (char*)malloc(x509Bio->num_write+1);    if(!szCertInfo)    {        goto free_all;    }    memset(szCertInfo, 0, x509Bio->num_write+1);    BIO_read(x509Bio, szCertInfo, x509Bio->num_write);    info = szCertInfo;free_all:    if(bio)        BIO_free(bio);    if(p12)        PKCS12_free(p12);    if(x509Bio)        BIO_free(x509Bio);    if(szCertInfo)        free(szCertInfo);}// crtint getCertInfo(string path, string &info){    BIO *bio = NULL;    X509 *x509 = NULL;    BIO *x509Bio = NULL;    char *szCertInfo = NULL;    bio = BIO_new_file(path.c_str(),"r");    if(!bio)    {        goto free_all;    }    x509 = d2i_X509_bio(bio, NULL);    if(!x509)    {        goto free_all;    }    x509Bio = BIO_new(BIO_s_mem());    X509_print(x509Bio, x509);    if(x509Bio->num_write == 0)    {        goto free_all;    }    szCertInfo = (char*)malloc(x509Bio->num_write+1);    if(!szCertInfo)    {        goto free_all;    }    memset(szCertInfo, 0, x509Bio->num_write+1);    BIO_read(x509Bio, szCertInfo, x509Bio->num_write);    info = szCertInfo;free_all:    if(bio)        BIO_free(bio);    if(x509)        X509_free(x509);    if(x509Bio)        BIO_free(x509Bio);    if(szCertInfo)        free(szCertInfo);}

5、读取证书和密钥

// p12void p_getP12FromCertFile(const string filePath, PKCS12 **p12){    BIO *bio = NULL;        bio = BIO_new_file(filePath.c_str(),"r");    if(!bio)    {        goto free_all;    }        *p12 = d2i_PKCS12_bio(bio, NULL);    if(!*p12)    {        goto free_all;    }    free_all:    if(bio)        BIO_free(bio);}void p_getRSAKeyFromP12(PKCS12 *p12, const string pass, RSA **rsa){    EVP_PKEY *pKey = NULL;    X509 *x509 = NULL;        if(PKCS12_parse(p12, pass.c_str(), &pKey, &x509, NULL) != 1)    {        return;    }        *rsa = EVP_PKEY_get1_RSA(pKey);}// crtvoid p_getX509FromCertFile(const string filePath, X509 **x509){    BIO *bio = NULL;        bio = BIO_new_file(filePath.c_str(),"r");    if(!bio)    {        goto free_all;    }        *x509 = d2i_X509_bio(bio, NULL);    if(!*x509)    {        goto free_all;    }    free_all:    if(bio)        BIO_free(bio);    }void p_getRSAKeyFromX509(X509 *x509, RSA **rsa){    EVP_PKEY *pKey = X509_get_pubkey(x509);    if(!pKey)    {        return;    }    *rsa = EVP_PKEY_get1_RSA(pKey);}

6、加解密

#define RSA_Data_Len 256int p_rsaCrypt(bool bPubKey, bool bEncrypt, RSA *rsa, unsigned char inData[RSA_Data_Len], unsigned char outData[RSA_Data_Len]){    memset(outData, 0, RSA_Data_Len);        int (*rsa_func)(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding);    if(bPubKey && bEncrypt)    {        rsa_func = &RSA_public_encrypt;    }    else if(bPubKey && !bEncrypt)    {        rsa_func = &RSA_public_decrypt;    }    else if(!bPubKey && bEncrypt)    {        rsa_func = &RSA_private_encrypt;    }    else    {        rsa_func = &RSA_private_decrypt;    }        int retLen = rsa_func(RSA_Data_Len, inData, outData, rsa, RSA_NO_PADDING);    if(retLen < RSA_Data_Len)    {        return 1;    }        return 0;}void rsaCrypt(bool bPubKey, bool bEncrypt, const string input, string &output){    int inLen;    char *szIn;    if(bEncrypt)    {        inLen = input.length();        szIn = (char*)input.c_str();    }    else    {        szIn = (char*)alloca(input.length());        if(!szIn)        {            return;        }                int ret = Base64_Decode(input.c_str(), input.length(), (unsigned char*)szIn, input.length(), &inLen);        if(ret)        {            return;        }    }        int round = (inLen+TP_RSA_Data_Len-1)/RSA_Data_Len;// 1024    int outLen = round*TP_RSA_Data_Len;    char *szOut = (char *)alloca(outLen);    if(!szOut)    {        return;    }        for(int i=0; i<round; i++)    {        int cryptLen = RSA_Data_Len;        if(i == round-1)        {            cryptLen = inLen-(round-1)*RSA_Data_Len;        }                char inBuf[RSA_Data_Len];        memset(inBuf, 0, RSA_Data_Len);        memcpy(inBuf, szIn+(i*RSA_Data_Len), cryptLen);                int ret = p_rsaCrypt(bPubKey, bEncrypt, m_rsa, (unsigned char*)inBuf, (unsigned char*)szOut+(i*TP_RSA_Data_Len));        if(ret)        {            return;        }    }        if(bEncrypt)    {        // base64        int base64Len = outLen*2;        char *szBase64 = (char*)alloca(base64Len);        int retLen;        int ret = Base64_Encode((unsigned char*)szOut, outLen, szBase64, base64Len, &retLen);        if(ret)        {            return;        }                output = szBase64;    }    else    {        output = szOut;    }}

7、签名/验签

// 签名int p_signWithSha256(RSA *rsa, unsigned char *inData, int inLen, unsigned char outData[RSA_Data_Len]){    unsigned char sha256[SHA256_DIGEST_LENGTH];        memset(sha256, 0, sizeof(sha256));        // sha256    SHA256_CTX c;    SHA256_Init(&c);    SHA256_Update(&c, inData, inLen);    SHA256_Final(sha256, &c);        // rsa pri key encrypt    memset(outData, 0, TP_RSA_Data_Len);    // OPENSSL_PKCS1_OAEP_PADDING support is only for: PublicKey::encrypt() -> PrivateKey::decrypt()    int len = RSA_private_encrypt(sizeof(sha256), sha256, outData, rsa, RSA_PKCS1_PADDING);    if(len != RSA_Data_Len)    {        return 1;    }        return 0;}void signWithSha256(string src, string &sign){    unsigned char *bSrc = (unsigned char*)src.c_str();    int srcLen = src.length();    unsigned char bSign[TP_RSA_Data_Len];    memset(bSign, 0, sizeof(bSign));    int ret = p_signWithSha256(m_rsa, bSrc, srcLen, bSign);    if(ret)    {        return ret;    }    // base64    int base64Len = sizeof(bSign)*2;    char *szBase64 = (char*)alloca(base64Len);    int retLen;    ret = Base64_Encode(bSign, sizeof(bSign), szBase64, base64Len, &retLen);    if(ret)    {        return;    }    sign = szBase64;}// 验签int p_verifySignWithSha256(RSA *rsa, unsigned char sign[RSA_Data_Len], unsigned char *src, int srcLen, bool *verify){    *verify = false;        // rsa pub key decrypt    unsigned char decSha256[SHA256_DIGEST_LENGTH];    memset(decSha256, 0, sizeof(decSha256));        int len = RSA_public_decrypt(RSA_Data_Len, sign, decSha256, rsa, RSA_PKCS1_PADDING);    if(len != sizeof(decSha256))    {        return 1;    }            // src sha256    unsigned char srcSha256[SHA256_DIGEST_LENGTH];    memset(srcSha256, 0, sizeof(srcSha256));        SHA256_CTX c;    SHA256_Init(&c);    SHA256_Update(&c, src, srcLen);    SHA256_Final(srcSha256, &c);        if(memcmp(decSha256, srcSha256, SHA256_DIGEST_LENGTH) == 0)    {        *verify = true;    }        return 0;}void verifySignWithSha256(string sign, string src, bool *verify){    unsigned char bSign[RSA_Data_Len];    memset(bSign, 0, sizeof(bSign));    int retLen;    int ret = Base64_Decode(sign.c_str(), sign.length(), bSign, sizeof(bSign), &retLen);    if(ret)    {        return;    }    p_verifySignWithSha256(m_rsa, bSign, (unsigned char *)src.c_str(), src.length(), verify);}






原创粉丝点击