转自 : http://blog.csdn.net/lzyuan1006/article/details/53905575
研究了一天,网上的代码写着是签名,实际上是加密,最开始把我弄得迷糊了,后来慢慢理清楚了,就把代码记下来,所有的说明都在代码注释里面,已实际应用于HTTP请求中,从读取私钥文件、sha1加密、rsa签名、base64、urlencode转换、CURL进行HTTP请求完整流程。
先将OPENSSL库编译好,并引入头文件:
- #include "openssl/sha.h"
- #include "openssl/rsa.h"
- #include "openssl/rand.h"
- #include "openssl/objects.h"
- #include "openssl/pem.h"
实现代码:
- char Dec2HexChar(short int n)
- {
- if (0 <= n && n <= 9) {
- return char(short('0') + n);
- }
- else if (10 <= n && n <= 15) {
- return char(short('A') + n - 10);
- }
- else {
- return char(0);
- }
- }
- short int HexChar2Dec(char c)
- {
- if ('0' <= c && c <= '9') {
- return short(c - '0');
- }
- else if ('a' <= c && c <= 'f') {
- return (short(c - 'a') + 10);
- }
- else if ('A' <= c && c <= 'F') {
- return (short(c - 'A') + 10);
- }
- else {
- return -1;
- }
- }
- std::string EncodeURL(const std::string &URL)
- {
- std::string strResult = "";
- for (unsigned int i = 0; i < URL.size(); i++)
- {
- char c = URL[i];
- if (
- ('0' <= c && c <= '9') ||
- ('a' <= c && c <= 'z') ||
- ('A' <= c && c <= 'Z') ||
- c == '.'
- ) {
- strResult += c;
- }
- else
- {
- int j = (short int)c;
- if (j < 0)
- {
- j += 256;
- }
- int i1, i0;
- i1 = j / 16;
- i0 = j - i1 * 16;
- strResult += '%';
- strResult += Dec2HexChar(i1);
- strResult += Dec2HexChar(i0);
- }
- }
- return strResult;
- }
- std::string DecodeURL(const std::string &URL)
- {
- std::string result = "";
- for (unsigned int i = 0; i < URL.size(); i++)
- {
- char c = URL[i];
- if (c != '%')
- {
- result += c;
- }
- else
- {
- char c1 = URL[++i];
- char c0 = URL[++i];
- int num = 0;
- num += HexChar2Dec(c1) * 16 + HexChar2Dec(c0);
- result += char(num);
- }
- }
- return result;
- }
- //--生成GUID
- const char* newGUID()
- {
- static char buf[64] = { 0 };
- GUID guid;
- if (S_OK == ::CoCreateGuid(&guid))
- {
- _snprintf(buf, sizeof(buf)
- , "%08X%04X%04X%02X%02X%02X%02X%02X%02X%02X%02X"
- , guid.Data1
- , guid.Data2
- , guid.Data3
- , guid.Data4[0], guid.Data4[1]
- , guid.Data4[2], guid.Data4[3], guid.Data4[4], guid.Data4[5]
- , guid.Data4[6], guid.Data4[7]
- );
- }
- return (const char*)buf;
- }
- //将二进制流转换成base64编码
- const char * base64char = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
- char * base64_encode(const unsigned char * bindata, char * base64, int binlength)
- {
- int i, j;
- unsigned char current;
- for (i = 0, j = 0; i < binlength; i += 3)
- {
- current = (bindata[i] >> 2);
- current &= (unsigned char)0x3F;
- base64[j++] = base64char[(int)current];
- current = ((unsigned char)(bindata[i] << 4)) & ((unsigned char)0x30);
- if (i + 1 >= binlength)
- {
- base64[j++] = base64char[(int)current];
- base64[j++] = '=';
- base64[j++] = '=';
- break;
- }
- current |= ((unsigned char)(bindata[i + 1] >> 4)) & ((unsigned char)0x0F);
- base64[j++] = base64char[(int)current];
- current = ((unsigned char)(bindata[i + 1] << 2)) & ((unsigned char)0x3C);
- if (i + 2 >= binlength)
- {
- base64[j++] = base64char[(int)current];
- base64[j++] = '=';
- break;
- }
- current |= ((unsigned char)(bindata[i + 2] >> 6)) & ((unsigned char)0x03);
- base64[j++] = base64char[(int)current];
- current = ((unsigned char)bindata[i + 2]) & ((unsigned char)0x3F);
- base64[j++] = base64char[(int)current];
- }
- base64[j] = '\0';
- return base64;
- }
- //签名
- bool EncryptWithPrivateKey(const unsigned char * pData, char *pSignOut)
- {
- RSA * rsa_pri_key = NULL;
- FILE * pFile = NULL;
- //获取路径
- TCHAR szWorkDir[MAX_PATH] = TEXT("");
- CWHService::GetWorkDirectory(szWorkDir, CountArray(szWorkDir));
- //构造路径
- TCHAR szrsa_private_keyFile[MAX_PATH] = TEXT("");
- _sntprintf(szrsa_private_keyFile, CountArray(szrsa_private_keyFile),
- TEXT("%s\\IniConfig\\rsa_private_key.pem"), szWorkDir);
- if (NULL != (pFile = _wfopen(szrsa_private_keyFile, TEXT("r"))))
- {
- //读取私钥文件
- rsa_pri_key = PEM_read_RSAPrivateKey(pFile, NULL, NULL, NULL);
- fclose(pFile);
- if (rsa_pri_key == NULL)
- {
- LOGException("读取私钥文件内容失败!");
- return false;
- }
- //先将源串SHA1算法加密, 后面+1是给结束符留的位置
- unsigned char szSha1Data[SHA_DIGEST_LENGTH+1] = { 0 };
- ZeroMemory(szSha1Data, sizeof(szSha1Data));
- SHA_CTX c;
- if (!SHA1_Init(&c))
- {
- LOGException("初始化sha1算法失败!");
- return false;
- }
- SHA1_Update(&c, pData, strlen((char*)pData));
- SHA1_Final(szSha1Data, &c);
- OPENSSL_cleanse(&c, sizeof(c));
- //RSA签名
- unsigned char szTBSign[512] = { 0 };
- ZeroMemory(szTBSign, sizeof(szTBSign));
- unsigned int nLen = 0;
- int r = RSA_sign(NID_sha1, szSha1Data, SHA_DIGEST_LENGTH, szTBSign, &nLen, rsa_pri_key);
- RSA_free(rsa_pri_key);
- if (1 == r)
- {
- //签名成功,转换成base64编码
- base64_encode(szTBSign, pSignOut, nLen);
- return true;
- }
- return false;
- }
- else
- {
- LOGException("读取私钥文件失败!");
- }
- return false;
- }
借用前辈CURL的HTTP请求代码:
.h头文件
- /**
- * @brief HTTP POST请求
- * @param strUrl 输入参数,请求的Url地址,如:http://www.baidu.com
- * @param strPost 输入参数,使用如下格式para1=val1¶2=val2&…
- * @param strResponse 输出参数,返回的内容
- * @return 返回是否Post成功
- */
- int Post(const std::string & strUrl, const std::string & strPost, std::string & strResponse);
- /**
- * @brief HTTP GET请求
- * @param strUrl 输入参数,请求的Url地址,如:http://www.baidu.com
- * @param strResponse 输出参数,返回的内容
- * @return 返回是否Post成功
- */
- int Get(const std::string & strUrl, std::string & strResponse);
- /**
- * @brief HTTPS POST请求,无证书版本
- * @param strUrl 输入参数,请求的Url地址,如:https://www.alipay.com
- * @param strPost 输入参数,使用如下格式para1=val1¶2=val2&…
- * @param strResponse 输出参数,返回的内容
- * @param pCaPath 输入参数,为CA证书的路径.如果输入为NULL,则不验证服务器端证书的有效性.
- * @return 返回是否Post成功
- */
- int Posts(const std::string & strUrl, const std::string & strPost, std::string & strResponse, const char * pCaPath = NULL);
- /**
- * @brief HTTPS GET请求,无证书版本
- * @param strUrl 输入参数,请求的Url地址,如:https://www.alipay.com
- * @param strResponse 输出参数,返回的内容
- * @param pCaPath 输入参数,为CA证书的路径.如果输入为NULL,则不验证服务器端证书的有效性.
- * @return 返回是否Post成功
- */
- int Gets(const std::string & strUrl, std::string & strResponse, const char * pCaPath = NULL);
.cpp文件
- int CAsyncEngineHttpSink::Post(const std::string & strUrl, const std::string & strPost, std::string & strResponse)
- {
- CURLcode res;
- CURL* curl = curl_easy_init();
- if (NULL == curl)
- {
- return CURLE_FAILED_INIT;
- }
- curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str());
- curl_easy_setopt(curl, CURLOPT_POST, 1);
- curl_easy_setopt(curl, CURLOPT_POSTFIELDS, strPost.c_str());
- curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData);
- curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&strResponse);
- curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
- curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3);
- curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3);
- res = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
- return res;
- }
- int CAsyncEngineHttpSink::Get(const std::string & strUrl, std::string & strResponse)
- {
- CURLcode res;
- CURL* curl = curl_easy_init();
- if (NULL == curl)
- {
- return CURLE_FAILED_INIT;
- }
- curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str());
- curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData);
- curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&strResponse);
- /**
- * 当多个线程都使用超时处理的时候,同时主线程中有sleep或是wait等操作。
- * 如果不设置这个选项,libcurl将会发信号打断这个wait从而导致程序退出。
- */
- curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
- curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3);
- curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3);
- res = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
- return res;
- }
- int CAsyncEngineHttpSink::Posts(const std::string & strUrl, const std::string & strPost, std::string & strResponse, const char * pCaPath)
- {
- CURLcode res;
- CURL* curl = curl_easy_init();
- if (NULL == curl)
- {
- return CURLE_FAILED_INIT;
- }
- curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str());
- curl_easy_setopt(curl, CURLOPT_POST, 1);
- curl_easy_setopt(curl, CURLOPT_POSTFIELDS, strPost.c_str());
- curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData);
- curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&strResponse);
- curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
- if (NULL == pCaPath)
- {
- curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);
- curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false);
- }
- else
- {
- //缺省情况就是PEM,所以无需设置,另外支持DER
- curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, true);
- curl_easy_setopt(curl, CURLOPT_CAINFO, pCaPath);
- }
- curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3);
- curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3);
- res = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
- return res;
- }
- int CAsyncEngineHttpSink::Gets(const std::string & strUrl, std::string & strResponse, const char * pCaPath)
- {
- CURLcode res;
- CURL* curl = curl_easy_init();
- if (NULL == curl)
- {
- return CURLE_FAILED_INIT;
- }
- curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str());
- curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData);
- curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&strResponse);
- curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
- if (NULL == pCaPath)
- {
- curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);
- curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false);
- }
- else
- {
- curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, true);
- curl_easy_setopt(curl, CURLOPT_CAINFO, pCaPath);
- }
- curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3);
- curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3);
- res = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
- return res;
- }