2014-07-15 42 views
1

我想使用CryptProtectData函數,因此我可以加密我的密碼並在我的MAPI配置文件中使用它。我正在使用這兩篇​​文章http://blogs.msdn.com/b/dvespa/archive/2013/05/21/how-to-mfcmapi-create-mapi-profile-exchange-2013.aspxhttp://blogs.msdn.com/b/dvespa/archive/2013/07/15/create-profile-connect-mfcmapi-to-office-365.aspx用於使用MFCMAPI連接到我的託管交換(2013)帳戶。在設置我的所有屬性時,系統會提示輸入我的憑據,並且我遇到了域爲域提供的域太短的問題。所以我必須手動設置這些屬性(howto在第二篇文章中有描述)。CryptProtectData:從Crypt32.dll調用MAPI配置文件的函數的C++代碼

現在我需要在我的MAPI配置文件中設置用戶名和密碼,它似乎我需要encrpyt我自己的密碼(我必須建立一個應用程序來這樣做)。我正在使用「MAPI Download configuration guidance.docx」(可以從www .microsoft.com/en-us/download/details.aspx?id = 39045下載我正在使用的代碼片段位於文檔末尾)用於構建我自己的應用程序來加密我的密碼(我正在使用較小的示例來加密密碼,而不是用於創建整個配置文件)。我遇到了很多問題,應用程序沒有運行在32位Windows上,比crypt32.lib丟失(我必須自己創建它)等等。現在我在64位機器上運行它,但現在我不知道如何向程序提供數據。

我有以下代碼:

std::string stemp = "myPassword"; 
    std::wstring stemp1 = std::wstring(stemp.begin(), stemp.end()); 
    LPWSTR pwszPassword = (LPWSTR)stemp1.c_str();//stemp.c_str();// 
    HRESULT  hr = S_OK; 
    DATA_BLOB dataBlobIn = {0}; 
    DATA_BLOB dataBlobOut = {0}; 
    SPropValue propValues[2] = {0}; 
    // Validate parameters 

    // Encrypt password based on local user authentication 
    dataBlobIn.pbData = (LPBYTE)pwszPassword; 
    // Include NULL character 
    dataBlobIn.cbData = (::wcslen(pwszPassword) + 1) * sizeof(WCHAR); 

    CryptProtectData(
     &dataBlobIn, 
     NULL, 
     NULL, 
     NULL, 
     NULL, 
     0, 
     &dataBlobOut); 

std::cout<<"\n-- "; 
std::wcout<<(dataBlobOut.cbData); 
std::cout<<" --\n"; 
std::wcout<<(dataBlobOut.pbData);        

現在這些輸出值2時,爲dataBlobOut.cbData我主要是得到「230」(我認爲,當我修改密碼的大小,這可能會改變,但它不,它具有相同的值,如「aaa」,「bbbbb」,「cc」...),併爲dataBlobOut.pbData我得到一個十六進制值(類似於0x2cde50),我認爲這是地址因爲pbData是一個指針。

由於我得到的diffrente密碼完全相同的值我認爲我的做法是不正確的。但是,爲了獲得我的加密密碼,我需要更改哪些內容才能填充MAP_PROFILE_AUTH_PASSWORD屬性中的屬性?

我在微軟的交流論壇上也提過這個問題,但我認爲他們的論壇比軟件開發更專注於技術。

親切的問候 RIMES

+1

加密數據的大小不隨密碼大小(小變化)而變化這一事實本身並不表示問題。我敢打賭,算法涉及到某種填充,比如說最近的X字節邊界。真正的測試是 - 'CryptUnprotectData'給你原始數據嗎? –

+0

我的問題是,我不知道如何從「dataBlobIn」取回密碼(也許我沒有設置正確的方式)。我得到一個數字(來自.cbData)或一個地址或一個奇怪的符號(如果我使用*(dataBlobIn.pbData [0])) – user3466562

+1

'wcout <<(LPCWSTR)(dataBlobIn.pbData)' –

回答

0

對不起好像我沒有我的正確的帳戶發佈消息(以及與此我不會寫評論)。

正如我所說的我試圖輸出加密數據到一個文本文件:

std::ofstream myfile; 
myfile.open ("encrypted.txt"); 
myfile << (LPCWSTR)(dataBlobIn.pbData); 

但是當我打開我的.txt我剛剛得到的東西,如「0xca7ee8」(或爲空時,我寫的它沒有(LPCWSTR))。這可能是「正確的」輸出嗎?我的意思是我期待更多的字符,但正如伊戈爾所說,當我更改普通密碼的大小時,加密密碼的大小並不是必須改變的,也許這個輸出是我需要的? (或有任何方式,所以我可以驗證這是加密的密碼,而不是從內存中的一些隨機地址)。

編輯:

我想我得到了解決方案。好像我需要輸出我的數據是這樣的:

for (unsigned int i=0;i<dataBlobOut.cbData;i++){ 
      myfile<<dataBlobOut.pbData+i; 
    } 

,所以我得到了很多nonsens數據在我的文本文件,但我認爲這是我的加密的口令。我會檢查它並報告它是否工作,將我的(加密的)密碼設置在我的MAPI配置文件中。 但我仍然有一個問題。輸出對於相同的輸入始終是相同的還是可以改變的(因爲當運行我的程序時,我有時會爲相同的密碼獲得不同的輸出)?

0

您可以使用這樣的事情:

#include <windows.h> 
#include <stdio.h> 
#pragma comment(lib, "crypt32") 

int main(int argc, char** argv) { 
    if(argc != 2) { 
     fprintf(stdout, "usage: cpd <string>\n"); 
     exit(1); 
    } 

    const char* u = argv[1]; 

    DATA_BLOB db_i; 
    db_i.cbData = static_cast<DWORD>(strlen(u)); 
    db_i.pbData = (BYTE*)(u); 

    DATA_BLOB db_o = {0, NULL}; 
    if(!::CryptProtectData(&db_i, 
     NULL, NULL, NULL, NULL, 
     CRYPTPROTECT_UI_FORBIDDEN, 
     &db_o)) { 
     fprintf(stdout, 
      "CryptProtectData failed with error %ld\n", 
      GetLastError()); 
    } 
    else { 
     short nl = 0; 
     for(DWORD c = 0; c < db_o.cbData; c++) { 
      if((c % 40) == 0) 
       fprintf(stdout, "\n"); 
      fprintf(stdout, "%2.2x", db_o.pbData[c]); 
     } 
     LocalFree(db_o.pbData); 
    } 

    return 0; 
} 

串寫爲十六進制表示(最大線80)。您可以將用於序列化的格式化爲std :: string的db_o.pbData累積起來(有多種方法可以做到這一點 - 我傾向於爲db_o.cbData * 2 + 1分配一個char *,以便爲十六進制表示分配2個字符,再加上1對於NUL終止符,然後從pbData中爲每個BYTE順序寫入2個字符)。

如果crypt32.lib不可用,您可以使用LoadLibrary/GetProcAddress動態加載函數。