Search code examples
c++encryptionaesaes-gcm

Are there values in IVs for AES-gcm encryption which are just not working?


I'm using Openssl EVP to encrypt, decrypt a plaintext with aes-gcm-256. I provide an empty string as additional data and randomly generate the IVs every time using RAND_bytes. My IVs are 16 bytes long. The key is static, just like the plaintext. So the only thing which is different on each run is the IV. If I loop this program 10.000 times it works approximately 82% of the time. Is it possible that some values don't work when included in the IV?

Here are some of the IVs not working: (provided in hex format for readability)

868DCDA3B6A47F9461CEFC1CF096E419    
942A3E63CB22BFFCF4309B038575D9DF    
7DABF472A03FCFD4AA88A17BF17049B5    
10E94264C5133011665978290D157FDF    
B33323638D679A4CDD17844C5E50A656    
D77CA61F54374F8AF76BF625F6065317    
A81C1087C2218E29DB5DBBE3DF31CF03    
15678C7484E20DD2C4BDB9E67D4FA7AD    
3DC18C3AAFE48367905091D6C760A2CA    
9940CA7685B92C46F716FE3E3EDD4675    
CA2E9EBACD824F06523A7471ABB1A637    
691D54DB476FF73C27D19B0BFD7191D2    
020FF1C6702BCF5D8715082768B14CC8    
F72623956640DDA62047821E3418F1EC    
743F1B9A8AF46D8EC2472DD44059E87E    
6CC0C96CFEA33DC96B9C8FB27587A6B6    
2A73F05FC73AB2BE0D3B78FD65824100    
0D44B61773986D5C4E11521121A9D7BF    
DEB9896F1EACE3B8F10F980595108578    
4AA5B4922564E664C67BC83B58C18A94    
AFF764905CAD86EF7ABA582853EAD2F5    
FD4C09E91EA36024E8BA8D4D5FA6751E    
5F764A3F0217EAA54D242E28C7E45640    
5ED5B3C23DF30E178517FAB51F28DE32    
34E9B4CF4E2149EBF919F75D9374267A    
31D65E7E61D888CF4C244B009B71117C

Of course, there are many more. If someone has a clue I would be very thankful.

int successful = 0;
for (int i = 1; i < 10001; ++i)
{
    unsigned char *key = (unsigned char *)"01234567890123456789012345678901";

    /* Message to be encrypted */
    unsigned char *plaintext = (unsigned char *)"The quick brown fox jumps over the lazy dog";

    unsigned char ciphertext[128];

    /* Buffer for the decrypted text */
    unsigned char decryptedtext[128];

    /* Buffer for the tag */
    unsigned char tag[16];

    int decryptedtext_len, ciphertext_len;

    //initialize random number generator (for IVs)
    int rv = RAND_load_file("/dev/urandom", 32);

    a:
    /* A 128 bit IV */
    size_t iv_len = 16;
    unsigned char iv[iv_len];
    RAND_bytes(iv, sizeof(iv));

    ciphertext_len = gcm_encrypt(plaintext, key, iv, iv_len, ciphertext, tag);

    decryptedtext_len = gcm_decrypt(ciphertext, tag, key, iv, iv_len, decryptedtext);

    if (decryptedtext_len >= 0)
    {
        /* Add a NULL terminator. We are expecting printable text */
        decryptedtext[decryptedtext_len] = '\0';

        ++successful;
        std::string dec(reinterpret_cast<char *>(iv), iv_len);
        //std::cout << (float)successful / i << " " << string_to_hex(dec) << "\n";
    }
    else
    {
        //printf("Decryption failed\n");
        std::string dec(reinterpret_cast<char *>(iv), iv_len);
        std::cout << string_to_hex(dec) << "\n";
        goto a;
    }
}

std::cout << (float)successful / 10000 << "\n";

The gcm_encrypt and gcm_decrypt functions are similar to the ones used in the documentation. I only changed that the function calculates the lengths itself,

https://wiki.openssl.org/images/0/08/Evp-gcm-encrypt.c


Solution

  • You appear not to be passing the ciphertext length to your decrypt function, how does it know how much ciphertext there is to decrypt? If you're just using strlen() or the like, what happens when the ciphertext contains a 0x00 byte? -- Iridium

    This solved my question, thanks.