2011-11-02 12 views
6

Potrzebuję wykonać proste jednoblokowe szyfrowanie/odszyfrowywanie AES w mojej aplikacji Qt/C++. Jest to implementacja "keep the honest people honest", więc wystarczy podstawowy encrypt(key, data) - nie martwię się wektorami inicjalizującymi, itd. Moje wejście i klucz zawsze będą dokładnie 16 bajtami.Proste szyfrowanie AES przy użyciu WinAPI

Byłbym naprawdę jak uniknąć innej zależności od kompilacji/link/statek z moją aplikacją, więc próbuję użyć tego, co jest dostępne na każdej platformie. W komputerach Mac był to jednolinijkowy numer CCCrypt. W systemie Windows gubię się w API od WinCrypt.h. Ich przykład szyfrowania pliku ma prawie 600 linii. Poważnie?

Patrzę na CryptEncrypt, ale spadam z króliczej dziury zależności, które musisz utworzyć, zanim będziesz mógł to nazwać.

Czy każdy może podać prosty przykład wykonania szyfrowania AES przy użyciu interfejsu API systemu Windows? Z pewnością istnieje sposób, aby to zrobić w linii lub dwóch. Załóżmy, że masz już 128-bitowy klucz i 128-bitowe dane do zaszyfrowania.

+0

Nie mogę podać prostego przykładu WinApi (ponieważ może nie istnieć, jak zauważyłeś), ale czy zaglądasz do OpenSSL? Używałem go w kilku projektach i jest to całkiem proste. Wiem, że nie chcesz dodawać kolejnej zależności, ale może to być prostsze rozwiązanie. – JoeFish

Odpowiedz

4

Oto najlepsze, jakie udało mi się wymyślić. Sugestie do poprawy są mile widziane!

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

To nie zadziała w Windows 2000; nie wiem, czy to ważne, czy nie (dość nieaktualne). Jeśli tak, oto [obejście] (http://support.microsoft.com/kb/228786). Poza tym wyjątki będą powodować wycieki rąk :) – Luke

+2

Nie działa. AesBlob128 jest niezdefiniowany w oknach ... –

Powiązane problemy