Posts Tagged ‘criptografia’

Links encriptados no PHP

junho 11th, 2008

Nesse post vou exemplificar como utilizar a classe XOR exemplificada no post Operador XOR no PHP para criação de URLs encriptadas usando uma espécie de checksum que irá impedir que alguem possa alrera-la. as vantagens dessa técnica são:

  • URLs camufladas
  • PHP camuflado
  • Variáveis passadas pela URL sempre válidas
  • Impossibilidade de Modificação da querystring manualmente

Aqui está o exemplo de hoje: http://ferrari.eti.br/exemplos/fw1

Esse exemplo utiliza jSon, se você não sabe o que é, veja aqui.

Para começar, vamos criar o arquivo: includes/classes/crypt.php e colocar o código do post: Operador XOR no PHP.

Depois criaremos a nossa classe mais importante: includes/classes/link.php e vamos edita-lá:

// incluímos a classe de criptografia
require_once "crypt.php";
 
// Variavel global similar a $_POST, porém sua função é
// armazenar os valores passados pela querystring
$_PAR = array();
 
class Link {
     // Variável que armazena a chave do checksum
     static $chave = "chavedockecksum";
 
     // Variável que armazena o link
     var $link = '';
 
     // construtor, os parâmetros são simples
     // pagina = arquovo php a ser chamado
     // parametros: parâmetros da chamada ex: "id=10&tipo=noticia"
     function Link($pagina='', $parametros=''){
          // chama o método responsável pela criação do link
          // repassando os parâmetros
          $this->link = $this->criaLink($pagina, $parametros);
 
          // retorna o link encriptado
          return $this->link;
     }
 
     static function criaLink($pagina='', $parametros=''){
          // transforma os parâmetros em um array associativo
          parse_str($parametros, $p);
 
          // adiciono nesse array na posição "_pagina" o arquivo php
          $p["_pagina"] = $pagina;
 
          // Aqui eu adiciono uma chave calculada a partir do que tem no array $p
          // porém adiciono somente os 5 primeiros caracteres para encurtar a chave
          // esse será o parâmetro responsável por garantir a integridade
          // da informação passada
          $p["_check"] = substr(crypt(json_encode($p), Link::$chave), 0, 5);
 
         // retornamos a URL encriptando a versão codificada em json dela.
         // rootvirtual é a constante que diz qual o root do site,
         // explicarei mais abaixo de onde ela vem
         return rootvirtual . "?" . Crypt::Encrypt(json_encode($p));
     }
 
     static function trataQuery(){
          // verifica a existência de query-string e adiciona ela na variável $q
          if ($q = $_SERVER['QUERY_STRING']){
               // decodifica a string
               $p = json_decode(Crypt::Decrypt($q), true);
                    // se o retorno for um array, quer dizer que a query é parcialmente válida
                    if (is_array($p) && isset($p["_check"])){
                        // carrega a chave do vetor
                        $chave = $p["_check"];
                        // remove a chave do vetor
                        unset($p["_check"]);
                        // recalcula a chave e verifica se é diferente a chave passada
                        if (substr(crypt(json_encode($p), Link::$chave), 0, 5) != $chave)
                             // Se for, a requisição eh redirecionada para o index.
                             header ("Location: " . rootvirtual);
                        else{
                             // se for válida é criada a variável global _PAR e o vetor
                             // de parâmetros é jogado nela
                             $GLOBALS["_PAR"] = $p;
                             // sai da função
                             return true;
                        }
               }else {
                     // se não for um vetor, houve modificação da url, e a requisição
                     // é enviada para o index
                     header ("Location: " . rootvirtual);
               }
               // termina a execução e redireciona
               die();
          }
     }
}

Agora vamos para a criação de três arquivos base do site e partir para um exemplo funcional.

o arquivo: includes/config.php irá armazenar as configurações básicas do site:

// Root no servidor do site
define ("rootfisico", "/var/www/fw/");
 
// Pasta do site no servidor
define ("rootvirtual", "/fw/");
 
// As linhas abaixo são a parte interessante do sistema, pra que usar chaves
// fixas se podemos definidas randomicamente a cada acesso ao sistema?
// assim, uma url usada por uma pessoa só será valida pra ela naquele acesso
 
if (!isset($_SESSION["cryptKey"])) $_SESSION["cryptKey"] = crypt(uniqid());
if (!isset($_SESSION["cryptKey2"])) $_SESSION["cryptKey2"] = crypt(uniqid());
 
Crypt::$chave = $_SESSION["cryptKey"];
Link::$chave =  $_SESSION["cryptKey2"];

Arquivo: includes/funcoes.php

// Essa função irá retornar valores de $_POST['var'] ou $_PAR['$var']
function p($v){
	global $_POST, $_PAR;
	return isset($_POST[$v]) ? $_POST[$v] : (isset($_PAR[$v]) ? $_PAR[$v] : '');
}

Arquivo: includes/inicio.php

// Definimos o charset e inicializamos a session
header('Content-type: text/html; charset=UTF-8');
@session_start();
 
// incluímos as classes e os outros arquivos
include "funcoes.php";
include "classes/link.php";
include "config.php";
 
// agora tratamos a URL atual
Link::trataQuery();

Ufs. finalmente chegou a hora, vamos botar o sistema de Links para funcionar e vamos brincar com ele um pouco. vamos criar o arquivo /index.php

Exemplo de Link:
 
<a href="&lt;? echo Link::criaLink('') ?&gt;">Página inicial</a>
 
<a href="&lt;? echo Link::criaLink('usuarios.php', 'id=10') ?&gt;">Exemplo 1</a>
 
<a href="&lt;? echo Link::criaLink('principal.php') ?&gt;">Exemplo 2</a>
 
<a href="&lt;? echo Link::criaLink('noticia.php', 'id=10&amp;tipo=ultima&amp;skin=azul') ?&gt;">Exemplo 3</a>
 
Parabéns, a página  foi passada
<h2>Página Inicial</h2>
Nenhuma página passada, ou alguem tentou mudar a URL
 
Resultados:
 
<strong>Página:</strong>
 
<strong>Parametros:</strong>

Bom, é isso. espero que tenha sido bem explicado um exemplo funcional e arquivo para download está aqui: http://ferrari.eti.br/exemplos/fw1

Operador XOR no PHP

maio 21st, 2008

Há alguns meses estava precisando criar uma classe de criptografia e quando eu fui desenvolver eu não encontrei nenhuma criptografia veloz o suficiente, até que o Luan me mostrou uma excelente utilização para o XOR. Este operador é muito parecido com o OR, porém a sua leitura é: “OU um OU outro” e não “UM ou OUTRO” como o OR. Confira a tabela abaixo exemplificando:

false ^ false = false
false ^ true = true
true ^ true = false
true ^ false = true

Legal não? só é verdadeiro se os valores forem diferentes.

Como exemplo vamos pegar 2 valores binários, como sendo uma chave e um valor:

valor: "11010110"
chave: "10011101"

Vamos operar cada bit usando o XOR, isso irá resultar o binário “encriptado”

11010110 ^ (valor)
10011101 = (chave)
01001011    (valor encriptado)

Na terceira linha obtivemos o valor encriptado, só para demonstrar, vamos usar esse valor encriptado e dar um XOR com a chave novamente.

01001011 ^ (valor encriptado)
10011101 = (chave)
11010110   (valor novamente)

Não precisa de mais exemplos certo? é uma forma fraca, porém muito veloz de gerar criptografia, e perfeita para usarmos em coisas simples, como a criptografia de URL’s e Salts

Mas não pense que programar isso é complexo, o PHP permite que façamos esse processo usando dois caracteres.

"a" ^ "b" = "?", logo
"?" ^ "b" = "a"

Com isso vou mostrar uma classe de criptografia extremamente simples:

class Crypt {
    static $chave = "xy";
    static function StringXor($a,$b) {
        if ($a=='') return '';
        $retorno = ""; $i = strlen($a)-1; $j = strlen($b);
        do{
            $retorno .= ($a{$i} ^ $b{$i % $j});
        }while ($i--);
        return strrev($retorno);
    }
    static function Encrypt($string) {
        return base64_encode(Crypt::StringXor($string, Crypt::$chave));
    }
    static function Decrypt($string) {
        return Crypt::StringXor(base64_decode($string), Crypt::$chave);
    }
}

O que essa classe faz basicamente é percorrer as strings da chave e do valor passado, calculando para cada caractere o seu valor encriptado, e ao final é codificado usando-se base64 para que não fique com caracteres inválidos na string.

Um exemplo:

texto = "andre"
chave = "xy"
resultado:
a ^ x
n ^ y
d ^ x
r ^ y
e ^ x

Código php:

$a = Crypt::Encrypt("andre");
echo "Encriptado:";
$b = Crypt::Decrypt($a);
echo "Decriptado: $b";

Saída:

Encriptado: GRccCx0=
Decriptado: andre

é isso, testem, entendam e qualquer coisa pergunte.