PHP 8.4.6 Released!

mcrypt_encrypt

(PHP 4 >= 4.0.2, PHP 5, PHP 7 < 7.2.0, PECL mcrypt >= 1.0.0)

mcrypt_encryptCriptografa texto simples com parâmetros fornecidos

Aviso

Esta função foi DESCONTINUADA a partir do PHP 7.1.0 e foi REMOVIDA a partir do PHP 7.2.0. O uso desta função é fortemente desencorajado.

Descrição

mcrypt_encrypt(
    string $cipher,
    string $key,
    string $data,
    string $mode,
    string $iv = ?
): string|false

Criptografa os dados e os retorna.

Parâmetros

cipher

Uma das constantes MCRYPT_nome_da_cifra ou o nome do algoritmo como string.

key

A chave com a qual os dados serão criptografados. Se o tamanho da chave fornecida não for suportado pela cifra, a função emitirá um aviso e retornará false.

data

Os dados que serão criptografados com cipher e mode fornecidos. Se o tamanho dos dados não for n * tamanho_do_bloco, os dados serão preenchidos com '\0'.

O texto criptografado retornado pode ser maior que o tamanho dos dados que foram fornecidos por data.

mode

Uma das constantes MCRYPT_MODE_nome_do_modo ou uma das seguintes strings: "ecb", "cbc", "cfb", "ofb", "nofb" ou "stream".

iv

Usado para a inicialização nos modos CBC, CFB, OFB e em alguns algoritmos no modo STREAM. Se o tamanho do IV fornecido não for suportado pelo modo de encadeamento ou nenhum IV for fornecido, mas o modo de encadeamento exigir um, a função emitirá um aviso e retornará false.

Valor Retornado

Retorna os dados criptografados como uma string ou false em caso de falha.

Exemplos

Exemplo #1 Exemplo de mcrypt_encrypt()

<?php
# --- CRIPTOGRAFIA ---

# A chave deve ser binária aleatória, use scrypt, bcrypt ou PBKDF2 para
# converter uma string em uma chave.
# A chave é especificada usando hexadecimal
$key = pack('H*', "bcb04b7e103a0cd8b54763051cef08bc55abe029fdebae5e1d417e2ffb2a00a3");

# Mostra o tamanho da chave. Use chaves de 16, 24 ou 32 bytes para AES-128, 192
# e 256 respectivamente
$key_size = strlen($key);
echo
"Tamanho da chave: " . $key_size . "\n";

$plaintext = "This string was AES-256 / CBC / ZeroBytePadding encrypted.";

# Cria um IV aleatório para usar com codificação CBC
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);

# Cria um texto criptografado compatível com AES (tamanho do bloco Rijndael = 128)
# para manter o texto confidencial.
# Adequado somente para entrada codificada que nunca termina com o valor 00h
# (por causa do preenchimento padrão com zero).
$ciphertext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key,
$plaintext, MCRYPT_MODE_CBC, $iv);

# Adiciona o IV para que ele fique disponível para descriptografia
$ciphertext = $iv . $ciphertext;

# Codifica o texto criptografado resultante para que possa ser representado por uma string
$ciphertext_base64 = base64_encode($ciphertext);

echo
$ciphertext_base64 . "\n";

# === ALERTA ===

# O texto criptografado resultante não tem integridade ou autenticidade adicionada
# e não é protegido contra ataques "padding oracle".

# --- DESCRIPTOGRAFIA ---

$ciphertext_dec = base64_decode($ciphertext_base64);

# Recupera o IV, iv_size deve ser criado usando mcrypt_get_iv_size()
$iv_dec = substr($ciphertext_dec, 0, $iv_size);

# Recupera o texto criptografado (tudo, exceto o $iv_size na frente)
$ciphertext_dec = substr($ciphertext_dec, $iv_size);

# Pode remover caracteres com valor 00h do final do texto simples
$plaintext_dec = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key,
$ciphertext_dec, MCRYPT_MODE_CBC, $iv_dec);

echo
$plaintext_dec . "\n";
?>

O exemplo acima produzirá:

Tamanho da chave: 32
ENJW8mS2KaJoNB5E5CoSAAu0xARgsR1bdzFWpEn+poYw45q+73az5kYi4j+0haevext1dGrcW8Qi59txfCBV8BBj3bzRP3dFCp3CPQSJ8eU=
This string was AES-256 / CBC / ZeroBytePadding encrypted.

Veja Também

adicione uma nota

Notas Enviadas por Usuários (em inglês) 2 notes

up
63
scott at paragonie dot com
9 years ago
If you're writing code to encrypt/encrypt data in 2015, you should use openssl_encrypt() and openssl_decrypt(). The underlying library (libmcrypt) has been abandoned since 2007, and performs far worse than OpenSSL (which leverages AES-NI on modern processors and is cache-timing safe).

Also, MCRYPT_RIJNDAEL_256 is not AES-256, it's a different variant of the Rijndael block cipher. If you want AES-256 in mcrypt, you have to use MCRYPT_RIJNDAEL_128 with a 32-byte key. OpenSSL makes it more obvious which mode you are using (i.e. 'aes-128-cbc' vs 'aes-256-ctr').

OpenSSL also uses PKCS7 padding with CBC mode rather than mcrypt's NULL byte padding. Thus, mcrypt is more likely to make your code vulnerable to padding oracle attacks than OpenSSL.

Finally, if you are not authenticating your ciphertexts (Encrypt Then MAC), you're doing it wrong.

Further reading:

https://paragonie.com/blog/2015/05/using-encryption-and-authentication-correctly

https://paragonie.com/blog/2015/05/if-you-re-typing-word-mcrypt-into-your-code-you-re-doing-it-wrong
up
24
jesse at pctest dot com
20 years ago
Solving 3DES incompatibilities with .NET's TripleDESCryptoServiceProvider

mcrypt's 3DES only accepts 192 bit keys, but Microsoft's .NET and many other tools accept both 128 and 192 bit keys.
If your key is too short, mcrypt will 'helpfully' pad null characters onto the end, but .NET refuses to use a key where the last third is all null (this is a Bad Key). This prevents you from emulating mcrypt's "short key" behaviour in .NET.

How to reconcile this? A little DES theory is in order
3DES runs the DES algorithm three times, using each third of your 192 bit key as the 64 bit DES key

Encrypt Key1 -> Decrypt Key2 -> Encrypt Key3

and both .NET and PHP's mcrypt do this the same way.
The problem arises in short key mode on .NET, since 128 bits is only two 64 bit DES keys
The algorithm that they use then is:

Encrypt Key1 -> Decrypt Key2 -> Encrypt Key1

mcrypt does not have this mode of operation natively.
but before you go and start running DES three times yourself, here's a Quick Fix
<?php
$my_key
= "12345678abcdefgh"; // a 128 bit (16 byte) key
$my_key .= substr($my_key,0,8); // append the first 8 bytes onto the end
$secret = mcrypt_encrypt(MCRYPT_3DES, $my_key, $data, MCRYPT_MODE_CBC, $iv); //CBC is the default mode in .NET
?>

And, like magic, it works.

There's one more caveat: Data padding
mcrypt always pads data will the null character
but .NET has two padding modes: "Zeros" and "PKCS7"
Zeros is identical to the mcrypt scheme, but PKCS7 is the default.
PKCS7 isn't much more complex, though:
instead of nulls, it appends the total number of padding bytes (which means, for 3DES, it can be a value from 0x01 to 0x07)
if your plaintext is "ABC", it will be padded into:
0x41 0x42 0x43 0x05 0x05 0x05 0x05 0x05

You can remove these from a decrypted string in PHP by counting the number of times that last character appears, and if it matches it's ordinal value, truncating the string by that many characters:
<?php
$block
= mcrypt_get_block_size('tripledes', 'cbc');
$packing = ord($text{strlen($text) - 1});
if(
$packing and ($packing < $block)){
for(
$P = strlen($text) - 1; $P >= strlen($text) - $packing; $P--){
if(
ord($text{$P}) != $packing){
$packing = 0;
}
}
}
$text = substr($text,0,strlen($text) - $packing);
?>

And to pad a string that you intend to decrypt with .NET, just add the chr() value of the number of padding bytes:
<?php
$block
= mcrypt_get_block_size('tripledes', 'cbc');
$len = strlen($dat);
$padding = $block - ($len % $block);
$dat .= str_repeat(chr($padding),$padding);
?>

That's all there is to it.
Knowing this, you can encrypt, decrypt, and duplicate exactly any .NET 3DES behaviour in PHP.
To Top