Skip to content

Instantly share code, notes, and snippets.

@nickyreinert
Created February 7, 2023 19:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nickyreinert/5621d17d63efbbd68584246d20fe4d2f to your computer and use it in GitHub Desktop.
Save nickyreinert/5621d17d63efbbd68584246d20fe4d2f to your computer and use it in GitHub Desktop.
Step-by-Step implementation of the SHA-256 algorithm in Python
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"outputs": [],
"source": [
"message = '1'\n",
"\n",
"verbose = True\n",
"\n",
"from math import floor\n",
"from IPython.display import clear_output\n",
"import time \n",
"from math import sqrt\n",
"from itertools import count, islice\n",
"\n",
"\n",
"def rotate(value, rotations, width=32):\n",
" # thx to https://stackoverflow.com/a/59005609/2360229\n",
" if int(rotations) != abs(int(rotations)):\n",
" rotations = width + int(rotations)\n",
" return (int(value) << (width - (rotations%width)) | (int(value) >> (rotations % width))) & ((1 << width) - 1)\n",
" \n",
"def sigma0(word):\n",
" part1 = bin(rotate(int(word, 2), 7, 32))\n",
" part2 = bin(rotate(int(word, 2), 18, 32))\n",
" part3 = bin(int(word, 2) >> 3)\n",
" return bin(int(part1, 2) ^ int(part2, 2) ^ int(part3, 2))[2:].zfill(32)\n",
"\n",
"def sigma1(word):\n",
" part1 = bin(rotate(int(word, 2), 17, 32))\n",
" part2 = bin(rotate(int(word, 2), 19, 32))\n",
" part3 = bin(int(word, 2) >> 10)\n",
" return bin(int(part1, 2) ^ int(part2, 2) ^ int(part3, 2))[2:].zfill(32)\n",
"\n",
"def upper_sigma0(word):\n",
" part1 = bin(rotate(int(word, 2), 2, 32))\n",
" part2 = bin(rotate(int(word, 2), 13, 32))\n",
" part3 = bin(rotate(int(word, 2), 22, 32))\n",
" return bin(int(part1, 2) ^ int(part2, 2) ^ int(part3, 2))[2:].zfill(32)\n",
"\n",
"def upper_sigma1(word):\n",
" part1 = bin(rotate(int(word, 2), 6, 32))\n",
" part2 = bin(rotate(int(word, 2), 11, 32))\n",
" part3 = bin(rotate(int(word, 2), 25, 32))\n",
" return bin(int(part1, 2) ^ int(part2, 2) ^ int(part3, 2))[2:].zfill(32)\n",
"\n",
"def choose(word1, word2, word3):\n",
" bin_word1 = (int(word1, 2))\n",
" bin_word2 = (int(word2, 2))\n",
" bin_word3 = (int(word3, 2))\n",
" return bin((bin_word1 & bin_word2) ^ (~bin_word1 & bin_word3))[2:].zfill(32)\n",
"\n",
"def majority(word1, word2, word3):\n",
" bin_word1 = (int(word1, 2))\n",
" bin_word2 = (int(word2, 2))\n",
" bin_word3 = (int(word3, 2))\n",
" return bin((bin_word1 & bin_word2) ^ (bin_word1 & bin_word3) ^ (bin_word2 & bin_word3))[2:].zfill(32)\n",
"\n",
"first_64_prime_numbers = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311]\n",
"\n",
"result_constants = []\n",
"for prime_number in first_64_prime_numbers:\n",
" # get cube root\n",
" cube_root = prime_number ** (1./3.)\n",
" # get fractional part\n",
" frac_part = cube_root - floor(cube_root)\n",
" # multiply with 2^32 (or shift left by 32 bits)\n",
" product = frac_part * (2**32)\n",
" floored_product = floor(product)\n",
" # floor, ready:\n",
" result_constants.append(bin(floored_product)[2:].zfill(32))\n",
"\n",
"first_8_prime_numbers = [2, 3, 5, 7, 11, 13, 17, 19]\n",
"\n",
"compression_constants = []\n",
"for prime_number in first_8_prime_numbers:\n",
" # get square root\n",
" square_root = prime_number ** (1./2.)\n",
" # get fractional part\n",
" frac_part = square_root - floor(square_root)\n",
" # multiply with 2^32 (or shift left by 32 bits)\n",
" product = frac_part * (2**32)\n",
" floored_product = floor(product)\n",
" compression_constants.append(bin(floored_product)[2:].zfill(32))\n",
"\n",
"# just some colors\n",
"default = \"\\x1b[0m\"\n",
"red = \"\\x1b[31m\"\n",
"green = \"\\x1b[32m\"\n",
"\n",
"# record the results individually\n",
"\n",
"log = [{\n",
" 'step': 'dummy',\n",
" 'block': 0,\n",
" 'word': 0,\n",
" 'func': 'sigma',\n",
" 'val': 0b0001\n",
"}]"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[2, 3, 5, 7, 11, 13, 17, 19]\n",
"['01101010000010011110011001100111', '10111011011001111010111010000101', '00111100011011101111001101110010', '10100101010011111111010100111010', '01010001000011100101001001111111', '10011011000001010110100010001100', '00011111100000111101100110101011', '01011011111000001100110100011001']\n",
"[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311]\n",
"['01000010100010100010111110011000', '01110001001101110100010010010001', '10110101110000001111101111001111', '11101001101101011101101110100101', '00111001010101101100001001011011', '01011001111100010001000111110001', '10010010001111111000001010100100', '10101011000111000101111011010101', '11011000000001111010101010011000', '00010010100000110101101100000001', '00100100001100011000010110111110', '01010101000011000111110111000011', '01110010101111100101110101110100', '10000000110111101011000111111110', '10011011110111000000011010100111', '11000001100110111111000101110100', '11100100100110110110100111000001', '11101111101111100100011110000110', '00001111110000011001110111000110', '00100100000011001010000111001100', '00101101111010010010110001101111', '01001010011101001000010010101010', '01011100101100001010100111011100', '01110110111110011000100011011010', '10011000001111100101000101010010', '10101000001100011100011001101101', '10110000000000110010011111001000', '10111111010110010111111111000111', '11000110111000000000101111110011', '11010101101001111001000101000111', '00000110110010100110001101010001', '00010100001010010010100101100111', '00100111101101110000101010000101', '00101110000110110010000100111000', '01001101001011000110110111111100', '01010011001110000000110100010011', '01100101000010100111001101010100', '01110110011010100000101010111011', '10000001110000101100100100101110', '10010010011100100010110010000101', '10100010101111111110100010100001', '10101000000110100110011001001011', '11000010010010111000101101110000', '11000111011011000101000110100011', '11010001100100101110100000011001', '11010110100110010000011000100100', '11110100000011100011010110000101', '00010000011010101010000001110000', '00011001101001001100000100010110', '00011110001101110110110000001000', '00100111010010000111011101001100', '00110100101100001011110010110101', '00111001000111000000110010110011', '01001110110110001010101001001010', '01011011100111001100101001001111', '01101000001011100110111111110011', '01110100100011111000001011101110', '01111000101001010110001101101111', '10000100110010000111100000010100', '10001100110001110000001000001000', '10010000101111101111111111111010', '10100100010100000110110011101011', '10111110111110011010001111110111', '11000110011100010111100011110010']\n"
]
}
],
"source": [
"print(first_8_prime_numbers)\n",
"print(compression_constants)\n",
"print(first_64_prime_numbers)\n",
"print(result_constants)"
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"The decimal representation of \u001b[31m`1`\u001b[0m is \n",
"[49]\n",
"The binary representation of \u001b[31m`1`\u001b[0m is \n",
"0110001\n",
"The binary representation has a length of\n",
"7 bits aka\n",
"111\n",
"Extended to 64 bits:\n",
"(64 Bits allows a total length of 2 exbibyte, or 2,3 ExaByte, guess that`s enough)\n",
"0000000000000000000000000000000000000000000000000000000000000\u001b[31m111\u001b[0m\n",
"Adding 440 zeros to get a multiple of 512 bits\n",
"\u001b[31m0110001\u001b[32m1\u001b[0m00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\u001b[31m0000000000000000000000000000000000000000000000000000000000000111\u001b[0m\n",
"Length-Check: 512 bits\n"
]
}
],
"source": [
"def prepare_message(message, verbose = True, skip_encoding = False):\n",
"\n",
" if skip_encoding == False:\n",
" dec_message = []\n",
" for char in message:\n",
" dec_message.append(ord(char))\n",
"\n",
" if verbose: print('The decimal representation of %s`%s`%s is ' % (red, message, default))\n",
" if verbose: print(dec_message)\n",
"\n",
" bin_message = ''\n",
" for decimal in dec_message:\n",
" bin_message += '0' + bin(decimal)[2:]\n",
" else:\n",
" bin_message = message\n",
" \n",
" if verbose: print('The binary representation of %s`%s`%s is ' % (red, message, default))\n",
" if verbose: print(bin_message)\n",
" len_bin_message = len(bin_message)\n",
"\n",
" if verbose: print('The binary representation has a length of')\n",
" if verbose: print(str(len_bin_message) + ' bits aka')\n",
" if verbose: print(bin(len_bin_message)[2:])\n",
"\n",
" if verbose: print('Extended to 64 bits:')\n",
" if verbose: print('(64 Bits allows a total length of 2 exbibyte, or 2,3 ExaByte, guess that`s enough)')\n",
" rest_to_64 = 64 - len(bin(len_bin_message)[2:])\n",
" bin_message_len = '0' * rest_to_64 + bin(len_bin_message)[2:]\n",
" if verbose: print('0' * rest_to_64 + '%s%s%s' % (\n",
" red, \n",
" bin(len_bin_message)[2:], \n",
" default))\n",
"\n",
" payload = bin_message + '1' + bin_message_len\n",
" len_payload = len(payload)\n",
" pad_string = int(512 - (len_payload % 512))\n",
" if verbose: print('Adding %s zeros to get a multiple of 512 bits' % pad_string)\n",
"\n",
" full_message = bin_message + '1' + ('0' * pad_string) + bin_message_len\n",
"\n",
" if verbose: print(('%s%s%s1%s' + '0' * pad_string + '%s%s%s') % (\n",
" red, \n",
" bin_message, \n",
" green,\n",
" default,\n",
" red, \n",
" bin_message_len, \n",
" default\n",
" ))\n",
"\n",
" if verbose: print('Length-Check: ' + str(len(full_message)) + ' bits')\n",
"\n",
" return full_message\n",
" \n",
"full_message = prepare_message(message, verbose)"
]
},
{
"cell_type": "code",
"execution_count": 26,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Split the message into chunks, each chunk has 512 bits\n",
"We have 1 message blocks\n",
"Split each message block into 16 words of 32 bit length each, called the message schedule\n",
"Expand the schedule to 64 words\n",
"['01100011000000000000000000000000', '00000000000000000000000000000000', '00000000000000000000000000000000', '00000000000000000000000000000000', '00000000000000000000000000000000', '00000000000000000000000000000000', '00000000000000000000000000000000', '00000000000000000000000000000000', '00000000000000000000000000000000', '00000000000000000000000000000000', '00000000000000000000000000000000', '00000000000000000000000000000000', '00000000000000000000000000000000', '00000000000000000000000000000000', '00000000000000000000000000000000', '00000000000000000000000000000111', '01100011000000000000000000000000', '00000000000000110110000000000000', '00000000000110001111110111100000', '11011100000000000000000011011001', '01100001010011000000011000110000', '00000000010000001101010110000000', '10000011110001100110111110010101', '11010011011100000001000000011101', '11111010000110111110000000000000', '00001010010100101000110110110010', '01101000001111101110010110001111', '01111000101110011101011011110000', '10101110101011010010110000100001', '01010101011111101000110011010011', '00010101001100010001100111100101', '10011110101010001001100001111010', '11110101000111100101110011101010', '11000110110100110010101001110111', '00000110101101101010111110100101', '11101000010110001101110100001100', '01101110010110101011110000110100', '00101011001010100001000001010001', '01010001110001011100101101010111', '11111001011011100101110011000001', '11100011111101101011010001011000', '10100001100001000101000011011001', '01110111100100011010101000100000', '10100110111101001010110110000001', '11001001010100110000011110011110', '11111001100100101011011011111100', '10110010101001010100010101111101', '11101100101100100001111010001011', '11011110101010101010011011001000', '01101100010001110111010011100101', '11101000110011101100101101011100', '11010000101110111110100010001000', '01001000000101001010101011011100', '00111101011111111001100100001011', '00001010100011101111101101111110', '00011000011100111010110110011101', '10100110010101100111101111000000', '01010010011000110101110000000101', '01110111111100100111101001111101', '10011001111111110110100010101111', '11000100101111011101100000011000', '00011001111101001000000100100000', '10110000010001010010010110011001', '10000111100101010100001101101101']\n",
"['01111101111100101111111101111111', '11110100011001111100110111000110', '11000110101011001101011011101101', '10001100101110100000010000110100', '00110001101110001110001010110010', '01000111111010100001110110111100', '10000111100010010001100011100010', '01010011000011011000100100001110']\n"
]
}
],
"source": [
"def calculate_hash(full_message, verbose = True):\n",
"\n",
" if verbose: print('Split the message into chunks, each chunk has 512 bits')\n",
" message_block_length = 512\n",
" message_blocks = [full_message[i:i+message_block_length] for i in range(0, len(full_message), message_block_length)]\n",
" if verbose: print('We have %s message blocks' % (len(message_blocks)))\n",
" \n",
" current_hash = compression_constants.copy()\n",
" \n",
" message_block_index = 0\n",
" \n",
" for message_block in message_blocks:\n",
" if verbose: print('Split each message block into 16 words of 32 bit length each, called the message schedule')\n",
" word_length = 32\n",
" message_schedule = [str(message_block[i:i+word_length]) for i in range(0, len(message_block), word_length)]\n",
" \n",
" if verbose: print('Expand the schedule to 64 words')\n",
" for i in range(16, 64):\n",
" word1 = message_schedule[i - 2]\n",
" word2 = message_schedule[i - 7]\n",
" word3 = message_schedule[i - 15]\n",
" word4 = message_schedule[i - 16]\n",
" \n",
" # addition is done using module 2^32 - if you get a number higher than 2^32, this can still be handled on 32 bit machines\n",
" # fun fact: n modulo 2^32 seems complicated, but it isnt: you can just logical and to 2^32 \n",
" # see https://stackoverflow.com/a/6670853/2360229\n",
" # thread says & n - 1, but video uses & n ....why?\n",
" \n",
" new_word = ( \\\n",
" int(sigma1(word1), 2) + \\\n",
" int(word2, 2) + \\\n",
" int(sigma0(word3), 2) + \\\n",
" int(word4, 2)) & \\\n",
" int('11111111111111111111111111111111', 2)\n",
" \n",
" log.append({'step': 'expansion', 'block': message_block_index, 'word': i, 'func': 'sigma1', 'val': sigma1(word1)})\n",
" log.append({'step': 'expansion', 'block': message_block_index, 'word': i, 'func': 'none', 'val': word2})\n",
" log.append({'step': 'expansion', 'block': message_block_index, 'word': i, 'func': 'sigma0', 'val': sigma0(word3)})\n",
" log.append({'step': 'expansion', 'block': message_block_index, 'word': i, 'func': 'none', 'val': word4})\n",
" \n",
" log.append({'step': 'expansion', 'block': message_block_index, 'word': i, 'func': 'sum', 'val': bin(int(sigma1(word1), 2) + int(word2, 2) + int(sigma0(word3), 2) + int(word4, 2))[2:]})\n",
" \n",
" log.append({'step': 'expansion', 'block': message_block_index, 'word': i, 'func': 'limited_sum', 'val': bin(new_word)[2:]})\n",
" \n",
" message_schedule.append(bin(new_word)[2:].zfill(32))\n",
" \n",
" if verbose: print(message_schedule)\n",
" \n",
" next_hash = current_hash.copy()\n",
" \n",
" # process every word in the message schedule\n",
" for i, word in enumerate(message_schedule):\n",
" \n",
" result_constant = result_constants[i]\n",
" \n",
" term1 = (int(upper_sigma1(next_hash[4]), 2) + \\\n",
" int(choose(next_hash[4], next_hash[5], next_hash[6]), 2) + \\\n",
" int(next_hash[7], 2) + \\\n",
" int(result_constant, 2) + \\\n",
" int(word, 2)) \\\n",
" & int('11111111111111111111111111111111', 2)\n",
" \n",
" term2 = (int(upper_sigma0(next_hash[0]), 2) + \\\n",
" int(majority(next_hash[0], next_hash[1], next_hash[2]), 2)) & int('11111111111111111111111111111111', 2)\n",
" \n",
" \n",
" log.append({'step': 'term1', 'block': message_block_index, 'word': i, 'func': 'upper_sigma1', 'val': upper_sigma1(next_hash[4])})\n",
" log.append({'step': 'term1', 'block': message_block_index, 'word': i, 'func': 'choose', 'val': choose(next_hash[4], next_hash[5], next_hash[6])})\n",
" log.append({'step': 'term1', 'block': message_block_index, 'word': i, 'func': 'none', 'val': next_hash[7]})\n",
" log.append({'step': 'term1', 'block': message_block_index, 'word': i, 'func': 'const', 'val': result_constant})\n",
" log.append({'step': 'term1', 'block': message_block_index, 'word': i, 'func': 'none', 'val': word})\n",
" \n",
" log.append({'step': 'term1', 'block': message_block_index, 'word': i, 'func': 'sum', 'val': bin(int(upper_sigma1(next_hash[4]), 2) + int(choose(next_hash[4], next_hash[5], next_hash[6]), 2) + int(next_hash[7], 2) + int(result_constant, 2) + int(word, 2))[2:]})\n",
" \n",
" log.append({'step': 'term1', 'block': message_block_index, 'word': i, 'func': 'limited_sum', 'val': bin(term1)[2:]})\n",
" \n",
" log.append({'step': 'term2', 'block': message_block_index, 'word': i, 'func': 'upper_sigma0', 'val': upper_sigma0(next_hash[0])})\n",
" log.append({'step': 'term2', 'block': message_block_index, 'word': i, 'func': 'majority', 'val': bin(int(majority(next_hash[0], next_hash[1], next_hash[2]),2) & int('11111111111111111111111111111111'))[2:]})\n",
" \n",
" log.append({'step': 'term2', 'block': message_block_index, 'word': i, 'func': 'sum', 'val': bin(int(upper_sigma0(next_hash[0]), 2) + int(majority(next_hash[0], next_hash[1], next_hash[2]), 2))[2:]})\n",
" \n",
" log.append({'step': 'term2', 'block': message_block_index, 'word': i, 'func': 'limited_sum', 'val': bin(term2)[2:]})\n",
" \n",
" # move elements in list one index down, means: last one will be dropped\n",
" # and first one is empty now\n",
" next_hash.insert(0, 1)\n",
" next_hash.pop()\n",
" \n",
" next_hash[0] = bin(\n",
" (term1 + term2) & int('11111111111111111111111111111111', 2)\n",
" )[2:].zfill(32)\n",
" \n",
" log.append({'step': 'replace', 'block': message_block_index, 'word': i, 'func': 'sum', 'val': bin(term1 + term2)[2:] })\n",
" \n",
" log.append({'step': 'replace', 'block': message_block_index, 'word': i, 'func': 'limited_sum', 'val': next_hash[0] })\n",
" \n",
" next_hash[4] = bin(\n",
" (int(next_hash[4], 2) + term1) & int('11111111111111111111111111111111', 2)\n",
" )[2:].zfill(32)\n",
" \n",
" log.append({'step': 'replace', 'block': message_block_index, 'word': i, 'func': 'sum', 'val': bin(int(next_hash[4], 2) + term1)[2:] })\n",
" \n",
" log.append({'step': 'replace', 'block': message_block_index, 'word': i, 'func': 'limited_sum', 'val': next_hash[4] })\n",
" \n",
" # print(next_hash)\n",
" # sys.exit()\n",
" # print(bin(term2)[2:].zfill(32))\n",
" \n",
" result = []\n",
" # add initial constants to compressed numbers\n",
" for i in range(0, 8):\n",
" result.append(\n",
" bin(int(current_hash[i], 2) + int(next_hash[i], 2) & int('11111111111111111111111111111111', 2))[2:].zfill(32)\n",
" )\n",
" log.append({'step': 'final', 'block': message_block_index, 'word': i, 'func': 'sum', 'val': bin(int(current_hash[i], 2) + int(next_hash[i], 2))[2:].zfill(32) })\n",
" \n",
" log.append({'step': 'final', 'block': message_block_index, 'word': i, 'func': 'limited_sum', 'val': bin(int(current_hash[i], 2) + int(next_hash[i], 2) & int('11111111111111111111111111111111', 2))[2:].zfill(32) })\n",
" \n",
" \n",
" current_hash = result.copy()\n",
" \n",
" message_block_index += 1\n",
" \n",
" if verbose: print(result)\n",
"\n",
" return result\n",
"\n",
"result = calculate_hash(full_message, verbose)"
]
},
{
"cell_type": "code",
"execution_count": 27,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0111110111110010111111110111111111110100011001111100110111000110110001101010110011010110111011011000110010111010000001000011010000110001101110001110001010110010010001111110101000011101101111001000011110001001000110001110001001010011000011011000100100001110\n",
"2,113,077,119-4,100,443,590-3,333,215,981-2,361,001,012-834,200,242-1,206,525,372-2,273,908,962-1,393,395,982-\n",
"7df2ff7f-f467cdc6-c6acd6ed-8cba0434-31b8e2b2-47ea1dbc-878918e2-530d890e-\n",
"7df2ff7ff467cdc6c6acd6ed8cba043431b8e2b247ea1dbc878918e2530d890e\n"
]
},
{
"ename": "TypeError",
"evalue": "Strings must be encoded before hashing",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)",
"Cell \u001b[0;32mIn [27], line 23\u001b[0m\n\u001b[1;32m 21\u001b[0m \u001b[39mimport\u001b[39;00m \u001b[39mhashlib\u001b[39;00m\n\u001b[1;32m 22\u001b[0m \u001b[39mprint\u001b[39m()\n\u001b[0;32m---> 23\u001b[0m \u001b[39mprint\u001b[39m(hashlib\u001b[39m.\u001b[39;49msha256(message)\u001b[39m.\u001b[39mhexdigest())\n",
"\u001b[0;31mTypeError\u001b[0m: Strings must be encoded before hashing"
]
}
],
"source": [
"for word in result:\n",
" print(bin(int(word, 2))[2:].zfill(32) + '', end = '')\n",
"\n",
"print()\n",
"\n",
"sum = 0\n",
"for word in result:\n",
" print(f'{int(word, 2):,}' + '-', end = '')\n",
" sum += int(word, 2)\n",
"\n",
"print()\n",
"\n",
"for word in result:\n",
" print(hex(int(word, 2))[2:].zfill(8) + '-', end = '')\n",
"\n",
"print()\n",
"\n",
"for word in result:\n",
" print(hex(int(word, 2))[2:].zfill(8) + '', end = '')\n",
"\n",
"import hashlib\n",
"print()\n",
"print(hashlib.sha256(message).hexdigest())\n"
]
},
{
"cell_type": "code",
"execution_count": 28,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Loop #47\n",
"Pos 47: 11101100101100100001111010001011 > word4\t = 11101100101100100001111010001011\n",
"Pos 48: 11011110101010101010011011001000 > sigma0(word3) = 00100011110110100011011000111110\n",
"Pos 49: 01101100010001110111010011100101\n",
"Pos 50: 11101000110011101100101101011100\n",
"Pos 51: 11010000101110111110100010001000\n",
"Pos 52: 01001000000101001010101011011100\n",
"Pos 53: 00111101011111111001100100001011\n",
"Pos 54: 00001010100011101111101101111110\n",
"Pos 55: 00011000011100111010110110011101\n",
"Pos 56: 10100110010101100111101111000000 > word2\t = 10100110010101100111101111000000\n",
"Pos 57: 01010010011000110101110000000101\n",
"Pos 58: 01110111111100100111101001111101\n",
"Pos 59: 10011001111111110110100010101111\n",
"Pos 60: 11000100101111011101100000011000\n",
"Pos 61: 00011001111101001000000100100000 > sigma1(word1) = 11010000101100100111001011100100\n",
"Pos 62: 10110000010001010010010110011001\n",
"\n",
"\t\t\t\t\t\t AND 11111111111111111111111111111111\n",
"\n",
"\t\t\t\t\t\tnew word = 10000111100101010100001101101101\n"
]
}
],
"source": [
"word_length = 32\n",
"\n",
"message_schedule = [str(full_message[i:i+word_length]) for i in range(0, len(full_message), word_length)]\n",
"\n",
"for i in range(16, 64):\n",
"\n",
" word1 = message_schedule[i - 2]\n",
" word2 = message_schedule[i - 7]\n",
" word3 = message_schedule[i - 15]\n",
" word4 = message_schedule[i - 16]\n",
"\n",
" print('Loop #%i' % (i - 16))\n",
" print('Pos ' + str(i - 16).zfill(2) + ': ' + message_schedule[i - 16] + ' > word4\\t = ' + word4)\n",
" print('Pos ' + str(i - 15).zfill(2) + ': ' + message_schedule[i - 15] + ' > sigma0(word3) = ' + bin(int(sigma0(word3), 2))[2:].zfill(32))\n",
" print('Pos ' + str(i - 14).zfill(2) + ': ' + message_schedule[i - 14])\n",
" print('Pos ' + str(i - 13).zfill(2) + ': ' + message_schedule[i - 13])\n",
" print('Pos ' + str(i - 12).zfill(2) + ': ' + message_schedule[i - 12])\n",
" print('Pos ' + str(i - 11).zfill(2) + ': ' + message_schedule[i - 11])\n",
" print('Pos ' + str(i - 10).zfill(2) + ': ' + message_schedule[i - 10])\n",
" print('Pos ' + str(i - 9).zfill(2) + ': ' + message_schedule[i - 9])\n",
" print('Pos ' + str(i - 8).zfill(2) + ': ' + message_schedule[i - 8])\n",
" print('Pos ' + str(i - 7).zfill(2) + ': ' + message_schedule[i - 7] + ' > word2\\t = ' + word2)\n",
" print('Pos ' + str(i - 6).zfill(2) + ': ' + message_schedule[i - 6])\n",
" print('Pos ' + str(i - 5).zfill(2) + ': ' + message_schedule[i - 5])\n",
" print('Pos ' + str(i - 4).zfill(2) + ': ' + message_schedule[i - 4])\n",
" print('Pos ' + str(i - 3).zfill(2) + ': ' + message_schedule[i - 3])\n",
" print('Pos ' + str(i - 2).zfill(2) + ': ' + message_schedule[i - 2] + ' > sigma1(word1) = '+ bin(int(sigma1(word1), 2))[2:].zfill(32))\n",
" print('Pos ' + str(i - 1).zfill(2) + ': ' + message_schedule[i - 1])\n",
"\n",
" new_word = ( \\\n",
" int(sigma1(word1), 2) + \\\n",
" int(word2, 2) + \\\n",
" int(sigma0(word3), 2) + \\\n",
" int(word4, 2)) & \\\n",
" int('11111111111111111111111111111111', 2)\n",
"\n",
" print()\n",
" print('\\t\\t\\t\\t\\t\\t AND 11111111111111111111111111111111')\n",
" print()\n",
" print('\\t\\t\\t\\t\\t\\tnew word = ' + bin(new_word)[2:].zfill(32))\n",
"\n",
" message_schedule.append(bin(new_word)[2:].zfill(32))\n",
"\n",
" time.sleep(1)\n",
"\n",
" clear_output(wait=True)\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": 29,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Pos 0:00111001000000000001111101000001\n",
"Pos 1:10001010001111011110001101111011\n",
"Pos 2:11100111011010100000111011111010\n",
"Pos 3:00101100000111100101000111001010\n",
"Pos 4:10101100111001001011010100110000\n",
"Pos 5:01101000000001010011111100110111\n",
"Pos 6:11110111001011001011101111110101\n",
"Pos 7:11010100011111001010110000000001\n",
"\n",
"upper_sigma1([Pos 4]) -> word1 = 00010110111111001001011000010100\n",
"Choose from [Pos 4], [Pos 5], [Pos 6] -> word2 = 01111011000011000011111111110101\n",
"[Pos 7] -> word3 = 11010100011111001010110000000001\n",
"result_constants[i] -> word4 = 11000110011100010111100011110010\n",
"message_schedule[i] -> word5 = 10000111100101010100001101101101\n",
"AND 11111111111111111111111111111111\n",
"term1 = 10110100100011000011111001101001\n",
"\n",
"upper_sigma0([Pos 0]) -> word1 = 01101100110011001000000011100010\n",
"Majority from [Pos 0], [Pos 1], [Pos 2] -> word2 = 01111011000011000011111111110101\n",
"AND 11111111111111111111111111111111\n",
"term2 = 01011111010111001101101010101111\n",
"\n",
"[Pos 0] = 00010011111010010001100100011000\n",
"[Pos 4] = 00010011111010010001100100011000\n"
]
}
],
"source": [
"new_compression_constants = compression_constants.copy()\n",
"\n",
"for i, word in enumerate(message_schedule):\n",
"\n",
" print('Pos 0:' + new_compression_constants[0])\n",
" print('Pos 1:' + new_compression_constants[1])\n",
" print('Pos 2:' + new_compression_constants[2])\n",
" print('Pos 3:' + new_compression_constants[3])\n",
" print('Pos 4:' + new_compression_constants[4])\n",
" print('Pos 5:' + new_compression_constants[5])\n",
" print('Pos 6:' + new_compression_constants[6])\n",
" print('Pos 7:' + new_compression_constants[7])\n",
"\n",
" print()\n",
" print('upper_sigma1([Pos 4]) -> word1 = ' + upper_sigma1(new_compression_constants[4]))\n",
" print('Choose from [Pos 4], [Pos 5], [Pos 6] -> word2 = ' + choose(new_compression_constants[4], new_compression_constants[5], new_compression_constants[6]))\n",
" print('[Pos 7] -> word3 = ' + new_compression_constants[7])\n",
" print('result_constants[i] -> word4 = ' + result_constants[i])\n",
" print('message_schedule[i] -> word5 = ' + word)\n",
" print('AND 11111111111111111111111111111111')\n",
"\n",
" term1 = (int(upper_sigma1(new_compression_constants[4]), 2) + \\\n",
" int(choose(new_compression_constants[4], new_compression_constants[5], new_compression_constants[6]), 2) + \\\n",
" int(new_compression_constants[7], 2) + \\\n",
" int(result_constants[i], 2) + \\\n",
" int(word, 2)) \\\n",
" & int('11111111111111111111111111111111', 2)\n",
"\n",
" print('term1 = ' + bin(term1)[2:].zfill(32))\n",
"\n",
" print()\n",
" print('upper_sigma0([Pos 0]) -> word1 = ' + upper_sigma1(new_compression_constants[0]))\n",
" print('Majority from [Pos 0], [Pos 1], [Pos 2] -> word2 = ' + choose(new_compression_constants[4], new_compression_constants[5], new_compression_constants[6]))\n",
" print('AND 11111111111111111111111111111111')\n",
"\n",
" term2 = (int(upper_sigma0(new_compression_constants[0]), 2) + \\\n",
" int(majority(new_compression_constants[0], new_compression_constants[1], new_compression_constants[2]), 2)) & \\\n",
" int('11111111111111111111111111111111', 2)\n",
"\n",
" print('term2 = ' + bin(term2)[2:].zfill(32))\n",
"\n",
" # move elements in list one index down, means: last one will be dropped\n",
" # and first one is empty now\n",
" new_compression_constants.insert(0, 1)\n",
" new_compression_constants.pop()\n",
"\n",
" new_compression_constants[0] = bin(\n",
" (term1 + term2) & int('11111111111111111111111111111111', 2)\n",
" )[2:].zfill(32)\n",
"\n",
" new_compression_constants[4] = bin(\n",
" (int(new_compression_constants[4], 2) + term1) & int('11111111111111111111111111111111', 2)\n",
" )[2:].zfill(32)\n",
"\n",
" print()\n",
" \n",
" print('[Pos 0] = ' + new_compression_constants[0])\n",
" print('[Pos 4] = ' + new_compression_constants[0])\n",
"\n",
" time.sleep(1)\n",
"\n",
" clear_output(wait=True)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"result = []\n",
"\n",
"for i in range(0, 8):\n",
"\n",
" time.sleep(0.25)\n",
"\n",
" # clear_output(wait=True)\n",
"\n",
" result.append(\n",
" bin(int(compression_constants[i], 2) + int(new_compression_constants[i], 2) & int('11111111111111111111111111111111', 2))[2:].zfill(32)\n",
" )\n",
"\n",
" print(compression_constants[i] + ' + ' + new_compression_constants[i] + ' AND 11111111111111111111111111111111 = ' + result[i])"
]
}
],
"metadata": {
"interpreter": {
"hash": "aee8b7b246df8f9039afb4144a1f6fd8d2ca17a180786b69acc140d282b71a49"
},
"kernelspec": {
"display_name": "Python 3.9.7 64-bit",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.13 (main, May 24 2022, 21:28:31) \n[Clang 13.1.6 (clang-1316.0.21.2)]"
},
"orig_nbformat": 4
},
"nbformat": 4,
"nbformat_minor": 2
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment