mirror of
https://github.com/billbuchanan/appliedcrypto.git
synced 2026-02-20 13:50:42 +00:00
395 lines
13 KiB
Plaintext
395 lines
13 KiB
Plaintext
{
|
||
"cells": [
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "a7782a35",
|
||
"metadata": {},
|
||
"source": [
|
||
"\n",
|
||
"# Diffie Hellman\n",
|
||
"With key exchange, Bob and Alice end up with the same secret key, even though Eve is listening to their communications:\n",
|
||
"\n",
|
||
"<img src='graphics/g_key_02.png' width=\"800px\">\n",
|
||
"\n",
|
||
"The Diffie-Hellman method allows Bob and Alice to pass public values to each other and then derive the same key:\n",
|
||
"\n",
|
||
"<img src='graphics/g_key_01.png' width=\"800px\">\n",
|
||
"\n",
|
||
"For this Bob generates a secret value (b) and Alice generates a secret value (a). Bob passes g^b mod p, and Alice passes g^a mod p.\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "1265ed12",
|
||
"metadata": {},
|
||
"source": [
|
||
"> Bob and Alice have agreed on the values:\n",
|
||
"\n",
|
||
"g=2879, N= 9929\n",
|
||
"\n",
|
||
"Bob Select x=6, Alice selects y=9\n",
|
||
"\n",
|
||
"Now calculate (using a calculator or Python:\n",
|
||
"\n",
|
||
"Alice’s A value (g^x mod N):\n",
|
||
"\n",
|
||
"Bob’s B value (g^y mod N):\n",
|
||
"\n",
|
||
"Now they exchange the values. Next calculate the shared key:\n",
|
||
"\n",
|
||
"Alice’s value (B^x mod N):\n",
|
||
"\n",
|
||
"Bobs’s value (A^y mod N):\n",
|
||
"\n",
|
||
"> Do they match? Yes/No"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "3ed130a0",
|
||
"metadata": {},
|
||
"source": [
|
||
"We can use Python to implement a simple example with a given base generator (g) and prime number (p):"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 6,
|
||
"id": "80911155",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"g: 5 (a shared value), n: 1001 (a prime number)\n",
|
||
"\n",
|
||
"Alice calculates:\n",
|
||
"a (Alice random): 410\n",
|
||
"Alice value (A): 298 (g^a) mod p\n",
|
||
"\n",
|
||
"Bob calculates:\n",
|
||
"b (Bob random): 105\n",
|
||
"Bob value (B): 265 (g^b) mod p\n",
|
||
"\n",
|
||
"Alice calculates:\n",
|
||
"Key: 155 (B^a) mod p\n",
|
||
"Key: 210e3b160c355818509425b9d9e9fd3ea2e287f2c43a13e5be8817140db0b9e6\n",
|
||
"\n",
|
||
"Bob calculates:\n",
|
||
"Key: 155 (A^b) mod p\n",
|
||
"Key: 210e3b160c355818509425b9d9e9fd3ea2e287f2c43a13e5be8817140db0b9e6\n"
|
||
]
|
||
}
|
||
],
|
||
"source": [
|
||
"# 04_01.py\n",
|
||
"# https://asecuritysite.com/keyexchange/diffie_py\n",
|
||
"import random\n",
|
||
"import hashlib\n",
|
||
"\n",
|
||
"g=5\n",
|
||
"p=1001\n",
|
||
"\n",
|
||
"a=random.randint(1, p)\n",
|
||
"\n",
|
||
"b=random.randint(1,p)\n",
|
||
"\n",
|
||
"A = (g**a) % p\n",
|
||
"B = (g**b) % p\n",
|
||
"\n",
|
||
"print('g: ',g,' (a shared value), n: ',p, ' (a prime number)')\n",
|
||
"\n",
|
||
"print('\\nAlice calculates:')\n",
|
||
"print('a (Alice random): ',a)\n",
|
||
"print('Alice value (A): ',A,' (g^a) mod p')\n",
|
||
"\n",
|
||
"print('\\nBob calculates:')\n",
|
||
"print('b (Bob random): ',b)\n",
|
||
"print('Bob value (B): ',B,' (g^b) mod p')\n",
|
||
"\n",
|
||
"print('\\nAlice calculates:')\n",
|
||
"keyA=(B**a) % p\n",
|
||
"print('Key: ',keyA,' (B^a) mod p')\n",
|
||
"print('Key: ',hashlib.sha256(str(keyA).encode()).hexdigest())\n",
|
||
"\n",
|
||
"print('\\nBob calculates:')\n",
|
||
"keyB=(A**b) % p\n",
|
||
"print('Key: ',keyB,' (A^b) mod p')\n",
|
||
"print('Key: ',hashlib.sha256(str(keyB).encode()).hexdigest())"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "6d22b5c8",
|
||
"metadata": {},
|
||
"source": [
|
||
"> Run the code and verify that Bob and Alice compute the same shared secret.\n",
|
||
"\n",
|
||
"> The (g**b) % p operation can be computationally intensive. Replace this operation with pow(g,b,p), and verify that the program still works.\n",
|
||
"\n",
|
||
"> Use a prime number of 997, and verify the operation of the code.\n",
|
||
"\n",
|
||
"> Use a prime number of 2^19-1, and verify the operation of the code."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "b8e14951",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Selecting generator for discrete logs\n",
|
||
"With a discrete log method, we have the form of:\n",
|
||
"\n",
|
||
"Y=g^x (mod p)\n",
|
||
"\n",
|
||
"For the base, we must select a base generator that produces all the possible values of Y for x, with a given prime number of p.\n",
|
||
"\n",
|
||
"\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 1,
|
||
"id": "548c6405",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"p: 11\n",
|
||
"Values for g^x mod p: \n",
|
||
"2 6 7 8 None\n"
|
||
]
|
||
}
|
||
],
|
||
"source": [
|
||
"# 04_02.py\n",
|
||
"# https://asecuritysite.com/dh/pickg2\n",
|
||
"p=11\n",
|
||
"\n",
|
||
"def getG(p):\n",
|
||
"\n",
|
||
" for x in range (1,p):\n",
|
||
"\t rand = x\n",
|
||
"\t exp=1\n",
|
||
"\t next = rand % p\n",
|
||
"\n",
|
||
"\t while (next != 1 ):\n",
|
||
"\t\t next = (next*rand) % p\n",
|
||
"\t\t exp = exp+1\n",
|
||
"\n",
|
||
"\n",
|
||
"\t if (exp==p-1):\n",
|
||
"\t\t print (rand,end=' ')\n",
|
||
"\n",
|
||
"print (\"p: \",p)\n",
|
||
"print (\"Values for g^x mod p: \")\n",
|
||
"print (getG(p))"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "222bec32",
|
||
"metadata": {},
|
||
"source": [
|
||
"> For a prime number of p=11, what are the possible base generator values?\n",
|
||
"> For a prime number of p=97, what are the possible base generator values?\n",
|
||
"> If we pick a value of p=11, and take a value of g=5, show that we do not output all the possible values for Y=g^x (mod p).\n",
|
||
"> If we pick a value of p=11, and take a value of g=6, show that we do output all the possible values for Y=g^x (mod p)."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "8c457f5e",
|
||
"metadata": {},
|
||
"source": [
|
||
"# Elliptic Curve Diffie Hellman (ECDH)\n",
|
||
"The most popular key exchange method is ECDH (Elliptic Curve Diffie Hellman). This uses an elliptic curve method, of which the most popular curve is P256 (SECP256R1). \n",
|
||
"\n",
|
||
"<img src='graphics/g_key_12.png' width=\"800px\">\n",
|
||
"\n",
|
||
"The following is the some code:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 7,
|
||
"id": "73037ef4",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"Name of curve: secp256r1\n",
|
||
"Generated key size: 32 bytes (256 bits)\n",
|
||
"\n",
|
||
"Bob private key value: 115386775143760985994606199743124500698563324842662591622007624940178885352350\n",
|
||
"Bob's public key: 3059301306072a8648ce3d020106082a8648ce3d0301070342000453c9db700d76051a285ac6ecf2a27bc82056faca157b52d9744d1f781577e2a8bd0011523ad95fc5012b2c1d5bbae06a51f4a64e34e5397e4c282fe595bf8037\n",
|
||
"\n",
|
||
"Alice private key value: 73556695653589803082300318169887127685187875212044508782243551530526730975658\n",
|
||
"Alice's public key: 3059301306072a8648ce3d020106082a8648ce3d03010703420004aa8ac00f7a33ab033eb047d9fe2892a9da3ad8381b8bd1f4e0007f89b13d5b6a243a3ec52af2c48903cdf662c6cf79acc05292bce510f4fcb11071cb6be338f2\n",
|
||
"\n",
|
||
"Bob's derived key: c1c76e98cb3ef84986fa5395b8da34bff86c180005ff3de1ea088807542ad517\n",
|
||
"Alice's derived key: c1c76e98cb3ef84986fa5395b8da34bff86c180005ff3de1ea088807542ad517\n"
|
||
]
|
||
}
|
||
],
|
||
"source": [
|
||
"# 04_03.py\n",
|
||
"# https://asecuritysite.com/hazmat/hashnew13\n",
|
||
"from cryptography.hazmat.primitives import hashes\n",
|
||
"from cryptography.hazmat.primitives.asymmetric import ec\n",
|
||
"from cryptography.hazmat.primitives.kdf.hkdf import HKDF\n",
|
||
"from cryptography.hazmat.primitives import serialization\n",
|
||
"from cryptography.hazmat.backends import default_backend\n",
|
||
"import binascii\n",
|
||
"import sys\n",
|
||
"\n",
|
||
"Bob_private_key = ec.generate_private_key(ec.SECP384R1(),default_backend())\n",
|
||
"\n",
|
||
"Alice_private_key = ec.generate_private_key(ec.SECP384R1(),default_backend())\n",
|
||
"size=32 # 256 bit key\n",
|
||
"\n",
|
||
"\n",
|
||
"\n",
|
||
"Bob_private_key = ec.generate_private_key(ec.SECP256R1(),default_backend())\n",
|
||
"Alice_private_key = ec.generate_private_key(ec.SECP256R1(),default_backend()) \n",
|
||
"\n",
|
||
"Bob_shared_key = Bob_private_key.exchange(ec.ECDH(), Alice_private_key.public_key())\n",
|
||
"\n",
|
||
"Bob_derived_key = HKDF(algorithm=hashes.SHA256(),length=size,salt=None,info=b'',backend=default_backend()).derive(Bob_shared_key)\n",
|
||
"\n",
|
||
"Alice_shared_key = Alice_private_key.exchange(ec.ECDH(), Bob_private_key.public_key())\n",
|
||
"\n",
|
||
"Alice_derived_key = HKDF(algorithm=hashes.SHA256(),length=size,salt=None,info=b'',backend=default_backend()).derive(Alice_shared_key)\n",
|
||
"\n",
|
||
"print (\"Name of curve: \",Bob_private_key.public_key().curve.name)\n",
|
||
"print (f\"Generated key size: {size} bytes ({size*8} bits)\")\n",
|
||
"\n",
|
||
"vals = Bob_private_key.private_numbers()\n",
|
||
"print (f\"\\nBob private key value: {vals.private_value}\")\n",
|
||
"vals=Bob_private_key.public_key()\n",
|
||
"enc_point=binascii.b2a_hex(vals.public_bytes(encoding=serialization.Encoding.DER,format=serialization.PublicFormat.SubjectPublicKeyInfo)).decode()\n",
|
||
"print(\"Bob's public key: \",enc_point)\n",
|
||
"\n",
|
||
"vals = Alice_private_key.private_numbers()\n",
|
||
"print (f\"\\nAlice private key value: {vals.private_value}\")\n",
|
||
"vals=Alice_private_key.public_key()\n",
|
||
"enc_point=binascii.b2a_hex(vals.public_bytes(encoding=serialization.Encoding.DER,format=serialization.PublicFormat.SubjectPublicKeyInfo)).decode()\n",
|
||
"print(\"Alice's public key: \",enc_point)\n",
|
||
"\n",
|
||
"print (\"\\nBob's derived key: \",binascii.b2a_hex(Bob_derived_key).decode())\n",
|
||
"print(\"Alice's derived key: \",binascii.b2a_hex(Alice_derived_key).decode())"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "4a3e413f",
|
||
"metadata": {},
|
||
"source": [
|
||
"> The program uses SECP256R1, and which is also known as the NIST P-256 curve. The Bitcoin curve is SECP256k1. Modify the program so that it uses this curve. Verify that it still works of the shared key.\n",
|
||
"\n",
|
||
"> An enhanced curve is SECP521R1. Modify the program so that it uses this curve. Verify that it still works of the shared key.\n",
|
||
"\n",
|
||
"> The Brainpool curves have some advantages over SECP2561. Modify the program so that it uses the P256R1 curve, and verify that it still works for the shared key.\n",
|
||
"\n",
|
||
"> The program creates a 256-bit key. Modify the program so that it generated a 128-bit key.\n",
|
||
"\n",
|
||
"> Modify the program so that is displays the shared key in a Base64 format.\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "1c0e6351",
|
||
"metadata": {},
|
||
"source": [
|
||
"## DH Parameters \n",
|
||
"In the DH key generation we have two base parameters: g and p. We can use OpenSSL to generate these parameters. Such as:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "ead31dbd",
|
||
"metadata": {},
|
||
"source": [
|
||
">> Generate 768-bit Diffie-Hellman parameters:\n",
|
||
"\n",
|
||
"openssl dhparam -out dhparams.pem -text 768 \n",
|
||
"\n",
|
||
">> View your key exchange parameters with:\n",
|
||
"\n",
|
||
"cat dhparams.pem\t\n",
|
||
"\n",
|
||
">> What is the value of g:\n",
|
||
"\n",
|
||
">> How many bits does the prime number have?\n",
|
||
"\n",
|
||
">> How long does it take to produce the parameters for 1,024 bits (Group 2)?\n",
|
||
"\n",
|
||
">> How long does it take to produce the parameters for 1536 bits (Group 5)?\n",
|
||
"\n",
|
||
">> How would we change the g value?"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "a4266944",
|
||
"metadata": {},
|
||
"source": [
|
||
"## EC Paramters\n",
|
||
"With elliptic curves, we can use OpenSSL to generate a curve:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "f844cbaf",
|
||
"metadata": {},
|
||
"source": [
|
||
">> Let’s look at the Elliptic curves we can create:\n",
|
||
"\n",
|
||
"openssl ecparam -list_curves\n",
|
||
"\n",
|
||
">> We can create our elliptic parameter file with:\n",
|
||
"\n",
|
||
"openssl ecparam -name secp256k1 -out secp256k1.pem\n",
|
||
"\n",
|
||
">> Now view the details with:\n",
|
||
"\n",
|
||
"openssl ecparam -in secp256k1.pem -text -param_enc explicit -noout\n",
|
||
"\n",
|
||
">> What are the details of the key?\n",
|
||
"\n",
|
||
">> Now we can create our key pair:\n",
|
||
"\n",
|
||
"openssl ecparam -in secp256k1.pem -genkey -noout -out mykey.pem\n",
|
||
"\n",
|
||
">> Name three 160-bit curves:"
|
||
]
|
||
}
|
||
],
|
||
"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.8.3"
|
||
}
|
||
},
|
||
"nbformat": 4,
|
||
"nbformat_minor": 5
|
||
}
|