static EVP_PKEY *capi_get_pkey(ENGINE *eng, CAPI_KEY * key) { unsigned char *pubkey = NULL; DWORD len; BLOBHEADER *bh; RSA *rkey = NULL; DSA *dkey = NULL; EVP_PKEY *ret = NULL; if (!CryptExportKey(key->key, 0, PUBLICKEYBLOB, 0, NULL, &len)) { CAPIerr(CAPI_F_CAPI_GET_PKEY, CAPI_R_PUBKEY_EXPORT_LENGTH_ERROR); capi_addlasterror(); return NULL; } pubkey = OPENSSL_malloc(len); if (!pubkey) goto memerr; if (!CryptExportKey(key->key, 0, PUBLICKEYBLOB, 0, pubkey, &len)) { CAPIerr(CAPI_F_CAPI_GET_PKEY, CAPI_R_PUBKEY_EXPORT_ERROR); capi_addlasterror(); goto err; } bh = (BLOBHEADER *) pubkey; if (bh->bType != PUBLICKEYBLOB) { CAPIerr(CAPI_F_CAPI_GET_PKEY, CAPI_R_INVALID_PUBLIC_KEY_BLOB); goto err; } if (bh->aiKeyAlg == CALG_RSA_SIGN || bh->aiKeyAlg == CALG_RSA_KEYX) { RSAPUBKEY *rp; DWORD rsa_modlen; unsigned char *rsa_modulus; rp = (RSAPUBKEY *) (bh + 1); if (rp->magic != 0x31415352) { char magstr[10]; BIO_snprintf(magstr, 10, "%lx", rp->magic); CAPIerr(CAPI_F_CAPI_GET_PKEY, CAPI_R_INVALID_RSA_PUBLIC_KEY_BLOB_MAGIC_NUMBER); ERR_add_error_data(2, "magic=0x", magstr); goto err; } rsa_modulus = (unsigned char *)(rp + 1); rkey = RSA_new_method(eng); if (!rkey) goto memerr; rkey->e = BN_new(); rkey->n = BN_new(); if (!rkey->e || !rkey->n) goto memerr; if (!BN_set_word(rkey->e, rp->pubexp)) goto memerr; rsa_modlen = rp->bitlen / 8; if (!lend_tobn(rkey->n, rsa_modulus, rsa_modlen)) goto memerr; RSA_set_ex_data(rkey, rsa_capi_idx, key); if (!(ret = EVP_PKEY_new())) goto memerr; EVP_PKEY_assign_RSA(ret, rkey); rkey = NULL; } else if (bh->aiKeyAlg == CALG_DSS_SIGN) { DSSPUBKEY *dp; DWORD dsa_plen; unsigned char *btmp; dp = (DSSPUBKEY *) (bh + 1); if (dp->magic != 0x31535344) { char magstr[10]; BIO_snprintf(magstr, 10, "%lx", dp->magic); CAPIerr(CAPI_F_CAPI_GET_PKEY, CAPI_R_INVALID_DSA_PUBLIC_KEY_BLOB_MAGIC_NUMBER); ERR_add_error_data(2, "magic=0x", magstr); goto err; } dsa_plen = dp->bitlen / 8; btmp = (unsigned char *)(dp + 1); dkey = DSA_new_method(eng); if (!dkey) goto memerr; dkey->p = BN_new(); dkey->q = BN_new(); dkey->g = BN_new(); dkey->pub_key = BN_new(); if (!dkey->p || !dkey->q || !dkey->g || !dkey->pub_key) goto memerr; if (!lend_tobn(dkey->p, btmp, dsa_plen)) goto memerr; btmp += dsa_plen; if (!lend_tobn(dkey->q, btmp, 20)) goto memerr; btmp += 20; if (!lend_tobn(dkey->g, btmp, dsa_plen)) goto memerr; btmp += dsa_plen; if (!lend_tobn(dkey->pub_key, btmp, dsa_plen)) goto memerr; btmp += dsa_plen; DSA_set_ex_data(dkey, dsa_capi_idx, key); if (!(ret = EVP_PKEY_new())) goto memerr; EVP_PKEY_assign_DSA(ret, dkey); dkey = NULL; } else { char algstr[10]; BIO_snprintf(algstr, 10, "%lx", bh->aiKeyAlg); CAPIerr(CAPI_F_CAPI_GET_PKEY, CAPI_R_UNSUPPORTED_PUBLIC_KEY_ALGORITHM); ERR_add_error_data(2, "aiKeyAlg=0x", algstr); goto err; } err: if (pubkey) OPENSSL_free(pubkey); if (!ret) { if (rkey) RSA_free(rkey); if (dkey) DSA_free(dkey); } return ret; memerr: CAPIerr(CAPI_F_CAPI_GET_PKEY, ERR_R_MALLOC_FAILURE); goto err; }
INT ProtectDataCAPI(const char* szKeyName, const void* pData, size_t nData, void** ppData, size_t* pnData) { USES_CONVERSION; ; HCRYPTPROV hProv=NULL; BOOL bResult = FALSE; ; HCRYPTKEY hExchangeKey = NULL; HCRYPTKEY hSessionKey = NULL; void* pTempBuffer = NULL; DWORD dwTempBuffer = 0; void* pSessionKeyBlob = NULL; DWORD dwSessionKeyBlob = 0; void* pResultBuffer = NULL; size_t nResultBuffer = 0; { if(!(bResult = CryptAcquireContext( &hProv, A2CT(szKeyName), MS_DEF_PROV, PROV_RSA_FULL, CRYPT_MACHINE_KEYSET))) { DWORD dwError = GetLastError(); if(dwError == NTE_BAD_KEYSET || dwError == NTE_KEYSET_NOT_DEF) { bResult = CreateContainer(A2CT(szKeyName), &hProv); if(!bResult) goto onCleanup; } else goto onCleanup; }; ; if(!(bResult = CryptGetUserKey(hProv, AT_KEYEXCHANGE, &hExchangeKey))) { DWORD dwError = GetLastError(); if(dwError == NTE_NO_KEY) { bResult = CreateExchangeKeyPair(hProv, &hExchangeKey); if(!bResult) goto onCleanup; } else goto onCleanup; }; ; bResult = CryptGenKey(hProv, CALG_RC4, CRYPT_EXPORTABLE, &hSessionKey); if(!bResult) goto onCleanup; ; //determining size of output buffer is redundant because RC4 is a stream cipher but as general it's required DWORD dwTempBufferSize = nData; bResult = CryptEncrypt(hSessionKey, NULL, TRUE, 0, NULL, &dwTempBufferSize, dwTempBufferSize); if(!bResult) goto onCleanup; pTempBuffer = malloc(dwTempBufferSize); dwTempBuffer = nData; memcpy(pTempBuffer, pData, nData); bResult = CryptEncrypt(hSessionKey, NULL, TRUE, 0, (PBYTE)pTempBuffer, &dwTempBuffer, dwTempBufferSize); if(!bResult) goto onCleanup; ; bResult = CryptExportKey(hSessionKey, hExchangeKey, SIMPLEBLOB, 0, NULL, &dwSessionKeyBlob); if(!bResult) goto onCleanup; pSessionKeyBlob = malloc(dwSessionKeyBlob); bResult = CryptExportKey(hSessionKey, hExchangeKey, SIMPLEBLOB, 0, (PBYTE)pSessionKeyBlob, &dwSessionKeyBlob); if(!bResult) goto onCleanup; ; nResultBuffer = dwTempBuffer + dwSessionKeyBlob + sizeof(dwSessionKeyBlob) + sizeof(dwTempBuffer); pResultBuffer = malloc(nResultBuffer); PBYTE p = (PBYTE)pResultBuffer; memcpy(p, &dwSessionKeyBlob, sizeof(dwSessionKeyBlob)); p += sizeof(dwSessionKeyBlob); memcpy(p, pSessionKeyBlob, dwSessionKeyBlob); p += dwSessionKeyBlob; memcpy(p, &dwTempBuffer, sizeof(dwTempBuffer)); p += sizeof(dwTempBuffer); memcpy(p, pTempBuffer, dwTempBuffer); p += dwTempBuffer; _ASSERTE(p == nResultBuffer + PBYTE(pResultBuffer)); *ppData = pResultBuffer; *pnData = nResultBuffer; pResultBuffer = NULL; }; onCleanup: DWORD dwError = bResult ? 0 : GetLastError(); if(hSessionKey) CryptDestroyKey(hSessionKey); if(hExchangeKey) CryptDestroyKey(hExchangeKey); if(hProv) CryptReleaseContext(hProv, 0); Free(pTempBuffer, dwTempBuffer); Free(pSessionKeyBlob, dwSessionKeyBlob); Free(pResultBuffer, nResultBuffer); return (int)dwError; };
/****************************************************************************** * * Utils * * Low level helper routines for importing plain text keys in MS HKEY handle, * since MSCrypto API does not support import of plain text (session) keys * just like that. These functions are based upon MS kb article #228786 * and "Base Provider Key BLOBs" article for priv key blob format. * ******************************************************************************/ BOOL xmlSecMSCryptoCreatePrivateExponentOneKey(HCRYPTPROV hProv, HCRYPTKEY *hPrivateKey) { HCRYPTKEY hKey = 0; LPBYTE keyBlob = NULL; DWORD keyBlobLen; PUBLICKEYSTRUC* pubKeyStruc; RSAPUBKEY* rsaPubKey; DWORD bitLen; BYTE *ptr; int n; BOOL res = FALSE; xmlSecAssert2(hProv != 0, FALSE); xmlSecAssert2(hPrivateKey != NULL, FALSE); /* just in case */ *hPrivateKey = 0; /* Generate the private key */ if(!CryptGenKey(hProv, AT_KEYEXCHANGE, CRYPT_EXPORTABLE, &hKey)) { xmlSecMSCryptoError("CryptGenKey", NULL); goto done; } /* Export the private key, we'll convert it to a private exponent of one key */ if(!CryptExportKey(hKey, 0, PRIVATEKEYBLOB, 0, NULL, &keyBlobLen)) { xmlSecMSCryptoError("CryptExportKey", NULL); goto done; } keyBlob = (LPBYTE)xmlMalloc(sizeof(BYTE) * keyBlobLen); if(keyBlob == NULL) { xmlSecMallocError(sizeof(BYTE) * keyBlobLen, NULL); goto done; } if(!CryptExportKey(hKey, 0, PRIVATEKEYBLOB, 0, keyBlob, &keyBlobLen)) { xmlSecMSCryptoError("CryptExportKey", NULL); goto done; } CryptDestroyKey(hKey); hKey = 0; /* Get the bit length of the key */ if(keyBlobLen < sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY)) { xmlSecMSCryptoError2("CryptExportKey", NULL, "len=%ld", (long int)keyBlobLen); goto done; } pubKeyStruc = (PUBLICKEYSTRUC*)keyBlob; if(pubKeyStruc->bVersion != 0x02) { xmlSecMSCryptoError2("CryptExportKey", NULL, "pubKeyStruc->bVersion=%ld", (long int)pubKeyStruc->bVersion); goto done; } if(pubKeyStruc->bType != PRIVATEKEYBLOB) { xmlSecMSCryptoError2("CryptExportKey", NULL, "pubKeyStruc->bType=%ld", (long int)pubKeyStruc->bType); goto done; } /* aleksey: don't ask me why it is RSAPUBKEY, just don't ask */ rsaPubKey = (RSAPUBKEY*)(keyBlob + sizeof(PUBLICKEYSTRUC)); /* check that we have RSA private key */ if(rsaPubKey->magic != 0x32415352) { xmlSecMSCryptoError2("CryptExportKey", NULL, "rsaPubKey->magic=0x%08lx", (long int)rsaPubKey->magic); goto done; } bitLen = rsaPubKey->bitlen; /* Modify the Exponent in Key BLOB format Key BLOB format is documented in SDK */ rsaPubKey->pubexp = 1; /* Private-key BLOBs, type PRIVATEKEYBLOB, are used to store private keys outside a CSP. * Base provider private-key BLOBs have the following format: * * PUBLICKEYSTRUC publickeystruc ; * RSAPUBKEY rsapubkey; * BYTE modulus[rsapubkey.bitlen/8]; 1/8 * BYTE prime1[rsapubkey.bitlen/16]; 1/16 * BYTE prime2[rsapubkey.bitlen/16]; 1/16 * BYTE exponent1[rsapubkey.bitlen/16]; 1/16 * BYTE exponent2[rsapubkey.bitlen/16]; 1/16 * BYTE coefficient[rsapubkey.bitlen/16]; 1/16 * BYTE privateExponent[rsapubkey.bitlen/8]; 1/8 */ if(keyBlobLen < sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY) + bitLen / 2 + bitLen / 16) { xmlSecMSCryptoError2("CryptExportKey", NULL, "keBlobLen=%ld", keyBlobLen); goto done; } ptr = (BYTE*)(keyBlob + sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY)); /* Skip modulus, prime1, prime2 */ ptr += bitLen / 8; ptr += bitLen / 16; ptr += bitLen / 16; /* Convert exponent1 to 1 */ for (n = 0; n < (bitLen / 16); n++) { if (n == 0) ptr[n] = 1; else ptr[n] = 0; } ptr += bitLen / 16; /* Convert exponent2 to 1 */ for (n = 0; n < (bitLen / 16); n++) { if (n == 0) ptr[n] = 1; else ptr[n] = 0; } ptr += bitLen / 16; /* Skip coefficient */ ptr += bitLen / 16; /* Convert privateExponent to 1 */ for (n = 0; n < (bitLen / 16); n++) { if (n == 0) ptr[n] = 1; else ptr[n] = 0; } /* Import the exponent-of-one private key. */ if (!CryptImportKey(hProv, keyBlob, keyBlobLen, 0, 0, &hKey)) { xmlSecMSCryptoError("CryptImportKey", NULL); goto done; } (*hPrivateKey) = hKey; hKey = 0; res = TRUE; done: if(keyBlob != NULL) { xmlFree(keyBlob); } if (hKey != 0) { CryptDestroyKey(hKey); } return res; }
BOOL EncryptDecryptFile(LPTSTR lpszCertificateName, LPTSTR lpszCertificateStoreName, DWORD dwCertStoreOpenFlags, LPTSTR lpszInputFileName, LPTSTR lpszOutputFileName, BOOL fEncrypt) { BOOL fResult = FALSE; HCRYPTPROV hProv = NULL; HCRYPTKEY hRSAKey = NULL; HCRYPTKEY hSessionKey = NULL; HANDLE hInFile = INVALID_HANDLE_VALUE; HANDLE hOutFile = INVALID_HANDLE_VALUE; BOOL finished = FALSE; BYTE pbBuffer[OUT_BUFFER_SIZE]; DWORD dwByteCount = 0; DWORD dwBytesRead = 0; DWORD dwBytesWritten = 0; LPBYTE pbSessionKeyBlob = NULL; DWORD dwSessionKeyBlob = 0; BOOL fCallerFreeProv = FALSE; PCCERT_CONTEXT pCertContext = NULL; BOOL fSuccess = FALSE; __try { pCertContext = GetCertificateContextFromName(lpszCertificateName, lpszCertificateStoreName, dwCertStoreOpenFlags); if (pCertContext == NULL) { __leave; } fResult = AcquireAndGetRSAKey(pCertContext, &hProv, &hRSAKey, fEncrypt, &fCallerFreeProv); if (fResult == FALSE) { __leave; } // Open the input file to be encrypted or decrypted hInFile = CreateFile(lpszInputFileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hInFile == INVALID_HANDLE_VALUE) { MyPrintf(_T("CreateFile failed with %d\n"), GetLastError()); __leave; } // Open the output file to write the encrypted or decrypted data hOutFile = CreateFile(lpszOutputFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hOutFile == INVALID_HANDLE_VALUE) { MyPrintf(_T("CreateFile failed with %d\n"), GetLastError()); __leave; } if (fEncrypt) { fResult = CryptGenKey(hProv, CALG_RC4, CRYPT_EXPORTABLE, &hSessionKey); if (!fResult) { MyPrintf(_T("CryptGenKey failed with %X\n"), GetLastError()); __leave; } // The first call to ExportKey with NULL gets the key size. dwSessionKeyBlob = 0; fResult = CryptExportKey(hSessionKey, hRSAKey, SIMPLEBLOB, 0, NULL, &dwSessionKeyBlob); if (!fResult) { MyPrintf(_T("CryptExportKey failed with %X\n"), GetLastError()); __leave; } // Allocate memory for Encrypted Session key blob pbSessionKeyBlob = (LPBYTE)LocalAlloc(LPTR, dwSessionKeyBlob); if (!pbSessionKeyBlob) { MyPrintf(_T("LocalAlloc failed with %d\n"), GetLastError()); __leave; } fResult = CryptExportKey(hSessionKey, hRSAKey, SIMPLEBLOB, 0, pbSessionKeyBlob, &dwSessionKeyBlob); if (!fResult) { MyPrintf(_T("CryptExportKey failed with %X\n"), GetLastError()); __leave; } // Write the size of key blob, then the key blob itself, to output file. fResult = WriteFile(hOutFile, &dwSessionKeyBlob, sizeof(dwSessionKeyBlob), &dwBytesWritten, NULL); if (!fResult) { MyPrintf(_T("WriteFile failed with %d\n"), GetLastError()); __leave; } fResult = WriteFile(hOutFile, pbSessionKeyBlob, dwSessionKeyBlob, &dwBytesWritten, NULL); if (!fResult) { MyPrintf(_T("WriteFile failed with %d\n"), GetLastError()); __leave; } } else { // Read in key block size, then key blob itself from input file. fResult = ReadFile(hInFile, &dwByteCount, sizeof(dwByteCount), &dwBytesRead, NULL); if (!fResult) { MyPrintf(_T("ReadFile failed with %d\n"), GetLastError()); __leave; } fResult = ReadFile(hInFile, pbBuffer, dwByteCount, &dwBytesRead, NULL); if (!fResult) { MyPrintf(_T("ReadFile failed with %d\n"), GetLastError()); __leave; } // import key blob into "CSP" fResult = CryptImportKey(hProv, pbBuffer, dwByteCount, hRSAKey, 0, &hSessionKey); if (!fResult) { MyPrintf(_T("CryptImportKey failed with %X\n"), GetLastError()); __leave; } } do { dwByteCount = 0; // Now read data from the input file 64K bytes at a time. fResult = ReadFile(hInFile, pbBuffer, IN_BUFFER_SIZE, &dwByteCount, NULL); // If the file size is exact multiple of 64K, dwByteCount will be zero after // all the data has been read from the input file. In this case, simply break // from the while loop. The check to do this is below if (dwByteCount == 0) break; if (!fResult) { MyPrintf(_T("ReadFile failed with %d\n"), GetLastError()); __leave; } finished = (dwByteCount < IN_BUFFER_SIZE); // Encrypt/Decrypt depending on the required action. if (fEncrypt) { fResult = CryptEncrypt(hSessionKey, 0, finished, 0, pbBuffer, &dwByteCount, OUT_BUFFER_SIZE); if (!fResult) { MyPrintf(_T("CryptEncrypt failed with %X\n"), GetLastError()); __leave; } } else { fResult = CryptDecrypt(hSessionKey, 0, finished, 0, pbBuffer, &dwByteCount); if (!fResult) { MyPrintf(_T("CryptDecrypt failed with %X\n"), GetLastError()); __leave; } } // Write the encrypted/decrypted data to the output file. fResult = WriteFile(hOutFile, pbBuffer, dwByteCount, &dwBytesWritten, NULL); if (!fResult) { MyPrintf(_T("WriteFile failed with %d\n"), GetLastError()); __leave; } } while (!finished); if (fEncrypt) MyPrintf(_T("File %s is encrypted successfully!\n"), lpszInputFileName); else MyPrintf(_T("File %s is decrypted successfully!\n"), lpszInputFileName); fSuccess = TRUE; } __finally { /* Cleanup */ CheckAndLocalFree(pbSessionKeyBlob); if (pCertContext != NULL) CertFreeCertificateContext(pCertContext); if (hRSAKey != NULL) CryptDestroyKey(hRSAKey); if (hSessionKey != NULL) CryptDestroyKey(hSessionKey); if (fCallerFreeProv && hProv != NULL) CryptReleaseContext(hProv, 0); if (hInFile != INVALID_HANDLE_VALUE) CloseHandle(hInFile); if (hOutFile != INVALID_HANDLE_VALUE) CloseHandle(hOutFile); } return fSuccess; }
int main (int argc, char *argv[]) { DWORD dwProvType = 75; DWORD data_len = 0; BYTE *oid = NULL; DWORD dwBlobLen = 0; DWORD cAlg = (ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK | 31); LPCSTR SourceName = NULL; LPCSTR Psdw = NULL; HANDLE hCurrProc = GetCurrentProcess(); char patch[] = {0x80,0xbd,0x1c,0x00,0x00,0x00,0x98,0x75,0x07,0xc6,0x85,0x1c,0x00,0x00,0x00,0x9c,0x90,0x90,0x90,0x90,0x90,0x90}; ///!!! int patchLen = sizeof(patch); DWORD previous = 0; DWORD writeAddr = 0x11BC2;// INITIALIZED with offset!!! //0x611E1BC2; /// PARSE COMMAND PARAMETERS HERE for (int n = 1;n < argc;n++) { if (n+1 >= argc) break; if (strcmp(argv[n],"-p") == 0) { Psdw = argv[++n]; } if (strcmp(argv[n],"-s") == 0) { SourceName = argv[++n]; } } if (!Psdw || !SourceName) { printf("[!] Dude, u specified incorrect parameters :/\n\tUsage: %s -s <source container name> -p <container password>",argv[0]); exit(1); } if(!CryptAcquireContextA( &hProvResponder, "\\\\.\\Registry\\DestCopy", //Hardcoded name for container we create!!! NULL, dwProvType, CRYPT_NEWKEYSET | CRYPT_SILENT)) { HandleError("Error during CryptAcquireContext"); } if(!CryptAcquireContextA( &hProvSender, SourceName, NULL, dwProvType, 0)) { HandleError("Error during CryptAcquireContext"); } /// FIND ADDRESS TO PATCH HMODULE hModules[1024]; DWORD needed; if (EnumProcessModules(hCurrProc,hModules,1024,&needed)) { for (int i = 0; i < (needed / sizeof(HMODULE)); i++ ) { char szModName[1024]; if ( GetModuleFileNameA( hModules[i], szModName, sizeof(szModName))) { if (StrStrA(szModName, "cpcspi.dll")) { writeAddr += (DWORD)hModules[i]; printf("[+] Address in memory for patching is '%08X'.\n",writeAddr); break; } } } } /// !!! printf("[+] Now we patch process memory, patch size is '%i' bytes...",patchLen); VirtualProtectEx(hCurrProc, (void*)writeAddr, 2, PAGE_EXECUTE_READWRITE, &previous); WriteProcessMemory(hCurrProc, (void*)writeAddr, &patch, patchLen, NULL); printf("Ok\n"); printf("[+] Now we export container '%s'...\n",SourceName); if(!CryptGetProvParam( hProvSender, 92, NULL, &data_len, 0)) { HandleError("Error computing buffer length"); } oid = (BYTE *)malloc( data_len ); if( !oid ) HandleError("Out of memory."); if(!CryptGetProvParam( hProvSender, 92, oid, &data_len, 0)) { HandleError("Error during CryptGetProvParam"); } if(!CryptSetProvParam( hProvResponder, 92, oid, 0 )) { free( oid ); HandleError("Error during CryptSetProvParam"); } free( oid ); data_len = 0; if(!CryptGetProvParam( hProvSender, 93, NULL, &data_len, 0)) { HandleError("Error computing buffer length"); } /// SPECIFY PASSWORD FOR CONTAINER HERE if(!CryptSetProvParam( hProvSender,PP_SIGNATURE_PIN,(LPBYTE)Psdw,0)) { HandleError("Error during CryptSetProvParam"); } oid = (BYTE *)malloc( data_len ); if( !oid ) HandleError("Out of memory"); if(!CryptGetProvParam( hProvSender, 93, oid, &data_len, 0)) { free( oid ); HandleError("Error during CryptGetProvParam"); } if(!CryptSetProvParam( hProvResponder, 93, oid, 0 )) { free( oid ); HandleError("Error during CryptSetProvParam"); } free( oid ); if(!CryptGetUserKey( hProvSender, AT_KEYEXCHANGE, &hSenderKey )) { HandleError("Error during CryptGetUserKey private key"); } if(!CryptGenKey( hProvSender, (ALG_CLASS_KEY_EXCHANGE | ALG_TYPE_DH | 37), CRYPT_EXPORTABLE, &hSenderEphemKey)) { HandleError("ERROR -- CryptGenKey"); } if(!CryptGenKey( hProvResponder, (ALG_CLASS_KEY_EXCHANGE | ALG_TYPE_DH | 37), CRYPT_EXPORTABLE | CRYPT_PREGEN, &hResponderEphemKey)) { HandleError("ERROR -- CryptGenKey"); } if(!CryptGetKeyParam( hSenderEphemKey, 106, NULL, &dwBlobLen, 0)) { HandleError("Error computing BLOB length"); } pbKeyBlob = (BYTE*)malloc(dwBlobLen); if(!pbKeyBlob) HandleError("Out of memory"); if(!CryptGetKeyParam( hSenderEphemKey, 106, pbKeyBlob, &dwBlobLen, 0)) { HandleError("Error during CryptGetProvParam"); } if(!CryptSetKeyParam( hResponderEphemKey, 106, pbKeyBlob, 0)) { HandleError("Error during CryptSetProvParam"); } free(pbKeyBlob); pbKeyBlob = NULL; dwBlobLen = 0; if(!CryptSetKeyParam( hResponderEphemKey, KP_X, NULL, 0)) { HandleError("Error during CryptSetKeyParam"); } if(!CryptExportKey( hSenderEphemKey, 0, PUBLICKEYBLOB, 0, NULL, &dwBlobLen )) { HandleError("Error computing BLOB length"); } pbKeyBlob = (BYTE*)malloc(dwBlobLen); if(!pbKeyBlob) HandleError("Out of memory"); if(!CryptExportKey( hSenderEphemKey, 0, PUBLICKEYBLOB, 0, pbKeyBlob, &dwBlobLen )) { HandleError("Error during CryptExportKey"); } if(!CryptImportKey( hProvResponder, pbKeyBlob, dwBlobLen, hResponderEphemKey, 0, &hResponderAgreeKey)) { HandleError("Error during CryptImportKey ephemeral key"); } free(pbKeyBlob); pbKeyBlob = NULL; dwBlobLen = 0; if(!CryptExportKey( hResponderEphemKey, 0, PUBLICKEYBLOB, 0, NULL, &dwBlobLen )) { HandleError("Error computing BLOB length"); } pbKeyBlob = (BYTE*)malloc(dwBlobLen); if(!pbKeyBlob) HandleError("Out of memory"); if(!CryptExportKey( hResponderEphemKey, 0, PUBLICKEYBLOB, 0, pbKeyBlob, &dwBlobLen )) { HandleError("Error during CryptExportKey"); } if(!CryptImportKey( hProvSender, pbKeyBlob, dwBlobLen, hSenderEphemKey, 0, &hSenderAgreeKey)) { HandleError("Error during CryptImportKey ephemeral key"); } free(pbKeyBlob); pbKeyBlob = NULL; dwBlobLen = 0; if(!CryptSetKeyParam( hSenderAgreeKey, KP_ALGID, (BYTE*)&cAlg, 0 )) { HandleError("Error during CryptSetKeyParam agree key"); } if(!CryptSetKeyParam( hResponderAgreeKey, KP_ALGID, (BYTE*)&cAlg, 0 )) { HandleError("Error during CryptSetKeyParam agree key"); } if(!CryptExportKey( hSenderKey, hSenderAgreeKey, PRIVATEKEYBLOB, 0, NULL, &dwBlobLen )) { HandleError("Error computing BLOB length"); } pbKeyBlob = (BYTE*)malloc(dwBlobLen); if(!pbKeyBlob) HandleError("Out of memory"); if(!CryptExportKey( hSenderKey, hSenderAgreeKey, PRIVATEKEYBLOB, 0, pbKeyBlob, &dwBlobLen )) { HandleError("Error during CryptExportKey"); } if(!CryptImportKey( hProvResponder, pbKeyBlob, dwBlobLen, hResponderAgreeKey, 0, &hResponderKey)) { HandleError("Error during CryptImportKey private key"); } free(pbKeyBlob); pbKeyBlob = NULL; dwBlobLen = 0; if(!CryptGetKeyParam( hSenderKey, KP_CERTIFICATE, NULL, &dwBlobLen, 0)) { HandleError("Error computing BLOB length"); } pbKeyBlob = (BYTE*)malloc(dwBlobLen); if(!pbKeyBlob) { HandleError("Out of memory"); } if(!CryptGetKeyParam( hSenderKey, KP_CERTIFICATE, pbKeyBlob, &dwBlobLen, 0)) { HandleError("Error during CryptGetProvParam"); } if(!CryptSetKeyParam( hResponderKey, KP_CERTIFICATE, pbKeyBlob, 0)) { HandleError("Error during CryptSetProvParam"); } printf("[+] D0n3!!!\n"); CleanUp(); return 0; }
STDMETHODIMP FileEncrypter::EncryptFile(BSTR szInFN,BSTR szOutFN,BSTR szPwd){ if (!szInFN || _tcslen(szInFN)==0) { InfoMsgBox(_T("对不起,您必须提供待加密的文件名!")); return S_OK; } if (!szOutFN || _tcslen(szOutFN)==0) { InfoMsgBox(_T("对不起,您必须提供加密后的文件名!")); return S_OK; } FILE *hSource=0; FILE *hDestination=0; HCRYPTPROV hCryptProv; HCRYPTKEY hKey; HCRYPTKEY hXchgKey; HCRYPTHASH hHash; PBYTE pbKeyBlob; DWORD dwKeyBlobLen; PBYTE pbBuffer; DWORD dwBlockLen; DWORD dwBufferLen; DWORD dwCount; char* utf8Pwd=NULL; TCHAR msgTip[STRLEN_DEFAULT]={0}; _tfopen_s(&hSource,szInFN,_T("rb")); if(!hSource){ _stprintf_s(msgTip,_T("对不起,无法打开文件“%s”!"),szInFN); InfoMsgBox(msgTip); goto clean; } _tfopen_s(&hDestination,szOutFN,_T("wb")); if(!hDestination){ _stprintf_s(msgTip,_T("对不起,无法打开文件“%s”!"),szOutFN); InfoMsgBox(msgTip); goto clean; } TCHAR szContainerName[]=_T("f0d74c20-4a68-47d2-a1d2-7c622399ad48"); //TODO:容器名称为“test”? //初始化CSP上下文 if(CryptAcquireContext(&hCryptProv,szContainerName,PROVIDER_NAME,PROV_RSA_FULL,0)) { //正确初始化CSP } else { if(!CryptAcquireContext(&hCryptProv,szContainerName,PROVIDER_NAME,PROV_RSA_FULL,CRYPT_NEWKEYSET)){ InfoMsgBox(_T("对不起,无法初始化CSP上下文,请确认UKey是否插入电脑且工作正常,并安装了正确的驱动程序!")); goto clean; } } //如果没有提供密码 if(!szPwd || _tcslen(szPwd)==0){ if(!CryptGenKey(hCryptProv,ENCRYPT_ALGORITHM,CRYPT_EXPORTABLE, /*KEYLENGTH | CRYPT_EXPORTABLE, */&hKey)) { InfoMsgBox(_T("对不起,无法生成密钥,请确认UKey是否插入电脑且工作正常,并安装了正确的驱动程序!")); goto clean; } if(CryptGetUserKey(hCryptProv,AT_KEYEXCHANGE,&hXchgKey)){ //公钥被成功获取 } else{ CryptGenKey(hCryptProv,AT_KEYEXCHANGE,0,&hXchgKey); } if(!CryptExportKey(hKey,hXchgKey,SIMPLEBLOB, 0,NULL, &dwKeyBlobLen)){ InfoMsgBox(_T("对不起,无法获取密钥块,请确认UKey是否插入电脑且工作正常,并安装了正确的驱动程序!")); goto clean; } if(!(pbKeyBlob =(BYTE *)malloc(dwKeyBlobLen))) { InfoMsgBox(_T("对不起,无法为密钥块分配内存!")); goto clean; } if(!CryptExportKey(hKey,hXchgKey,SIMPLEBLOB,0, pbKeyBlob, &dwKeyBlobLen)){ InfoMsgBox(_T("对不起,无法为导出密钥!")); goto clean; } CryptDestroyKey(hXchgKey); hXchgKey = 0; fwrite(&dwKeyBlobLen, sizeof(DWORD), 1, hDestination); if(ferror(hDestination)) { InfoMsgBox(_T("无法写入输出文件!")); goto clean; } fwrite(pbKeyBlob, 1, dwKeyBlobLen, hDestination); if(ferror(hDestination)) { InfoMsgBox(_T("无法写入输出文件!")); goto clean; } } else{ //提供了密码 if(!CryptCreateHash(hCryptProv,CALG_MD5, 0,0,&hHash)) { InfoMsgBox(_T("无法创建哈希!")); goto clean; } int keyLen=FromUTF16(szPwd,NULL,0); if (keyLen>0) keyLen+=1; utf8Pwd=new char[keyLen]; FromUTF16(szPwd,utf8Pwd,keyLen); if(!CryptHashData( hHash, (BYTE *)utf8Pwd, keyLen-1, 0)) { InfoMsgBox(_T("无法创建密码哈希值!")); goto clean; } if(!CryptDeriveKey( hCryptProv,ENCRYPT_ALGORITHM, hHash, KEYLENGTH, &hKey)) { InfoMsgBox(_T("无法从哈希值创建密钥!")); goto clean; } CryptDestroyHash(hHash); hHash = 0; } dwBlockLen = 1024 - 1024 % ENCRYPT_BLOCK_SIZE; if(ENCRYPT_BLOCK_SIZE > 1) dwBufferLen = dwBlockLen + ENCRYPT_BLOCK_SIZE; else dwBufferLen = dwBlockLen; if(!(pbBuffer = (BYTE *)malloc(dwBufferLen))) { InfoMsgBox(_T("对不起,无法为缓冲区分配内存!")); goto clean; } //循环读取源文件的数据然后加密数据并把结果写入目标文件 do { dwCount = fread(pbBuffer, 1, dwBlockLen, hSource); if(ferror(hSource)) { InfoMsgBox(_T("对不起,无法读取待加密文件数据!")); goto clean; } if(!CryptEncrypt(hKey,0,feof(hSource),0,pbBuffer,&dwCount,dwBufferLen)) { InfoMsgBox(_T("加密过程出现错误!")); goto clean; } fwrite(pbBuffer, 1, dwCount, hDestination); if(ferror(hDestination)) { InfoMsgBox(_T("对不起,无法写入加密后的数据到目标文件!")); goto clean; } } while(!feof(hSource)); InfoMsgBox(_T("加密成功!")); //资源释放 clean: if(utf8Pwd) delete[] utf8Pwd; if(hSource) fclose(hSource); if(hDestination) fclose(hDestination); if(pbBuffer) free(pbBuffer); if(hKey) CryptDestroyKey(hKey); if(hXchgKey) CryptDestroyKey(hXchgKey); if(hHash) CryptDestroyHash(hHash); if(hCryptProv) CryptReleaseContext(hCryptProv, 0); return S_OK; }
static BOOL decodeSK( BOOL aes256, DWORD keylen, BYTE *keybuf ) { BYTE buffer[ 1024 ]; DWORD i, size, length; struct skb { PUBLICKEYSTRUC hdr; ALG_ID algId; BYTE key[1]; } *expKey = (struct skb *)buffer; struct ptkb { PUBLICKEYSTRUC hdr; DWORD keysize; BYTE key[1]; } *txtKey = (struct ptkb *)buffer; length = (expKey->key - buffer) + keylen; if ( length > sizeof( buffer ) ) { fprintf( stderr, "CryptImportKey() requires %d bytes\n", length ); return( FALSE ); } expKey->hdr.bType = SIMPLEBLOB; expKey->hdr.bVersion = CUR_BLOB_VERSION; expKey->hdr.reserved = 0; expKey->hdr.aiKeyAlg = aes256 ? SessKey256 : SessKey128; expKey->algId = XchgKeyType; /* ** NOTE: it appears that the encoded key is byte swapped compared ** to external standards. There is a cryptic reference to a ** ReverseMemCopy() function in the RSA/SChannel server master ** key creation example. Also, the internal RSA modulus is ** byte swapped compared to the X509 encoding. This swap is ** required to interoperate with JavaSSE. */ for( i = 0; i < keylen; i++ ) expKey->key[i] = keybuf[ keylen - i - 1 ]; if ( ! CryptImportKey( provider, (BYTE *)expKey, length, xchgKey, CRYPT_EXPORTABLE, &sessKey ) ) { fprintf( stderr, "CryptImportKey() failed: 0x%x\n", GetLastError() ); return( FALSE ); } if ( ! CryptSetKeyParam( sessKey, KP_MODE, (BYTE *)&sessKeyMode, 0 ) ) { fprintf( stderr, "CryptSetKeyParam() MODE failed: 0x%x\n", GetLastError() ); return( 0 ); } if ( ! CryptSetKeyParam( sessKey, KP_PADDING, (BYTE *)&sessKeyPadding, 0 ) ) { fprintf( stderr, "CryptSetKeyParam() PADDING failed: 0x%x\n", GetLastError() ); return( 0 ); } if ( sessKeyMode == CRYPT_MODE_CBC ) { size = sizeof( length ); if ( ! CryptGetKeyParam( sessKey, KP_BLOCKLEN, (BYTE *)&length, &size, 0 ) ) { fprintf( stderr, "CryptGetKeyParam() BLOCKLEN failed: 0x%x\n", GetLastError() ); exit( 1 ); } length /= 8; /* Bits -> bytes */ for( i = 0; i < length; i++ ) buffer[i] = 0; if ( ! CryptSetKeyParam( sessKey, KP_IV, buffer, 0 ) ) { fprintf( stderr, "CryptSetKeyParam() PADDING failed: 0x%x\n", GetLastError() ); return( 0 ); } } if ( verbose ) { if ( ! CryptExportKey( sessKey, 0, PLAINTEXTKEYBLOB, 0, NULL, &size ) ) { fprintf( stderr, "CryptExportKey() [1] failed: 0x%x\n", GetLastError() ); return( FALSE ); } if ( size > sizeof( buffer ) ) { fprintf( stderr, "CryptExportKey() requires %d bytes\n", size ); return( FALSE ); } length = sizeof( buffer ); if ( ! CryptExportKey( sessKey, 0, PLAINTEXTKEYBLOB, 0, (BYTE *)txtKey, &length ) ) { fprintf( stderr, "CryptExportKey() [2] failed: 0x%x\n", GetLastError() ); return( FALSE ); } printf( "Sess Key: \n" ); hexDump( txtKey->keysize, txtKey->key ); keyInfo( sessKey ); } return( TRUE ); }
BOOL EncryptData(char *buffer, char **encrData,DWORD *dwBufferSize) { HCRYPTPROV hProv = 0; HCRYPTKEY hKey = 0; HCRYPTKEY hXchgKey = 0; BYTE *pbBuffer; DWORD dwCount; DWORD dwBlobLen; BOOL res; DWORD srcIndex=0,destIndex,actSize; DWORD error; // Get a handle to the default provider. //if(!(res=CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, 0))) { if(FALSE == (res=CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, 0))) { if((GetLastError()==NTE_KEYSET_NOT_DEF)||(GetLastError()==NTE_BAD_KEYSET)) res=CreateKeyset(&hProv); } if(!res) { goto done; } res=FALSE; // Get a handle to key exchange key. if(!CryptGetUserKey(hProv, AT_KEYEXCHANGE, &hXchgKey)) { //Si DWORD errcode = GetLastError(); if ( errcode == NTE_NO_KEY) { //create key exchange key pair if (! CryptGenKey(hProv,AT_KEYEXCHANGE,0,&hXchgKey)) { goto done; } } else { SetLastError(errcode); goto done; } } // Create a random block cipher session key. if(!CryptGenKey(hProv, CALG_RC4, CRYPT_EXPORTABLE, &hKey)) { goto done; } // Determine the size of the key blob and allocate memory. CryptExportKey(hKey, hXchgKey, SIMPLEBLOB, 0, NULL, &dwBlobLen); actSize=dwBlobLen+sizeof(DWORD)+*dwBufferSize+64; if((pbBuffer = (PBYTE)malloc(actSize)) == NULL) goto done; *(DWORD*)pbBuffer=dwBlobLen; // Export the key into a simple key blob. if(!CryptExportKey(hKey, hXchgKey, SIMPLEBLOB, 0, pbBuffer+sizeof(DWORD),&dwBlobLen)) { free(pbBuffer); goto done; } destIndex=dwBlobLen+sizeof(DWORD); while(srcIndex<*dwBufferSize) { dwCount = min(BLOCK_SIZE,*dwBufferSize-srcIndex); memcpy(pbBuffer+destIndex,buffer+srcIndex,dwCount); srcIndex+=dwCount; if(actSize<destIndex) { pbBuffer=(PBYTE)realloc(pbBuffer,2*destIndex); actSize=2*destIndex; } if(!CryptEncrypt(hKey, 0, srcIndex>=*dwBufferSize, 0, pbBuffer+destIndex, &dwCount, actSize-destIndex)) { free(pbBuffer); *dwBufferSize=0; *encrData = 0; goto done; } destIndex+=dwCount; } res=TRUE; *dwBufferSize=destIndex; *encrData=(char*)pbBuffer; done: error=GetLastError(); // Destroy the session key. if(hKey != 0) CryptDestroyKey(hKey); // Destroy the key exchange key. if(hXchgKey != 0) CryptDestroyKey(hXchgKey); // Release the provider handle. if(hProv != 0) CryptReleaseContext(hProv, 0); //if(pbBuffer) free(pbBuffer); SetLastError(error); return res; }
static BOOL initCrypt() { BYTE buffer[ 1024 ]; DWORD size, flags; if ( ! CryptAcquireContext( &provider, NULL, NULL, ProvType, CRYPT_VERIFYCONTEXT ) ) { fprintf( stderr, "CryptAcquireContext() failed: 0x%x\n", GetLastError() ); return( FALSE ); } if ( ! CryptGenKey( provider, XchgKeyType, XchgKeyFlags, &xchgKey ) ) { fprintf( stderr, "CryptGenKey() failed: 0x%x\n", GetLastError() ); return( FALSE ); } for( flags = CRYPT_FIRST; ; flags = CRYPT_NEXT ) { PROV_ENUMALGS_EX *info = (PROV_ENUMALGS_EX *)buffer; size = sizeof( buffer ); if ( ! CryptGetProvParam( provider, PP_ENUMALGS_EX, buffer, &size, flags ) ) { DWORD status = GetLastError(); if ( status == ERROR_NO_MORE_ITEMS ) break; fprintf( stderr, "CryptGetProvParam() failed: 0x%x\n", GetLastError() ); return( FALSE ); } switch( info->aiAlgid ) { case CALG_RSA_KEYX : rsaMaxKey = max( rsaMaxKey, info->dwMaxLen ); break; case CALG_AES_128 : case CALG_AES_192 : case CALG_AES_256 : aesMaxKey = max( aesMaxKey, info->dwMaxLen ); break; } } if ( verbose ) { struct pkb { PUBLICKEYSTRUC hdr; RSAPUBKEY rsa; BYTE mod[1]; } *rsaKey= (struct pkb *)buffer; printf( "RSA Max Key Length: %d\n", rsaMaxKey ); printf( "AES Max Key Length: %d\n", aesMaxKey ); if ( ! CryptExportKey( xchgKey, 0, PUBLICKEYBLOB, 0, NULL, &size ) ) { fprintf( stderr, "CryptExportKey() [1] failed: 0x%x\n", GetLastError() ); return( FALSE ); } if ( size > sizeof( buffer ) ) { fprintf( stderr, "CryptExportKey() requires %d bytes\n", size ); return( FALSE ); } size = sizeof( buffer ); if ( ! CryptExportKey( xchgKey, 0, PUBLICKEYBLOB, 0, (BYTE *)rsaKey, &size ) ) { fprintf( stderr, "CryptExportKey() [2] failed: 0x%x\n", GetLastError() ); return( FALSE ); } printf( "Xchg Exp: %d\n", rsaKey->rsa.pubexp ); printf( "Xchg Mod: \n" ); hexDump( rsaKey->rsa.bitlen / 8, rsaKey->mod ); } if ( rsaMaxKey < 1024 || aesMaxKey < 128 ) { fprintf( stderr, "Invalid minimum key length\n" ); return( FALSE ); } return( TRUE ); }
static BOOL CAPIEncryptFile(PCHAR szSource, PCHAR szDestination, PCHAR szPassword) { FILE *hSource = NULL; FILE *hDestination = NULL; errno_t err; INT eof = 0; HCRYPTPROV hProv = 0; HCRYPTKEY hKey = 0; HCRYPTKEY hXchgKey = 0; HCRYPTHASH hHash = 0; PBYTE pbKeyBlob = NULL; DWORD dwKeyBlobLen; PBYTE pbBuffer = NULL; DWORD dwBlockLen; DWORD dwBufferLen; DWORD dwCount; BOOL status = FALSE; // Open source file. err=fopen_s(&hSource,szSource,"rb"); if(err !=0) { printf("Error opening Plaintext file!\n"); goto done; } // Open destination file. err=fopen_s(&hDestination,szDestination,"wb"); if(err != 0){ printf("Error opening Ciphertext file!\n"); goto done; } // Get handle to the CSP. In order to be used with different OSs // with different default provides, the CSP is explicitly set. // If the Microsoft Enhanced Provider is not installed, set parameter // three to MS_DEF_PROV if(!CryptAcquireContext(&hProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, 0)) { printf("Error %x during CryptAcquireContext!\n", GetLastError()); goto done; } if(szPassword == NULL) { // Encrypt the file with a random session key. // Create a random session key. if(!CryptGenKey(hProv, ENCRYPT_ALGORITHM, KEYLENGTH | CRYPT_EXPORTABLE, &hKey)) { printf("Error %x during CryptGenKey!\n", GetLastError()); goto done; } // Get handle to key exchange public key. if(!CryptGetUserKey(hProv, AT_KEYEXCHANGE, &hXchgKey)) { printf("Error %x during CryptGetUserKey!\n", GetLastError()); goto done; } // Determine size of the key blob and allocate memory. if(!CryptExportKey(hKey, hXchgKey, SIMPLEBLOB, 0, NULL, &dwKeyBlobLen)) { printf("Error %x computing blob length!\n", GetLastError()); goto done; } if((pbKeyBlob = (unsigned char *) malloc(dwKeyBlobLen)) == NULL) { printf("Out of memory!\n"); goto done; } // Export session key into a simple key blob. if(!CryptExportKey(hKey, hXchgKey, SIMPLEBLOB, 0, pbKeyBlob, &dwKeyBlobLen)) { printf("Error %x during CryptExportKey!\n", GetLastError()); goto done; } // Release key exchange key handle. CryptDestroyKey(hXchgKey); hXchgKey = 0; // Write size of key blob to destination file. fwrite(&dwKeyBlobLen, sizeof(DWORD), 1, hDestination); if(ferror(hDestination)) { printf("Error writing header!\n"); goto done; } // Write key blob to destination file. fwrite(pbKeyBlob, 1, dwKeyBlobLen, hDestination); if(ferror(hDestination)) { printf("Error writing header!\n"); goto done; } } else { // Encrypt the file with a session key derived from a password. // Create a hash object. if(!CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash)) { printf("Error %x during CryptCreateHash!\n", GetLastError()); goto done; } // Hash in the password data. if(!CryptHashData(hHash, (const unsigned char *)szPassword, (DWORD)strlen(szPassword), 0)) { printf("Error %x during CryptHashData!\n", GetLastError()); goto done; } // Derive a session key from the hash object. if(!CryptDeriveKey(hProv, ENCRYPT_ALGORITHM, hHash, KEYLENGTH, &hKey)) { printf("Error %x during CryptDeriveKey!\n", GetLastError()); goto done; } // Destroy the hash object. CryptDestroyHash(hHash); hHash = 0; } // Determine number of bytes to encrypt at a time. This must be a multiple // of ENCRYPT_BLOCK_SIZE. dwBlockLen = 1000 - 1000 % ENCRYPT_BLOCK_SIZE; // Determine the block size. If a block cipher is used this must have // room for an extra block. #ifdef USE_BLOCK_CIPHER dwBufferLen = dwBlockLen + ENCRYPT_BLOCK_SIZE; #else dwBufferLen = dwBlockLen; #endif // Allocate memory. if((pbBuffer = (unsigned char *) malloc(dwBufferLen)) == NULL) { printf("Out of memory!\n"); goto done; } // Encrypt source file and write to Source file. do { // Read up to 'dwBlockLen' bytes from source file. dwCount = (DWORD)fread(pbBuffer, 1, dwBlockLen, hSource); if(ferror(hSource)) { printf("Error reading Plaintext!\n"); goto done; } eof = feof(hSource); // Encrypt data if(!CryptEncrypt(hKey, 0, eof, 0, pbBuffer, &dwCount, dwBufferLen)) { printf("bytes required:%d\n",dwCount); printf("Error %x during CryptEncrypt!\n", GetLastError()); goto done; } // Write data to destination file. fwrite(pbBuffer, 1, dwCount, hDestination); if(ferror(hDestination)) { printf("Error writing Ciphertext!\n"); goto done; } } while(!feof(hSource)); status = TRUE; printf("OK\n"); done: // Close files. if(hSource) fclose(hSource); if(hDestination) fclose(hDestination); // Free memory. if(pbKeyBlob) free(pbKeyBlob); if(pbBuffer) free(pbBuffer); // Destroy session key. if(hKey) CryptDestroyKey(hKey); // Release key exchange key handle. if(hXchgKey) CryptDestroyKey(hXchgKey); // Destroy hash object. if(hHash) CryptDestroyHash(hHash); // Release provider handle. if(hProv) CryptReleaseContext(hProv, 0); return(status); }
BOOL CreatePrivateExponentOneKey(LPTSTR szProvider, DWORD dwProvType, LPTSTR szContainer, DWORD dwKeySpec, HCRYPTPROV *hProv, HCRYPTKEY *hPrivateKey) { BOOL fReturn = FALSE; BOOL fResult; int n; LPBYTE keyblob = NULL; DWORD dwkeyblob; DWORD dwBitLen; BYTE *ptr; __try { *hProv = 0; *hPrivateKey = 0; if ((dwKeySpec != AT_KEYEXCHANGE) && (dwKeySpec != AT_SIGNATURE)) __leave; // Try to create new container fResult = CryptAcquireContext(hProv, szContainer, szProvider, dwProvType, CRYPT_NEWKEYSET); if (!fResult) { // If the container exists, open it if (GetLastError() == NTE_EXISTS) { fResult = CryptAcquireContext(hProv, szContainer, szProvider, dwProvType, 0); if (!fResult) { // No good, leave __leave; } } else { // No good, leave __leave; } } // Generate the private key fResult = CryptGenKey(*hProv, dwKeySpec, CRYPT_EXPORTABLE, hPrivateKey); if (!fResult) __leave; // Export the private key, we'll convert it to a private // exponent of one key fResult = CryptExportKey(*hPrivateKey, 0, PRIVATEKEYBLOB, 0, NULL, &dwkeyblob); if (!fResult) __leave; keyblob = (LPBYTE)LocalAlloc(LPTR, dwkeyblob); if (!keyblob) __leave; fResult = CryptExportKey(*hPrivateKey, 0, PRIVATEKEYBLOB, 0, keyblob, &dwkeyblob); if (!fResult) __leave; CryptDestroyKey(*hPrivateKey); *hPrivateKey = 0; // Get the bit length of the key memcpy(&dwBitLen, &keyblob[12], 4); // Modify the Exponent in Key BLOB format // Key BLOB format is documented in SDK // Convert pubexp in rsapubkey to 1 ptr = &keyblob[16]; for (n = 0; n < 4; n++) { if (n == 0) ptr[n] = 1; else ptr[n] = 0; } // Skip pubexp ptr += 4; // Skip modulus, prime1, prime2 ptr += (dwBitLen/8); ptr += (dwBitLen/16); ptr += (dwBitLen/16); // Convert exponent1 to 1 for (n = 0; n < (dwBitLen/16); n++) { if (n == 0) ptr[n] = 1; else ptr[n] = 0; } // Skip exponent1 ptr += (dwBitLen/16); // Convert exponent2 to 1 for (n = 0; n < (dwBitLen/16); n++) { if (n == 0) ptr[n] = 1; else ptr[n] = 0; } // Skip exponent2, coefficient ptr += (dwBitLen/16); ptr += (dwBitLen/16); // Convert privateExponent to 1 for (n = 0; n < (dwBitLen/8); n++) { if (n == 0) ptr[n] = 1; else ptr[n] = 0; } // Import the exponent-of-one private key. if (!CryptImportKey(*hProv, keyblob, dwkeyblob, 0, 0, hPrivateKey)) { __leave; } fReturn = TRUE; } __finally { if (keyblob) LocalFree(keyblob); if (!fReturn) { if (*hPrivateKey) CryptDestroyKey(*hPrivateKey); if (*hProv) CryptReleaseContext(*hProv, 0); } } return fReturn; }
HRESULT CPkcs10::put_PublicKey(HCRYPTPROV hprov, DWORD dwKeySpec) // Store the indicated public key in the subjectPublicKeyInfo field // of the CertificationRequest. From PKCS #10: // // subjectPublicKeyInfo contains information about the public // key being certified. The information identifies the entity's // public-key algorithm (and any associated parameters); examples // of public-key algorithms include X.509's rsa and PKCS #1's // rsaEncryption. // // The information also includes a bit-string representation of // the entity's public key. For both public-key algorithms just // mentioned, the bit string contains the BER encoding of a // value of X.509/PKCS #1 type RSAPublicKey // { HRESULT hr = m_pworld->HprovToSubjectPublicKeyInfo( hprov, dwKeySpec, m_preq->certificationRequestInfo.subjectPublicKeyInfo ); #if defined(_DEBUG) // Check to to make sure we can read what we wrote if (hr==S_OK) { HCRYPTKEY hkeyuser; VERIFY(CryptGetUserKey(hprov, dwKeySpec, &hkeyuser)); BYTE rgb1[1024]; DWORD cb1 = 1024; // BYTE rgb2[1024]; DWORD cb2 = 1024; VERIFY(CryptExportKey(hkeyuser, 0, PUBLICKEYBLOB, 0, rgb1, &cb1)); // VERIFY(CryptExportKey(hkeypub, 0, PUBLICKEYBLOB, 0, rgb2, &cb2)); // Would like to do the above, but CAPI won't let us export an imported key // (*(&(*##$^*&. So, having verified we can successfully fully import, we just // go get the raw bits again. BLOB b; m_pworld->Init(b); HCRYPTKEY hkeypub; if (get_PublicKey(hprov, &hkeypub) == S_OK) { VERIFY(CryptDestroyKey(hkeypub)); } else OutputDebugString("DigSig: Public key retrieval failed\n"); VERIFY(m_pworld->PublicKeyBlobFromBitString(m_preq->certificationRequestInfo.subjectPublicKeyInfo, dwKeySpec, &b) == S_OK); DWORD cb2 = b.cbSize; BYTE* rgb2 = b.pBlobData; VERIFY(cb1 == cb2); if (cb1 != cb2) { cb1 = min(cb1,cb2); cb2 = cb1; } ((PUBLICKEYSTRUC*)rgb1)->reserved = 0; ((PUBLICKEYSTRUC*)rgb2)->reserved = 0; VERIFY(memcmp(rgb1, rgb2, cb1) == 0); VERIFY(CryptDestroyKey(hkeyuser)); m_pworld->Free(b); } #endif MakeDirty(); return hr; }
int _tmain(int argc, _TCHAR* argv[]) { //-------------------------------------------------------------------- // Declare and initialize variables. HCERTSTORE hCertStore = NULL; PCCERT_CONTEXT pCertContext = NULL; TCHAR * pszStoreName = TEXT("MY"); HCRYPTKEY hKey = NULL; HCRYPTPROV hProv = NULL; DWORD dwKeySpec = 0; BOOL bCallerFreeProv = FALSE; HCRYPTHASH hHash; DWORD dwSigLen= 0; BYTE * pbSignature = NULL; //------------------------------------------------------------- // Declare and initialize variables. BYTE *pbBuffer= (BYTE *)"The data that is to be hashed and signed."; DWORD dwBufferLen = strlen((char *)pbBuffer)+1; //-------------------------------------------------------------------- // Open a certificate store. if ( hCertStore = CertOpenSystemStore( NULL, pszStoreName)) { fprintf(stderr,"The store has been opened.\n"); } else { printf("Unable to open store.\n"); goto err; } //-------------------------------------------------------------------- // Display a list of the certificates in the store and // allow the user to select a certificate. if(!(pCertContext = CryptUIDlgSelectCertificateFromStore( hCertStore, // Open the store that contains the certificates to // display NULL, NULL, NULL, CRYPTUI_SELECT_LOCATION_COLUMN, 0, NULL))) { printf("Select Certificate UI failed.\n" ); goto err; } #if 1 //获取CSP句柄 if (!CryptAcquireCertificatePrivateKey(pCertContext, 0, NULL, &hProv, &dwKeySpec, &bCallerFreeProv)) { printf("CryptAcquireCertificatePrivateKey failed.\n" ); goto err; } //获取密钥句柄 if(!CryptGetUserKey(hProv, dwKeySpec, &hKey)) { printf("CryptGetUserKey failed.\n" ); goto err; } //-------------------------------------------------------------------- // Acquire a hash object handle. if(CryptCreateHash( hProv, CALG_MD5, 0, 0, &hHash)) { printf("An empty hash object has been created. \n"); } else { printf("Error during CryptBeginHash!\n"); goto err; } //-------------------------------------------------------------------- // This code assumes that the handle of a cryptographic context // has been acquired and that a hash object has been created // and its handle (hHash) is available. if(CryptHashData( hHash, pbBuffer, dwBufferLen, 0)) { printf("The data buffer has been added to the hash.\n"); } else { printf("Error during CryptHashData.\n"); goto err; } //-------------------------------------------------------------------- // Determine the size of the signature and allocate memory. dwSigLen= 0; if(CryptSignHash( hHash, dwKeySpec, NULL, 0, NULL, &dwSigLen)) { printf("Signature length %d found.\n",dwSigLen); } else { printf("Error during CryptSignHash\n"); goto err; } //-------------------------------------------------------------------- // Allocate memory for the signature buffer. if(pbSignature = (BYTE *)malloc(dwSigLen)) { printf("Memory allocated for the signature.\n"); } else { printf("Out of memory\n"); goto err; } //-------------------------------------------------------------------- // Sign the hash object. if(CryptSignHash( hHash, dwKeySpec, NULL, 0, pbSignature, &dwSigLen)) { printf("pbSignature is the hash signature.\n"); } else { printf("Error during CryptSignHash.\n"); goto err; } { DWORD dwBlobLen = 0; BYTE * pbKeyBlob = 0; HCRYPTKEY hPubKey = 0; if(CryptExportKey( hKey, NULL, PUBLICKEYBLOB, //导出公钥 0, NULL, &dwBlobLen)) //返回密钥数据长度 { printf("Size of the BLOB for the public key determined. \n"); } else { printf("Error computing BLOB length.\n"); goto err; } if(pbKeyBlob = (BYTE*)malloc(dwBlobLen)) { printf("Memory has been allocated for the BLOB. \n"); } else { printf("Out of memory. \n"); goto err; } if(CryptExportKey( hKey, NULL, PUBLICKEYBLOB, 0, pbKeyBlob, //返回密钥数据 &dwBlobLen)) //导出的密钥数据的长度 { printf("Contents have been written to the BLOB. \n"); } else { printf("Error exporting key.\n"); goto err; } if(CryptImportKey(hProv,pbKeyBlob, dwBlobLen, NULL, 0, &hPubKey)) { printf("CryptImportKey OK. \n"); } else { printf("Error CryptImportKey.\n"); goto err; } if(CryptVerifySignature(hHash, pbSignature, dwSigLen,hPubKey,NULL,0)) { printf("verify OK.\n"); } else { printf("Error during CryptVerifySignature.\n"); goto err; } } if(CryptVerifySignature(hHash, pbSignature, dwSigLen,hKey,NULL,0)) { printf("verify OK.\n"); } else { printf("Error during CryptVerifySignature.\n"); goto err; } #endif BYTE* pbMessage = (BYTE*)"CryptoAPI is a good way to handle security"; DWORD cbMessage = strlen((char*) pbMessage)+1; //证书的上下文 CRYPT_SIGN_MESSAGE_PARA SigParams; DWORD cbSignedMessageBlob; BYTE *pbSignedMessageBlob; DWORD cbDecodedMessageBlob; BYTE *pbDecodedMessageBlob; CRYPT_VERIFY_MESSAGE_PARA VerifyParams; const BYTE* MessageArray[] = {pbMessage}; DWORD MessageSizeArray[1]; MessageSizeArray[0] = cbMessage; printf("Begin processing. \n"); printf(" The message to be signed is\n-> %s.\n",pbMessage); //-------------------------------------------------------------------- //初始化签名结构 SigParams.cbSize = sizeof(CRYPT_SIGN_MESSAGE_PARA); SigParams.dwMsgEncodingType = (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING); SigParams.pSigningCert = pCertContext; SigParams.HashAlgorithm.pszObjId = szOID_RSA_MD5; SigParams.HashAlgorithm.Parameters.cbData = NULL; SigParams.cMsgCert = 1; SigParams.rgpMsgCert = &pCertContext; SigParams.cAuthAttr = 0; SigParams.dwInnerContentType = 0; SigParams.cMsgCrl = 0; SigParams.cUnauthAttr = 0; SigParams.dwFlags = 0; SigParams.pvHashAuxInfo = NULL; SigParams.rgAuthAttr = NULL; //首先得到BLOB的大小 if(CryptSignMessage( &SigParams, // Signature parameters FALSE, // Not detached 1, // Number of messages MessageArray, // Messages to be signed MessageSizeArray, // Size of messages NULL, // Buffer for signed message &cbSignedMessageBlob)) // Size of buffer { printf("The size of the BLOB is %d.\n",cbSignedMessageBlob); } else { printf("Getting signed BLOB size failed"); } //-------------------------------------------------------------------- //分配BLOB的内存. if(!(pbSignedMessageBlob = (BYTE*)malloc(cbSignedMessageBlob))) { printf("Memory allocation error while signing."); } if(CryptSignMessage( &SigParams, // FALSE, // 1, //消息数量 MessageArray, //待签名的消息 MessageSizeArray, //消息大小 pbSignedMessageBlob, //缓冲区 &cbSignedMessageBlob)) //缓冲区大小 { printf("The message was signed successfully. \n"); } else { printf("Error getting signed BLOB"); } //-------------------------------------------------------------------- //验证签名信息 //-------------------------------------------------------------------- //初始化VerifyParams结构. VerifyParams.cbSize = sizeof(CRYPT_VERIFY_MESSAGE_PARA); VerifyParams.dwMsgAndCertEncodingType = (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING); VerifyParams.hCryptProv = 0; VerifyParams.pfnGetSignerCertificate = NULL; VerifyParams.pvGetArg = NULL; if(CryptVerifyMessageSignature( &VerifyParams, //. 0, // pbSignedMessageBlob, //. cbSignedMessageBlob, // NULL, // &cbDecodedMessageBlob, // NULL)) // Pointer to signer certificate. { printf("%d bytes need for the buffer.\n",cbDecodedMessageBlob); } else { printf("Verification message failed. \n"); } //为缓冲区分配内存. if(!(pbDecodedMessageBlob = (BYTE*)malloc(cbDecodedMessageBlob))) { printf("Memory allocation error allocating decode BLOB."); } //得到缓冲区的大小 if(CryptVerifyMessageSignature( &VerifyParams, // Verify parameters. 0, // Signer index. pbSignedMessageBlob, // Pointer to signed BLOB. cbSignedMessageBlob, // Size of signed BLOB. pbDecodedMessageBlob, // Buffer for decoded message. &cbDecodedMessageBlob, // Size of buffer. NULL)) // Pointer to signer certificate. { printf("The verified message is \n-> %s \n",pbDecodedMessageBlob); } else { printf("Verification message failed. \n"); } err: WTF_PrintErrorMsg(); if(pbSignedMessageBlob) { free(pbSignedMessageBlob); } if(pbDecodedMessageBlob) { free(pbDecodedMessageBlob); } if (pbSignature) { free(pbSignature); } if(hHash) { CryptDestroyHash(hHash); } if (hKey) { CryptDestroyKey(hKey); } if (hProv) { CryptReleaseContext(hProv, 0); } if (pCertContext) { CertFreeCertificateContext(pCertContext); } if (hCertStore) { CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG); } return 0; }