Ir para conteúdo

POWERED BY:

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

João Batista Neto

[Resolvido] SHA-1, Secure Hash Algorithm

Recommended Posts

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: %snSHA-1: %sn" , sha1( $message ) , SecureHash::sha1( $message ) );

A saída será:

 

nativo: f0c8faeacb1df5cebc50c63d1d9aef0f0266535d

SHA-1: f0c8faeacb1df5cebc50c63d1d9aef0f0266535d

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.