Semplice crittografia AES utilizza WinAPI

Ho bisogno per fare un semplice blocco unico AES crittografia /decrittografia nel mio Qt /C++ applicazione. Questo è un “mantenere le persone oneste onesti” attuazione, in modo che solo una base encrypt(key, data) è necessario–io non sono preoccupato per l’inizializzazione di vettori, etc. Il mio ingresso e la chiave sarà sempre esattamente 16 byte.

Mi piacerebbe davvero come evitare un’altra dipendenza compilazione /link /nave con la mia domanda, quindi sto cercando di utilizzare ciò che è disponibile su ogni piattaforma. Su Mac, questo è stato un one-liner CCCrypt. Su Windows, io sono sempre perso nelle API da WinCrypt.h. Il loro esempio di crittografia di un file è di quasi 600 linee a lungo. Sul serio?

Sto guardando CryptEncrypt, ma io sono caduta nella tana del coniglio e delle dipendenze è necessario creare prima si può chiamare tale.

Qualcuno può fornire un semplice esempio di crittografia AES utilizzando le API di Windows? Sicuramente c’è un modo per fare questo in una riga o due. Si supponga di disporre già di una chiave a 128 bit e 128-bit di dati da cifrare.

Io non posso fornire un semplice WinApi esempio (perché uno non può esistere come avrete notato), ma hai guardato in OpenSSL? Io l’ho utilizzato in diversi progetti ed è abbastanza semplice. So che non si desidera aggiungere un’altra dipendenza, ma può essere una soluzione più semplice.

OriginaleL’autore Dave Mateer | 2011-11-02

One Reply
  1. 4

    Il meglio che ho potuto venire con. Suggerimenti per il loro miglioramento sono i benvenuti!

    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);
    }
    Questo non funziona su Windows 2000, non so se è importante o meno (abbastanza datate). Se lo è, ecco il soluzione. Inoltre, le eccezioni di causare perdite di handle 🙂
    Non funziona. AesBlob128 è definito in windows…

    OriginaleL’autore Dave Mateer

Lascia un commento