CryptoAPI与openssl数字签名与验证交互

昨天写过了RSA非对称加密解密的交互方式,

其实数字签名也是RSA非对称加密,只不过用私钥加密的,再加上个hash摘要

CryptoAPI与openssl RSA非对称加密解密(PKCS1 PADDING)交互已经提到关于证书和私钥的数据以及对象获取,这里就不再重复讨论


1.openssl的签名及验证

[cpp]  view plain  copy
 print ?
  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加密的交互部分

[cpp]  view plain  copy
 print ?
  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. }  
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
CryptoAPI是一组用于加密和解密数据的API,其中包括数字签名的实现。数字签名是一种用于验证数据完整性和身份验证的技术,它使用公钥密码学来验证数字签名的真实性。 要使用CryptoAPI实现数字签名,可以按照以下步骤进行: 1. 创建一个Cryptographic Service Provider(CSP)对象,用于执行加密和解密操作。 2. 创建一个密钥容器,用于存储数字证书。 3. 获取数字证书并将其存储在密钥容器中。 4. 使用密钥容器中的私钥创建数字签名。 5. 验证数字签名的有效性。 以下是一个示例代码,用于使用CryptoAPI实现数字签名: ``` #include <windows.h> #include <wincrypt.h> #define ENCODING (X509_ASN_ENCODING | PKCS_7_ASN_ENCODING) int main() { HCRYPTPROV hProv = 0; HCRYPTKEY hKey = 0; HCRYPTHASH hHash = 0; DWORD dwSigLen = 0; BYTE *pbSig = NULL; // Acquire a cryptographic context. if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, 0)) { printf("Error: CryptAcquireContext failed\n"); return 1; } // Create a hash object. if (!CryptCreateHash(hProv, CALG_SHA1, 0, 0, &hHash)) { printf("Error: CryptCreateHash failed\n"); return 1; } // Hash the data. BYTE pbData[] = "Hello, world!"; DWORD dwDataLen = strlen(pbData); if (!CryptHashData(hHash, pbData, dwDataLen, 0)) { printf("Error: CryptHashData failed\n"); return 1; } // Create a signature of the hash. if (!CryptGetUserKey(hProv, AT_SIGNATURE, &hKey)) { printf("Error: CryptGetUserKey failed\n"); return 1; } if (!CryptSignHash(hHash, AT_SIGNATURE, NULL, 0, NULL, &dwSigLen)) { printf("Error: CryptSignHash failed (1)\n"); return 1; } pbSig = (BYTE*)malloc(dwSigLen); if (!CryptSignHash(hHash, AT_SIGNATURE, NULL, 0, pbSig, &dwSigLen)) { printf("Error: CryptSignHash failed (2)\n"); return 1; } // Verify the signature. if (!CryptVerifySignature(hHash, pbSig, dwSigLen, hKey, NULL, 0)) { printf("Error: CryptVerifySignature failed\n"); return 1; } printf("Signature verified successfully.\n"); // Clean up. CryptDestroyHash(hHash); CryptReleaseContext(hProv, 0); return 0; } ``` 此代码使用SHA1算法对数据进行哈希,并使用AT_SIGNATURE标识符获取密钥容器中的私钥来创建数字签名。然后,它验证数字签名的有效性。在实际情况下,您需要从数字证书中获取公钥并使用它来验证数字签名

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值