Ir para conteúdo
Fórum Script Brasil
  • 0

SHA-1, Secure Hash Algorithm


neto.joaobatista

Pergunta

Bom, aqui vai uma implementação do hash SHA-1, estou trabalhando na serie SHA-2 (atualmente SHA-256 e futuramente SHA-512).

O código abaixo é para quem gosta de saber o que acontece debaixo dos panos quando você usa uma função nativa ou quando a função nativa não está disponível no seu servidor...

<?php
 /**
  * Implementação PHP do Secure Hash Algorithm segundo a Secure Hash Standard (SHS) (FIPS PUB 180-3) de outubro de 2008.
  * <p>
  * Nessa primeira versão está sendo implementado apenas o hash SHA-1, a proxima versão já contará com SHA-256
  * e futuramente SHA-384 e SHA-512
  * </p>
  *
  * @version 0.1
  * @author João Batista Neto <neto.joaobatista@gmail.com>
  * @since 2009-08-06
  * @license LGLP
  * @link http://csrc.nist.gov/publications/fips/fips180-3/fips180-3_final.pdf
  * @category Computer Security, Cryptography, Hash.
  */
 abstract class SecureHash {
     /**
      * Identifica o hash SHA-1
      */
     const SHA_1        = "sha1";

     /**
      * Identifica o hash SHA-256
      */
     const SHA_256    = "sha256";

     /**
      * Implementação do algorítimo de via única SHA-1 (Secure Hash Algorithm 1) definido pela especificação FIPS 180-3
      * <p>
      * Message Size: < 2**64
      * Block Size: 512 bits
      * Word Size: 32 bits
      * Message Digest Size: 160 bits
      * </p>
      * @link http://csrc.nist.gov/publications/fips/fips180-3/fips180-3_final.pdf
      * @param $message
      * @return string
      */
     static public function sha1( $message ){
         /**
          * Pre-processamento
          */
         $M = self::pre_process( $message );

         /**
          * Define os valores iniciais [5.3.1]
          */
         $H = array( 0x67452301 , 0xefcdab89 , 0x98badcfe , 0x10325476 , 0xc3d2e1f0 );

         /**
          * Calculando o Hash [6.1.2]
          */
         for ( $i = 0 , $N = count( $M ); $i < $N; $i += 16 ){
             $W = array();

             /**
              * [6.1.2.1]
              */
             for ( $t = 0; $t < 80; $t++ ){
                 $W[ $t ] = ( $t <= 15 ) ? $M[ $i + $t ] : self::ROTL( $W[ $t - 3 ] ^ $W[ $t - 8 ] ^ $W[ $t - 14 ] ^ $W[ $t - 16 ] , 1 );
             }

             /**
              *  [6.1.2.2]
              */
             $a = $H[ 0 ];
             $b = $H[ 1 ];
             $c = $H[ 2 ];
             $d = $H[ 3 ];
             $e = $H[ 4 ];

             /**
              * [6.1.2.3]
              */
             for ( $t = 0; $t < 80; $t++  ){
                 $T = self::add( self::add( self::ROTL( $a , 5 ) , self::f( $t , $b , $c , $d ) ) , self::add( self::add( $e , $W[ $t ] ) , self::Kt( $t ) ) );
                 $e = $d;
                 $d = $c;
                 $c = self::ROTL( $b , 30 );
                 $b = $a;
                 $a = $T;
             }

             /**
              * [6.1.2.4]
              */
             $H[ 0 ] = self::add( $H[ 0 ] , $a );
             $H[ 1 ] = self::add( $H[ 1 ] , $b );
             $H[ 2 ] = self::add( $H[ 2 ] , $c );
             $H[ 3 ] = self::add( $H[ 3 ] , $d );
             $H[ 4 ] = self::add( $H[ 4 ] , $e );
         }

         return ( sprintf( "%08x%08x%08x%08x%08x" , $H[ 0 ] , $H[ 1 ] , $H[ 2 ] , $H[ 3 ] , $H[ 4 ] ) );
     }

     /**
      * Pre-processamento [5]
      * @return array
      */
     static private function pre_process( $message ){
         $size = strlen( $message );
         $M = array();
         $N = ( ( $size + 8 ) >> 6 ) + 1;

         /**
          * [5.1.1]
          */
         $message .= "x80";

         for ( $i = 0; $i < $N * 16; $i++  ) $M[ $i ] = 0;
         for ( $i = 0; $i < $size; $i++  ) $M[ $i >> 2 ] |= ord( $message{ $i } ) << ( 24 - ( $i % 4 ) * 8 );

         $M[ $i >> 2 ] |= 0x80 << ( 24 - ( $i % 4 ) * 8 );
         $M[ $N * 16 - 1 ] = $size * 8;

         return( $M );
     }

     /**
      * Operação AND [3.2.2]
      * Z = (X + Y) mod 2^32
      * @param integer $x
      * @param integer $y
      * @return integer O novo valor
      */
     static private function add( $x , $y ){
         $lsw = ( $x & 0xffff ) + ( $y & 0xffff );
         $msw = ( $x >> 16 ) + ( $y >> 16 ) + ( $lsw >> 16 );

         return ( ( $msw << 16 ) | ( $lsw & 0xFFFF ) );
     }

     /**
      * Operação Right Shift [3.2.3]
      * @param $x
      * @param $n
      * @return integer
      */
     static private function SHR( $x , $n ){
         $z = hexdec( 80000000 );

         if ( $z & $x ){
             $x = ( $x >> 1 );
             $x &= ~$z;
             $x |= 0x40000000;
             $x = ( $x >> ( $n - 1 ) );
         } else {
             $x = ( $x >> $n );
         }

         return( $x );
     }

     /**
      * Operação Circular Right Shift [3.2.4]
      * @param integer $x
      * @param integer $n
      * @return integer
      */
     static private function ROTR( $x , $n ){
         return( ( self::SHR( $x , $n ) | ( $x << ( 32 - $n ) ) & 0xFFFFFFFF ) );
     }

     /**
      * Operação Circular Left Shift [3.2.5]
      * @param integer $num
      * @param integer $n
      * @return integer
      */
     static private function ROTL( $x , $n ){
         return ( ( $x << $n ) | self::SHR( $x , 32 - $n ) );
     }

     /**
      * Função f [4.1.1]
      * @param $t
      * @param $b
      * @param $c
      * @param $d
      * @return integer
      */
     static private function f( $t , $b , $c , $d ){
         if ( ( $t >=  0 ) && ( $t <= 19 ) ) return ( self::Ch( $b , $c , $d ) );
         if ( ( $t >= 20 ) && ( $t <= 39 ) ) return ( self::Parity( $b , $c , $d ) );
         if ( ( $t >= 40 ) && ( $t <= 59 ) ) return ( self::Maj( $b , $c , $d ) );
         if ( ( $t >= 60 ) && ( $t <= 79 ) ) return ( self::Parity( $b , $c , $d ) );
     }

     /**
      * Ch [4.1.1]
      * @param integer $x
      * @param integer $y
      * @param integer $z
      * @return integer
      */
     static private function Ch( $x , $y , $z ){
         return ( ( $x & $y ) ^ ( ~$x & $z ) );
     }

     /**
      * Parity [4.1.1]
      * @param integer $x
      * @param integer $y
      * @param integer $z
      * @return integer
      */
     static private function Parity( $x , $y , $z ){
         return ( $x ^ $y ^ $z );
     }

     /**
      * Maj [4.1.1]
      * @param integer $x
      * @param integer $y
      * @param integer $z
      * @return integer
      */
     static private function Maj( $x , $y , $z ){
         return ( ( $x & $y ) ^ ( $x & $z ) ^ ( $y & $z ) );
     }

     /**
      * Sigma{256} 0 [4.1.2]
      * @param integer $x
      * @return integer
      */
     static private function Sigma_0( $x ){
         return( ( self::ROTR( $x , 2 ) ^ self::ROTR( $x , 13 ) ^ self::ROTR( $x , 22 ) ) );
     }

     /**
      * Sigma{256} 1 [4.1.2]
      * @param integer $x
      * @return integer
      */
     static private function Sigma_1( $x ){
         return( ( self::ROTR( $x , 6 ) ^ self::ROTR( $x , 11 ) ^ self::ROTR( $x , 25 ) ) );
     }

     /**
      * sigma{256} 0 [4.1.2]
      * @param integer $x
      * @return integer
      */
     static private function sigma0( $x ){
         return( ( self::ROTR( $x , 7 ) ^ self::ROTR( $x , 18 ) ^ ( self::SHR( $x , 3 ) ) ) );
     }

     /**
      * sigma{256} 1 [4.1.2]
      * @param integer $x
      * @return integer
      */
     static private function sigma1( $x ){
         return( ( self::ROTR( $x , 17 ) ^ self::ROTR( $x , 19 ) ^ ( self::SHR( $x , 10 ) ) ) );
     }

     /**
      * Recupera o valor da constante Kt [4.2.1] e [4.2.2]
      * @param integer $t
      * @param string $type
      * @return integer
      */
     static private function Kt( $t , $type = self::SHA_1 ){
         /**
          * Kt [4.2.1]
          */
         $k_SHA1        = array( 0x5a827999 , 0x6ed9eba1 , 0x8f1bbcdc , 0xca62c1d6 );

         /**
          * Kt [4.2.2]
          */
         $k_SHA256    = array(
             0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
             0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
             0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
             0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
             0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
             0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
             0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
             0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
         );

         /**
          * Retorna a constante segundo o hash usado
          */
         switch ( $type ){
             case self::SHA_1 :
                 if ( ( $t >=  0 ) && ( $t <= 19 ) ) return ( $k_SHA1[ 0 ] );
                 if ( ( $t >= 20 ) && ( $t <= 39 ) ) return ( $k_SHA1[ 1 ] );
                 if ( ( $t >= 40 ) && ( $t <= 59 ) ) return ( $k_SHA1[ 2 ] );
                 if ( ( $t >= 60 ) && ( $t <= 79 ) ) return ( $k_SHA1[ 3 ] );

                 throw new UnexpectedValueException( sprintf( "O valor %08x não era esperado." , $t ) );
             case self::SHA_256:
                 return( $k_SHA256[ $t ] );
         }
     }
 }
Agora fazendo o cálculo:
$message = "João Batista Neto";

printf( "nativo: %s\nSHA-1: %s\n" , sha1( $message ) , SecureHash::sha1( $message ) );

A saída será:

nativo: f0c8faeacb1df5cebc50c63d1d9aef0f0266535d

SHA-1: f0c8faeacb1df5cebc50c63d1d9aef0f0266535d

Link para o comentário
Compartilhar em outros sites

0 respostass a esta questão

Posts Recomendados

Até agora não há respostas para essa pergunta

Participe da discussão

Você pode postar agora e se registrar depois. Se você já tem uma conta, acesse agora para postar com sua conta.

Visitante
Responder esta pergunta...

×   Você colou conteúdo com formatação.   Remover formatação

  Apenas 75 emoticons são permitidos.

×   Seu link foi incorporado automaticamente.   Exibir como um link em vez disso

×   Seu conteúdo anterior foi restaurado.   Limpar Editor

×   Você não pode colar imagens diretamente. Carregar ou inserir imagens do URL.



  • Estatísticas dos Fóruns

    • Tópicos
      152,3k
    • Posts
      652,3k
×
×
  • Criar Novo...