Library encryption - Codeigniter

0

I have a problem, I'm passing an id via GET and I need to encrypt it. So, I decided to use the codeigniter's native encryption library, but when the message is encrypted, it generates many characters, which results in a problem with URL passing. Can you reduce the size of the encrypted message output?

Encrypt and decrypt code:

class Welcome extends CI_Controller {
    public function index(){
        $dados['url'] = base_url();
        $dados['msg'] = '123';
        $dados['msg_cripto'] = $this->encryption->encrypt($dados['msg']);
        $dados['msg_decripto'] = $this->encryption->decrypt($dados['msg_cripto']);
        $this->parser->parse('welcome_message', $dados);
    }
}

    
asked by anonymous 12.04.2018 / 20:15

1 answer

0

The message gets larger because it uses AES-CBC and uses the HMAC-SHA512. This causes the minimum size to be 16 bytes + 16 bytes + 64 bytes, in total at least 96 bytes. When encoded for Base64 the "size increases".

The AES-CBC works with blocks of 16 bytes, so the smallest possible block (even if the message is 1 byte) will be 16 bytes. If message is 17 bytes, AES will be 32 bytes, always 16 bytes.

HMAC, to ensure message integrity, uses SHA-512, which will always be 64 bytes long.

In addition you have the IV, which is a nonce, it has 16 bytes and is a public value.

What is the "solution" to reduce size?

  • Encryption: Do not use block ciphers.
  • Integrity: Do not use HMAC.

You can use XChaCha20Poly1305. ChaCha20 is a stream cipher, so its size is 1: 1. If the message has 1 byte, the encrypted data will also have 1 byte, with nothing additional. The Poly1305 is a MAC algorithm that uses only 16 bytes, as opposed to 64 bytes, and guarantees better security, in theory.

There is a "problem" in the original ChaCha20Poly1305, that the nonce is too small, so it is recommended that the nonce is sequential. This is why XChaCha20Poly1305 is used, so you can use nonce random, not having to know the last state used.

At the end you will have at least 1 bytes + 24 bytes + 16 bytes, at least 41 bytes, considering the nonce next to the ciphertext.

To use it you have LibSodium, native to PHP 7.2:

$nonce = random_bytes(SODIUM_CRYPTO_AEAD_XCHACHA20POLY1305_IETF_NPUBBYTES);
$encriptado = $nonce . sodium_crypto_aead_xchacha20poly1305_ietf_encrypt(
    $dados['msg'],
    '',
    $nonce,
    $chave
);

To decrypt:

$desencriptado = sodium_crypto_aead_xchacha20poly1305_ietf_decrypt(
    mb_substr($encriptado, SODIUM_CRYPTO_AEAD_XCHACHA20POLY1305_IETF_NPUBBYTES, null, '8bit'),
    $ad,
    mb_substr($encriptado, 0, SODIUM_CRYPTO_AEAD_XCHACHA20POLY1305_IETF_NPUBBYTES, '8bit'),
    $chave
);
  

I have not tested the code posted here, so check its operation and documentation before using it!

By default LibSodium encodes in hexadecimal, which is worse than Base64 in size, but you can decode and encode in Base64.

Note that your message is a numeric string, this will give you hints of its value across the length of the text. That is, if it is only 0 to 9 it will have 1 byte, whereas if it is from 100 to 999 it will be 3 bytes ... This can be a problem, since the person may have great chances to guess the real value across the length.

Use pack() to always use 8 bytes, or 4 bytes in case of int32, similar to the one described here.

Now the problem of "a problem with URL passing," you should use an encoding that is URL-compliant, PHP, as always, has no native capability for this. By default, base64_encode uses RFC 2045, not RFC 3548. Default base64_encode will have characters that invalidate the URL, such as + and = , for example. You can use url_encode , however this will further increase the size.

If size is really a problem you can also use Base91 or a custom encoding, which is more efficient and still safe to use in URLs.

    
29.04.2018 / 23:18