Você pode converter a saída de php cript () para md5 válido?
-
19-08-2019 - |
Pergunta
Eu tenho algumas cordas que foram criptografadas usando o Função PHP crypt()
.
As saídas se parecem com a seguinte:
$1$Vf/.4.1.$CgCo33ebiHVuFhpwS.kMI0
$1$84..vD4.$Ps1PdaLWRoaiWDKCfjLyV1
$1$or1.RY4.$v3xo04v1yfB7JxDj1sC/J/
Enquanto eu acredito que o Crypt () está usando o algoritmo MD5, as saídas não são hashes md5 válidos.
Existe uma maneira de converter os hashes produzidos em hashes md5 válidos (valores de 16 bytes)?
Atualizar:
Obrigado pelas respostas, então as respostas até agora. Tenho certeza de que a função de cripta usada está usando algum tipo de algoritmo MD5. O que estou procurando fazer é converter o grupo que tenho em um hash do MD5 que se parece com o seguinte:
9e107d9d372bb6826bd81d3542a419d6
e4d909c290d0fb1ca068ffaddf22cbd0
d41d8cd98f00b204e9800998ecf8427e
(Tirado de Wikipedia)
Existe uma maneira de se converter dos hashes que tenho para aqueles como o acima?
Solução
OK, então talvez essa resposta esteja um ano atrasada, mas eu vou tentar. Em sua própria resposta, você observa que crypt()
está usando o FreeBSD MD5, que também faz algumas transformações interessantes no sal antes de executar o hash, então o resultado do que estou prestes a dar você nunca combinará com os resultados de uma chamada para md5()
. Dito isto, a única diferença entre a saída que você está vendo e o formato que você está acostumado é que a saída que você está vendo é codificada da seguinte maneira
$1$ # this indicates that it is MD5
Vf/.4.1. # these eight characters are the significant portion of the salt
$ # this character is technically part of the salt, but it is ignored
CgCo33eb # the last 22 characters are the actual hash
iHVuFhpw # they are base64 encoded (to be printable) using crypt's alphabet
S.kMI0 # floor(22 * 6 / 8) = 16 (the length in bytes of a raw MD5 hash)
Que eu saiba, o alfabeto usado pela cripta é assim:
./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
Então, com tudo isso em mente, aqui está como você pode converter o hash de 22 caracteres da cripta-Base64 em um hash de 32 caracteres base16 (hexadecimal):
Primeiro, você precisa de algo para converter o Base64 (com alfabeto personalizado) em um hash de 16 bytes MD5.
define('CRYPT_ALPHA','./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz');
/**
* Decodes a base64 string based on the alphabet set in constant CRYPT_ALPHA
* Uses string functions rather than binary transformations, because said
* transformations aren't really much faster in PHP
* @params string $str The string to decode
* @return string The raw output, which may include unprintable characters
*/
function base64_decode_ex($str) {
// set up the array to feed numerical data using characters as keys
$alpha = array_flip(str_split(CRYPT_ALPHA));
// split the input into single-character (6 bit) chunks
$bitArray = str_split($str);
$decodedStr = '';
foreach ($bitArray as &$bits) {
if ($bits == '$') { // $ indicates the end of the string, to stop processing here
break;
}
if (!isset($alpha[$bits])) { // if we encounter a character not in the alphabet
return false; // then break execution, the string is invalid
}
// decbin will only return significant digits, so use sprintf to pad to 6 bits
$decodedStr .= sprintf('%06s', decbin($alpha[$bits]));
}
// there can be up to 6 unused bits at the end of a string, so discard them
$decodedStr = substr($decodedStr, 0, strlen($decodedStr) - (strlen($decodedStr) % 8));
$byteArray = str_split($decodedStr, 8);
foreach ($byteArray as &$byte) {
$byte = chr(bindec($byte));
}
return join($byteArray);
}
Agora que você tem os dados brutos, precisará de um método para convertê-los no formato Base-16 que está esperando, o que não poderia ser mais fácil.
/**
* Takes an input in base 256 and encodes it to base 16 using the Hex alphabet
* This function will not be commented. For more info:
* @see http://php.net/str-split
* @see http://php.net/sprintf
*
* @param string $str The value to convert
* @return string The base 16 rendering
*/
function base16_encode($str) {
$byteArray = str_split($str);
foreach ($byteArray as &$byte) {
$byte = sprintf('%02x', ord($byte));
}
return join($byteArray);
}
Finalmente, como a saída da cripta inclui muitos dados de que não precisamos (e, de fato, não podem usar) para esse processo, uma função curta e doce não apenas vincula esses dois, mas também para permitir a entrada direta da saída de cripta.
/**
* Takes a 22 byte crypt-base-64 hash and converts it to base 16
* If the input is longer than 22 chars (e.g., the entire output of crypt()),
* then this function will strip all but the last 22. Fails if under 22 chars
*
* @param string $hash The hash to convert
* @param string The equivalent base16 hash (therefore a number)
*/
function md5_b64tob16($hash) {
if (strlen($hash) < 22) {
return false;
}
if (strlen($hash) > 22) {
$hash = substr($hash,-22);
}
return base16_encode(base64_decode_ex($hash));
}
Dadas essas funções, a representação base16 de seus três exemplos é:
3ac3b4145aa7b9387a46dd7c780c1850
6f80dba665e27749ae88f58eaef5fe84
ec5f74086ec3fab34957d3ef0f838154
Obviamente, é importante lembrar que eles sempre eram válidos, apenas formatados de maneira diferente.
Outras dicas
$ 1 $ realmente significa que este é um hash do MD5, mas a cripta gera um sal aleatório. É por isso que você encontra um valor MD5 diferente. Se você incluir o sal gerado, encontrará o mesmo resultado.
O sal é base64 codificado na saída, como o hash.
O algoritmo usado é um parâmetro amplo do sistema. Geralmente é MD5, você está certo.
Acredito que a resposta para minha pergunta original é não, você não pode se converter de um formato para o outro.
Os hashes gerados por php Crypt () parecem ser gerados por uma versão da implementação do hash FreeBSD MD5 criada pelo Kamp de Henning.
A partir da documentação, isso depende do sistema. Você pode forçar o algoritmo usado definindo o parâmetro de sal. Dos documentos:
O tipo de criptografia é desencadeado pelo argumento do sal. No momento da instalação, o PHP determina os recursos da função da cripta e aceitará sais para outros tipos de criptografia. Se nenhum sal for fornecido, o PHP gerará automaticamente um sal padrão de dois caracteres por padrão, a menos que o tipo de criptografia padrão no sistema seja MD5, caso em que um sal compatível com MD5 aleatório será gerado.
A partir de http://php.net/crypt:
Crypt () retornará uma string criptografada usando o algoritmo de criptografia baseado em UNIX DEIX ou algoritmos alternativos que podem estar disponíveis no sistema.
Você quer o md5()
função:
Calcula o hash do MD5 de STR usando o algoritmo de mession-digest »RSA Data Security, Inc. MD5 e retornos que hash.
Se o RAW_OUTPUT opcional for definido como true, o MD5 Digest será retornado em formato binário bruto com um comprimento de 16. Padrões para false.