Esempio n. 1
0
////////////////////////////////////////////////////////////////////////////////////
//The Signing Method
//Sign.getSignedHash
// in:
//		sHash -- hash string
//		selectedCert -- reserved (if 0 cleans the KeyContainerName cache)
// out:
//		signed hash in hex form
////Additionaly change values of attributes corresponding with signing cert (SigningKeyContainerName, SigningCSPName, SigningCertName, SigningCertIssuer)
////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CSign::getSignedHash(BSTR sHash, long selectedCert, BSTR *SignedHash)
////////////////////////////////////////////////////////////////////////////////////
{

    PCCERT_CONTEXT pCertContext;
    BYTE pbHash[20];
    //char * sHashHex;
    char sHashHex[41];
    DWORD dwSelectedCert;

    DWORD dwSignature=1024; //RSA signatuuri pikkus - this parameter specifies the max size of signature value buffer
    BYTE cSignature[1025]; //the buffer receiving signature value
    TCHAR pbhSignature[2049]; //2*256 + 1 for null-terminating char

    BOOL fResult, fFreeProv;

    HCRYPTPROV hProv = NULL;
    HCRYPTKEY hPubKey = NULL;
    DWORD dwKeySpec;
    DWORD dwResult;
    char pSignatureRev[1025]; //the buffer for reversed signature value
    int i;

    memset(cSignature,0,1025);
    memset(pbhSignature,0,2049);
    memset(pSignatureRev,0,1025);
    memset(sHashHex,0,41);

    if(sHash=='\0')
        goto SIGDONE;

    for(i=0; i< 40; i++)
    {
        sHashHex[i]=(TCHAR)sHash[i];
        if(sHashHex[i]==0) break;
    }
    if(strlen(sHashHex)!=40)
        goto SIGDONE;


    HexBin(sHashHex,(char *)pbHash,20);

    dwSelectedCert=selectedCert;
    pCertContext=DigiCrypt_FindContext(0, &dwResult, &dwSelectedCert);

    if(!pCertContext)
        goto SIGDONE;

    fResult = GetRSAKeyFromCert(pCertContext,&hProv,&hPubKey, &dwKeySpec,&fFreeProv);
    if(fResult==NULL)
        goto SIGDONE;

    fResult = SignHashString(hProv,hPubKey,dwKeySpec,pbHash,cSignature,&dwSignature/*this parameter will be updated with the actual value of the signature*/);
    if(fResult==NULL)
        goto SIGDONE;

    BinHex((char*)pbHash,20,sHashHex);

    for(i=dwSignature-1; i>=0; i--) //allowed indexes for an array of size N are from 0 to N-1, this is fixed now
    {
        pSignatureRev[dwSignature-1-i]=cSignature[i];
    }
    pSignatureRev[dwSignature]=0;


    BinHex((char *)pSignatureRev, dwSignature, pbhSignature);

    *SignedHash=_bstr_t((LPCTSTR)pbhSignature).copy();

SIGDONE:
    if(fFreeProv)
    {
        if(hPubKey)
        {
            CryptDestroyKey(hPubKey);
        }
        if(hProv)
            CryptReleaseContext(hProv, 0);
    }
    pCertContext=NULL;

    return S_OK;
}
void _tmain(int argc, TCHAR *argv[])
{
   HCRYPTPROV hProv = NULL;
   HCRYPTKEY hPubKey = NULL;   
   PCCERT_CONTEXT pCertContext = NULL;
   LPTSTR szCertificateName = NULL;
   LPTSTR szStoreName = NULL;
   LPTSTR szContainerName = NULL;   
   LPTSTR szFileToSign = NULL;
   LPTSTR szSigFile = NULL;
   DWORD dwOpenFlags = CERT_SYSTEM_STORE_CURRENT_USER;
   DWORD dwAcquireFlags = 0;
   DWORD dwKeySpec = AT_SIGNATURE;
   ALG_ID AlgId;   
   BOOL fSign = FALSE;
   BOOL fResult = FALSE;
   BOOL fUseCert = FALSE;
   BOOL fFreeProv = FALSE;

   if (argc != 9)
   {
      PrintUsage();
      return;
   }

   __try
   {  
      // Determine hash algorithm
      if (lstrcmpi(argv[1], _T("sha1")) == 0)
      {
         AlgId = CALG_SHA1;
      }
      else if (lstrcmpi(argv[1], _T("md5")) == 0)
      {
         AlgId = CALG_MD5;
      }
      else
      {
         PrintUsage();
         return;
      }

      /* Check whether the action to be performed is to sign or verify */
      if (lstrcmpi(argv[2], _T("/s")) == 0)
      {
         fSign = TRUE;
      }
      else if (lstrcmpi(argv[2], _T("/v")) == 0)
      {
         fSign = FALSE;
      }
      else
      {
         PrintUsage();
         return;
      }

      szFileToSign = argv[3];
      szSigFile = argv[4];

      // check to see if user wants to use a certificate
      if (lstrcmpi(argv[5], _T("/cert")) == 0)
      {
         fUseCert = TRUE;
         
         szCertificateName = argv[6];
         szStoreName = argv[7];

         // Determine if we have to use user or machine store
         if (lstrcmpi(argv[8], _T("u")) == 0)
         {
            dwOpenFlags = CERT_SYSTEM_STORE_CURRENT_USER;
         }
         else if (lstrcmpi(argv[8], _T("m")) == 0)
         {
            dwOpenFlags = CERT_SYSTEM_STORE_LOCAL_MACHINE;
         }
         else
         {
            PrintUsage();
            return;
         }
      }
      else if (lstrcmpi(argv[5], _T("/key")) == 0)
      {
         fUseCert = FALSE;

         szContainerName = argv[6];

         if (lstrcmpi(argv[7], _T("u")) == 0)
         {
            dwAcquireFlags = 0;
         }
         else if (lstrcmpi(argv[7], _T("m")) == 0)
         {
            dwAcquireFlags = CRYPT_MACHINE_KEYSET;
         }
         else
         {
            PrintUsage();
            return;
         }

         // Use exchange key or signature key
         if (lstrcmpi(argv[8], _T("x")) == 0)
         {
            dwKeySpec = AT_KEYEXCHANGE;
         }
         else if (lstrcmpi(argv[8], _T("s")) == 0)
         {
            dwKeySpec = AT_SIGNATURE;
         }
         else
         {
            PrintUsage();
            return;
         }
      }
      else
      {
         PrintUsage();
         return;
      }

      if (fUseCert)
      {
         pCertContext = GetCertificateContextFromName(szCertificateName,
                                                      szStoreName,
                                                      dwOpenFlags);
         if (!pCertContext) __leave;
         
         fResult = GetRSAKeyFromCert(pCertContext,
                                     fSign,
                                     &hProv,
                                     &hPubKey,
                                     &dwKeySpec,
                                     &fFreeProv);
         if (!fResult) __leave;
      }
      else
      {
         fResult = GetRSAKeyFromContainer(szContainerName,
                                          dwAcquireFlags,
                                          dwKeySpec,
                                          &hProv,                            
                                          &hPubKey);         
         if (!fResult) __leave;

         fFreeProv = TRUE;
      }
      
      fResult = SignVerifyFile(hProv,
                               hPubKey,
                               dwKeySpec,
                               AlgId,
                               szFileToSign,
                               szSigFile,
                               fSign);
      if (!fResult) __leave;
      
      if (fSign)
      {
         MyPrintf(_T("File %s hashed and signed successfully!\n"), szFileToSign);
      }
      else
      {
         MyPrintf(_T("File %s verified successfully!\n"), szSigFile);
      }
   }
   __finally
   {
      // Clean up      
      if (hPubKey != NULL) CryptDestroyKey(hPubKey);
      if (fFreeProv && (hProv != NULL)) CryptReleaseContext(hProv, 0);
      if (pCertContext != NULL) CertFreeCertificateContext(pCertContext);      
   }
}