« 2008年06月 | メイン

2008年07月 アーカイブ

2008年07月09日

ATLアプリでDPAPIを使用するサンプル

Win32のDPAPIをC++/ATLで使用するサンプルがあまりないので公開。

DPAPIを使用すると、システムがWindowsのユーザープロファイルから暗号鍵を生成するため、アプリケーションはキーの管理をすることなくデータの暗号化が可能です。
dwFlagsにCRYPTPROTECT_LOCAL_MACHINEを指定すると、ユーザーではなくシステムプロファイルで解読可能となります。

CAtlArray<BYTE> cypherBytes;
CryptDPAPI::Encrypt(L"DPAPI sample", cypherBytes);
CString strPlain = CryptDPAPI::Decrypt(cypherBytes); 
#pragma once
#pragma comment(lib, "Crypt32.lib")

#include "stdafx.h"
#include <Wincrypt.h>
#include <atlcoll.h>
#include <atlstr.h>


class CryptDPAPI
{
public:
    static DWORD Encrypt(LPCTSTR szSource, CAtlArray<BYTE> &result, LPCTSTR szDescription = L"", DWORD dwFlags = 0L)
    {
        DATA_BLOB plainData;
        DATA_BLOB cypherData = {0};

        plainData.pbData = (BYTE *)szSource;    
        plainData.cbData = (lstrlen(szSource)+1) * sizeof(TCHAR);

        if(CryptProtectData(&plainData, szDescription, NULL, NULL, NULL, dwFlags, &cypherData))
        {
            result.SetCount(cypherData.cbData);
            ::CopyMemory(&result[0], cypherData.pbData, cypherData.cbData);
            LocalFree(cypherData.pbData);

            return cypherData.cbData;
        }
        return 0L;
    }

    static CString Decrypt(CAtlArray<BYTE> &cypherBytes, LPTSTR *pszDescription = NULL, DWORD dwFlags = 0L)
    {
        return Decrypt(&cypherBytes[0], cypherBytes.GetCount(), pszDescription, dwFlags);
    }

    static CString Decrypt(BYTE *pCypherBytes, DWORD count, LPTSTR *pszDescription = NULL, DWORD dwFlags = 0L)
    {
        DATA_BLOB cypherData;
        DATA_BLOB plainData = {0};
        cypherData.pbData = pCypherBytes;
        cypherData.cbData = count;
        if (CryptUnprotectData(&cypherData, pszDescription, NULL, NULL, NULL, dwFlags, &plainData))
        {
            CString strResult;
            strResult = (LPTSTR)plainData.pbData;
            LocalFree(plainData.pbData);

            return strResult;
        }
    }
};

おかしなところなどあれば乞ご指摘。

2008年07月10日

x64環境でVS2008のATLスマートデバイスプロジェクトがビルドできない件

結論: 単純に、include/lib設定が Program Files (x86) に対応してないだけでした。

既定値で動かないのは明らかにテスト不足だと思います。>VS開発チーム
(ひょっとしたら、うちの環境の作る順番とか原因かもしれないけど...)

具体的に言うと、Wizardでプロジェクト作るだけで、

midl : command line error MIDL1001 : cannot open input file oaidl.idl

こんなビルドエラー。

対策としては、

[ツール]/[オプション]/[プロジェクトおよびソリューション]/[VC++ディレクトリ]
の、

[プラットフォーム] → 作成したいWindows Mobile環境
[ディレクトリを表示するプロジェクト] → [インクルード ファイル] と[ライブラリ ファイル]

を開くと、

C:\Program Files\Windows Mobile 5.0 SDK R2\PocketPC\include\ARMV4I
C:\Program Files\Windows Mobile 5.0 SDK R2\PocketPC\include

とかなっていると思います。

x64環境で、Windows Mobile SDKは通常 Program Files (x86)にインストールされるので、[Program Files] → [Program Files (x86)] と変更するだけ。

あと、おかしいなー、と思ってMIDLの[追加のインクルードファイル]にフルpathを入れたら、空白を含むpathに対応してなかったのもちょっと酷いかも...。

About 2008年07月

2008年07月にブログ「Neutral Scent」に投稿されたすべてのエントリーです。過去のものから新しいものへ順番に並んでいます。

前のアーカイブは2008年06月です。

他にも多くのエントリーがあります。メインページアーカイブページも見てください。