2014-07-15 21 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动态加载函数。