Q:

Criptografar / Descriptografar ID de autoincrement do MYSQL / PHP

Preciso criptografar/descriptografar o ID original do MySQL impresso no HTML, para posteriormente reverter e receber o ID original no back-end.
Ex:
$var = $arr['id']; // 120

<table>
  <tr>
    <td>Logradouro tal e tal, 123</td>
    <td> <button class='excluirRegistro' data-id='<?php echo $var; ?>'>Excluir</button> </td> // data-id='120'
  </tr>
</table>

Gostaria de criptografar para algo do tipo:
$varCrypt = funcao( $var, 'crypt' ); // 012980123324312

<table>
  <tr>
    <td>Logradouro tal e tal, 123</td>
    <td> <button class='excluirRegistro' data-id='<?php echo $var; ?>'>Excluir</button> </td> // data-id='012980123324312'
  </tr>
</table>

Posteriormente receber na variável:
$id = $_GET['idregistro']; // 012980123324312
$id = funcao( $id, 'decrypt' );
$id = "120"; // ID original

O cenário é o seguinte, uma tabela com os registros de endereços cadastrados pelo usuário, com um botão relacionado para editar e excluir o registro.

A:

Sem ser rude, mas já sendo: se você consegue descriptografar alguma coisa, o seu algoritmo de criptografia é uma porcaria mesmo.
Os algoritmos de hoje, os mais seguros, são one-way. Isso quer dizer que não dá pra voltar. Uma vez criptografado, não dá pra "descriptografar".
O que as aplicações fazem é comparar os hash do que é criptografado, se der um match okay, se não sinto muito.
O que você pode fazer, no máximo, é criptografar o ID que está sendo enviado no formulário. O hash gerado vai ser comparado com o hash guardado no banco de dados e aí você faz o que quiser. Lembre que você tem que usar as mesmas funções de criptografia.
Se você guardou o ID no banco de dados com SHA256, você deve encriptar o formulário com SHA256.
Em PHP:
<?php

$hash_id_do_formulario = hash("sha256", $_POST['id_do_formulario']);

// Procura no banco de dados pelo mesmo hash depois
$query = "DELETE FROM minha_tabela WHERE ID = :hash_formulario";

$statement = $minha_conexao_pdo->prepare($query);

$statement->bindParam(':hash_formulario', $hash_id_do_formulario);

$statement->execute();

Pesquise pela função hash em PHP.
Descrição da documentação do PHP:
string hash ( string $algo , string $data [, bool $raw_output = FALSE ] )

A:

A resposta marcada correta tem alguns erros, na minha opinião, que resolvi dar uma outra resposta.

O mt_rand() (e o str_shuffle()) é previsível, uma pessoa com acesso a algumas resposta poderá conseguir a seed utilizada, por exemplo usando o UnTwister ou o PHP_MT_SEED Cracker, fora outras diversas maneiras.
Seu código está publico, então algo como (date('s') + date('i') * 10000) é  inútil, afinal as chances dos nossos relógios estarem diferentes é desprezível.
O strrev() não irá adicionar nenhuma segurança, isso é pior do que o Cifra de Cesar, porque ela pelo menos tinha "alguma chave".
Quando você exectar o SELECT, como SELECT * FROM tabela WHERE token = $token, você estará claramente vulnerável a timing-attack, um usuário poderá obter informações através do tempo consumido para executar as queries.

Uma solução seria criar dois identificadores e buscar por eles, sendo um deles comparado de maneira segura, com o hash_equals.
Crie dois identificadores:
$pesquisar = random_bytes(8);
$confirmar = random_bytes(24);
$confirmar_hashed = hash("sha256", $confirmar, true);

Então insira ele no banco de dados, como:
INSERT tabela (`pesquisar`, `confirmar`) VALUES ($pesquisar, $confirmar_hashed)

O usuário deve receber os valores de $pesquisar e $confirmar, considerando que isto seja passado em URL, seria como:
seusite.com/?pesquisar=$pesquisar&confirmar=$confirmar

Lembrando que ambos devem ser únicos, o $pesquisar tem a mesma capacidade de um int64, ou BIGINT no caso do MySQL.
Pesquise pelo valor:
Para pesquisar, utilize o pesquisar como parâmetro principal, tal como:
SELECT * FROM tabela WHERE pesquisar = $pesquisar

Então compare o confirmar usando o hash_equals, como:
$stmt = $mysqli->prepare('SELECT confirmar FROM tabela WHERE pesquisar = ?')
$stmt->bind_param("s", $_GET['pesquisar']);

$stmt->execute();
$stmt->bind_result($confirmar_hashed);
$stmt->fetch();

if(hash_equals($confirmar_hashed, hash("sha256", $_GET['confirmar'], true)) === false){
    echo 'Valor de "confirmar" é incorreto';
}

Por mim isto seria minimamente seguro. Claro, pressupondo que esteja utilizando um sistema operacional seguro, o random_bytes se escora no /dev/urandom.
EDIT (2020-08-22): Após revisar, notei que não foi assumido que poderia haver um ataque de "somente-leitura". Modifiquei a resposta para assumir esta possibilidade. Foi adicionado o uso do hash("sha256", ...) para impedir um ataque de somente-leitura, como um "Read-Only SQL Injection". Isto supõe que o atacante tenha alguma acesso de leitura aos bancos de dados, mas não de edição. Neste cenário e com o uso de hash, o invasor terá apenas acesso aos dados que são resultado de uma hash (o $confirmar_hashed), portanto ele não terá o valor original (o $confirmar). Na versão anterior, e nestas condições,o atacante teria acesso aos códigos, normalmente.

