openssl rsa公钥验签名

转自  : http://blog.csdn.net/dingzhaoyan/article/details/55254059


场景:

只有公钥字符串(base64编码),需验证签名。

环境:

c++ + openssl

step1 从内存读取公钥

[cpp]  view plain  copy
  1. static RSA* GetPublicKeyRSA(string strPublicKey)  
  2.     {  
  3.         int nPublicKeyLen = strPublicKey.size();      //strPublicKey为base64编码的公钥字符串  
  4.         for(int i = 64; i < nPublicKeyLen; i+=64)  
  5.         {  
  6.             if(strPublicKey[i] != '\n')  
  7.             {  
  8.                 strPublicKey.insert(i, "\n");  
  9.             }  
  10.             i++;  
  11.         }  
  12.         strPublicKey.insert(0, "-----BEGIN PUBLIC KEY-----\n");  
  13.         strPublicKey.append("\n-----END PUBLIC KEY-----\n");  
  14.   
  15.         BIO *bio = NULL;   
  16.         RSA *rsa = NULL;   
  17.         char *chPublicKey = const_cast<char *>(strPublicKey.c_str());  
  18.         if ((bio = BIO_new_mem_buf(chPublicKey, -1)) == NULL)       //从字符串读取RSA公钥  
  19.         {       
  20.             cout<<"BIO_new_mem_buf failed!"<<endl;        
  21.         }         
  22.         rsa = PEM_read_bio_RSA_PUBKEY(bio, NULL, NULL, NULL);   //从bio结构中得到rsa结构  
  23.         if (NULL == rsa)  
  24.         {  
  25.             BIO_free_all(bio);  
  26.             unsigned long ulErr = ERR_get_error(); // 获取错误号  
  27.             char szErrMsg[1024] = {0};  
  28.             char *pTmp = NULL;  
  29.             pTmp = ERR_error_string(ulErr,szErrMsg); // 格式:error:errId:库:函数:原因  
  30.             cout << szErrMsg;  
  31.             cout << "load public key fail error=" <<ulErr << " msg=" << szErrMsg;  
  32.         }  
  33.         else  
  34.         {  
  35.             cout<< "load public key ok "<<endl;  
  36.         }     
  37.         return rsa;   
  38.     }  

step2 开始验证啦

[cpp]  view plain  copy
  1. static bool verify( string sign, string content )  
  2. {  
  3.     // 公钥字符串,经过base64编码  
  4.     string publicKey = "xxxxxxxxxxxxx";  
  5.     // 得到公钥的RSA结构体  
  6.     RSA* rsa = GetPublicKeyRSA(publicKey);  
  7.     if (NULL == rsa)  
  8.     {  
  9.         return false;  
  10.     }  
  11.     // 将原串经过sha256摘要(摘要算法根据实际使用来,此处以sha256为例)  
  12.     string hash = Sha256(content.c_str(),false);   
  13.     // 将待验证签名用base64解码(一般给的签名是经过base64编码的)  
  14.     string sign = Base64Decode((char *)gameAuthSign.c_str(), strlen(gameAuthSign.c_str()));  
  15.     // 此处签名长度根据实际使用来,最好不要直接strlen(sign),可能发生截断  
  16.     int sign_len = 256;   
  17.     int res = RSA_verify(NID_sha256, (const unsigned char*)hash.c_str(), strlen(hash.c_str()), (unsigned char*)sign.c_str(),sign_len, rsa);    
  18.     if (res == 1)  
  19.     {  
  20.         gDebugStream("huawei verify ok");  
  21.     }  
  22.     else  
  23.     {// 此api打印了验证失败的原因(bad signature,sigature length error等)  
  24.         unsigned long ulErr = ERR_get_error(); // 获取错误号  
  25.         char szErrMsg[1024] = {0};  
  26.         char *pTmp = NULL;  
  27.         pTmp = ERR_error_string(ulErr,szErrMsg); // 格式:error:errId:库:函数:原因  
  28.         cout << szErrMsg;  
  29.         gDebugStream("verify error:" << szErrMsg);  
  30.     }  
  31.     return res == 1;    
  32. }  
ps base64解码,编码 sha256摘要 都能过openssl实现 

base64解码

[cpp]  view plain  copy
  1. static string Base64Decode(char * input, int length)    
  2.     {    
  3.         string result;  
  4.         static char decode[1024] = {0};  
  5.         if (NULL == input || length <= 0 || length >= 1024)  
  6.         {  
  7.             return result;  
  8.         }         
  9.         int len = EVP_DecodeBlock((unsigned char*)decode, (const unsigned char*)input, length);    
  10.         if (len >= 1024 || len <= 0)  
  11.         {  
  12.             return result;  
  13.         }  
  14.         decode[len] = '\0';  
  15.           
  16.         result.resize(len);  
  17.         for(int i = 0; i < len; i++)   
  18.         {  
  19.             result[i] = decode[i];  
  20.         }  
  21.         return result;  
  22.     }  

base64编码

[cpp]  view plain  copy
  1. static string Base64Encode(char * input, int length)  
  2. {  
  3.     static char encoded[1024] = {0};  
  4.     string result;  
  5.     if (NULL == input || length <= 0 || length >= 1024)  
  6.     {  
  7.         return result;  
  8.     }  
  9.       
  10.     int len = EVP_EncodeBlock((unsigned char*)encoded, (const unsigned char*)input, length);      
  11.     if (len >= 1024 || len <= 0)  
  12.     {  
  13.         return result;  
  14.     }  
  15.     encoded[len] = '\0';  
  16.     result = string(encoded);  
  17.     return result;  
  18. }  
sha256

[cpp]  view plain  copy
  1. static string Sha256(const char* data, bool bHex = true)  
  2.     {  
  3.         unsigned char md[SHA256_DIGEST_LENGTH] = {0};  
  4.   
  5.         SHA256((const unsigned char *)data, strlen(data), md);    
  6.         if (!bHex)  
  7.         {  
  8.             string s;  
  9.             s.resize(SHA256_DIGEST_LENGTH);  
  10.             for(int i = 0; i < SHA256_DIGEST_LENGTH; i++)   
  11.             {  
  12.                 s[i] = md[i];  
  13.             }  
  14.             return s;  
  15.         }  
  16.         else  
  17.         {  
  18.             string s;  
  19.             s.resize(SHA256_DIGEST_LENGTH * 2);  
  20.             int k = 0;  
  21.             for(unsigned int i = 0; i < SHA256_DIGEST_LENGTH ; i++)   
  22.             {    
  23.                 sprintf(&s.at(k), "%02x", md[i]);  
  24.                 k += 2;  
  25.             }    
  26.             return s;  
  27.         }  
  28.     }  

另外,尝试过php来验证

但是读取公钥时总用报错 $openssl_public_key = @openssl_get_publickey($pubKey);

error:0906D06C:PEM routines:PEM_read_bio:no start line

似乎是openssl_get_publickey这个api不支持只用公钥的字符串,应该读取的是证书,但是只有公钥字符串,我也不知道如何生成证书。。

最后~希望你顺利验证通过~~~~


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值