2011-11-02 55 views
6

私のQt/C++アプリケーションでは、単純なシングルブロックAES暗号化/復号化を行う必要があります。これは "正直な人々を正直に保つ"実装なので、ちょっと基本的なencrypt(key, data)が必要です - 私は初期化ベクトルなどを心配しません。私の入力とキーは常に正確に16バイトです。WinAPIを使用した単純なAES暗号化

私のアプリケーションとのコンパイル/リンク/出荷の別の依存関係を避けるのが好きなので、各プラットフォームで利用可能なものを使用しようとしています。 Macでは、これはCCCryptへの1つのライナーでした。 Windowsでは、APIでWinCrypt.hから迷子になりました。ファイルを暗号化する例は、ほぼ600行です。 真剣に?

私はCryptEncryptを見ていますが、私はそれを呼び出す前に作成しなければならない依存関係のウサギの穴に落ちています。

誰でもWindows APIを使用してAES暗号化を行う簡単な例を提供できますか?確かに1行か2行でこれを行う方法があります。すでに暗号化する128ビットの鍵と128ビットのデータがあるとします。

+0

私は単純なWinApiの例を提供することはできませんが(注記したように存在しない可能性があります)、OpenSSLを調べましたか?私はいくつかのプロジェクトでそれを使いましたが、それはかなり簡単です。別の依存関係を追加したくないのは分かっていますが、単純な解決策に終わる可能性があります。 – JoeFish

答えて

4

私が思いつきました最高のものです。改善のための提案は大歓迎です!

static void encrypt(const QByteArray &data, 
        const QByteArray &key, 
        QByteArray *encrypted) { 
    // Create the crypto provider context. 
    HCRYPTPROV hProvider = NULL; 
    if (!CryptAcquireContext(&hProvider, 
          NULL, // pszContainer = no named container 
          NULL, // pszProvider = default provider 
          PROV_RSA_AES, 
          CRYPT_VERIFYCONTEXT)) { 
    throw std::runtime_error("Unable to create crypto provider context."); 
    } 

    // Construct the blob necessary for the key generation. 
    AesBlob128 aes_blob; 
    aes_blob.header.bType = PLAINTEXTKEYBLOB; 
    aes_blob.header.bVersion = CUR_BLOB_VERSION; 
    aes_blob.header.reserved = 0; 
    aes_blob.header.aiKeyAlg = CALG_AES_128; 
    aes_blob.key_length = kAesBytes128; 
    memcpy(aes_blob.key_bytes, key.constData(), kAesBytes128); 

    // Create the crypto key struct that Windows needs. 
    HCRYPTKEY hKey = NULL; 
    if (!CryptImportKey(hProvider, 
         reinterpret_cast<BYTE*>(&aes_blob), 
         sizeof(AesBlob128), 
         NULL, // hPubKey = not encrypted 
         0,  // dwFlags 
         &hKey)) { 
    throw std::runtime_error("Unable to create crypto key."); 
    } 

    // The CryptEncrypt method uses the *same* buffer for both the input and 
    // output (!), so we copy the data to be encrypted into the output array. 
    // Also, for some reason, the AES-128 block cipher on Windows requires twice 
    // the block size in the output buffer. So we resize it to that length and 
    // then chop off the excess after we are done. 
    encrypted->clear(); 
    encrypted->append(data); 
    encrypted->resize(kAesBytes128 * 2); 

    // This acts as both the length of bytes to be encoded (on input) and the 
    // number of bytes used in the resulting encrypted data (on output). 
    DWORD length = kAesBytes128; 
    if (!CryptEncrypt(hKey, 
        NULL, // hHash = no hash 
        true, // Final 
        0,  // dwFlags 
        reinterpret_cast<BYTE*>(encrypted->data()), 
        &length, 
        encrypted->length())) { 
    throw std::runtime_error("Encryption failed"); 
    } 

    // See comment above. 
    encrypted->chop(length - kAesBytes128); 

    CryptDestroyKey(hKey); 
    CryptReleaseContext(hProvider, 0); 
} 
+2

これはWindows 2000では動作しません。それが重要かどうかわからない(かなり古い)。存在する場合は、[回避策](http://support.microsoft.com/kb/228786)を参照してください。また、あなたの例外はハンドルリークを引き起こします:) – Luke

+2

動作しません。 AesBlob128はウィンドウでは未定義です... –

関連する問題