-4
$\begingroup$

I am using a AutoSeededRNG from Crypto++ to generate IVs for use in CBC encryption.
I am encoding the IVs using Base64 for future use (decryption).

I notice that all the Base64 encoded IVs end with gB. Why is this? Is it a security problem?

Here is the code:

for (int i = 0; i < 10; i++) {
    CryptoPP::AutoSeededX917RNG<CryptoPP::Serpent> rng;
    rng.GenerateBlock(iv, CryptoPP::Serpent::BLOCKSIZE);

    std::string ivs(reinterpret_cast<char const *>(iv));
    lcl_log(lcl_cCrypto, lcl_vDebug, @"Random IV:%s",ivs.c_str());

    std::string ivB64;
    ivs.erase(std::remove(ivs.begin(), ivs.end(), '\n'), ivs.end());


    CryptoPP::StringSource base64IVEncoder (ivs , true, new CryptoPP::Base64Encoder(new CryptoPP::StringSink(ivB64)));

    lcl_log(lcl_cCrypto, lcl_vDebug, @"IV base64[size:%lu]:%s",ivB64.length(),ivB64.c_str());


    std::string encoded;

    CryptoPP::StringSource ss(ivs, true,
                    new CryptoPP::HexEncoder(
                                   new CryptoPP::StringSink(encoded)
                                   ) // HexEncoder
                    ); // StringSource

    lcl_log(lcl_cCrypto, lcl_vDebug, @"IV hex[size:%lu]:%s",encoded.length(),encoded.c_str());


}

Here are the logs:

2013-12-02 21:28:31.616 app[8043:70b] D Crypto:PSCryptoCore.mm:83:-[PSCryptoCore encryptUsingSerpentWithPlaintext:andKey:] Random IV:À’àà·Ùº@‹œ©$"˜Ó0VÊ
2013-12-02 21:28:31.617 app[8043:70b] D Crypto:PSCryptoCore.mm:91:-[PSCryptoCore encryptUsingSerpentWithPlaintext:andKey:] IV base64[size:29]:y9WIiOH0vEDcz6kkESL37jBW5ggB
2013-12-02 21:28:31.617 app[8043:70b] D Crypto:PSCryptoCore.mm:102:-[PSCryptoCore encryptUsingSerpentWithPlaintext:andKey:] IV hex[size:42]:CBD58888E1F4BC40DCCFA9241122F7EE3056E60801
2013-12-02 21:28:31.618 app[8043:70b] D Crypto:PSCryptoCore.mm:83:-[PSCryptoCore encryptUsingSerpentWithPlaintext:andKey:] Random IV:8À⁄    $]Q#:u   ‚»ëʪ0VÊ
2013-12-02 21:28:31.618 app[8043:70b] D Crypto:PSCryptoCore.mm:91:-[PSCryptoCore encryptUsingSerpentWithPlaintext:andKey:] IV base64[size:29]:OMvaDSRdUSM6dQniyJHmuzBW5ggB
2013-12-02 21:28:31.619 app[8043:70b] D Crypto:PSCryptoCore.mm:102:-[PSCryptoCore encryptUsingSerpentWithPlaintext:andKey:] IV hex[size:42]:38CBDA0D245D51233A7509E2C891E6BB3056E60801
2013-12-02 21:28:31.619 app[8043:70b] D Crypto:PSCryptoCore.mm:83:-[PSCryptoCore encryptUsingSerpentWithPlaintext:andKey:] Random IV:\^Ê(U%‰◊ΩΩ+ÿ0VÊ
2013-12-02 21:28:31.619 app[8043:70b] D Crypto:PSCryptoCore.mm:91:-[PSCryptoCore encryptUsingSerpentWithPlaintext:andKey:] IV base64[size:29]:XANe5ihVJRrk1729HSsR2DBW5ggB
2013-12-02 21:28:31.620 app[8043:70b] D Crypto:PSCryptoCore.mm:102:-[PSCryptoCore encryptUsingSerpentWithPlaintext:andKey:] IV hex[size:42]:5C035EE62855251AE4D7BDBD1D2B11D83056E60801
2013-12-02 21:28:31.620 app[8043:70b] D Crypto:PSCryptoCore.mm:83:-[PSCryptoCore encryptUsingSerpentWithPlaintext:andKey:] Random IV:Eo(æ`¨ösˇ ?‡ˆäFÿ0VÊ
2013-12-02 21:28:31.621 app[8043:70b] D Crypto:PSCryptoCore.mm:91:-[PSCryptoCore encryptUsingSerpentWithPlaintext:andKey:] IV base64[size:29]:RW8ovmCsmnP/DT/g9opG2DBW5ggB
2013-12-02 21:28:31.621 app[8043:70b] D Crypto:PSCryptoCore.mm:102:-[PSCryptoCore encryptUsingSerpentWithPlaintext:andKey:] IV hex[size:42]:456F28BE60AC9A73FF0D3FE0F68A46D83056E60801
2013-12-02 21:28:31.622 app[8043:70b] D Crypto:PSCryptoCore.mm:83:-[PSCryptoCore encryptUsingSerpentWithPlaintext:andKey:] Random IV:)ø´èÏ˙.êu\ø=uk®ä0VÊ
2013-12-02 21:28:31.622 app[8043:70b] D Crypto:PSCryptoCore.mm:91:-[PSCryptoCore encryptUsingSerpentWithPlaintext:andKey:] IV base64[size:29]:Kb+rj+z6LpB1XL89dWuoijBW5ggB
2013-12-02 21:28:31.623 app[8043:70b] D Crypto:PSCryptoCore.mm:102:-[PSCryptoCore encryptUsingSerpentWithPlaintext:andKey:] IV hex[size:42]:29BFAB8FECFA2E90755CBF3D756BA88A3056E60801

At first I believed it had something to do with the newline character and removed that, but the gB at the end stayed. If I concatenate the IV to the ciphertext any attacker will know where the IV is based on that gB. Apparently it's also in the HEX… Maybe it has something to do with the StringSource?

$\endgroup$
7
  • $\begingroup$ Looks like an implementation problem to me, base64 should not output 29 character strings for 16 char inputs. Also all the IVs end with ," but look to be longer than 16 chars. $\endgroup$ Dec 2, 2013 at 18:50
  • $\begingroup$ Yes, but where is the implementation problem? In my code? in the library? $\endgroup$ Dec 2, 2013 at 19:10
  • $\begingroup$ Cant say, have the debug print the IV in hex as well as base64 $\endgroup$ Dec 2, 2013 at 19:21
  • $\begingroup$ updated question to show HEX $\endgroup$ Dec 2, 2013 at 19:33
  • 5
    $\begingroup$ This question appears to be off-topic because it is about artifacts produced by buggy debug code written in C++, not cryptography as we handle it here. A migration towards StackOverflow might be appropriate… $\endgroup$
    – e-sushi
    May 28, 2014 at 2:56

3 Answers 3

2
$\begingroup$

The hexadecimal output of an IV matching the block size of Serpent should be 32 characters. Since you are getting 42, that is an extra 5 bytes of data. The last 5 bytes of every IV you posted is 3056E60801, which leads me to strongly believe this is an implementation issue, possibly related to reinterpret_cast.

In terms of the RNG itself, it appears to be ok, although at first glance there appears to be a stronger bias towards B and 8 in the hex output, which may indicate a problem. Larger quantities of RNG output would be needed to detect bias. You may want to generate more RNG data (40 bytes or so) and then pass it to a cryptographic hash to generate IVs.

The easy fix here is to truncate the generated IV to 16 bytes before use, but that may cause an issue if the program is expecting 21 bytes for whatever reason.

Another fix (and method I use) is to prepend the IV to the plaintext before encrypting, then passing an all 0 IV to the encryption class. During decryption the first output block is simply ignored. This allows the IV to be stored with the encrypted data in an encrypted format, and is at least as secure as storing the IV in plaintext and using it in the normal method. The IV must be the block length for this to work as expected.

$\endgroup$
6
  • $\begingroup$ I like your prepend the IV to the ciphertext method. In the debugger it shows the iv as a 16 byte random array. So the stuff at the end appears when it's converted to hex/base64... but I need it in that format so I can write it in a text file... $\endgroup$ Dec 3, 2013 at 13:20
  • $\begingroup$ I have tryed this with the secCopyRandomBytes RNG from apple ... the same result ...the hex/base64 has a fixed string at the end $\endgroup$ Dec 3, 2013 at 13:22
  • $\begingroup$ Your iv storing method requires double encryption, right? $\endgroup$ Dec 13, 2013 at 8:57
  • $\begingroup$ No, the IV simply becomes the first plaintext block, only 1 addition block is encrypted, and it is only encrypted once. $\endgroup$ Dec 13, 2013 at 19:46
  • $\begingroup$ Man, I don't believe your encryption scheme is secure at all... Where are you using the prepended IV? It seems to me you're just adding it , and encrypting with an all 0 IV and then discarding it.. but not using it anywhere $\endgroup$ Dec 15, 2013 at 11:58
2
+25
$\begingroup$

This question is about artifacts produced by buggy debug code written in C++, and squarely off-topic; but I can't vote to close it (I tried), because there is a bounty.

IMHO the problem is: char const * is not the appropriate type for a pointer to an arbitrary collection of bytes of some length, like an IV is. The thing pointed-to by a char const * is a C string, that is a collection of non-zero bytes, up to the next 0 byte (conventionally: not included in the length of the C string), which location determines the length of the thing.

Thus, after std::string ivs(reinterpret_cast<char const *>(iv)); the object ivs contains a copy of the bytes forming the object iv and whatever bytes happen to be in memory after that, up to the first 0 byte in iv or said memory. Possibly the IV (in the cryptographic sense) is at the beginning of that, unless of course it contains a 0 (a real possibility). We'd need to know the details of type iv to ascertain that, but they are not given.

Assuming this, whatever we get afterwards from ivs is thus the reinterpretation in a human-readable form of the (possibly partial) IV and whatever extra lays afterwards.

$\endgroup$
1
$\begingroup$

An IV is a binary value which can contain arbitrary bytes, including null bytes. But when you initialize a string from const char* it treats the input as null terminated string. This string is shorter than the the IV if the IV does contain a null byte, and reads beyond the buffer if the IV does not contain null bytes.

$\endgroup$
1
  • $\begingroup$ see my comment on Richie's question $\endgroup$ Dec 3, 2013 at 13:21

Not the answer you're looking for? Browse other questions tagged or ask your own question.