CryptProtectData:从Crypt32.dll调用MAPI Profile函数的c++代码

CryptProtectData: C++ Code for calling function from Crypt32.dll for MAPI Profile

本文关键字:函数 Profile c++ 代码 MAPI 调用 Crypt32 dll CryptProtectData      更新时间:2023-10-16

我试图使用CryptProtectData函数,这样我就可以加密我的密码并在我的MAPI配置文件中使用它。我正在使用这2篇文章http://blogs.msdn.com/b/dvespa/archive/2013/05/21/how-to-mfcmapi-create-mapi-profile-exchange-2013.aspx和http://blogs.msdn.com/b/dvespa/archive/2013/07/15/create-profile-connect-mfcmapi-to-office-365.aspx连接到我的托管交换(2013)帐户与MFCMAPI。当设置我的所有属性时,我正在提示我的凭据,并且在那里我遇到了为域提供的字段对我的域太短的问题。所以我必须手动设置这些属性(如何在第二篇文章中描述)。

现在我需要在我的MAPI配置文件中设置用户名和密码,似乎我需要自己加密密码(我必须构建一个应用程序这样做)。我使用"MAPI下载配置指南。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);                              

现在当输出这两个值时,对于dataBlobOut。cbData我大多得到"230"(我认为这可能会改变,当我改变密码的大小,但它没有,它具有相同的值为密码,如"aaa","bbbbb","cc"…),并为dataBlobOut。pbData我得到一个十六进制值(像0x2cde50),我认为这是变量的地址,因为pbData是一个指针。

由于我对不同的密码得到完全相同的值,我认为我的方法是不正确的。但是,我必须更改什么才能获得我的加密密码,以便我可以在我的MAPI配置文件中填写属性PR_PROFILE_AUTH_PASSWORD ?

我在微软交流论坛上也问过这个问题,但我认为他们的论坛更注重技术而不是软件开发。

亲切的问候rim

对不起,我似乎没有用我的正确帐户发布消息(并且我不能写评论)。

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

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

但是当我打开我的。txt时,我只是得到像"0xca7ee8"这样的东西(或者当我在没有(LPCWSTR)的情况下写它时它是空的)。这可能是"正确的"输出吗?我的意思是,我期待更多的字符,但正如Igor所说,加密密码的大小不一定要改变,当我改变普通密码的大小,也许这个输出是我需要的?(或者有什么方法可以让我验证这是加密的密码,而不是内存中的随机地址)

编辑:

我想我有办法了。似乎我需要这样输出我的数据:
for (unsigned int i=0;i<dataBlobOut.cbData;i++){ 
            myfile<<dataBlobOut.pbData+i; 
     }  

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

你可以这样写:

#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 %ldn", 
            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_0。pbData格式化为std::string进行序列化(有多种方法可以做到这一点——我更喜欢为db_o分配一个char*)。cbData * 2 + 1有2个字符用于十六进制表示,加上1为NUL终止符,然后为pbData中的每个字节顺序写入2个字符)。

如果crypt32

使用LoadLibrary/GetProcAddress动态加载函数。