2011-11-02 61 views
6

Tôi cần thực hiện mã hóa/giải mã AES đơn khối trong ứng dụng Qt/C++ của mình. Đây là một "giữ cho người trung thực thực hiện" thực hiện, do đó, chỉ cần encrypt(key, data) cơ bản là cần thiết - Tôi không lo lắng về các vectơ khởi tạo, vv. Đầu vào và khóa của tôi sẽ luôn chính xác là 16 byte.Mã hóa AES đơn giản bằng cách sử dụng WinAPI

Tôi muốn thực sự muốn tránh một sự phụ thuộc khác để biên dịch/liên kết/gửi với ứng dụng của tôi, vì vậy tôi đang cố gắng sử dụng những gì có sẵn trên mỗi nền tảng. Trên máy Mac, đây là một lớp lót đến CCCrypt. Trên Windows, tôi bị lạc trong API từ WinCrypt.h. Ví dụ về mã hóa một tệp của họ dài gần 600 dòng. Nghiêm túc?

Tôi đang xem CryptEncrypt, nhưng tôi đang rơi xuống lỗ thỏ phụ thuộc mà bạn phải tạo trước khi bạn có thể gọi điều đó.

Có ai có thể cung cấp ví dụ đơn giản về mã hóa AES bằng API Windows không? Chắc chắn có một cách để làm điều này trong một hoặc hai dòng. Giả sử bạn đã có khóa 128 bit và 128 bit dữ liệu để mã hóa.

+0

Tôi không thể cung cấp một ví dụ WinApi đơn giản (vì có thể không tồn tại như bạn đã lưu ý), nhưng bạn đã xem xét OpenSSL chưa? Tôi đã sử dụng nó trong một số dự án và nó khá đơn giản. Tôi biết bạn không muốn thêm phụ thuộc khác, nhưng nó có thể sẽ trở thành một giải pháp đơn giản hơn. – JoeFish

Trả lời

4

Đây là điều tốt nhất tôi có thể đưa ra. Đề xuất cải tiến được hoan nghênh!

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

Điều này sẽ không hoạt động trên Windows 2000; không biết nếu đó là quan trọng hay không (khá lỗi thời). Nếu có, đây là [workaround] (http://support.microsoft.com/kb/228786). Ngoài ra, ngoại lệ của bạn sẽ gây ra rò rỉ xử lý :) – Luke

+2

Không hoạt động. AesBlob128 không được xác định trong cửa sổ ... –

Các vấn đề liên quan