转自 : http://blog.csdn.net/dingzhaoyan/article/details/55254059
场景:
只有公钥字符串(base64编码),需验证签名。
环境:
c++ + openssl
step1 从内存读取公钥
- static RSA* GetPublicKeyRSA(string strPublicKey)
- {
- int nPublicKeyLen = strPublicKey.size(); //strPublicKey为base64编码的公钥字符串
- for(int i = 64; i < nPublicKeyLen; i+=64)
- {
- if(strPublicKey[i] != '\n')
- {
- strPublicKey.insert(i, "\n");
- }
- i++;
- }
- strPublicKey.insert(0, "-----BEGIN PUBLIC KEY-----\n");
- strPublicKey.append("\n-----END PUBLIC KEY-----\n");
- BIO *bio = NULL;
- RSA *rsa = NULL;
- char *chPublicKey = const_cast<char *>(strPublicKey.c_str());
- if ((bio = BIO_new_mem_buf(chPublicKey, -1)) == NULL) //从字符串读取RSA公钥
- {
- cout<<"BIO_new_mem_buf failed!"<<endl;
- }
- rsa = PEM_read_bio_RSA_PUBKEY(bio, NULL, NULL, NULL); //从bio结构中得到rsa结构
- if (NULL == rsa)
- {
- BIO_free_all(bio);
- unsigned long ulErr = ERR_get_error(); // 获取错误号
- char szErrMsg[1024] = {0};
- char *pTmp = NULL;
- pTmp = ERR_error_string(ulErr,szErrMsg); // 格式:error:errId:库:函数:原因
- cout << szErrMsg;
- cout << "load public key fail error=" <<ulErr << " msg=" << szErrMsg;
- }
- else
- {
- cout<< "load public key ok "<<endl;
- }
- return rsa;
- }
step2 开始验证啦
- static bool verify( string sign, string content )
- {
- // 公钥字符串,经过base64编码
- string publicKey = "xxxxxxxxxxxxx";
- // 得到公钥的RSA结构体
- RSA* rsa = GetPublicKeyRSA(publicKey);
- if (NULL == rsa)
- {
- return false;
- }
- // 将原串经过sha256摘要(摘要算法根据实际使用来,此处以sha256为例)
- string hash = Sha256(content.c_str(),false);
- // 将待验证签名用base64解码(一般给的签名是经过base64编码的)
- string sign = Base64Decode((char *)gameAuthSign.c_str(), strlen(gameAuthSign.c_str()));
- // 此处签名长度根据实际使用来,最好不要直接strlen(sign),可能发生截断
- int sign_len = 256;
- int res = RSA_verify(NID_sha256, (const unsigned char*)hash.c_str(), strlen(hash.c_str()), (unsigned char*)sign.c_str(),sign_len, rsa);
- if (res == 1)
- {
- gDebugStream("huawei verify ok");
- }
- else
- {// 此api打印了验证失败的原因(bad signature,sigature length error等)
- unsigned long ulErr = ERR_get_error(); // 获取错误号
- char szErrMsg[1024] = {0};
- char *pTmp = NULL;
- pTmp = ERR_error_string(ulErr,szErrMsg); // 格式:error:errId:库:函数:原因
- cout << szErrMsg;
- gDebugStream("verify error:" << szErrMsg);
- }
- return res == 1;
- }
base64解码
- static string Base64Decode(char * input, int length)
- {
- string result;
- static char decode[1024] = {0};
- if (NULL == input || length <= 0 || length >= 1024)
- {
- return result;
- }
- int len = EVP_DecodeBlock((unsigned char*)decode, (const unsigned char*)input, length);
- if (len >= 1024 || len <= 0)
- {
- return result;
- }
- decode[len] = '\0';
- result.resize(len);
- for(int i = 0; i < len; i++)
- {
- result[i] = decode[i];
- }
- return result;
- }
base64编码
- static string Base64Encode(char * input, int length)
- {
- static char encoded[1024] = {0};
- string result;
- if (NULL == input || length <= 0 || length >= 1024)
- {
- return result;
- }
- int len = EVP_EncodeBlock((unsigned char*)encoded, (const unsigned char*)input, length);
- if (len >= 1024 || len <= 0)
- {
- return result;
- }
- encoded[len] = '\0';
- result = string(encoded);
- return result;
- }
- static string Sha256(const char* data, bool bHex = true)
- {
- unsigned char md[SHA256_DIGEST_LENGTH] = {0};
- SHA256((const unsigned char *)data, strlen(data), md);
- if (!bHex)
- {
- string s;
- s.resize(SHA256_DIGEST_LENGTH);
- for(int i = 0; i < SHA256_DIGEST_LENGTH; i++)
- {
- s[i] = md[i];
- }
- return s;
- }
- else
- {
- string s;
- s.resize(SHA256_DIGEST_LENGTH * 2);
- int k = 0;
- for(unsigned int i = 0; i < SHA256_DIGEST_LENGTH ; i++)
- {
- sprintf(&s.at(k), "%02x", md[i]);
- k += 2;
- }
- return s;
- }
- }
另外,尝试过php来验证
但是读取公钥时总用报错 $openssl_public_key = @openssl_get_publickey($pubKey);
error:0906D06C:PEM routines:PEM_read_bio:no start line
似乎是openssl_get_publickey这个api不支持只用公钥的字符串,应该读取的是证书,但是只有公钥字符串,我也不知道如何生成证书。。
最后~希望你顺利验证通过~~~~

348

被折叠的 条评论
为什么被折叠?



