Skip to content

Instantly share code, notes, and snippets.

@cathalmccabe
Last active April 24, 2019 18:23
Show Gist options
  • Save cathalmccabe/2c53db61f27cb2a09a01e3d5401318c4 to your computer and use it in GitHub Desktop.
Save cathalmccabe/2c53db61f27cb2a09a01e3d5401318c4 to your computer and use it in GitHub Desktop.
SHA1 test
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Implementation of SHA-1 Core on SoC Ported to Python"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"# Internal constants definitions\n",
"ADDR_I_CS_DATA = 0x10\n",
"BITS_I_CS_DATA = 1\n",
"ADDR_I_WE_DATA = 0x18\n",
"BITS_I_WE_DATA = 1\n",
"ADDR_I_ADDRESS_DATA = 0x20\n",
"BITS_I_ADDRESS_DATA = 8\n",
"ADDR_I_WRITE_DATA = 0x28\n",
"BITS_I_WRITE_DATA = 32\n",
"ADDR_O_READ_DATA = 0x30\n",
"BITS_O_READ_DATA = 32\n",
"ADDR_O_READ_CTRL = 0x34\n",
"ADDR_O_ERROR_DATA = 0x38\n",
"BITS_O_ERROR_DATA = 1\n",
"ADDR_O_ERROR_CTRL = 0x3c"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"data": {
"application/javascript": [
"\n",
"require(['notebook/js/codecell'], function(codecell) {\n",
" codecell.CodeCell.options_default.highlight_modes[\n",
" 'magic_text/x-csrc'] = {'reg':[/^%%microblaze/]};\n",
" Jupyter.notebook.events.one('kernel_ready.Kernel', function(){\n",
" Jupyter.notebook.get_cells().map(function(cell){\n",
" if (cell.cell_type == 'code'){ cell.auto_highlight(); } }) ;\n",
" });\n",
"});\n"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# Load the overlay containing the IP\n",
"from pynq import Overlay\n",
"\n",
"overlay = Overlay('/usr/local/lib/python3.6/dist-packages/sha1_pynq/bitstream/sha1_overlay.bit')"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"# See what attributes the overlay has\n",
"overlay?"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"# Access the the sha1 attribute to create a driver for the IP\n",
"sha1_ip = overlay.sha1_control_0\n",
"sha1_ip?"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"def check_core():\n",
" '''Print the name of the IP core and the version.\n",
" \n",
" Arguments:\n",
" None\n",
" \n",
" Return:\n",
" None\n",
" '''\n",
" \n",
" sha1_ip.write(ADDR_I_ADDRESS_DATA, 0)\n",
" sha1_ip.write(ADDR_I_CS_DATA, 1)\n",
" sha1_ip.write(ADDR_I_WE_DATA, 0)\n",
" name0 = sha1_ip.read(ADDR_O_READ_DATA)\n",
" print(bytearray.fromhex(hex(name0)[2:]).decode())\n",
" \n",
" sha1_ip.write(ADDR_I_ADDRESS_DATA, 1)\n",
" sha1_ip.write(ADDR_I_CS_DATA, 1)\n",
" sha1_ip.write(ADDR_I_WE_DATA, 0)\n",
" name1 = sha1_ip.read(ADDR_O_READ_DATA)\n",
" print(bytearray.fromhex(hex(name1)[2:]).decode())\n",
" \n",
" sha1_ip.write(ADDR_I_ADDRESS_DATA, 2)\n",
" sha1_ip.write(ADDR_I_CS_DATA, 1)\n",
" sha1_ip.write(ADDR_I_WE_DATA, 0)\n",
" version = sha1_ip.read(ADDR_O_READ_DATA)\n",
" print(bytearray.fromhex(hex(version)[2:]).decode())"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"def read_word(address):\n",
" '''Read a data word from the given address\n",
" \n",
" Arguments:\n",
" address - the address to read data from\n",
" \n",
" Return:\n",
" The data that was read from memory\n",
" '''\n",
" \n",
" sha1_ip.write(ADDR_I_ADDRESS_DATA, address)\n",
" sha1_ip.write(ADDR_I_CS_DATA, 1)\n",
" sha1_ip.write(ADDR_I_WE_DATA, 0)\n",
" word =0;\n",
" while(sha1_ip.read(ADDR_O_READ_DATA) != 0):\n",
" word = sha1_ip.read(ADDR_O_READ_DATA)\n",
" break\n",
" return word"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"def read_digest():\n",
" '''Read the digest of the message that was input\n",
" \n",
" Arguments:\n",
" None\n",
" \n",
" Return:\n",
" A byte array of length 20 containing the digest data\n",
" '''\n",
" \n",
" digest = bytearray()\n",
" for i in range(5):\n",
" data = read_word(0x20 + i)\n",
" digest.extend(data.to_bytes(4, byteorder='big'))\n",
" return digest"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"def write_word(address, word):\n",
" '''Write a data word to the given address\n",
" \n",
" Arguments:\n",
" address - the address to write to\n",
" word - the data to write\n",
" \n",
" Return:\n",
" None\n",
" '''\n",
" \n",
" sha1_ip.write(ADDR_I_ADDRESS_DATA, address)\n",
" sha1_ip.write(ADDR_I_WRITE_DATA, word)"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [],
"source": [
"def pad_message(msg):\n",
" '''Pad the input message following the SHA1 documentation.\n",
" The purpose of the padding is to make the padded message have \n",
" a total length that is a multiple of 512, which can be processed\n",
" as sequential blocks of 512 bits.\n",
" \n",
" Arguments:\n",
" msg - input message as an ascii string\n",
" \n",
" Return:\n",
" A byte array containing the bytes of the padded message\n",
" '''\n",
" \n",
" blocks = bytearray(msg, 'ascii')\n",
" msgSize = len(msg)\n",
" blocks.append(0x80)\n",
" while len(blocks) % 64 != 56:\n",
" blocks.append(0x00)\n",
" reserved = (msgSize * 8).to_bytes(8, byteorder='big')\n",
" blocks.extend(reserved)\n",
" return bytes(blocks)"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [],
"source": [
"def write_block(block, ctrl_val):\n",
" '''Write a block of the padded message.\n",
" \n",
" Arguments:\n",
" block - 512 bits of data to be written\n",
" ctrl_val - control value based on what block is being written\n",
" \n",
" Return:\n",
" None\n",
" '''\n",
" \n",
" sha1_ip.write(ADDR_I_CS_DATA, 1)\n",
" sha1_ip.write(ADDR_I_WE_DATA, 1)\n",
" j = 0\n",
" for i in range(16):\n",
" word = int.from_bytes(block[j:j+4], byteorder='big')\n",
" write_word(0x10 + i, word)\n",
" j += 4\n",
" write_word(0x8, ctrl_val)\n",
" sha1_ip.write(ADDR_I_WE_DATA, 0)\n",
" sha1_ip.write(ADDR_I_CS_DATA, 0)\n",
" sha1_ip.write(ADDR_I_CS_DATA, 1)"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [],
"source": [
"def write_blocks(blocks):\n",
" '''Write each block of the padded message.\n",
" \n",
" Arguments:\n",
" blocks - A byte array containing the bytes of the padded message\n",
" \n",
" Return:\n",
" None\n",
" '''\n",
" \n",
" bytesWritten = 0\n",
" while bytesWritten < len(blocks):\n",
" if bytesWritten == 0:\n",
" write_block(blocks[bytesWritten:bytesWritten + 64], 0x1)\n",
" else:\n",
" write_block(blocks[bytesWritten:bytesWritten + 64], 0x2)\n",
" \n",
" status = read_word(0x09)\n",
" while status == 0:\n",
" status = read_word(0x09)\n",
" print(\"status:\", status)\n",
" \n",
" bytesWritten += 64"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [],
"source": [
"def hw_digest(msg):\n",
" '''Pad the inpute message, write the sequential blocks, and read the digest of the input.\n",
" \n",
" Arguements:\n",
" msg - input message as an ascii string\n",
" \n",
" Return:\n",
" A byte array of length 20 containing the digest data\n",
" '''\n",
" \n",
" msgPadded = pad_message(msg)\n",
" write_blocks(msgPadded)\n",
" digest = read_digest()\n",
" return digest"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [],
"source": [
"import hashlib\n",
"def sw_digest(msg):\n",
" '''Get the SHA1 digest of an ascii message using internal Python library.\n",
" \n",
" Arguments:\n",
" msg - input message as an ascii string\n",
" \n",
" Return:\n",
" A SHA1 hash object of the digest for the input message\n",
" '''\n",
" \n",
" digest = hashlib.sha1(msg.encode())\n",
" return digest"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [],
"source": [
"def test_sha1(msg):\n",
" '''Check if the message digests from hardware and software are the same.\n",
" \n",
" Arguments:\n",
" msg - input message as an ascii string\n",
" \n",
" Return:\n",
" None\n",
" '''\n",
" \n",
" swDigest = sw_digest(msg).hexdigest()\n",
" hwDigest = hw_digest(msg).hex()\n",
" print(\"hw digest: {}\".format(hwDigest))\n",
" print(\"sw digest: {}\".format(swDigest))\n",
" \n",
" if swDigest == hwDigest:\n",
" print(\"Test Passed!\")\n",
" else:\n",
" print(\"Test Failed!\")"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"----------------------------------------\n",
"Single Block Test\n",
"----------------------------------------\n",
"hw digest: a9993e364706816aba3e25717850c26c9cd0d89d\n",
"sw digest: a9993e364706816aba3e25717850c26c9cd0d89d\n",
"Test Passed!\n",
"\n",
"----------------------------------------\n",
"Double Block Test\n",
"----------------------------------------\n",
"hw digest: d4b3a5cfda922d7f02dbc77279682d73f00703d0\n",
"sw digest: 84983e441c3bd26ebaae4aa1f95129e5e54670f1\n",
"Test Failed!\n"
]
}
],
"source": [
"# Test 1\n",
"print(\"----------------------------------------\")\n",
"print(\"Single Block Test\")\n",
"print(\"----------------------------------------\")\n",
"test_sha1(\"abc\")\n",
"print(\"\\n----------------------------------------\")\n",
"print(\"Double Block Test\")\n",
"print(\"----------------------------------------\")\n",
"test_sha1(\"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq\")"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"hw digest: 7b502c3a1f48c8609ae212cdfb639dee39673f5e\n",
"sw digest: 7b502c3a1f48c8609ae212cdfb639dee39673f5e\n",
"Test Passed!\n"
]
}
],
"source": [
"# Test 2\n",
"test_sha1(\"Hello world\")"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"hw digest: a3e0394d4643674d303170641382f6efefa15b7a\n",
"sw digest: a3e0394d4643674d303170641382f6efefa15b7a\n",
"Test Passed!\n"
]
}
],
"source": [
"# Test 3\n",
"test_sha1(\"Reconfigurable GPU Computing Lab\")"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Enter a message to hash with SHA1: f69f2445df4f9b17ad2b417be66c3710f69f2445df4f9b17ad2b417be66c3710f69f2445df4f9b17ad2b417be66c3710\n",
"hw digest: 594aed687bb569ee459c1e8d6ae04161cb6f7731\n",
"sw digest: 064743b8a9e3413abec46f784894429e283dd194\n",
"Test Failed!\n"
]
}
],
"source": [
"# Custom message test\n",
"m = input(\"Enter a message to hash with SHA1: \")\n",
"test_sha1(m)"
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"The slowest run took 4.03 times longer than the fastest. This could mean that an intermediate result is being cached.\n",
"100000 loops, best of 3: 10.1 µs per loop\n"
]
}
],
"source": [
"%%timeit\n",
"# Software Timing\n",
"sw_digest(\"Hello World!\")"
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"100 loops, best of 3: 2.87 ms per loop\n"
]
}
],
"source": [
"%%timeit\n",
"# Hardware Timing\n",
"hw_digest(\"Hello World!\")"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"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.6.5"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment