def pad(message, size): "Pad message to size, so that length message modulo size is 0" # 5.1 Padding the Message # Implementation note; because of the similarities of padding to 512 or 1024 # and it is not 'core' to the algorithm, both "5.1.1 SHA-1, SHA-224 and # SHA-256" and "5.1.2 SHA-384 and SHA-512" are implemented as one. allowed_sizes = [512, 1024] if size not in allowed_sizes: text = "Split size '%s' not allowed must be in: %s" raise(ValueError(text % (size, allowed_sizes))) if size == 512: pad_len = 64 elif size == 1024: pad_len = 128 message = Bits(message) pad_txt = Bits(len(message), pad_len) message.append('1') length = len(message) + pad_len delta = length % size padding = size - delta padding = '0' * padding message.append(padding) message.append(pad_txt) return(message)
def computation(message): # 6.4.1 SHA-512 Preprocessing # 5.1.2 Padding the Message padded = pad(message, SIZE_BLOCK) # 5.2.2 Parsing the Padded Message # ! Meaning splitting it into blocks of 1024 bits blocks = padded.split(SIZE_BLOCK) # 5.3 Setting the Initial Hash Value (H(0)) / 5.3.5 SHA-512 #hd = H0_SHA_512 hd = H0_SHA_512_224 # 6.6 - 1 h0 = Bits(hd[0], SIZE_WORD) h1 = Bits(hd[1], SIZE_WORD) h2 = Bits(hd[2], SIZE_WORD) h3 = Bits(hd[3], SIZE_WORD) h4 = Bits(hd[4], SIZE_WORD) h5 = Bits(hd[5], SIZE_WORD) h6 = Bits(hd[6], SIZE_WORD) h7 = Bits(hd[7], SIZE_WORD) # 6. SECURE HASH ALGORITHMS # 6.4.2 SHA-512 Hash Computation for block in blocks: # Step 1. Prepare the message schedule # - Fill with 80 64 bits word values message_schedule = dict() # This set's up the first 16 words, using the words in the block # see the 0 <=t<=15 part of the specification for count, word in enumerate(block.split(SIZE_WORD)): word = Bits(word, SIZE_WORD) message_schedule[count] = word # This set's up the remaining 64 words for index in range(16, 80): # Implementation Note: # The following code-block is an on-liner in the documentation, # see the 16 <=t<=79 part of the specification w02 = message_schedule[index - 2] w07 = message_schedule[index - 7] w15 = message_schedule[index - 15] w16 = message_schedule[index - 16] # sl1 = sigma_lower_512_1(w02) sl0 = sigma_lower_512_0(w15) word = sl1 + w07 + sl0 + w16 # message_schedule[index] = word # Step 2. Initialize working variables a = h0 b = h1 c = h2 d = h3 e = h4 f = h5 g = h6 h = h7 # Step 3. 80 rounds of calculation # For t=0 to 79: for index in range(80): kt = Bits(K_SHA_512_224[index], SIZE_WORD) wt = message_schedule[index] ch = function_ch(e, f, g) s1 = sigma_upper_512_1(e) t1 = h + s1 + ch + kt + wt s0 = sigma_upper_512_0(a) ma = function_maj(a, b, c) t2 = s0 + ma h = g g = f f = e e = d + t1 d = c c = b b = a a = t1 + t2 # Step 4. compute the intermediate hash value h0 = a + h0 h1 = b + h1 h2 = c + h2 h3 = d + h3 h4 = e + h4 h5 = f + h5 h6 = g + h6 h7 = h + h7 #return(h0, h1, h2, h3, h4, h5, h6, h7) first_192 = h0, h1, h2 last_part = h3.split(32)[0] return (first_192 + (last_part, )) # 6.6 - 2
def shift_right(word, amount): # 2.2.2 Symbols and Operations # SHRn(x) binary = word._binary shift = binary[:-amount] return_value = Bits(shift, SIZE_WORD) return (return_value)
def rotate_right(word, amount): # 2.2.2 Symbols and Operations # ROTRn(x) binary = word._binary rotate = binary[-amount:] + binary[:-amount] return_value = Bits(rotate, SIZE_WORD) return (return_value)
def computation(message): # 5. Preprocessing # 5.1 Padding the Message padded = pad(message, SIZE_BLOCK) # 5.2 Parsing the Padded Message / 5.2.1 SHA-1, SHA-224 and SHA-256 # ! Meaning splitting it into blocks of 512 bits blocks = padded.split(SIZE_BLOCK) # 5.3 Setting the Initial Hash Value (H(0)) / 5.3.3 SHA-256 # override by 6.3, specifies 5.3.2 # # hd = H0_SHA_256 hd = H0_SHA_224 h0 = Bits(hd[0], SIZE_WORD) h1 = Bits(hd[1], SIZE_WORD) h2 = Bits(hd[2], SIZE_WORD) h3 = Bits(hd[3], SIZE_WORD) h4 = Bits(hd[4], SIZE_WORD) h5 = Bits(hd[5], SIZE_WORD) h6 = Bits(hd[6], SIZE_WORD) h7 = Bits(hd[7], SIZE_WORD) # 6. SECURE HASH ALGORITHMS # 6.2.2 SHA-256 Hash Computation for block in blocks: # Step 1. Prepare the message schedule # - Fill with 64 32 bits word values message_schedule = dict() # This set's up the first 16 words, using the words in the block # see the 0 <= t <= 15 part for count, word in enumerate(block.split(SIZE_WORD)): word = Bits(word, SIZE_WORD) message_schedule[count] = word # This set's up the remaining 48 words for index in range(16, 64): # Implementation Note: # The following code-block is an on-liner in the documentation, # see the 16<=t<=63 part w02 = message_schedule[index - 2] w07 = message_schedule[index - 7] w15 = message_schedule[index - 15] w16 = message_schedule[index - 16] # sl1 = sigma_lower_256_1(w02) sl0 = sigma_lower_256_0(w15) word = sl1 + w07 + sl0 + w16 # message_schedule[index] = word # Step 2. Initialize working variables a = h0 b = h1 c = h2 d = h3 e = h4 f = h5 g = h6 h = h7 # Step 3. 64 rounds of calculation for index in range(64): kt = Bits(K_SHA_224[index], SIZE_WORD) wt = message_schedule[index] ch = function_ch(e, f, g) s1 = sigma_upper_256_1(e) t1 = h + s1 + ch + kt + wt s0 = sigma_upper_256_0(a) ma = function_maj(a, b, c) t2 = s0 + ma h = g g = f f = e e = d + t1 d = c c = b b = a a = t1 + t2 # Step 4. compute the intermediate hash value h0 = a + h0 h1 = b + h1 h2 = c + h2 h3 = d + h3 h4 = e + h4 h5 = f + h5 h6 = g + h6 h7 = h + h7 # 6.3:2 Overrides, only the left most 224 bits # # return(h0, h1, h2, h3, h4, h5, h6, h7) return (h0, h1, h2, h3, h4, h5, h6)
def computation(message): # 6.1.1 SHA-1 Preprocessing # 5.1 Padding the Message padded = pad(message, SIZE_BLOCK) # 5.2 Parsing the Padded Message / 5.2.1 SHA-1 # ! Meaning splitting it into blocks of 512 bits blocks = padded.split(SIZE_BLOCK) # 5.3 Setting the Initial Hash Value (H(0)) / 5.3.1 SHA-1 h0 = Bits(H0_SHA_1[0], SIZE_WORD) h1 = Bits(H0_SHA_1[1], SIZE_WORD) h2 = Bits(H0_SHA_1[2], SIZE_WORD) h3 = Bits(H0_SHA_1[3], SIZE_WORD) h4 = Bits(H0_SHA_1[4], SIZE_WORD) # 6. SECURE HASH ALGORITHMS # 6.1.2 SHA-256 Hash Computation for block in blocks: # Step 1. Prepare the message schedule # - Fill with 80 32 bits word values # 6.1 First Paragraph message_schedule = dict() # 0 <= t <= 15 # This set's up the first 16 words, using the words in the block # As the block can only have 16 words, we do not have to worry about # remainders. for count, word in enumerate(block.split(SIZE_WORD)): word = Bits(word, SIZE_WORD) message_schedule[count] = word # 16 <= t <= 79 # This set's up the remaining 64 words for index in range(16, 80): # Implementation Note: # The following code-block is an on-liner in the documentation. w03 = message_schedule[index - 3] w08 = message_schedule[index - 8] w14 = message_schedule[index - 14] w16 = message_schedule[index - 16] # word = w03 ^ w08 ^ w14 ^ w16 word = rotate_left(word, 1) # message_schedule[index] = word # Step 2. Initialize 5 working variables a = h0 b = h1 c = h2 d = h3 e = h4 # Step 3. 80 rounds of calculation for index in range(80): ft = SHA1_FUNCTIONS[index] kt = Bits(K_SHA_1[index], SIZE_WORD) wt = message_schedule[index] t = rotate_left(a, 5) + ft(b, c, d) + e + kt + wt e = d d = c c = rotate_left(b, 30) b = a a = t # Step 4. compute the intermediate hash value h0 = a + h0 h1 = b + h1 h2 = c + h2 h3 = d + h3 h4 = e + h4 return (h0, h1, h2, h3, h4)
def rotate_left(word, amount): # 2.2.2 # ROTLn(x) binary = word._binary rotate = binary[amount:] + binary[:amount] return_value = Bits(rotate, SIZE_WORD) return (return_value)