zoukankan      html  css  js  c++  java
  • CryptoAPI与openssl数字签名与验证交互

    昨天写过了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 ");    
    8.         return;    
    9.     }    
    10.       
    11.     //以下是计算签名的代码    
    12.     EVP_MD_CTX_init(&mdctx);        //初始化摘要上下文    
    13.     if(!EVP_SignInit_ex(&mdctx,EVP_md5(),NULL)) //签名初始化,设置摘要算法    
    14.     {    
    15.         printf("err ");    
    16.         EVP_PKEY_free(evpKey);    
    17.         return;    
    18.     }    
    19.     if(!EVP_SignUpdate(&mdctx,text,textLen)) //计算签名(摘要)Update    
    20.     {    
    21.         printf("err ");    
    22.         EVP_PKEY_free(evpKey);    
    23.         return;    
    24.     }    
    25.     if(!EVP_SignFinal(&mdctx,*signValue,&signLen,evpKey))  //签名输出    
    26.     {    
    27.         printf("err ");    
    28.         EVP_PKEY_free(evpKey);    
    29.         return;    
    30.     }    
    31.     printf("消息"%s"的签名值是: ",text);    
    32.     printByte(*signValue,signLen);  
    33.     printf(" ");    
    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 ");    
    46.         EVP_PKEY_free(evpKey);    
    47.         return;    
    48.     }    
    49.     if(!EVP_VerifyUpdate(&mdctx, text, textLen)) //验证签名(摘要)Update    
    50.     {    
    51.         printf("err ");    
    52.         EVP_PKEY_free(evpKey);    
    53.         return;    
    54.     }    
    55.     if(!EVP_VerifyFinal(&mdctx,signValue,signLen,evpKey))    
    56.     {    
    57.         printf("verify err ");    
    58.         EVP_PKEY_free(evpKey);    
    59.         EVP_MD_CTX_cleanup(&mdctx);    
    60.         return;  
    61.     }    
    62.     else    
    63.     {    
    64.         printf("验证签名正确. ");    
    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. ",GetLastError());  
      21.         return;  
      22.     }      
      23.       
      24.     // 计算数据摘要      
      25.     if(CryptHashData(hHash, text, len, 0) == 0)      
      26.     {      
      27.         printf("CryptHashData error:0X%x. ",GetLastError());  
      28.         return;  
      29.     }      
      30.   
      31.   
      32.     if(cert == NULL)      
      33.     {      
      34.         printf("pCertContext == NULL:0X%x. ",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. ",GetLastError());  
      42.         return;  
      43.     }      
      44.     //验证签名    
      45.     if(!CryptVerifySignature(hHash, signValue, signLen, hPubKey, NULL, 0))      
      46.     {      
      47.         printf("CryptVerifySignature error:0X%x. ",GetLastError());  
      48.         return;  
      49.     }      
      50.     cout << "sign verify successfully" << endl;  
  • 相关阅读:
    网易数帆实时数据湖 Arctic 的探索和实践
    私有化场景下大规模云原生应用的交付实践
    Apache Kyuubi 在 T3 出行的深度实践
    Win7 32位原版镜像无法安装VMware Tools
    VB.NET代码转C#的方法
    ArcGIS Pro导入OSGB倾斜摄影数据
    基于倾斜摄影测量的三维建模实验
    解决QTTabBar标签不能置顶的问题
    GIS中图斑椭球面积的计算
    ISaveAs导出栅格显示异常
  • 原文地址:https://www.cnblogs.com/adylee/p/3611580.html
Copyright © 2011-2022 走看看