Let's take this PHP code. We use libsodium and libsodium-php. You have $text, $senderPrivateKey, $recipientPublicKey and a $nonce. The latter was obviously created like this by just using Sodium:

$nonce = \Sodium\randombytes_buf($size);

Now this is the code which adds PKCS#7 padding:

/* determine random amount of PKCS7 padding */
$padBytes = mt_rand(1, 255);

/* append padding */
$textBytes .= str_repeat(chr($padBytes), $padBytes);

Afterwards this is encrypted using \Sodium\crypto_box_keypair_from_secretkey_and_publickey and \Sodium\crypto_box.

So is it okay to use mt_rand here? I mean in the PHP documentation it is discouraged to use this for any "cryptographic purposes". However here it is only used for choosing a ("random") character and the length of the padding.

So is this secure? Would using openssl_random_pseudo_bytes(), random_bytes (in PHP 7) or libsodiums \Sodium\randombytes_buf (like it is used for the nonce) be more secure? And is this a correct implementation of PKCS#7? Especially as the same variable is used for the length and the character of the padding.

Edit: As there was some confusing here some more information: Actually this implementation is only supposed to hide the file size (especially for short pieces of data) a bit to prevent an attacker from guessing the plain-text message. This is implemented in some open-source libraries related to Threema and here is an issue about this. So basically in the Threema client a cryptographically secure RNG is used where in this example here a unsecure PRNG is used. And this is what this question is about: Is it less secure to use a PRNG here?

  • 1
    $\begingroup$ This type of padding doesn't make any sense, because it doesn't necessarily lead to a properly padded plaintext. It might require a second padding operation. It could be used to hide the length a bit. $\endgroup$ – Artjom B. Dec 21 '15 at 15:56
  • $\begingroup$ "It could be used to hide the length a bit." - Right, I think that's exactly what it is supposed to do. I'll update my main post with more details. $\endgroup$ – rugk Dec 21 '15 at 19:32
  • $\begingroup$ If the goal is to hide data length in addition to the data itself, then no, it's insecure. I think. $\endgroup$ – Artjom B. Dec 21 '15 at 20:28
  • 1
    $\begingroup$ instead of using a PRNG, it would probably be just as secure (or more) to pad the data to an interval of a specific block size, like 1KB, and use a different padding method $\endgroup$ – Richie Frame Dec 21 '15 at 20:49

If the intent of the padding is to make a passive attacker learn only a range instead of the exact message length, do not use real_len + rand(max_padlen). It is more efficient to make the length of the padded message a multiple of a given block size instead.

If your protocol has enough latitude to allow large variations of the padding length, you can use a randomized length, but watch out for replay attacks. If for a given question, the same response is always sent, the question can be sent multiple times, so that the actual response length can be eventually inferred. In order to mitigate this, the padding length should always be the same for a given question. A simple PRF can be used to achieve this.

  • $\begingroup$ For all later viewers: We've also discussed this idea on GitHub. $\endgroup$ – rugk Dec 25 '15 at 20:00
  • $\begingroup$ I've told this to Threema and they say the solution with fixed block sizes also has disadvantages: With a fixed blocksize small messages always have the same length - with a random padding they also can get longer. Optimally the padded messages always have the same length, but this would either restrict message lengths or it would be a great waste. $\endgroup$ – rugk Jan 9 '16 at 13:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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