歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

CryptoAPI與OpenSSL數字簽名與驗證交互

這裡(http://www.linuxidc.com/Linux/2012-08/68722.htm)寫過了RSA非對稱加密解密的交互方式,

其實數字簽名也是RSA非對稱加密,只不過用私鑰加密的,再加上個hash摘要

CryptoAPI與openssl RSA非對稱加密解密(PKCS1 PADDING)交互已經提到關於證書和私鑰的數據以及對象獲取,這裡就不再重復討論

1.openssl的簽名及驗證

  1. void opensslSigner::sign(EVP_PKEY* evpKey,BYTE** signValue,unsigned int &signLen,BYTE* text,int textLen)  
  2. {  
  3.     EVP_MD_CTX mdctx;   //摘要算法上下文變量     
  4.        
  5.     if(evpKey == NULL)    
  6.     {    
  7.         printf("EVP_PKEY_new err\n");    
  8.         return;    
  9.     }    
  10.       
  11.     //以下是計算簽名的代碼     
  12.     EVP_MD_CTX_init(&mdctx);        //初始化摘要上下文     
  13.     if(!EVP_SignInit_ex(&mdctx,EVP_md5(),NULL)) //簽名初始化,設置摘要算法     
  14.     {    
  15.         printf("err\n");    
  16.         EVP_PKEY_free(evpKey);    
  17.         return;    
  18.     }    
  19.     if(!EVP_SignUpdate(&mdctx,text,textLen)) //計算簽名(摘要)Update     
  20.     {    
  21.         printf("err\n");    
  22.         EVP_PKEY_free(evpKey);    
  23.         return;    
  24.     }    
  25.     if(!EVP_SignFinal(&mdctx,*signValue,&signLen,evpKey))  //簽名輸出     
  26.     {    
  27.         printf("err\n");    
  28.         EVP_PKEY_free(evpKey);    
  29.         return;    
  30.     }    
  31.     printf("消息\"%s\"的簽名值是:\n",text);    
  32.     printByte(*signValue,signLen);  
  33.     printf("\n");    
  34.     EVP_MD_CTX_cleanup(&mdctx);    
  35.   
  36. }  
  37.   
  38. void opensslSigner::verify(EVP_PKEY* evpKey,BYTE* text,unsigned int textLen,BYTE* signValue,unsigned int signLen)  
  39. {  
  40.     ERR_load_EVP_strings();  
  41.     EVP_MD_CTX mdctx;   //摘要算法上下文變量     
  42.     EVP_MD_CTX_init(&mdctx);    //初始化摘要上下文     
  43.     if(!EVP_VerifyInit_ex(&mdctx, EVP_md5(), NULL)) //驗證初始化,設置摘要算法,一定要和簽名一致     
  44.     {    
  45.         printf("EVP_VerifyInit_ex err\n");    
  46.         EVP_PKEY_free(evpKey);    
  47.         return;    
  48.     }    
  49.     if(!EVP_VerifyUpdate(&mdctx, text, textLen)) //驗證簽名(摘要)Update     
  50.     {    
  51.         printf("err\n");    
  52.         EVP_PKEY_free(evpKey);    
  53.         return;    
  54.     }    
  55.     if(!EVP_VerifyFinal(&mdctx,signValue,signLen,evpKey))    
  56.     {    
  57.         printf("verify err\n");    
  58.         EVP_PKEY_free(evpKey);    
  59.         EVP_MD_CTX_cleanup(&mdctx);    
  60.         return;  
  61.     }    
  62.     else    
  63.     {    
  64.         printf("驗證簽名正確.\n");    
  65.     }    
  66.     //釋放內存     
  67.     EVP_PKEY_free(evpKey);    
  68.     EVP_MD_CTX_cleanup(&mdctx);    
  69. }  

2.CryptoAPI的簽名驗證

依然是私鑰的問題,沒時間再去嘗試導入私鑰,暫且只寫驗證

因為也是RSA加密,所以同樣要注意字節排列方式,具體看RSA加密的交互部分

  1. void verify(HCRYPTPROV hProv,PCCERT_CONTEXT cert,BYTE* text,unsigned long len,BYTE* signValue,unsigned long signLen)  
  2. {  
  3.         //反序與openssl一致   
  4.     for(int i = 0 ; i < signLen / 2;i++)  
  5.     {  
  6.         BYTE temp = signValue[i];  
  7.         signValue[i] = signValue[signLen - i - 1];  
  8.         signValue[signLen - i - 1] = temp;  
  9.     }  
  10.   
  11.     // 創建離散對象       
  12.     HCRYPTHASH hHash = NULL;      
  13.     if(!CryptCreateHash(      
  14.         hProv,                        // 容器句柄        
  15.         CALG_MD5,                    // 算法標識       
  16.         NULL,                        // 算法使用的Key       
  17.         0,                            // 算法標識       
  18.         &hHash))                    // 返回的HASH對象       
  19.     {      
  20.         printf("CryptCreateHash error:0X%x.\n",GetLastError());  
  21.         return;  
  22.     }      
  23.       
  24.     // 計算數據摘要       
  25.     if(CryptHashData(hHash, text, len, 0) == 0)      
  26.     {      
  27.         printf("CryptHashData error:0X%x.\n",GetLastError());  
  28.         return;  
  29.     }      
  30.   
  31.   
  32.     if(cert == NULL)      
  33.     {      
  34.         printf("pCertContext == NULL:0X%x.\n",GetLastError());  
  35.         return;  
  36.     }      
  37.     //獲取公鑰句柄     
  38.     HCRYPTKEY hPubKey;      
  39.     if(!CryptImportPublicKeyInfo(hProv, cert->dwCertEncodingType, &cert->pCertInfo->SubjectPublicKeyInfo, &hPubKey))      
  40.     {      
  41.         printf("CryptImportPublicKeyInfo error:0X%x.\n",GetLastError());  
  42.         return;  
  43.     }      
  44.     //驗證簽名     
  45.     if(!CryptVerifySignature(hHash, signValue, signLen, hPubKey, NULL, 0))      
  46.     {      
  47.         printf("CryptVerifySignature error:0X%x.\n",GetLastError());  
  48.         return;  
  49.     }      
  50.     cout << "sign verify successfully" << endl;  
  51. }  
Copyright © Linux教程網 All Rights Reserved