歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> CryptoAPI與OpenSSL數字簽名與驗證交互

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

日期:2017/3/1 10:12:03   编辑:Linux編程

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

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. HCRYPTHASH hHash = NULL;
  12. if(!CryptCreateHash(
  13. hProv, // 容器句柄
  14. CALG_MD5, // 算法標識
  15. NULL, // 算法使用的Key
  16. 0, // 算法標識
  17. &hHash)) // 返回的HASH對象
  18. {
  19. printf("CryptCreateHash error:0X%x.\n",GetLastError());
  20. return;
  21. }
  22. // 計算數據摘要
  23. if(CryptHashData(hHash, text, len, 0) == 0)
  24. {
  25. printf("CryptHashData error:0X%x.\n",GetLastError());
  26. return;
  27. }
  28. if(cert == NULL)
  29. {
  30. printf("pCertContext == NULL:0X%x.\n",GetLastError());
  31. return;
  32. }
  33. //獲取公鑰句柄
  34. HCRYPTKEY hPubKey;
  35. if(!CryptImportPublicKeyInfo(hProv, cert->dwCertEncodingType, &cert->pCertInfo->SubjectPublicKeyInfo, &hPubKey))
  36. {
  37. printf("CryptImportPublicKeyInfo error:0X%x.\n",GetLastError());
  38. return;
  39. }
  40. //驗證簽名
  41. if(!CryptVerifySignature(hHash, signValue, signLen, hPubKey, NULL, 0))
  42. {
  43. printf("CryptVerifySignature error:0X%x.\n",GetLastError());
  44. return;
  45. }
  46. cout << "sign verify successfully" << endl;
  47. }
Copyright © Linux教程網 All Rights Reserved