The message gets bigger because it uses AES-CBC and uses HMAC-SHA512. This makes the minimum size 16 bytes + 16 bytes + 64 bytes, in total at least 96 bytes. When encoded for Base64 the "size increases".
AES-CBC works with 16 byte blocks, so the smallest possible block (even if the message is 1 byte) will be 16 byte. If message has 17 bytes, AES will have 32 bytes, always 16 blocks.
HMAC, to ensure message integrity, uses SHA-512, which will always have 64 bytes.
Also you have the IV, which a nonce, it has 16 bytes and is a public value.
What is the "solution" to reduce the size?
- Encryption: Do not use block cipher.
- Integrity: Do not use HMAC.
You can use Xchacha20poly1305. Chacha20 is a flow cipher, so its size is 1:1. If the message is 1 byte, the encrypted data will also be 1 byte, with nothing additional. Poly1305 is a MAC algorithm that uses only 16 bytes, unlike 64 bytes, and ensures better security, theoretically.
There is a "problem" in the original Chacha20poly1305, that nonce is very small, so it is recommended that nonce be sequential. That’s why Xchacha20poly1305 is used, so it can use random nonce, not having to know the last used state.
At the end you will have at least 1 bytes + 24 bytes + 16 bytes, being at least 41 bytes, considering the nonce next to the text-crifrado.
To use it you have Libsodium, native in 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 working and documentation before using it!
By default Libsodium encodes in hexadecimal, which is worse than Base64 in terms of size, but you can decode and encode in Base64.
Note that your message is a numeric string, this will give hints of its value through the length of the text. That is, if it is only 0 until 9 it will be 1 byte, while if it is from 100 until 999 it will be with three bytes... This can be a problem, since the person may have great chances to guess the real value over the length.
Use the pack()
so that it always uses 8 bytes, or 4 bytes in case of int32, similar to the one described here.
Now the problem of "a problem in passing through the URL", you should use an encoding that is compatible with URL, PHP, as always, has no native resource for this. By default the base64_encode
uses RFC 2045, not RFC 3548. The base64_encode
, default, will have characters that invalidate the URL, such as the +
and the =
, for example. You can use the url_encode
, but 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.
To clarify the ideas: why even you need to encrypt the id in the URI?
– ShutUpMagda