//////////////////////////////////////////////////////////////////////////////////// //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); } }