Don't like ads? PRO users don't see any ads ;-)
Guest

Untitled

By: a guest on May 7th, 2012  |  syntax: None  |  size: 7.96 KB  |  hits: 14  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. #--
  2. # sha2.rb - defines Digest::SHA2 class which wraps up the SHA256,
  3. #           SHA384, and SHA512 classes.
  4. #++
  5. # Copyright (c) 2006 Akinori MUSHA <knu@iDaemons.org>
  6. #
  7. # All rights reserved.  You can redistribute and/or modify it under the same
  8. # terms as Ruby.
  9. #
  10. #   $Id: sha2.rb 11708 2007-02-12 23:01:19Z shyouhei $
  11.  
  12. require 'digest'
  13. #require 'ext/digest/sha2/sha2'
  14.  
  15. module Digest
  16.   #
  17.   # A meta digest provider class for SHA256, SHA384 and SHA512.
  18.   #
  19.   class SHA2 < Digest::Class
  20.  
  21.     SHA384_BLOCK_LENGTH = 128
  22.     SHA384_DIGEST_LENGTH = 48
  23.     SHA384_DIGEST_STRING_LENGTH = (SHA384_DIGEST_LENGTH * 2 + 1)
  24.     SHA512_BLOCK_LENGTH = 128
  25.     SHA512_DIGEST_LENGTH = 64
  26.     SHA512_DIGEST_STRING_LENGTH = (SHA512_DIGEST_LENGTH * 2 + 1)
  27.    
  28.     # call-seq:
  29.     #     Digest::SHA2.new(bitlen = 256) -> digest_obj
  30.     #
  31.     # Creates a new SHA2 hash object with a given bit length.
  32.     def initialize(bitlen = 256)
  33.       case bitlen
  34.       when 256
  35.         @sha2 = Digest::SHA256.new
  36.       when 384
  37.         @sha2 = Digest::SHA384.new
  38.       when 512
  39.         @sha2 = Digest::SHA512.new
  40.       else
  41.         raise ArgumentError, "unsupported bit length: %s" % bitlen.inspect
  42.       end
  43.       @bitlen = bitlen
  44.     end
  45.  
  46.     # :nodoc:
  47.     def reset
  48.       @sha2.reset
  49.       self
  50.     end
  51.  
  52.     # :nodoc:
  53.     def update(str)
  54.       @sha2.update(str)
  55.       self
  56.     end
  57.     alias << update
  58.  
  59.     def finish
  60.       @sha2.digest!
  61.     end
  62.     private :finish
  63.  
  64.     def block_length
  65.       @sha2.block_length
  66.     end
  67.  
  68.     def digest_length
  69.       @sha2.digest_length
  70.     end
  71.  
  72.     # :nodoc:
  73.     def initialize_copy(other)
  74.       @sha2 = other.instance_eval { @sha2.clone }
  75.     end
  76.  
  77.     # :nodoc:
  78.     def inspect
  79.       "#<%s:%d %s>" % [self.class.name, @bitlen, hexdigest]
  80.     end
  81.   end
  82.  
  83.   class SHA256 < Digest::Base
  84.     UNPACK = { :byte => 'C', :word32 => 'L', :word64 => 'Q' }
  85.     PACK = { :byte => 'C', :word32 => 'L', :word64 => 'Q' }
  86.     LENGTH = { :byte => 1, :word32 => 4, :word64 => 8 }
  87.    
  88.     INITIAL_HASH_VALUE = [
  89.       0x6a09e667,
  90.         0xbb67ae85,
  91.         0x3c6ef372,
  92.         0xa54ff53a,
  93.         0x510e527f,
  94.         0x9b05688c,
  95.         0x1f83d9ab,
  96.         0x5be0cd19
  97.     ].pack(PACK[:word32]*8)
  98.    
  99.     K = [
  100.       0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
  101.         0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
  102.         0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
  103.         0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
  104.         0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
  105.         0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
  106.         0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
  107.         0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
  108.         0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
  109.         0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
  110.         0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
  111.         0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
  112.         0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
  113.         0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
  114.         0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
  115.         0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
  116.     ]
  117.    
  118.     BLOCK_LENGTH        = 64
  119.     DIGEST_LENGTH = 32
  120.     DIGEST_STRING_LENGTH = (DIGEST_LENGTH * 2 + 1)
  121.     SHORT_BLOCK_LENGTH = (BLOCK_LENGTH - 8)
  122.  
  123.     def a2s_b(a)
  124.       a.map {|i| i % 2**8}.pack('C'*a.length)
  125.     end
  126.    
  127.     def s2a_b(s)
  128.       s.unpack('C'*s.length)
  129.     end
  130.    
  131.     def a2s_32(a)
  132.       a.map {|i| i % 2**32}.pack('L'*a.length)
  133.     end
  134.    
  135.     def s2a_32(s)
  136.       s.unpack('L'*(s.length/4))
  137.     end
  138.    
  139.     def a2s_64(a)
  140.       a.map {|i| i % 2**64}.pack('Q'*a.length)
  141.     end
  142.    
  143.     def s2a_64(s)
  144.       s.unpack('Q'*(s.length/8))
  145.     end
  146.    
  147.     def initialize
  148.       reset
  149.     end
  150.    
  151.     def update(data)
  152.       # Calling with no data is valid - we do nothing
  153.       return if data.length == 0
  154.      
  155.       usedspace = (@context[:bitcount] >> 3) % BLOCK_LENGTH
  156.       if usedspace > 0
  157.         # Calculate how much free space is available in the buffer
  158.         freespace = BLOCK_LENGTH - usedspace
  159.        
  160.         if data.length >= freespace
  161.           # Fill the buffer completely and process it
  162.           @context[:buffer][usedspace,freespace] = data.slice!(0..freespace)
  163.           @context[:bitcount] += freespace << 3
  164.           transform(@context[:buffer])
  165.         else
  166.           # The buffer is not yet full
  167.           @context[:buffer][usedspace,data.length] = data
  168.           @context[:bitcount] += data.length << 3
  169.         end
  170.       end
  171.       while data.length >= BLOCK_LENGTH
  172.         # Process as many complete blocks as we can
  173.         transform(data.slice!(0..BLOCK_LENGTH))
  174.         @context[:bitcount] += BLOCK_LENGTH << 3
  175.       end
  176.       if data.length > 0
  177.         # There's left-overs, so save 'em
  178.         @context[:buffer] = data
  179.         @context[:bitcount] += data.length << 3
  180.       end
  181.     end
  182.  
  183.     def finish
  184.       buffer = s2a_b(@context[:buffer])
  185.       usedspace = (@context[:bitcount] >> 3) % BLOCK_LENGTH
  186.       if usedspace > 0
  187.         # Begin padding with a 1 bit
  188.         buffer[usedspace] = 0x80
  189.         usedspace += 1
  190.        
  191.         if usedspace <= SHORT_BLOCK_LENGTH
  192.           # Set-up for the last transform:
  193.           buffer[usedspace,(SHORT_BLOCK_LENGTH - usedspace)] = [0]*(SHORT_BLOCK_LENGTH - usedspace)
  194.         else
  195.           if usedspace < BLOCK_LENGTH
  196.             buffer[usedspace,(BLOCK_LENGTH - usedspace)] = [0]*(BLOCK_LENGTH - usedspace)
  197.           end
  198.           # Do second-to-last transform:
  199.           transform(s2a_b(buffer))
  200.          
  201.           # And set-up for the last transform:
  202.           buffer = [0]*SHORT_BLOCK_LENGTH
  203.         end
  204.       else
  205.         # Set-up for the last transform:
  206.         buffer = [0]*SHORT_BLOCK_LENGTH
  207.         # Begin padding with a 1 bit:
  208.         buffer[0] = 0x80
  209.       end
  210.       # Set the bit count:
  211.       buffer[SHORT_BLOCK_LENGTH,8] = @context[:bitcount].pack('Q').unpack('CCCC')
  212.       # Final transform:
  213.       transform(@context[:buffer])
  214.      
  215.       d = @context[:state][0..DIGEST_LENGTH]
  216.       @context = {}
  217.       d
  218.     end
  219.    
  220.     def reset
  221.       @context = {
  222.         :bitcount => 0,
  223.         :state => INITIAL_HASH_VALUE,
  224.         :buffer => "\x0"*BLOCK_LENGTH
  225.       }
  226.     end
  227.    
  228.     def transform(data)
  229.       # Initialize registers with the previous intermediate value
  230.       registers = s2a_32(@context[:state])
  231.       w256 = s2a_32(@context[:buffer])
  232.       data = s2a_32(data)
  233.      
  234.       # Rounds 0 to 15 (unrolled)
  235.       16.times do |j|
  236.         t1 = registers[7] +
  237.           Sigma1(registers[4]) +
  238.           ch(*registers[4..6]) +
  239.           K[j] +
  240.           (w256[j] = data[j])
  241.         registers[3] += t1
  242.         registers[7] = t1 + Sigma0(registers[0]) + maj(*registers[0..2])
  243.         registers.map {|i| i % 2**32 }
  244.         w256.map {|i| i % 2**32 }
  245.         registers.unshift(registers.pop)
  246.       end
  247.      
  248.       (16...64).each do |j|
  249.         s0 = w256[(j+1)&0x0f]
  250.         s0 = sigma0(s0)
  251.         s1 = w256[(j+14)&0x0f]
  252.         s1 = sigma1(s1)
  253.         t1 = registers[7] +
  254.           Sigma1(registers[4]) +
  255.           ch(*registers[4..6]) +
  256.           K[j] +
  257.           (w256[j&0x0f] += s1 + w256[(j+9)&0x0f] + s0)
  258.         registers[3] += t1
  259.         registers[7] = t1 + Sigma0(registers[0]) + maj(*registers[0..2])
  260.         registers.map {|i| i % 2**32 }
  261.         w256.map {|i| i % 2**32 }
  262.         registers.unshift(registers.pop)
  263.       end
  264.      
  265.       @context[:state] = a2s_32(registers)
  266.       @context[:buffer] = a2s_32(w256)
  267.     end
  268.     private :transform
  269.    
  270.     def sigma0(x)
  271.       (s32(7,  (x)) ^ s32(18, (x)) ^ r(3 ,   (x)))
  272.     end
  273.     private :sigma0
  274.    
  275.     def Sigma0(x)
  276.       (s32(2,  (x)) ^ s32(13, (x)) ^ s32(22, (x)))
  277.     end
  278.     private :Sigma0
  279.    
  280.     def sigma1(x)
  281.       (s32(17, (x)) ^ s32(19, (x)) ^ r(10,   (x)))
  282.     end
  283.     private :sigma1
  284.    
  285.     def Sigma1(x)
  286.       (s32(6,  (x)) ^ s32(11, (x)) ^ s32(25, (x)))
  287.     end
  288.     private :Sigma1
  289.    
  290.     def s32(b,x)
  291.       (((x) >> (b)) | ((x) << (32 - (b))))
  292.     end
  293.     private :s32
  294.    
  295.     def r(b,x)
  296.       ((x) >> (b))
  297.     end
  298.     private :r
  299.    
  300.     def ch(x,y,z)
  301.       (((x) & (y)) ^ ((~(x)) & (z)))
  302.     end
  303.     private :ch
  304.    
  305.     def maj(x,y,z)
  306.       (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
  307.     end
  308.     private :maj
  309.   end
  310. end