Pergunta

Não sei muito sobre criptografia, mas consegui fazer com que o AES trabalhasse no PHP ... um pouco. Aqui estão algumas funções que estou usando:

function aes_decrypt($val,$ky) 
{ 
    $key="\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; 
    for($a=0;$a<strlen($ky);$a++) 
      $key[$a%16]=chr(ord($key[$a%16]) ^ ord($ky[$a])); 
    $mode = MCRYPT_MODE_ECB; 
    $enc = MCRYPT_RIJNDAEL_128; 
    $dec = @mcrypt_decrypt($enc, $key, $val, $mode, @mcrypt_create_iv( @mcrypt_get_iv_size($enc, $mode), MCRYPT_RAND) ); 
    return rtrim($dec,(( ord(substr($dec,strlen($dec)-1,1))>=0 and ord(substr($dec, strlen($dec)-1,1))<=16)? chr(ord( substr($dec,strlen($dec)-1,1))):null)); 
} 

function aes_encrypt($val,$ky) 
{ 
    $key="\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; 
    for($a=0;$a<strlen($ky);$a++) 
      $key[$a%16]=chr(ord($key[$a%16]) ^ ord($ky[$a])); 
    $mode=MCRYPT_MODE_ECB; 
    $enc=MCRYPT_RIJNDAEL_128; 
    $val=str_pad($val, (16*(floor(strlen($val) / 16)+(strlen($val) % 16==0?2:1))), chr(16-(strlen($val) % 16))); 
    return mcrypt_encrypt($enc, $key, $val, $mode, mcrypt_create_iv( mcrypt_get_iv_size($enc, $mode), MCRYPT_RAND)); 
} 

Estes são ligeiramente modificados de um Comente na página de documentação do PHP para McRypt. (Mudei de dev_urandom para rand, pois estou em uma caixa do Windows, onde dev_urandom não está disponível.)

De qualquer forma, a chave que eu uso nessas funções é definida assim:

define("PSK", pack("H*", "abcd7b5ca46e12345678a8161fdacee9"));

Eu chamo minha função assim:

echo bin2hex(aes_encrypt("wootwootwootwootwootwootwoo", PSK));

Agora, os primeiros 16 bytes (32 dígitos) da sequência hexadecipal resultante estão bem. Os próximos 16 bytes não correspondem ao que é esperado.

Veja, estou postando esses dados em um serviço da Web externo que os descriptografa. Eu (infelizmente) não posso dar o caso de teste que tenho sem distribuir minha chave de criptografia e dados. Sinto muito por isso, mas espero que alguém familiarizado com McRypt possa olhar para isso e me dizer o que estou fazendo de errado.

Novamente, desculpe pela falta de um caso de teste sólido, mas agradeço muito qualquer ajuda que você possa dar!

EDITAR: Parece que meu provedor que estou postando está usando um IV nulo. Seguindo o conselho de Rook, mudei para o modo CBC e removi o código desnecessário relacionado à chave. Aqui estão minhas novas funções:

function aes_decrypt($val,$key)
{
    $mode = MCRYPT_MODE_CBC;
    $enc = MCRYPT_RIJNDAEL_128; 
    $dec = @mcrypt_decrypt($enc, $key, $val, $mode, null); 
    return rtrim($dec,(( ord(substr($dec,strlen($dec)-1,1))>=0 and ord(substr($dec, strlen($dec)-1,1))<=16)? chr(ord( substr($dec,strlen($dec)-1,1))):null)); 
}

function aes_encrypt($val,$key) 
{
    $mode = MCRYPT_MODE_CBC;
    $enc=MCRYPT_RIJNDAEL_128; 
    $val=str_pad($val, (16*(floor(strlen($val) / 16)+(strlen($val) % 16==0?2:1))), chr(16-(strlen($val) % 16))); 
    return mcrypt_encrypt($enc, $key, $val, $mode, null); 
}
Foi útil?

Solução

É provável que esse serviço de criptografia esteja usando um modo de operação de cifra de bloco diferente, como a CBC. Se um IV nulo estiver sendo usado com o modo CBC, o primeiro bloco (neste caso 16 bytes) do BCE e CBC produzirá o mesmo texto cifra. O modo BCE nunca deve ser usado por ninguém por qualquer motivo.

Aqui está um exemplo de mensagem criptografada do modo BCE:

alt text

Outras dicas

Eu e uma faculdade em que codifica um aplicativo para iPhone e onde usando os métodos acima para criptografar e descriptografar dados. Mas encontramos um problema quando eu estava criptografando os dados para serem lidos no iPhone dele. O iPhone usou o preenchimento PKCS7. O código acima estava adicionando preenchimento extra, isso falharia que o método de descriptografia do iPhone falhasse. Alteramos o código para corrigir o problema atual:

public static function  aes128Encrypt($key,$val) 
{
    $mode = MCRYPT_MODE_CBC;
    $enc=MCRYPT_RIJNDAEL_128; 
    $blocksize= mcrypt_get_block_size($enc,$mode);
    $stringLength = strlen($val);
    $paddingLength =$blocksize-($stringLength%$blocksize);
    $val=str_pad($val,$paddingLength+$stringLength,chr($paddingLength));
    return base64_encode(mcrypt_encrypt($enc, $key, $val, $mode, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0")); 
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top