zoukankan      html  css  js  c++  java
  • 签名解密,内容验证

    前面一个文章里面,我们把一个字符串进行hash计算,而且签名。

    如今就须要在接收方来验证了。

    CryptImportKey

    首先,我们须要把发方发过来的公钥导入到CSP里面。

    我们这里如果pbKeyBlob就是收到的公钥信息(比方从证书里面获取)。

        if (CryptImportKey(
            hProv,
            pbKeyBlob,
            dwBlobLen,
            0,
            0,
            &hPubKey))
        {
            printf("The key has been imported.
    ");
        }
        else
        {
            MyHandleError("Public key import failed.");
        }


    CryptCreateHash,CrypteHashData

    如果pbBuffer就是收到的内容,以下的代码就计算了一个hash值。

        //-------------------------------------------------------------------
        // Create a new hash object.
    
        if (CryptCreateHash(
            hProv,
            CALG_MD5,
            0,
            0,
            &hHash))
        {
            printf("The hash object has been recreated. 
    ");
        }
        else
        {
            MyHandleError("Error during CryptCreateHash.");
        }
        //-------------------------------------------------------------------
        // Compute the cryptographic hash of the buffer.
    
        if (CryptHashData(
            hHash,
            pbBuffer,
            dwBufferLen,
            0))
        {
            printf("The new hash has been created.
    ");
        }
        else
        {
            MyHandleError("Error during CryptHashData.");
        }

    如今就能够verify了。

    CryptVerifySignature

    这个API会把pbSignature用hPubKey解密而且和hHash进行比較。

        //-------------------------------------------------------------------
        // Validate the digital signature.
    
        if (CryptVerifySignature(
            hHash,
            pbSignature,
            dwSigLen,
            hPubKey,
            NULL,
            0))
        {
            printf("The signature has been verified.
    ");
        }
        else
        {
            printf("Signature not validated!
    ");
        }


    就这样,我们能够把发方发过来的数据进行验证了。


    附:完整代码

    //--------------------------------------------------------------------
    // Copyright (C) Microsoft.  All rights reserved.
    // Example of signing a hash and 
    // verifying the hash signature.
    #pragma comment(lib, "crypt32.lib")
    
    #include "stdafx.h"
    #include <stdio.h>
    #include <windows.h>
    #include <Wincrypt.h>
    #define MY_ENCODING_TYPE  (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
    void MyHandleError(char *s);
    
    void main(void)
    {
        //-------------------------------------------------------------------
        // Declare and initialize variables.
    
        HCRYPTPROV hProv;
        BYTE *pbBuffer = (BYTE *)"The data that is to be hashed and signed.";
        DWORD dwBufferLen = strlen((char *)pbBuffer) + 1;
        HCRYPTHASH hHash;
        HCRYPTKEY hKey;
        HCRYPTKEY hPubKey;
        BYTE *pbKeyBlob;
        BYTE *pbSignature;
        DWORD dwSigLen;
        DWORD dwBlobLen;
    
        //-------------------------------------------------------------------
        // Acquire a cryptographic provider context handle.
    
        if (CryptAcquireContext(
            &hProv,
            L"MyContainer",
            NULL,
            PROV_RSA_FULL,
            0))
        {
            printf("CSP context acquired.
    ");
        }
        else
        {
            if (GetLastError() == NTE_BAD_KEYSET)
            {
                if (!CryptAcquireContext(
                    &hProv,
                    L"MyContainer",
                    NULL,
                    PROV_RSA_FULL,
                    CRYPT_NEWKEYSET))
                {
                    MyHandleError("Error during CryptAcquireContext.");
                }
    
            }
            else
            {
                MyHandleError("Error during CryptAcquireContext.");
            }
        }
    
    
        HCRYPTPROV hCryptProv;
        BYTE       pbData[1000];       // 1000 will hold the longest 
        // key container name.
        DWORD cbData;
    
        //-------------------------------------------------------------------
        // An HCRYPTPROV must be acquired before using code like that in 
        // "Example C Program Using CryptAcquireContext."
    
        //-------------------------------------------------------------------
        // Read the name of the default CSP.
    
        cbData = 1000;
        CryptGetProvParam(
            hProv,
            PP_NAME,
            pbData,  // should be "Microsoft Strong Cryptographic Provider"
            &cbData,
            0);
    
        cbData = 1000;
        CryptGetProvParam(
            hProv,
            PP_CONTAINER,
            pbData,  // should be "MyContainter"
            &cbData,
            0);
    
        //-------------------------------------------------------------------
        // Get the public at signature key. This is the public key
        // that will be used by the receiver of the hash to verify
        // the signature. In situations where the receiver could obtain the
        // sender's public key from a certificate, this step would not be
        // needed.
    
        if (CryptGetUserKey(
            hProv,
            AT_SIGNATURE,
            &hKey))
        {
            printf("The signature key has been acquired. 
    ");
        }
        else
        {
            if (GetLastError() == NTE_NO_KEY)               // NTE_NO_KEY意味着密钥不存在。以下就生成一个密钥
            {
                _tprintf(TEXT("The signature key does not exist./n"));
                _tprintf(TEXT("Create a signature key pair./n"));
                if (CryptGenKey(                           // CryptGenKey生成一个密钥
                    hProv,                           //指定CSP模块的句柄
                    AT_SIGNATURE,                     //对于公钥password系统,生成一个私钥和一个公钥,这个參数指定了这个密钥是公钥,于是生成了一个password对。假设不是公钥系统,则指定了password算法,详细看MSDN。
                    0,                                  //指定了生成密钥的类型。这个參数的说明挺多的,想获取更为详尽的资料请看MSDN。
                    &hKey))
                {
                    _tprintf(TEXT("Created a signature key pair./n"));
                }
                else
                {
                    MyHandleError("CryptGenKey failed");
                }
            }
            else
            {
                MyHandleError("Error during CryptGetUserKey for signkey.");
            }
        }
        //-------------------------------------------------------------------
        // Export the public key. Here the public key is exported to a 
        // PUBLICKEYBOLB so that the receiver of the signed hash can
        // verify the signature. This BLOB could be written to a file and
        // sent to another user.
    
        if (CryptExportKey(
            hKey,
            NULL,
            PUBLICKEYBLOB,
            0,
            NULL,
            &dwBlobLen))
        {
            printf("Size of the BLOB for the public key determined. 
    ");
        }
        else
        {
            MyHandleError("Error computing BLOB length.");
        }
        //-------------------------------------------------------------------
        // Allocate memory for the pbKeyBlob.
    
        if (pbKeyBlob = (BYTE*)malloc(dwBlobLen))
        {
            printf("Memory has been allocated for the BLOB. 
    ");
        }
        else
        {
            MyHandleError("Out of memory. 
    ");
        }
        //-------------------------------------------------------------------
        // Do the actual exporting into the key BLOB.
    
        if (CryptExportKey(
            hKey,
            NULL,
            PUBLICKEYBLOB,
            0,
            pbKeyBlob,
            &dwBlobLen))
        {
            printf("Contents have been written to the BLOB. 
    ");
        }
        else
        {
            MyHandleError("Error during CryptExportKey.");
        }
        //-------------------------------------------------------------------
        // Create the hash object.
    
        if (CryptCreateHash(
            hProv,
            CALG_MD5,
            0,
            0,
            &hHash))
        {
            printf("Hash object created. 
    ");
        }
        else
        {
            MyHandleError("Error during CryptCreateHash.");
        }
        //-------------------------------------------------------------------
        // Compute the cryptographic hash of the buffer.
    
        if (CryptHashData(
            hHash,
            pbBuffer,
            dwBufferLen,
            0))
        {
            printf("The data buffer has been hashed.
    ");
        }
        else
        {
            MyHandleError("Error during CryptHashData.");
        }
        //-------------------------------------------------------------------
        // Determine the size of the signature and allocate memory.
    
        dwSigLen = 0;
        if (CryptSignHash(
            hHash,
            AT_SIGNATURE,
            NULL,
            0,
            NULL,
            &dwSigLen))
        {
            printf("Signature length %d found.
    ", dwSigLen);
        }
        else
        {
            MyHandleError("Error during CryptSignHash.");
        }
        //-------------------------------------------------------------------
        // Allocate memory for the signature buffer.
    
        if (pbSignature = (BYTE *)malloc(dwSigLen))
        {
            printf("Memory allocated for the signature.
    ");
        }
        else
        {
            MyHandleError("Out of memory.");
        }
        //-------------------------------------------------------------------
        // Sign the hash object.
    
        if (CryptSignHash(
            hHash,
            AT_SIGNATURE,
            NULL,
            0,
            pbSignature,
            &dwSigLen))
        {
            printf("pbSignature is the hash signature.
    ");
        }
        else
        {
            MyHandleError("Error during CryptSignHash.");
        }
        //-------------------------------------------------------------------
        // Destroy the hash object.
    
        if (hHash)
            CryptDestroyHash(hHash);
    
        printf("The hash object has been destroyed.
    ");
        printf("The signing phase of this program is completed.
    
    ");
    
        //-------------------------------------------------------------------
        // In the second phase, the hash signature is verified.
        // This would most often be done by a different user in a
        // separate program. The hash, signature, and the PUBLICKEYBLOB
        // would be read from a file, an email message, 
        // or some other source.
    
        // Here, the original pbBuffer, pbSignature, szDescription. 
        // pbKeyBlob, and their lengths are used.
    
        // The contents of the pbBuffer must be the same data 
        // that was originally signed.
    
        //-------------------------------------------------------------------
        // Get the public key of the user who created the digital signature 
        // and import it into the CSP by using CryptImportKey. This returns
        // a handle to the public key in hPubKey.
    
        if (CryptImportKey(
            hProv,
            pbKeyBlob,
            dwBlobLen,
            0,
            0,
            &hPubKey))
        {
            printf("The key has been imported.
    ");
        }
        else
        {
            MyHandleError("Public key import failed.");
        }
        //-------------------------------------------------------------------
        // Create a new hash object.
    
        if (CryptCreateHash(
            hProv,
            CALG_MD5,
            0,
            0,
            &hHash))
        {
            printf("The hash object has been recreated. 
    ");
        }
        else
        {
            MyHandleError("Error during CryptCreateHash.");
        }
        //-------------------------------------------------------------------
        // Compute the cryptographic hash of the buffer.
    
        if (CryptHashData(
            hHash,
            pbBuffer,
            dwBufferLen,
            0))
        {
            printf("The new hash has been created.
    ");
        }
        else
        {
            MyHandleError("Error during CryptHashData.");
        }
        //-------------------------------------------------------------------
        // Validate the digital signature.
    
        if (CryptVerifySignature(
            hHash,
            pbSignature,
            dwSigLen,
            hPubKey,
            NULL,
            0))
        {
            printf("The signature has been verified.
    ");
        }
        else
        {
            printf("Signature not validated!
    ");
        }
        //-------------------------------------------------------------------
        // Free memory to be used to store signature.
    
        if (pbSignature)
            free(pbSignature);
    
        //-------------------------------------------------------------------
        // Destroy the hash object.
    
        if (hHash)
            CryptDestroyHash(hHash);
    
        //-------------------------------------------------------------------
        // Release the provider handle.
    
        if (hProv)
            CryptReleaseContext(hProv, 0);
    } //  End of main
    
    //-------------------------------------------------------------------
    //  This example uses the function MyHandleError, a simple error
    //  handling function, to print an error message to the  
    //  standard error (stderr) file and exit the program. 
    //  For most applications, replace this function with one 
    //  that does more extensive error reporting.
    
    void MyHandleError(char *s)
    {
        fprintf(stderr, "An error occurred in running the program. 
    ");
        fprintf(stderr, "%s
    ", s);
        fprintf(stderr, "Error number %x.
    ", GetLastError());
        fprintf(stderr, "Program terminating. 
    ");
        exit(1);
    } // End of MyHandleError
    
    


  • 相关阅读:
    一个棒棒糖引发的。。。
    做完了一个程序
    C# 串口操作系列(2) 入门篇,为什么我的串口程序在关闭串口时候会死锁 ? .
    MSSQL操作类
    煤矿粉尘监控系统需求分析
    C# 串口操作系列(3) 协议篇,二进制协议数据解析 .
    wp7 手机归属地查询
    .NET设计模式系列文章
    C# 串口操作系列(1) 入门篇,一个标准的,简陋的串口例子。
    常用经典算法
  • 原文地址:https://www.cnblogs.com/gcczhongduan/p/5215090.html
Copyright © 2011-2022 走看看