CryptProtectData:用于从Crypt32.dll为MAPI配置文件调用函数的C ++代码

时间:2014-07-15 19:34:07

标签: c++ encryption exchange-server mapi

我正在尝试使用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)帐户。设置我的所有属性时,系统会提示我输入我的凭据,并且我遇到了为域提供的字段太短的问题。所以我必须手动设置这些属性(如何在第二篇文章中描述)。

现在我需要在我的MAPI配置文件中设置用户名和密码,似乎我需要自己加密密码(我必须构建一个应用程序来执行此操作)。我正在使用" MAPI下载配置指南.docx" (可以从www .microsoft.com / en-us / download / details.aspx下载?id = 39045我正在使用的代码片段在文档末尾)用于构建我自己的应用程序来加密我的密码(i我使用较小的例子来加密密码,而不是创建整个配置文件)。我有很多问题,应用程序没有在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);                              

现在输出这两个值时,对于dataBlobOut.cbData,我主要得到&#34; 230&#34; (我认为当我改变密码的大小时,这可能会改变,但事实并非如此,它对于密码有相同的价值,例如&#34; aaa&#34;,&#34; bbbbb&#34;,&#34 ; cc&#34; ...),对于dataBlobOut.pbData,我得到一个Hexadezimal值(类似于0x2cde50)我认为它是变量的地址,因为pbData是一个指针。

由于我得到了diffrente密码的完全相同的值,我认为我的方法不对。但是我需要更改以获取加密密码,以便在MAPI配置文件中填写属性PR_PROFILE_AUTH_PASSWORD?

我在微软交流论坛上也提到了这个问题,但我认为他们的论坛比软件开发更注重技术。

亲切的问候 RIMES

2 个答案:

答案 0 :(得分:0)

很抱歉,好像我没有用我的正确帐户发布邮件(并且我不能写评论)。

正如我所说,我试图将加密数据输出到文本文件中:

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

但是当我打开我的.txt时,我会得到类似&#34; 0xca7ee8&#34; (或者在没有(LPCWSTR)的情况下写它时它是空的)。愿这是&#34;对&#34;输出完全?我的意思是我期待更多的字符,但正如伊戈尔所说,当我改变普通密码的大小时,加密密码的大小不会改变,也许这个输出是我需要的? (或者有什么方法可以验证这是加密密码而不是内存中的随机地址)。

编辑:

我想我得到了解决方案。好像我需要以这种方式输出我的数据:

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

所以我在我的文本文件中获得了很多nonsens数据,但我认为这是我的加密密码。我将检查它并报告它是否有效在我的MAPI配置文件中设置我的(加密)密码。 但我还有一个问题。对于相同的输入,输出总是相同的还是可以改变(因为在运行我的程序时,我有时会得到相同密码的不同输出)?

答案 1 :(得分: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)。您可以将db_o.pbData格式化为std :: string以进行序列化(有多种方法可以执行此操作 - 我更喜欢为db_o.cbData * 2 + 1分配一个char *,以便为十六进制表示提供2个字符,加上1对于NUL终结符,然后从pbData为每个BYTE顺序写入2个字符。

如果crypt32.lib不可用,您可以使用LoadLibrary / GetProcAddress动态加载函数。