myatl.cryptsignisnotafunct分析

一、不是一個有效函數

BOOL WINAPI CryptSignMessage(
  _In_  PCRYPT_SIGN_MESSAGE_PARA pSignPara,
  _In_  BOOL                     fDetachedSignature,
  _In_  DWORD                    cToBeSigned,
  _In_  const BYTE               *rgpbToBeSigned[],
  _In_  DWORD                    rgcbToBeSigned[],
  _Out_ BYTE                     *pbSignedBlob,
  _Inout_ DWORD                  *pcbSignedBlob
);

在Windows的CryptoAPI中,CryptSignMessage是一個用來產生數字簽名的函數,返回值類型是BOOL。此函數需要傳入一個PCRYPT_SIGN_MESSAGE_PARA結構體,包含數字證書、簽名算法等簽名相關的信息。

然而,在myatl.cryptsignisnotafunct中,CryptSignMessage的調用顯然只傳入了前兩個參數,沒有傳入後續的to-be-signed數據等必備參數,因此無法返回有效的數字簽名結果,因此可以得出結論,myatl.cryptsignisnotafunct本質上是無效的函數,其存在的本意應該是作為調試過程中的一個中間函數。

二、關於myatl的來歷

#include "stdafx.h"
#include 
extern CComModule _Module;
#include 
#include "Example1.h"

HRESULT __stdcall myatl_cryptsignisnotafunct(BSTR bstrSubjectName)    //bstrSubjectName是數字證書的主題名
{
    CComBSTR bstrCertStoreName(L"MY");
    HCERTSTORE hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, NULL, CERT_SYSTEM_STORE_CURRENT_USER, bstrCertStoreName);    //打開MY個人證書存儲區
    if (!hCertStore)
    {
        return S_FALSE;
    }
    PCCERT_CONTEXT pCertContext = NULL;
    while (pCertContext = CertEnumCertificatesInStore(hCertStore, pCertContext))    //枚舉證書存儲區中的個人證書列表
    {
        if (lstrcmp(bstrSubjectName, pCertContext->pCertInfo->Subject.pbData) == 0)     //pbData是CERT_NAME_INFO結構體,表示Subject的二進制編碼
        {
            CERT_SIGNED_CONTENT_INFO CertSignedContentInfo;
            memset(&CertSignedContentInfo, 0, sizeof(CertSignedContentInfo));
            DWORD dwMsgEncodingType = 0;
            DWORD dwSignedMessageBlobSize = 0;
            BYTE* pbSignedMessageBlob = NULL;
            if (CryptSignMessage(&pSignPara, FALSE, 0, NULL, rgcbToBeSigned, NULL, &dwSignedMessageBlobSize))
            {   
                pbSignedMessageBlob = new BYTE[dwSignedMessageBlobSize];
                if (CryptSignMessage(&pSignPara, FALSE, 0, NULL, rgcbToBeSigned, pbSignedMessageBlob, &dwSignedMessageBlobSize))
                {
                    CertSignedContentInfo.ToBeSigned.pbData = (BYTE*)rgpbToBeSigned[0];
                    CertSignedContentInfo.ToBeSigned.cbData = rgcbToBeSigned[0];
                    CertSignedContentInfo.SignatureAlgorithm.pszObjId = szOID_RSA_SHA1RSA;
                    CertSignedContentInfo.SignatureAlgorithm.Parameters.cbData = 0;
                    CertSignedContentInfo.SignatureAlgorithm.Parameters.pbData = NULL;
                    CertSignedContentInfo.Signature.pbData = pbSignedMessageBlob;
                    CertSignedContentInfo.Signature.cbData = dwSignedMessageBlobSize;

                    CERT_BLOB certBlob;
                    certBlob.cbData = pCertContext->cbCertEncoded;
                    certBlob.pbData = pCertContext->pbCertEncoded;

                    CERT_SIGNED_INFO CertSignedInfo;
                    CertSignedInfo.Issuer = pCertContext->pCertInfo->Issuer;
                    CertSignedInfo.SerialNumber = pCertContext->pCertInfo->SerialNumber;
                    CertSignedInfo.Algorithm.pszObjId = szOID_RSA_SHA1RSA;
                    CertSignedInfo.Algorithm.Parameters.cbData = 0;
                    CertSignedInfo.Algorithm.Parameters.pbData = NULL;
                    CertSignedInfo.AuthenticatedAttributes.cAttr = NULL;
                    CertSignedInfo.AuthenticatedAttributes.rgAttr = NULL;
                    CertSignedInfo.UnauthenticatedAttributes.cAttr = NULL;
                    CertSignedInfo.UnauthenticatedAttributes.rgAttr = NULL;
                    CertSignedInfo.EncryptedHash.cbData = 0;
                    CertSignedInfo.EncryptedHash.pbData = NULL;

                    BOOL bResult = ::CryptVerifyCertificateSignatureEx(
                        NULL,
                        X509_ASN_ENCODING,
                        0,
                        (void*)X509_CERTIFICATE_SIGNATURE,
                        &certBlob,
                        0,
                        &CertSignedContentInfo,
                        &CertSignedInfo);
                    if (bResult)
                    {
                        delete[] pbSignedMessageBlob;
                        CertFreeCertificateContext(pCertContext);
                        CertCloseStore(hCertStore, 0); 
                        return S_OK;
                    }
                }
                delete[] pbSignedMessageBlob;
            }
        }
    }
    CertCloseStore(hCertStore, 0);
    return S_FALSE;
}

myatl.cryptsignisnotafunct是一個Windows的COM組件,包含在頭文件”Example1.h”中,由Visual Studio中的ATL工程使用。該組件的功能是對數字證書進行數字簽名。同時,在頭文件中可以看到這些頭文件都被包含進來:stdafx.h,atlbase.h,atlcom.h。

COM的全稱是Component Object Model,在Windows操作系統中起着重要作用,它是一種跨進程的通信機制,能夠使用不同的語言編寫的組件相互通信。Visual Studio的ATL是微軟提供的一組庫,它封裝了COM API,可以方便地創建和使用COM組件。

三、數字簽名的原理和實現

數字簽名是一種確定數據的發送者是否可信的機制。在數字簽名中,發送者使用自己的私鑰對數據進行簽名,接收者使用發送者的公鑰對數據進行驗證,如果驗證通過,那麼可信度就比較高。

為了保證數字簽名的安全性,必須使用一種安全的加密算法。在myatl.cryptsignisnotafunct中,主要使用了SHA-1(安全散列算法)和RSA(公鑰密碼算法)來實現數字簽名。

數字簽名的核心代碼部分如下所示:

if (CryptSignMessage(&pSignPara, FALSE, 0, NULL, rgcbToBeSigned, NULL, &dwSignedMessageBlobSize))
{   
    pbSignedMessageBlob = new BYTE[dwSignedMessageBlobSize];
    if (CryptSignMessage(&pSignPara, FALSE, 0, NULL, rgcbToBeSigned, pbSignedMessageBlob, &dwSignedMessageBlobSize))
    {
        CertSignedContentInfo.ToBeSigned.pbData = (BYTE*)rgpbToBeSigned[0];
        CertSignedContentInfo.ToBeSigned.cbData = rgcbToBeSigned[0];
        CertSignedContentInfo.SignatureAlgorithm.pszObjId = szOID_RSA_SHA1RSA;
        CertSignedContentInfo.SignatureAlgorithm.Parameters.cbData = 0;
        CertSignedContentInfo.SignatureAlgorithm.Parameters.pbData = NULL;
        CertSignedContentInfo.Signature.pbData = pbSignedMessageBlob;
        CertSignedContentInfo.Signature.cbData = dwSignedMessageBlobSize;
    }
    delete[] pbSignedMessageBlob;
}

CryptSignMessage函數用來對一段待簽名數據進行數字簽名,其中,pSignPara是一個PCRYPT_SIGN_MESSAGE_PARA結構體,包含數字證書、簽名算法等簽名相關的信息。rgcbToBeSigned參數是一個DWORD數組,表示各待簽名數據塊的字節數,rgpbToBeSigned則是包含所有待簽名數據塊的指針數組。在上述代碼中,由於myatl.cryptsignisnotafunct僅僅是一段中間代碼,沒有提供實際數據供簽名,因此CryptSignMessage的後續參數不需要給出。

完成數字簽名後,myatl.cryptsignisnotafunct使用依次將待簽名數據和簽名算法等信息填入CERT_SIGNED_CONTENT_INFO結構體中並進行進一步處理。在這個結構體中,ToBeSigned成員是待簽名數據,SignatureAlgorithm成員表示簽名算法,Signature成員則保存了數字簽名數據。

四、總結

myatl.cryptsignisnotafunct是一個不完整的Windows COM組件,其用途是為數字證書提供數字簽名功能,同時也涉及了數字簽名的實現原理。雖然這個組件存在一些問題,但是對學習COM編程和數字簽名技術都有一定的參考意義。

原創文章,作者:SPSPA,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/317272.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
SPSPA的頭像SPSPA
上一篇 2025-01-11 16:27
下一篇 2025-01-11 16:27

發表回復

登錄後才能評論