Incorreto, o tamanho da chave ao portar Crypto++ criptografia AES para PHP mcrypt
Pergunta
Anteriormente eu consegui porta alguns C++ CryptoPP Rijndael_128 CBC código para MCrypt PHP, mas agora eu estou tendo problemas com o modo CFB.O C++ e PHP resultados não coincidem (bem, o primeiro byte corresponde, mas isso poderia ser uma coincidência, tudo o resto não).Com alguns diagnósticos, parece que o PHP mcrypt não é definir o comprimento da chave corretamente?
Aqui está o C++ (diagnóstico e diversos removido por simplicidade):
CFB_Mode<AES>::Encryption encryptor(g_encrypt_key, AES::DEFAULT_KEYLENGTH, g_encrypt_iv);
StringSource ss( sInput.c_str(), true,
new StreamTransformationFilter( encryptor,
new HexEncoder( new StringSink( sEncryptedOut ) )
));
E aqui está o PHP:
$cipher = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CFB, '')
mcrypt_generic_init($cipher, $g_encrypt_key, $g_encrypt_iv);
$sEncryptedOutput = mcrypt_generic( $cipher, $sInput);
mcrypt_generic_deinit($cipher);
mcrypt_module_close($cipher);
g_encrypt_key
e g_encrypt_iv
são ambos de 16 bytes e bytes correspondência para o C++ e PHP versões.Para a versão de PHP é uma string binária construída a partir de bytes (sim, eu tenho verificado estes são idênticos).
Eu adicionei chamadas para o PHP versão para verificar $cipher
's tamanho do bloco, tamanho da chave, etc.O tamanho do bloco e iv, tamanho 16;suportados tamanhos de chave são relatados como 16, 24 e 32, tudo como esperado.
Onde eu acho que o problema é que o algoritmo está sendo relatado como um de 32 bytes.Olhando para o mcrypt docs, a única maneira de definir o algoritmo é através do fornecimento de uma chave do tamanho necessário.Mas estou passando uma chave de 16 bytes!Então, porque é relatar a presença de uma versão de 32 bytes de chave?Se CFB modo deve usar uma versão de 32 bytes de chave e, em seguida, por que CryptoPP aceitá-lo como tá?Qual é a solução?Posso forçar o PHP para usar a chave de 16 bytes que foi fornecido?Ou existe um parâmetro que eu estou ausente que é padrão para uma configuração diferente no CryptoPP que em MCrypt?
Eu estou usando o modo CFB porque eu quero minimizar o comprimento dos dados criptografados resultantes.A poucos bytes de preenchimento introduziria, não importa nesse aplicativo.
Eu preciso ser capaz de criptografar/descriptografar em C++, mas apenas criptografar em PHP.AES é, sem dúvida, um exagero para meu aplicativo - o mínimo que eu preciso é "um bom misturar os bytes" para que a função de bytes individuais em que os dados não são óbvias.
Solução
Já faz algum tempo, mas tive alguns problemas semelhantes com McRypt e OpenSSL usando o CFB há alguns anos. No final, descobri que o MCRYPT usava um tamanho de cadeia de feedback padrão diferente do OpenSSL no modo CFB. Ou seja, acredito que um OpenSSL AES128 no CFB usou um tamanho de bloco e tamanho de feedback de 128 bits, enquanto McRypt usou um tamanho de bloco de 128 bits e um tamanho de feedback de 8 bits. Não tenho como confirmar isso, foi apenas especulação na época com base na leitura de algumas postagens antigas do fórum. Independentemente da verdade dessa teoria, eu não era a única pessoa ou primeiro a ter essa questão em particular.
A solução para mim era usar o NOFB como você. De acordo com Referência da biblioteca PHP McRypt MCRYPT_MODE_NOFB
força a cadeia de feedback a igualar o tamanho do bloco do algoritmo, neste caso um bloco/feedback de 128 bits para o AES128 (Rijndael), que corresponde ao que o MANPAGE Para o módulo McRypt, declara sobre Nofb. Isso é bom, pois tudo o que achei que o feedback nofb é síncrono com o tamanho do bloco. Assim, o MCRYPT e o OpenSSL no NOFB agora eram de 128 bits -chave/iv/bloqueio/feedback para o AES128 e tudo funcionou bem.
No que diz respeito ao relatório de PHP de 256 bits (32 bytes), a função que retorna o tamanho da chave atual do algoritmo cifra realmente retorna o tamanho máximo da chave, que não está claramente declarado na documentação. Eu sei disso porque minha pequena classe que uso o tempo todo agora para vários projetos funciona perfeitamente bem com o OpenSSL e quaisquer outras bibliotecas da AES no CBC ou NOFB. Não seria esse o caso se McRypt estivesse preenchendo minha chave de 128 bits (16 char) com 128 bits adicionais de corda nula, ou o que quer que seja, e não estaria tecnicamente correto de qualquer maneira.
Não é realmente uma boa resposta, mas o melhor que tive baseado em uma incursão muito amadora na criptografia há vários anos.
Outras dicas
Confira phpseclib:
http://phpseclib.sourceforge.net/
Você pode definir o tamanho da chave e o tamanho do bloqueio para o que quiser.
por exemplo. $ aes-> setKeyLength (128) ou $ aes-> setKeyLength (256);
Eu tive esse problema - par de pontos.Por padrão o PHP Rijndael modo define o ciclo de feedback para 8bits - para ser AES é necessário ser o mesmo comprimento que o IV/Chave.
Você pode fazer isso usando o modo 'ncfb" em vez de " cfb " ou MCRYPT_MODE_CFB.
Detalhes completos da escrita aes_cfb_128 compatível com o PHP estão em Segurança Stackexchange pergunta: aes cfb 128 descriptografia /problema de criptografia entre Erlang e PHP.O curto do que é (de Tom Alho-porro):
...para tanto CFB e OFB (que são distintos uns dos outros e não podem ser usados de forma intercambiável), você terá de se preocupar com o "feedback comprimento" o que não é, necessariamente, documentado com grande clareza em várias bibliotecas de criptografia.A criptografia e a descriptografia deve usar a mesma resposta de comprimento para interoperar.