mirror of
https://github.com/billbuchanan/appliedcrypto.git
synced 2026-02-20 13:50:42 +00:00
338 lines
9.7 KiB
Plaintext
338 lines
9.7 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "a7782a35",
|
|
"metadata": {},
|
|
"source": [
|
|
"\n",
|
|
"# Message Authentication Code (MAC)\n",
|
|
"A MAC involves a hashing being signed by a shared secret key between Bob and Alice. For this, we define a given hashing method, such as SHA-256, and a given MAC type.\n",
|
|
"\n",
|
|
"## HMAC\n",
|
|
"HMAC (hash-based message authentication code) supports the usage of a key to hash data. This key is kept secret between Bob and Alice, and can be used to authentication both the data and that the sender still knows the secret. Overall HMAC can be used with a range of different hashing methods, such as MD5, SHA-1, SHA-256 (SHA-2) and SHA-3. \n",
|
|
"\n",
|
|
"<img src='graphics/g_mac_01.png' width=\"800px\">\n",
|
|
"\n",
|
|
"For HMAC-BLAKE2, we can have:\n",
|
|
"\n",
|
|
"<img src='graphics/g_mac_02.png' width=\"800px\">\n",
|
|
"\n",
|
|
"\n",
|
|
"The code to implement this is:\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 2,
|
|
"id": "52ead7e5",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Data: The quick brown fox jumps over the lazy dog\n",
|
|
" Hex: 54686520717569636b2062726f776e20666f78206a756d7073206f76657220746865206c617a7920646f67\n",
|
|
"Key: key\n",
|
|
" Hex: 6b6579\n",
|
|
"\n",
|
|
"HMAC-SHA256: f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8 97yD9DBThCSxMpjmqm+xQ+9NWaFJRhdZl0edvC0aPNg=\n",
|
|
"\n",
|
|
"HMAC Verified\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"# 05_01.py\n",
|
|
"# https://asecuritysite.com/hazmat/hashnew2\n",
|
|
"\n",
|
|
"from cryptography.hazmat.primitives import hashes, hmac\n",
|
|
"import binascii\n",
|
|
"from cryptography.hazmat.backends import default_backend\n",
|
|
"\n",
|
|
"st = \"The quick brown fox jumps over the lazy dog\"\n",
|
|
"hex=False\n",
|
|
"showhex=\"No\"\n",
|
|
"k=\"key\"\n",
|
|
"\n",
|
|
"def show_hmac(name,type,data,key):\n",
|
|
" digest = hmac.HMAC(key, type,backend=default_backend())\n",
|
|
" digest.update(data)\n",
|
|
" res=digest.finalize()\n",
|
|
" hex=binascii.b2a_hex(res).decode()\n",
|
|
" b64=binascii.b2a_base64(res).decode()\n",
|
|
" print (f\"HMAC-{name}: {hex} {b64}\")\n",
|
|
" \n",
|
|
" digest2 = hmac.HMAC(key, type,backend=default_backend())\n",
|
|
" digest2.update(data)\n",
|
|
" rtn=digest2.verify(res)\n",
|
|
" if (rtn==None): print(\"HMAC Verified\")\n",
|
|
"\n",
|
|
"try:\n",
|
|
"\tif (hex==True): data = binascii.a2b_hex(st)\n",
|
|
"\telse: data=st.encode()\n",
|
|
"\n",
|
|
"\tif (hex==True): key = binascii.a2b_hex(k)\n",
|
|
"\telse: key=k.encode()\n",
|
|
"\n",
|
|
"\tprint (\"Data: \",st)\n",
|
|
"\tprint (\" Hex: \",binascii.b2a_hex(data).decode())\n",
|
|
"\tprint (\"Key: \",k)\n",
|
|
"\tprint (\" Hex: \",binascii.b2a_hex(key).decode())\n",
|
|
"\tprint()\n",
|
|
"\n",
|
|
"\tshow_hmac(\"SHA256\",hashes.SHA256(),data,key)\n",
|
|
"\n",
|
|
"except Exception as e:\n",
|
|
" print(e)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "7b15458c",
|
|
"metadata": {},
|
|
"source": [
|
|
"> Verify that the HMAC signature works with the given message.\n",
|
|
"\n",
|
|
"> Modify the program for HMAC-MD5 and verify that it works.\n",
|
|
"\n",
|
|
"> Modify the program for HMAC-SHA1 and verify that it works.\n",
|
|
"\n",
|
|
"> Modify the program for HMAC-SHA512 and verify that it works.\n",
|
|
"\n",
|
|
"> Observe how the signature varies for different hashing methods."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "e4358ba5",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Poly1305\n",
|
|
"For a stream cipher, it is important that we have a MAC, so that we can detect any changes in the bits in the cipher. ChaCha20 typically uses Poly1305 for its MAC. \n",
|
|
"\n",
|
|
"<img src='graphics/g_mac_05.png' width=\"800px\">"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 9,
|
|
"id": "3e3b1107",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Message: --f=/Users/billbuchanan/Library/Jupyter/runtime/kernel-v2-71602TT5d9wYK6Zod.json\n",
|
|
"Key: a84edba3b95371406aa09d7f3c0e36b8fb1ac7808dd204078f0660cf9dfe3834\n",
|
|
"\n",
|
|
"Poly1305 tag (16 bytes): cf7fd40e03581a380911434fc41d40c2\n",
|
|
"Signature matches\n",
|
|
"\n",
|
|
"\n",
|
|
"--- Generating with alternative method ---\n",
|
|
"cf7fd40e03581a380911434fc41d40c2\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"# 05_02.py\n",
|
|
"# https://asecuritysite.com/hazmat/hashnew27\n",
|
|
"import os\n",
|
|
"import sys\n",
|
|
"import binascii\n",
|
|
"\n",
|
|
"from cryptography.hazmat.primitives import poly1305\n",
|
|
"\n",
|
|
"\n",
|
|
"message = \"message\"\n",
|
|
"\n",
|
|
"if (len(sys.argv)>1):\n",
|
|
"\tmessage=str(sys.argv[1])\n",
|
|
"\n",
|
|
"\n",
|
|
"message=message.encode()\n",
|
|
"key = os.urandom(32)\n",
|
|
"\n",
|
|
"c = poly1305.Poly1305(key)\n",
|
|
"\n",
|
|
"c.update(message)\n",
|
|
"\n",
|
|
"\n",
|
|
"signature = c.finalize()\n",
|
|
"\n",
|
|
"print (f\"Message: {message.decode()}\" )\n",
|
|
"\n",
|
|
"print (f\"Key: {binascii.b2a_hex(key).decode()}\")\n",
|
|
"\n",
|
|
"print (f\"\\nPoly1305 tag (16 bytes): {binascii.b2a_hex(signature).decode()}\")\n",
|
|
"\n",
|
|
"c = poly1305.Poly1305(key)\n",
|
|
"c.update(message)\n",
|
|
"\n",
|
|
"try:\n",
|
|
" rtn=c.verify(signature)\n",
|
|
" print (\"Signature matches\")\n",
|
|
"except:\n",
|
|
" print (\"Signature does not match\")\n",
|
|
"\n",
|
|
"\n",
|
|
"\n",
|
|
"print (\"\\n\\n--- Generating with alternative method ---\")\n",
|
|
"tag=poly1305.Poly1305.generate_tag(key,message)\n",
|
|
"print (binascii.b2a_hex(tag).decode())\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "7a469b7b",
|
|
"metadata": {},
|
|
"source": [
|
|
"> Verify the the operation of the Poly1305 in this program.\n",
|
|
"\n",
|
|
"> What is the size of the key used in this example?\n",
|
|
"\n",
|
|
"> How many bits does the Poly1305 tag have?"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "5eafe837",
|
|
"metadata": {},
|
|
"source": [
|
|
"## CMAC\n",
|
|
"CMACs (Cipher-based message authentication codes) create a message authentication codes (MACs) using a block cipher and a secret key. They differ from HMACs in that they use a symmetric key method for the MACs rather than a hashing method. In the following, we use the AES method to create the MAC:\n",
|
|
"\n",
|
|
"<img src='graphics/g_mac_03.png' width=\"800px\">"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 11,
|
|
"id": "c613e949",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Message: --f=/Users/billbuchanan/Library/Jupyter/runtime/kernel-v2-71602TT5d9wYK6Zod.json\n",
|
|
"Type: TripleDES\n",
|
|
"Key: 56837cb6ddfc06db9f55553e653628cc3cdfaf738f45deee83698fdf60bd1c87\n",
|
|
"CMAC signature: 58118c98fa654fb7a42a392b5df31c26\n",
|
|
"Signature matches\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"# 05_03.py\n",
|
|
"# https://asecuritysite.com/hazmat/hashnew26\n",
|
|
"import os\n",
|
|
"import sys\n",
|
|
"import binascii\n",
|
|
"\n",
|
|
"from cryptography.hazmat.primitives import cmac\n",
|
|
"\n",
|
|
"from cryptography.hazmat.primitives.ciphers import algorithms\n",
|
|
"\n",
|
|
"message = \"message\"\n",
|
|
"ctype=\"TripleDES\"\n",
|
|
"\n",
|
|
"if (len(sys.argv)>1):\n",
|
|
"\tmessage=str(sys.argv[1])\n",
|
|
"if (len(sys.argv)>2):\n",
|
|
"\tctype=str(sys.argv[2])\n",
|
|
"\n",
|
|
"message=message.encode()\n",
|
|
"key = os.urandom(32)\n",
|
|
"\n",
|
|
"c = cmac.CMAC(algorithms.AES(key),backend=default_backend())\n",
|
|
"\n",
|
|
"\n",
|
|
"\n",
|
|
"c.update(message)\n",
|
|
"\n",
|
|
"c_copy = c.copy() \n",
|
|
"\n",
|
|
"signature = c.finalize()\n",
|
|
"\n",
|
|
"print (f\"Message: {message.decode()}\" )\n",
|
|
"print (f\"Type: {ctype}\" )\n",
|
|
"print (f\"Key: {binascii.b2a_hex(key).decode()}\")\n",
|
|
"\n",
|
|
"print (f\"CMAC signature: {binascii.b2a_hex(signature).decode()}\")\n",
|
|
"\n",
|
|
"try:\n",
|
|
" rtn=c_copy.verify(signature)\n",
|
|
" print (\"Signature matches\")\n",
|
|
"except:\n",
|
|
" print (\"Signature does not match\")\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "928069a0",
|
|
"metadata": {},
|
|
"source": [
|
|
"> Verify the operation of the code.\n",
|
|
"\n",
|
|
"> Rather than using AES, implement the code using 3DES.\n",
|
|
"\n",
|
|
"> Rather than using AES, implement the code using Blowfish."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "472d880e",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Generate HMAC with OpenSSL\n",
|
|
"We can use OpenSSL to generate MACs. For HMAC, we can generate:\n",
|
|
"\n",
|
|
"```\n",
|
|
"Message: Hello\n",
|
|
"Password: test\n",
|
|
"Hash: sha256\n",
|
|
"========================\n",
|
|
"HMAC:\n",
|
|
"Windows command: \"echo set /p=\"Hello\" | openssl dgst -sha256 -hmac test\"\n",
|
|
"Linux command: \"echo -n \"Hello\" | openssl dgst -sha256 -hmac test\"\n",
|
|
"Result:\n",
|
|
"e2bb88dfaff4fea88d7dc7a00d18b79bb971653de0fe54c7f3985e4daa1e6a25\n",
|
|
"```"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "b74c84f4",
|
|
"metadata": {},
|
|
"source": [
|
|
">> With OpenSSL, generate the HMAC signature for a message of \"Goodbye\" and a key of \"qwerty123\". Use a hash of SHA1, SHA256, and SHA3-256. Check your answer [here](https://asecuritysite.com/mac/openssl_hmac)."
|
|
]
|
|
}
|
|
],
|
|
"metadata": {
|
|
"kernelspec": {
|
|
"display_name": "Python 3 (ipykernel)",
|
|
"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.11.9"
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 5
|
|
}
|