Files
appliedcrypto/crypto.ipynb
billbuchanan cc191e655e Update
2022-01-27 20:38:42 +00:00

1497 lines
59 KiB
Plaintext

{
"cells": [
{
"cell_type": "markdown",
"id": "ddb45b14",
"metadata": {},
"source": [
"# Hazmat Primitives in Cryptography"
]
},
{
"cell_type": "markdown",
"id": "27a217f9",
"metadata": {},
"source": [
"One of the useful library for crypto primitives in Python is called cryptography. It contain both \"secure\" primitives and a \"hazmat\" layer. Overall the \"hazmat\" layer should be treated with care, as it could contain security vulnerabilities. In this case we will implement a number of hashing primitives with the \"hazmat\" layer."
]
},
{
"cell_type": "markdown",
"id": "bd1df656",
"metadata": {},
"source": [
"## Hashing"
]
},
{
"cell_type": "markdown",
"id": "a71b189d",
"metadata": {},
"source": [
"Within hashing methods, we take data in the form of a byte array, and then create a fixed length hash value. For MD5, the length of the hash is 128 bits, for SHA-1 it is 160 bits, and for SHA-256, it is 256 bits. In the following we will use the hashing methods supported by the Hazmat primitive. This includes MD5, SHA-1 and SHA-256:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "5b576b95",
"metadata": {},
"outputs": [],
"source": [
"from cryptography.hazmat.primitives import hashes\n",
"import binascii\n",
"import sys\n",
"from cryptography.hazmat.backends import default_backend\n",
"\n",
"st = \"00\"\n",
"hex=False\n",
"showhex=\"No\"\n",
"\n",
"def show_hash(name,type,data):\n",
" digest = hashes.Hash(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\"{name}: {hex} {b64}\")\n",
"\n",
"if (showhex==\"yes\"): hex=True\n",
"\n",
"try:\n",
"\tif (hex==True): data = binascii.a2b_hex(st)\n",
"\telse: data=st.encode()\n",
"\n",
"\n",
"\tprint (\"Data: \",st)\n",
"\tprint (\" Hex: \",binascii.b2a_hex(data).decode())\n",
"\tprint()\n",
"\n",
"\tshow_hash(\"Blake2p (64 bytes)\",hashes.BLAKE2b(64),data)\n",
"\tshow_hash(\"Blake2s (32 bytes)\",hashes.BLAKE2s(32),data)\n",
"\tshow_hash(\"MD5\",hashes.MD5(),data)\n",
"\tshow_hash(\"SHA1\",hashes.SHA1(),data)\t\n",
"\tshow_hash(\"SHA224\",hashes.SHA224(),data)\n",
"\tshow_hash(\"SHA256\",hashes.SHA256(),data)\n",
"\tshow_hash(\"SHA384\",hashes.SHA384(),data)\n",
"\tshow_hash(\"SHA3_224\",hashes.SHA3_224(),data)\n",
"\tshow_hash(\"SHA3_256\",hashes.SHA3_256(),data)\n",
"\tshow_hash(\"SHA3_384\",hashes.SHA3_384(),data)\n",
"\tshow_hash(\"SHA3_512\",hashes.SHA3_512(),data)\n",
"\tshow_hash(\"SHA512\",hashes.SHA512(),data)\n",
"\tshow_hash(\"SHA512_224\",hashes.SHA512_224(),data)\n",
"\tshow_hash(\"SHA512_256\",hashes.SHA512_256(),data)\n",
"\tshow_hash(\"SHAKE128 (64 bytes)\",hashes.SHAKE128(64),data)\n",
"\tshow_hash(\"SHAKE256 (64 bytes)\",hashes.SHAKE256(64),data)\n",
"\n",
"except Exception as e:\n",
" print(e)"
]
},
{
"cell_type": "markdown",
"id": "15aa36f1",
"metadata": {},
"source": [
"In this case the input data is \"00\". Can you run the program again, and this time use the data input of \"The quick brown fox jumps over the lazy dog\". Prove that:\n",
"\n",
"- MD5 hash value is \"9e107d9d372bb6826bd81d3542a419d6\"\n",
"- SHA-1 hash value is \"2fd4e1c67a2d28fced849ee1bb76e7391b93eb12\"\n",
"- SHA-256 hash value is \"d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592\""
]
},
{
"cell_type": "markdown",
"id": "baf56309",
"metadata": {},
"source": [
"## HMAC"
]
},
{
"cell_type": "markdown",
"id": "0d2ca3fe",
"metadata": {},
"source": [
"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. This page outlines the main HMAC methods used in the Hazmat cryptography layer. You can either enter as a hexademical string or an ASCII string, and the output is displayed in a hexademical and a Base-64 format."
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "7e78337d",
"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-Blake2p (64 bytes): 92294f92c0dfb9b00ec9ae8bd94d7e7d8a036b885a499f149dfe2fd2199394aaaf6b8894a1730cccb2cd050f9bcf5062a38b51b0dab33207f8ef35ae2c9df51b kilPksDfubAOya6L2U1+fYoDa4haSZ8Unf4v0hmTlKqva4iUoXMMzLLNBQ+bz1Bio4tRsNqzMgf47zWuLJ31Gw==\n",
"\n",
"HMAC-Blake2s (32 bytes): f93215bb90d4af4c3061cd932fb169fb8bb8a91d0b4022baea1271e1323cd9a0 +TIVu5DUr0wwYc2TL7Fp+4u4qR0LQCK66hJx4TI82aA=\n",
"\n",
"HMAC-MD5: 80070713463e7749b90c2dc24911e275 gAcHE0Y+d0m5DC3CSRHidQ==\n",
"\n",
"HMAC-SHA1: de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9 3nybhbi3iqa8ino29wqQcBydtNk=\n",
"\n",
"HMAC-SHA224: 88ff8b54675d39b8f72322e65ff945c52d96379988ada25639747e69 iP+LVGddObj3IyLmX/lFxS2WN5mIraJWOXR+aQ==\n",
"\n",
"HMAC-SHA256: f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8 97yD9DBThCSxMpjmqm+xQ+9NWaFJRhdZl0edvC0aPNg=\n",
"\n",
"HMAC-SHA384: d7f4727e2c0b39ae0f1e40cc96f60242d5b7801841cea6fc592c5d3e1ae50700582a96cf35e1e554995fe4e03381c237 1/RyfiwLOa4PHkDMlvYCQtW3gBhBzqb8WSxdPhrlBwBYKpbPNeHlVJlf5OAzgcI3\n",
"\n",
"HMAC-SHA3_224: ff6fa8447ce10fb1efdccfe62caf8b640fe46c4fb1007912bf85100f /2+oRHzhD7Hv3M/mLK+LZA/kbE+xAHkSv4UQDw==\n",
"\n",
"HMAC-SHA3_256: 8c6e0683409427f8931711b10ca92a506eb1fafa48fadd66d76126f47ac2c333 jG4Gg0CUJ/iTFxGxDKkqUG6x+vpI+t1m12Em9HrCwzM=\n",
"\n",
"HMAC-SHA3_384: aa739ad9fcdf9be4a04f06680ade7a1bd1e01a0af64accb04366234cf9f6934a0f8589772f857681fcde8acc256091a2 qnOa2fzfm+SgTwZoCt56G9HgGgr2SsywQ2YjTPn2k0oPhYl3L4V2gfzeiswlYJGi\n",
"\n",
"HMAC-SHA3_512: 237a35049c40b3ef5ddd960b3dc893d8284953b9a4756611b1b61bffcf53edd979f93547db714b06ef0a692062c609b70208ab8d4a280ceee40ed8100f293063 I3o1BJxAs+9d3ZYLPciT2ChJU7mkdWYRsbYb/89T7dl5+TVH23FLBu8KaSBixgm3AgirjUooDO7kDtgQDykwYw==\n",
"\n",
"HMAC-SHA512: b42af09057bac1e2d41708e48a902e09b5ff7f12ab428a4fe86653c73dd248fb82f948a549f7b791a5b41915ee4d1ec3935357e4e2317250d0372afa2ebeeb3a tCrwkFe6weLUFwjkipAuCbX/fxKrQopP6GZTxz3SSPuC+UilSfe3kaW0GRXuTR7Dk1NX5OIxclDQNyr6Lr7rOg==\n",
"\n",
"HMAC-SHA512_224: a1afb4f708cb63570639195121785ada3dc615989cc3c73f38e306a3 oa+09wjLY1cGORlRIXha2j3GFZicw8c/OOMGow==\n",
"\n",
"HMAC-SHA512_256: 7fb65e03577da9151a1016e9c2e514d4d48842857f13927f348588173dca6d89 f7ZeA1d9qRUaEBbpwuUU1NSIQoV/E5J/NIWIFz3KbYk=\n",
"\n"
]
}
],
"source": [
"from cryptography.hazmat.primitives import hashes, hmac\n",
"import binascii\n",
"import sys\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",
"if (showhex==\"yes\"): hex=True\n",
"\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(\"Blake2p (64 bytes)\",hashes.BLAKE2b(64),data,key)\n",
"\tshow_hmac(\"Blake2s (32 bytes)\",hashes.BLAKE2s(32),data,key)\n",
"\tshow_hmac(\"MD5\",hashes.MD5(),data,key)\n",
"\tshow_hmac(\"SHA1\",hashes.SHA1(),data,key)\t\n",
"\tshow_hmac(\"SHA224\",hashes.SHA224(),data,key)\n",
"\tshow_hmac(\"SHA256\",hashes.SHA256(),data,key)\n",
"\tshow_hmac(\"SHA384\",hashes.SHA384(),data,key)\n",
"\tshow_hmac(\"SHA3_224\",hashes.SHA3_224(),data,key)\n",
"\tshow_hmac(\"SHA3_256\",hashes.SHA3_256(),data,key)\n",
"\tshow_hmac(\"SHA3_384\",hashes.SHA3_384(),data,key)\n",
"\tshow_hmac(\"SHA3_512\",hashes.SHA3_512(),data,key)\n",
"\tshow_hmac(\"SHA512\",hashes.SHA512(),data,key)\n",
"\tshow_hmac(\"SHA512_224\",hashes.SHA512_224(),data,key)\n",
"\tshow_hmac(\"SHA512_256\",hashes.SHA512_256(),data,key)\n",
"\n",
"\n",
"except Exception as e:\n",
" print(e)"
]
},
{
"cell_type": "markdown",
"id": "4d58782c",
"metadata": {},
"source": [
"## HKDF"
]
},
{
"cell_type": "markdown",
"id": "8b676e51",
"metadata": {},
"source": [
"HKDF (HMAC Key Derivation Function) is used to generate an encryption key based on a password. We can use a range of hashing methods to dervie the encryption key. In this case we will use a range of hashing methods, and derive a key of a given size."
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "144316a0",
"metadata": {
"scrolled": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Key: 00\n",
" Hex: 3030\n",
"Salt: \n",
" Hex: \n",
"\n",
"name 'default_backend' is not defined\n"
]
}
],
"source": [
"from cryptography.hazmat.primitives import hashes\n",
"from cryptography.hazmat.primitives.kdf.hkdf import HKDF\n",
"from cryptography.hazmat.primitives.kdf.scrypt import Scrypt\n",
"from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC\n",
"from cryptography.hazmat.primitives.kdf.concatkdf import ConcatKDFHash,ConcatKDFHMAC\n",
"from cryptography.hazmat.primitives.kdf.x963kdf import X963KDF\n",
"from cryptography.hazmat.backends import default_backend\n",
"\n",
"\n",
"import binascii\n",
"import sys\n",
"\n",
"st = \"00\"\n",
"hex=False\n",
"showhex=\"No\"\n",
"k=\"00\"\n",
"length=16\n",
"slt=\"\"\n",
"\n",
"def show_hash(name,type,data,length,salt):\n",
"\n",
" hkdf = HKDF(algorithm=type, length=length,salt=salt, info=b\"\",backend=default_backend())\n",
" mykey=hkdf.derive(data)\n",
" hex=binascii.b2a_hex(mykey).decode()\n",
" b64=binascii.b2a_base64(mykey).decode()\n",
" print (f\"HKDF {name}: {hex} {b64}\")\n",
"\n",
"def show_hash_pbkdf2(name,type,data,length,salt):\n",
"\n",
" hkdf = PBKDF2HMAC(algorithm=type, length=length,salt=salt, iterations=1000,backend=default_backend())\n",
" mykey=hkdf.derive(data)\n",
" hex=binascii.b2a_hex(mykey).decode()\n",
" b64=binascii.b2a_base64(mykey).decode()\n",
" print (f\"HKDF {name}: {hex} {b64}\")\n",
"\n",
"def show_hash_scrypt(name,data,length,salt):\n",
"\n",
" hkdf = Scrypt(length=length,salt=salt,n=2**14,r=8, p=1,backend=default_backend())\n",
" mykey=hkdf.derive(data)\n",
" hex=binascii.b2a_hex(mykey).decode()\n",
" b64=binascii.b2a_base64(mykey).decode()\n",
" print (f\"HKDF {name}: {hex} {b64}\")\n",
"\n",
"def show_hash_concat(name,type,data,length,salt):\n",
"\n",
" hkdf = ConcatKDFHash(algorithm=type, length=length,otherinfo=b\"\",backend=default_backend())\n",
" mykey=hkdf.derive(data)\n",
" hex=binascii.b2a_hex(mykey).decode()\n",
" b64=binascii.b2a_base64(mykey).decode()\n",
" print (f\"HKDF {name}: {hex} {b64}\")\n",
"\n",
"\n",
"if (showhex==\"yes\"): hex=True\n",
"\n",
"\n",
"\n",
"try:\n",
"\tif (hex==True): data = binascii.a2b_hex(st)\n",
"\telse: data=st.encode()\n",
"\tif (hex==True): salt = binascii.a2b_hex(slt)\n",
"\telse: salt=slt.encode()\n",
"\n",
"\n",
"\tprint (\"Key: \",st)\n",
"\tprint (\" Hex: \",binascii.b2a_hex(data).decode())\n",
"\n",
"\tprint (\"Salt: \",slt)\n",
"\tprint (\" Hex: \",binascii.b2a_hex(salt).decode())\n",
"\n",
"\tprint()\n",
"\n",
"\n",
"\tshow_hash(\"Blake2p (64 bytes)\",hashes.BLAKE2b(64),data,length,salt)\n",
"\tshow_hash(\"Blake2s (32 bytes)\",hashes.BLAKE2s(32),data,length,salt)\n",
"\tshow_hash(\"MD5\",hashes.MD5(),data,length,salt)\n",
"\tshow_hash(\"SHA1\",hashes.SHA1(),data,length,salt)\t\n",
"\tshow_hash(\"SHA224\",hashes.SHA224(),data,length,salt)\n",
"\tshow_hash(\"SHA256\",hashes.SHA256(),data,length,salt)\n",
"\tshow_hash(\"SHA384\",hashes.SHA384(),data,length,salt)\n",
"\tshow_hash(\"SHA3_224\",hashes.SHA3_224(),data,length,salt)\n",
"\tshow_hash(\"SHA3_256\",hashes.SHA3_256(),data,length,salt)\n",
"\tshow_hash(\"SHA3_384\",hashes.SHA3_384(),data,length,salt)\n",
"\tshow_hash(\"SHA3_512\",hashes.SHA3_512(),data,length,salt)\n",
"\tshow_hash(\"SHA512\",hashes.SHA512(),data,length,salt)\n",
"\tshow_hash(\"SHA512_224\",hashes.SHA512_224(),data,length,salt)\n",
"\tshow_hash(\"SHA512_256\",hashes.SHA512_256(),data,length,salt)\n",
"\tshow_hash_pbkdf2(\"PBKDF2\",hashes.SHA256(),data,length,salt)\n",
"\tshow_hash_scrypt(\"Scrypt SHA256\",data,length,salt)\n",
"\tshow_hash_concat(\"Concat SHA256\",hashes.SHA256(),data,length,salt)\n",
"\n",
"except Exception as e:\n",
" print(e)"
]
},
{
"cell_type": "markdown",
"id": "9154359d",
"metadata": {},
"source": []
},
{
"cell_type": "markdown",
"id": "509b908c",
"metadata": {},
"source": [
"## Symmetric Key"
]
},
{
"cell_type": "markdown",
"id": "e8a9af38",
"metadata": {},
"source": [
"Symmetric key encryption involves the same key being used to encrypt and decrypt. Apart from ECB mode, we also normally apply a salt value known as an IV (Initialization Vector). The main modes are ECB (Electronic Code Book), CBC (Cipher Block Chaining), CTR (Counter), OFB (Output Feedback) and GCM (Galois/Counter Mode). In this case we will use the cryptography library in Python, and implement AES, Chacha20, Camellia, 3DES, IDEA, CAST5 and Blowfish. The Python program will use a random 256-bit encryption key, and a random 128-bit IV value. In most of the modes, we need to pad the plaintext to the size of the block (typically this is 128 bits or 16 bytes), but AES GCM mode we do not need to pad the cipher as it is a stream cipher."
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "1fed6488",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Message:\t Hello\n",
"Key:\t b'75108231d759b576e9e26d74a69fac01de5412c427b01779fefe805640ee7756'\n",
"IV:\t b'b3c3f903d81e2f47a5bb9d6d7102c46a'\n",
"\n",
"\n",
"=== AES ECB === \n",
"Cipher: b'52710346abd34fdd302a33a103009310'\n",
"Decrypted: Hello\n",
"=== AES CBC === \n",
"Cipher: b'0b3e0cc6c8f580f8a658b69e9982e3a3'\n",
"Decrypted: Hello\n",
"=== AES OFB === \n",
"Cipher: b'3d2139534946484050cc14b3129cf67e'\n",
"Decrypted: Hello\n",
"=== AES CFB === \n",
"Cipher: b'3d2139534946484050cc14b3129cf67e'\n",
"Decrypted: Hello\n",
"=== AES CTR === \n",
"Cipher: b'3d2139534946484050cc14b3129cf67e'\n",
"Decrypted: Hello\n",
"=== AES GCM === \n",
"Cipher: b'5de7889741'\n",
"Decrypted: Hello\n",
"=== AES XTS === \n",
"Cipher: b'84b89b9f920d781443e6e959a278c800'\n",
"Decrypted: Hello\n",
"\n",
"=== Blowfish ECB === \n",
"Cipher: b'53a677a4b06b48fc764539ff9b357a5a'\n",
"Decrypted: Hello\n",
"=== Blowfish CBC === \n",
"Cipher: b'e414ca26835d193aa1095c4b99656d87'\n",
"Decrypted: Hello\n",
"\n",
"=== ChaCha20 === \n",
"Cipher: b'43d3ff9fd6'\n",
"Decrypted: Hello\n",
"\n",
"=== 3DES ECB === \n",
"Cipher: b'1a6a67bbeb161e73b8df6e840a944b04'\n",
"Decrypted: Hello\n",
"=== 3DES CBC === \n",
"Cipher: b'd1590a192c68beced42474dbe595f114'\n",
"Decrypted: Hello\n",
"\n",
"=== Camellia ECB === \n",
"Cipher: b'eb1d01d74a0699e1aa5e338d8ee1992b'\n",
"Decrypted: Hello\n",
"=== Camellia CBC === \n",
"Cipher: b'f9c418b9b73680015c0c19944a7a836f'\n",
"Decrypted: Hello\n",
"=== IDEA ECB === \n",
"Cipher: b'0e1e83b4b6cf9c73fa96477e41c095fd'\n",
"Decrypted: Hello\n",
"=== IDEA CBC === \n",
"Cipher: b'eb04b675cc1c20cfa09828fe3a8f4975'\n",
"Decrypted: Hello\n",
"\n",
"=== CAST5 ECB === \n",
"Cipher: b'9a35089a74674806069fa63712384c1b'\n",
"Decrypted: Hello\n",
"=== CAST5 CBC === \n",
"Cipher: b'a31fccf6db4a119bf8f04507c1927c6d'\n",
"Decrypted: Hello\n"
]
}
],
"source": [
"import os\n",
"from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes \n",
"from cryptography.hazmat.primitives import padding\n",
"import sys\n",
"from cryptography.hazmat.backends import default_backend\n",
"\n",
"import binascii\n",
"\n",
"def go_encrypt(msg,method,mode):\n",
" cipher = Cipher(method, mode,backend=default_backend())\n",
" encryptor = cipher.encryptor()\n",
" ct = encryptor.update(msg) + encryptor.finalize()\n",
" return (ct)\n",
"\n",
"\n",
"def go_decrypt(ct,method,mode):\n",
" cipher = Cipher(method, mode,backend=default_backend())\n",
" decryptor = cipher.decryptor()\n",
" return (decryptor.update(ct) + decryptor.finalize())\n",
"\n",
"def go_encrypt_with_auth(msg,method,mode,add):\n",
" cipher = Cipher(method, mode,backend=default_backend())\n",
" encryptor = cipher.encryptor()\n",
" encryptor.authenticate_additional_data(add)\n",
" ct = encryptor.update(msg) + encryptor.finalize()\n",
" return (ct,encryptor.tag)\n",
"\n",
"\n",
"def go_decrypt_with_auth(ct,method,mode,add):\n",
" cipher = Cipher(method, mode,backend=default_backend())\n",
" decryptor = cipher.decryptor()\n",
" decryptor.authenticate_additional_data(add)\n",
" pl=decryptor.update(ct) + decryptor.finalize()\n",
" return (pl)\n",
"\n",
"def pad(data,size=128):\n",
" padder = padding.PKCS7(size).padder()\n",
" padded_data = padder.update(data)\n",
" padded_data += padder.finalize()\n",
" return(padded_data)\n",
"\n",
"def unpad(data,size=128):\n",
" padder = padding.PKCS7(size).unpadder()\n",
" unpadded_data = padder.update(data)\n",
" unpadded_data += padder.finalize()\n",
" return(unpadded_data)\n",
"\n",
"\n",
"key = os.urandom(32)\n",
"iv = os.urandom(16)\n",
"msg=b\"Hello\"\n",
"tag= b\"Some data for the authentication tag\"\n",
"\n",
"\n",
"print (\"Message:\\t\",msg.decode())\n",
"print (\"Key:\\t\",binascii.b2a_hex(key))\n",
"print (\"IV:\\t\",binascii.b2a_hex(iv))\n",
"\n",
"padded_data=pad(msg)\n",
"\n",
"\n",
"print (\"\\n\\n=== AES ECB === \")\n",
"cipher=go_encrypt(padded_data,algorithms.AES(key), modes.ECB())\n",
"\n",
"plain=go_decrypt(cipher,algorithms.AES(key), modes.ECB())\n",
"data=unpad(plain)\n",
"\n",
"print (\"Cipher: \",binascii.b2a_hex(cipher))\n",
"print (f\"Decrypted: {data.decode()}\")\n",
"\n",
"cipher=go_encrypt(padded_data,algorithms.AES(key), modes.CBC(iv))\n",
"\n",
"print (\"=== AES CBC === \")\n",
"cipher=go_encrypt(padded_data,algorithms.AES(key), modes.CBC(iv))\n",
"\n",
"plain=go_decrypt(cipher,algorithms.AES(key), modes.CBC(iv))\n",
"data=unpad(plain)\n",
"\n",
"print (\"Cipher: \",binascii.b2a_hex(cipher))\n",
"print (f\"Decrypted: {data.decode()}\")\n",
"\n",
"cipher=go_encrypt(padded_data,algorithms.AES(key), modes.CBC(iv))\n",
"\n",
"print (\"=== AES OFB === \")\n",
"cipher=go_encrypt(padded_data,algorithms.AES(key), modes.OFB(iv))\n",
"\n",
"plain=go_decrypt(cipher,algorithms.AES(key), modes.OFB(iv))\n",
"data=unpad(plain)\n",
"\n",
"print (\"Cipher: \",binascii.b2a_hex(cipher))\n",
"print (f\"Decrypted: {data.decode()}\")\n",
"\n",
"print (\"=== AES CFB === \")\n",
"cipher=go_encrypt(padded_data,algorithms.AES(key), modes.CFB(iv))\n",
"\n",
"plain=go_decrypt(cipher,algorithms.AES(key), modes.CFB(iv))\n",
"data=unpad(plain)\n",
"\n",
"print (\"Cipher: \",binascii.b2a_hex(cipher))\n",
"print (f\"Decrypted: {data.decode()}\")\n",
"\n",
"print (\"=== AES CTR === \")\n",
"cipher=go_encrypt(padded_data,algorithms.AES(key), modes.CTR(iv))\n",
"\n",
"plain=go_decrypt(cipher,algorithms.AES(key), modes.CTR(iv))\n",
"data=unpad(plain)\n",
"\n",
"print (\"Cipher: \",binascii.b2a_hex(cipher))\n",
"print (f\"Decrypted: {data.decode()}\")\n",
"\n",
"print (\"=== AES GCM === \")\n",
"# In GCM mode we convert to a stream cipher, so there is no need for padding\n",
"cipher,auth_tag=go_encrypt_with_auth(msg,algorithms.AES(key), modes.GCM(iv),tag)\n",
"\n",
"plain=go_decrypt_with_auth(cipher,algorithms.AES(key), modes.GCM(iv,auth_tag),tag)\n",
"\n",
"print (\"Cipher: \",binascii.b2a_hex(cipher))\n",
"print (f\"Decrypted: {plain.decode()}\")\n",
"\n",
"\n",
"print (\"=== AES XTS === \")\n",
"# In XTS the iv value is known as a tweak - and relates to the sector number\n",
"# The keys are double length, so that a 32 byte key (256 bits) is actually AES-128\n",
"cipher=go_encrypt(padded_data,algorithms.AES(key), modes.XTS(iv))\n",
"\n",
"plain=go_decrypt(cipher,algorithms.AES(key), modes.XTS(iv))\n",
"data=unpad(plain)\n",
"print (\"Cipher: \",binascii.b2a_hex(cipher))\n",
"print (f\"Decrypted: {data.decode()}\")\n",
"\n",
"\n",
"print (\"\\n=== Blowfish ECB === \")\n",
"\n",
"cipher=go_encrypt(padded_data,algorithms.Blowfish(key), modes.ECB())\n",
"\n",
"plain=go_decrypt(cipher,algorithms.Blowfish(key), modes.ECB())\n",
"\n",
"data=unpad(plain)\n",
"\n",
"print (\"Cipher: \",binascii.b2a_hex(cipher))\n",
"print (f\"Decrypted: {data.decode()}\")\n",
"\n",
"print (\"=== Blowfish CBC === \")\n",
"\n",
"cipher=go_encrypt(padded_data,algorithms.Blowfish(key), modes.CBC(iv[:8]))\n",
"\n",
"plain=go_decrypt(cipher,algorithms.Blowfish(key), modes.CBC(iv[:8]))\n",
"\n",
"data=unpad(plain)\n",
"\n",
"print (\"Cipher: \",binascii.b2a_hex(cipher))\n",
"print (f\"Decrypted: {data.decode()}\")\n",
"\n",
"\n",
"print (\"\\n=== ChaCha20 === \")\n",
"\n",
"cipher=go_encrypt(msg,algorithms.ChaCha20(key,iv), None)\n",
"\n",
"plain=go_decrypt(cipher,algorithms.ChaCha20(key,iv), None)\n",
"\n",
"print (\"Cipher: \",binascii.b2a_hex(cipher))\n",
"print (f\"Decrypted: {data.decode()}\")\n",
"\n",
"print (\"\\n=== 3DES ECB === \")\n",
"cipher=go_encrypt(padded_data,algorithms.TripleDES(key[:16]), modes.ECB())\n",
"\n",
"plain=go_decrypt(cipher,algorithms.TripleDES(key[:16]), modes.ECB())\n",
"\n",
"print (\"Cipher: \",binascii.b2a_hex(cipher))\n",
"print (f\"Decrypted: {data.decode()}\")\n",
"\n",
"print (\"=== 3DES CBC === \")\n",
"cipher=go_encrypt(padded_data,algorithms.TripleDES(key[:16]), modes.CBC(iv[:8]))\n",
"\n",
"plain=go_decrypt(cipher,algorithms.TripleDES(key[:16]), modes.CBC(iv[:8]))\n",
"\n",
"print (\"Cipher: \",binascii.b2a_hex(cipher))\n",
"print (f\"Decrypted: {data.decode()}\")\n",
"\n",
"\n",
"print (\"\\n=== Camellia ECB === \")\n",
"cipher=go_encrypt(padded_data,algorithms.Camellia(key), modes.ECB())\n",
"\n",
"plain=go_decrypt(cipher,algorithms.Camellia(key), modes.ECB())\n",
"\n",
"print (\"Cipher: \",binascii.b2a_hex(cipher))\n",
"print (f\"Decrypted: {data.decode()}\")\n",
"\n",
"\n",
"print (\"=== Camellia CBC === \")\n",
"cipher=go_encrypt(padded_data,algorithms.Camellia(key), modes.CBC(iv))\n",
"\n",
"plain=go_decrypt(cipher,algorithms.Camellia(key), modes.CBC(iv))\n",
"\n",
"print (\"Cipher: \",binascii.b2a_hex(cipher))\n",
"print (f\"Decrypted: {data.decode()}\")\n",
"\n",
"print (\"=== IDEA ECB === \")\n",
"cipher=go_encrypt(padded_data,algorithms.IDEA(key[:16]), modes.ECB())\n",
"\n",
"plain=go_decrypt(cipher,algorithms.IDEA(key[:16]), modes.ECB())\n",
"\n",
"print (\"Cipher: \",binascii.b2a_hex(cipher))\n",
"print (f\"Decrypted: {data.decode()}\")\n",
"\n",
"print (\"=== IDEA CBC === \")\n",
"cipher=go_encrypt(padded_data,algorithms.IDEA(key[:16]), modes.CBC(iv[:8]))\n",
"\n",
"plain=go_decrypt(cipher,algorithms.IDEA(key[:16]), modes.CBC(iv[:8]))\n",
"\n",
"print (\"Cipher: \",binascii.b2a_hex(cipher))\n",
"print (f\"Decrypted: {data.decode()}\")\n",
"\n",
"print (\"\\n=== CAST5 ECB === \")\n",
"cipher=go_encrypt(padded_data,algorithms.CAST5(key[:16]), modes.ECB())\n",
"\n",
"plain=go_decrypt(cipher,algorithms.CAST5(key[:16]), modes.ECB())\n",
"\n",
"print (\"Cipher: \",binascii.b2a_hex(cipher))\n",
"print (f\"Decrypted: {data.decode()}\")\n",
"\n",
"print (\"=== CAST5 CBC === \")\n",
"cipher=go_encrypt(padded_data,algorithms.CAST5(key[:16]), modes.CBC(iv[:8]))\n",
"\n",
"plain=go_decrypt(cipher,algorithms.CAST5(key[:16]), modes.CBC(iv[:8]))\n",
"\n",
"print (\"Cipher: \",binascii.b2a_hex(cipher))\n",
"print (f\"Decrypted: {data.decode()}\")"
]
},
{
"cell_type": "markdown",
"id": "9172ce8d",
"metadata": {},
"source": [
"## RSA Keys "
]
},
{
"cell_type": "markdown",
"id": "3526088c",
"metadata": {},
"source": [
"With RSA, we have the magic of public key encryption, and where Bob can generate a key pair: a public key and a private key, and then send Alice his public key. If she wants to encrypt something for him, she encrypts it with his public key, and then the only key which can decrypt it is his private key. A truly wonderful concept, and it was Rivest, Shamir and Adleman who made it come alive with the RSA method. In RSA, we start by generating two prime numbers (p,q) and then calculate the modulus (N) of N=pq. It is this modulus (N) that provides the core of the security of RSA, and it must be difficult to determine the prime numbers for a given modulus value. Our prime numbers must thus be of a size that makes it difficult to factorize, and they must be randomly generated."
]
},
{
"cell_type": "code",
"execution_count": 15,
"id": "b0559a57",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"RSA key size: 512\n",
"M=5\n",
"\n",
"=== RSA Private key ===\n",
"p=114240027289133679916853601188430818342505970058336223690127546253419301921291 q=106927850855783140995262884657855361840603034156020906226195283705417869958079 d=12056263550552130122923905739070666874031192187927860369377606874056401919958137436002088193238240131651226273674194799808471728408204851623607010221110053 N=12215440599733082136976701922011568649001781649277680148229058975388191837550991125104446323995201242037017634104455399946932098494548782067414314327559989\n",
"\n",
"Bit length of p and q is 256\n",
"Bit length of N is 512\n",
"\n",
"=== RSA Public key ===\n",
"\n",
"N=12215440599733082136976701922011568649001781649277680148229058975388191837550991125104446323995201242037017634104455399946932098494548782067414314327559989 e=65537\n",
"\n",
"Message=5\n",
"Cipher=8681388997006403186260644889804391620158460251057105492554241431796114500559026556435367120212960187799018356532032536157753321962365210361500584359919374\n",
"Decrypt=5\n",
"\n",
"=== Private Key PEM format ===\n",
"Private key: -----BEGIN PRIVATE KEY-----\n",
"MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEA6TvUc/1/kZ9IKfWE\n",
"GcSYGaNKqDpJ4kwZVrMvZIe+3sGq0w4ZusEvPitTX9ahWiZqoyRwfC9Lhuxowjpi\n",
"kj1PNQIDAQABAkEA5jHJ500cmnJ1/Au4/OG/KRa0ecNF5tcq7xpdPUCJTzo9r046\n",
"MQh0TB9yHoFAYeTYQx9MOL6lNTpfy5GQhJgzJQIhAPyRkGbBar/VjIoNvFNgYk7J\n",
"a2cq0xksTi4o/H+LsWILAiEA7GcE1L2WtDlWfzU0pd14mhpvGJo/MMBnzjw6mwFq\n",
"G78CIH54oZdiyQKQe5RxtlkFzZRoNdjuT9CuJ+PjcDSqDcPrAiAYb1WKf8Yx/rM4\n",
"FtHISyoKE61kB518dobERGlyWCUVlQIgJh6O3xe8W6fQCwY3y1StRWo4pQmsJ/VY\n",
"R953mvvhQ3E=\n",
"-----END PRIVATE KEY-----\n",
"\n",
"\n",
"=== Public Key PEM format ===\n",
"Public key: -----BEGIN PUBLIC KEY-----\n",
"MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAOk71HP9f5GfSCn1hBnEmBmjSqg6SeJM\n",
"GVazL2SHvt7BqtMOGbrBLz4rU1/WoVomaqMkcHwvS4bsaMI6YpI9TzUCAwEAAQ==\n",
"-----END PUBLIC KEY-----\n",
"\n"
]
}
],
"source": [
"from cryptography.hazmat.primitives.asymmetric import rsa\n",
"from cryptography.hazmat.primitives import serialization\n",
"import sys\n",
"from cryptography.hazmat.backends import default_backend\n",
"\n",
"size=512\n",
"M=5\n",
"\n",
"\n",
"try:\n",
"\tprint(f\"RSA key size: {size}\\nM={M}\\n\")\n",
"\n",
"\tprivate_key = rsa.generate_private_key(public_exponent=65537,key_size=size,backend=default_backend())\n",
"\n",
"\tpriv= private_key.private_numbers()\n",
"\tp=priv.p\n",
"\tq=priv.q \n",
"\td=priv.d\n",
"\tn=p*q\n",
"\tprint(\"=== RSA Private key ===\")\n",
"\tprint (f\"p={p} q={q} d={d} N={n}\")\n",
"\tprint (f\"\\nBit length of p and q is {p.bit_length()}\")\n",
"\tprint (f\"Bit length of N is {n.bit_length()}\")\n",
"\n",
"\tprint(\"\\n=== RSA Public key ===\")\n",
"\tpub = private_key.public_key()\n",
"\te=pub.public_numbers().e\n",
"\tn=pub.public_numbers().n\n",
"\tprint (f\"\\nN={n} e={e}\")\n",
"\n",
"\n",
"\n",
"\tC = pow(M,e,n)\n",
"\tPlain = pow(C,d,n)\n",
"\tprint (f\"\\nMessage={M}\")\n",
"\tprint (f\"Cipher={C}\")\n",
"\tprint (f\"Decrypt={Plain}\")\n",
"\n",
"\n",
"\n",
"\tprint(\"\\n=== Private Key PEM format ===\")\n",
"\tpem = private_key.private_bytes(encoding=serialization.Encoding.PEM,format=serialization.PrivateFormat.PKCS8,encryption_algorithm=serialization.NoEncryption())\n",
"\tprint (\"Private key: \",pem.decode())\n",
"\n",
"\n",
"\tpem = pub.public_bytes(encoding=serialization.Encoding.PEM,format=serialization.PublicFormat.SubjectPublicKeyInfo)\n",
"\n",
"\tprint(\"\\n=== Public Key PEM format ===\")\n",
"\tprint (\"Public key: \",pem.decode())\n",
"\n",
"except Exception as e:\n",
" print(e)"
]
},
{
"cell_type": "markdown",
"id": "bca147bd",
"metadata": {},
"source": [
"## RSA Key Formats"
]
},
{
"cell_type": "markdown",
"id": "888b3824",
"metadata": {},
"source": [
"We need ways to distribute our public keys, private keys and digital certificates in a portable format. One of the most common forms is Distinguished Encoding Rules (DER) encoding of ASN.1. Overall it is truly binary representation of the encoded data. The other common format is PEM, and which converts the binary encoding into a text readable format. With PEM we can encode cryptographic infromation in a Base64 ASCII format and with plain-text headers and footers of \"-----BEGIN RSA PRIVATE KEY-----\" and \"-----END RSA PRIVATE KEY-----\", whereas with DER we have binary format. In this page, we will read in a DER encoded hex string and determine its contents. "
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "3455e9c4",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"name 'default_backend' is not defined\n"
]
}
],
"source": [
"from cryptography.hazmat.primitives.asymmetric import rsa\n",
"from cryptography.hazmat.primitives import serialization\n",
"import sys\n",
"import binascii\n",
"from cryptography.hazmat.backends import default_backend\n",
"\n",
"size=512\n",
"\n",
"try:\n",
" private_key = rsa.generate_private_key(public_exponent=65537,key_size=size,backend=default_backend())\n",
"\n",
"\n",
" pub = private_key.public_key()\n",
"\n",
" print(\"\\n=== Private Key PEM format ===\")\n",
" pem = private_key.private_bytes(encoding=serialization.Encoding.PEM,format=serialization.PrivateFormat.PKCS8,encryption_algorithm=serialization.NoEncryption())\n",
"\n",
" der= private_key.private_bytes(encoding=serialization.Encoding.DER,format=serialization.PrivateFormat.PKCS8,encryption_algorithm=serialization.NoEncryption())\n",
"\n",
"\n",
" print (\"\\nPrivate key (PEM):\\n\",pem.decode())\n",
" print (\"\\nPrivate key (DER):\\n\",binascii.b2a_hex(der).decode())\n",
"\n",
"\n",
" pem = pub.public_bytes(encoding=serialization.Encoding.PEM,format=serialization.PublicFormat.SubjectPublicKeyInfo).decode(\"utf-8\")\n",
"\n",
" openssh = pub.public_bytes(encoding=serialization.Encoding.OpenSSH,format=serialization.PublicFormat.OpenSSH)\n",
"\n",
"\n",
" print(\"\\n=== Public Key format ===\")\n",
"\n",
" der=''.join(pem.split('\\n')[1:-2])\n",
" print (\"Public key (PEM):\\n\",pem)\n",
" print (\"\\nPublic key (DER):\\n\",binascii.b2a_hex(binascii.a2b_base64(der)).decode())\n",
" print (\"\\nPublic key (OpenSSL):\\n\",openssh.decode())\n",
"\n",
"except Exception as e:\n",
" print(e)"
]
},
{
"cell_type": "markdown",
"id": "b715d4bd",
"metadata": {},
"source": [
"## RSA Signatures"
]
},
{
"cell_type": "markdown",
"id": "0b7f433a",
"metadata": {},
"source": [
"At the core of digital trust is the usage of digital signatures. With this we can verify the creator of the data, and also that it has not been modified. We do this using public key encryption, and in this article we will look at how we can use the hazmat primitives in the Python cryptograpy library. With public key encryption we create a key pair: a public key and a private key. If Alice is sending data to Bob, she can add her digital signature, and which will prove that she is the sender and also verify that the data has not been changed. She does this by signing the data with her private key, and then Bob can prove the signature with Alices's public key. In this example we will use RSA keys to sign a message, and then verify the correct signature, but verify that an incorrect signature will fail. "
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "7d14ac0a",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Message: b'Hello world'\n",
"Key size: 512\n",
"\n",
"Signature: a01c26461569ecc39e6b66527789510d8a311f642e85c3bd7635a7974d1d58ac3d571439ed8fef4682df3c38759192f3bc255162be81e6c1c2b08fecbf7772da\n",
"Good signature verified\n",
"A bad signature failed\n",
"\n",
"Verified: None\n",
"\n",
"=== Private Key PEM format ===\n",
"\n",
"Private key (PEM):\n",
" -----BEGIN PRIVATE KEY-----\n",
"MIIBVQIBADANBgkqhkiG9w0BAQEFAASCAT8wggE7AgEAAkEA2Ywlcqf634Jsqt9Y\n",
"GJFKTDiXoYWuZ8zI4LqT9191ZpOqkUK4vaPwJONDx1rng4YDsclSMU7RFXesDRbi\n",
"a5ksuwIDAQABAkBm+RRcsjBojYa8Vt2PO25sp7j2Rp2oGmHXJdmWFQQwGcQGDBJv\n",
"Ct1se31q3aXK50/ATMdVkKuENL98G1YvSaLZAiEA8KGLf27nltaRpLt3/TiYVg7g\n",
"opp677t37V2w1MendiUCIQDncSvm0JxXh15wLX1rvIf4KM8n39hzlAL/t0GoT7Zx\n",
"XwIhAL8ajP8XxTU2E1UQzap9V/6AskZxCVF7QTNyRQ23wndBAiEAkEVu3XoLC1D6\n",
"IKlqtn8Wry4ZPD0Ae8O3PtpollfiXbcCIBGFaDpLQxDacjdJlQFQxO4EEtk4icLx\n",
"6uPLf87z2l7c\n",
"-----END PRIVATE KEY-----\n",
"\n",
"\n",
"=== Public Key format ===\n",
"Public key (PEM):\n",
" -----BEGIN PUBLIC KEY-----\n",
"MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANmMJXKn+t+CbKrfWBiRSkw4l6GFrmfM\n",
"yOC6k/dfdWaTqpFCuL2j8CTjQ8da54OGA7HJUjFO0RV3rA0W4muZLLsCAwEAAQ==\n",
"-----END PUBLIC KEY-----\n",
"\n"
]
}
],
"source": [
"from cryptography.hazmat.primitives.asymmetric import rsa\n",
"from cryptography.hazmat.primitives import serialization\n",
"from cryptography.hazmat.primitives.asymmetric import padding\n",
"from cryptography.hazmat.primitives import hashes\n",
"from cryptography import exceptions\n",
"from cryptography.hazmat.backends import default_backend\n",
"\n",
"import sys\n",
"import binascii\n",
"\n",
"size=512\n",
"message = b\"Hello world\"\n",
"\n",
"\n",
"print(\"Message: \",message)\n",
"print(\"Key size: \",size)\n",
"try:\n",
" private_key = rsa.generate_private_key(public_exponent=65537,key_size=size,backend=default_backend())\n",
"\n",
"\n",
" pub = private_key.public_key()\n",
"\n",
"\n",
"\n",
" signature = private_key.sign(message,padding.PSS(mgf=padding.MGF1(hashes.SHA256()), salt_length=padding.PSS.MAX_LENGTH),hashes.SHA256())\n",
"\n",
" print (\"\\nSignature: \",binascii.b2a_hex(signature).decode())\n",
"\n",
" try:\n",
" rtn=pub.verify(signature,message,padding.PSS(mgf=padding.MGF1(hashes.SHA256()),salt_length=padding.PSS.MAX_LENGTH),hashes.SHA256())\n",
" except exceptions.InvalidSignature:\n",
" print(\"A bad signature failed\")\n",
" else:\n",
" print(\"Good signature verified\")\n",
"\n",
"\n",
" try:\n",
" pub.verify(signature,b\"test\",padding.PSS(mgf=padding.MGF1(hashes.SHA256()),salt_length=padding.PSS.MAX_LENGTH),hashes.SHA256())\n",
" except exceptions.InvalidSignature:\n",
" print(\"A bad signature failed\")\n",
" else:\n",
" print(\"Bad signature verified\")\n",
"\n",
"\n",
"\n",
" print (\"\\nVerified: \",rtn)\n",
" print(\"\\n=== Private Key PEM format ===\")\n",
" pem = private_key.private_bytes(encoding=serialization.Encoding.PEM,format=serialization.PrivateFormat.PKCS8,encryption_algorithm=serialization.NoEncryption())\n",
"\n",
"\n",
" print (\"\\nPrivate key (PEM):\\n\",pem.decode())\n",
"\n",
"\n",
" pem = pub.public_bytes(encoding=serialization.Encoding.PEM,format=serialization.PublicFormat.SubjectPublicKeyInfo).decode(\"utf-8\")\n",
"\n",
"\n",
"\n",
" print(\"\\n=== Public Key format ===\")\n",
" print (\"Public key (PEM):\\n\",pem)\n",
"\n",
"\n",
"except Exception as e:\n",
" print(e)"
]
},
{
"cell_type": "markdown",
"id": "67f3eb96",
"metadata": {},
"source": [
"## RSA Encryption"
]
},
{
"cell_type": "markdown",
"id": "00f1f9d7",
"metadata": {},
"source": [
"With public-key encryption, we create a key pair: a public key and a private key. If Alice is sending data to Bob, she can add her digital signature, and which will prove that she is the sender and also verify that the data has not been changed. She does this by signing the data with her private key, and then Bob can prove the signature with Alice's public key. In this example, we will use RSA keys to sign a message, and then verify the correct signature, but verify that an incorrect signature will fail."
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "750c45e4",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Message: b'Hello world'\n",
"Key size: 1024\n",
"\n",
"Ciphertext:\n",
" a03bc31a7e3fca1abaecff8dd7a252def14ae50faeeb28989f69978acc71395059b4bdee36028dd3707418b21d08c2aec311165725ead1374551807c574ad425fa946475396f1abe4acba69da0ab1c71e417df74648f077f2d58e70eb88fa5123d96638e2ace9e6b9a3b46245d8f97bdba67c1c89a5c8b21ea75c2775a1d74e3\n",
"\n",
"Decrypted Message: Hello world\n",
"\n",
"=== Private Key PEM format ===\n",
"\n",
"Private key (PEM):\n",
" -----BEGIN PRIVATE KEY-----\n",
"MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAM9h+pN2k/Vyrb24\n",
"uLh89E8QzoOXszBpkQYVqMTnZHcLpJarAcNmlP15Hx6YtDfQWL47FapqCWBbUr2E\n",
"gwFhzFZbIz4t8DnUROwQLAJcsz/aQ0zxEJUS8taOg9oFUvHYg7MdD2FnG30tEBSx\n",
"roXMT1Mt4RhxK9YA2+27gF0IHSA3AgMBAAECgYEAvSPjYbL4ZxfclfhvoPN17tap\n",
"QyOMbk8Z0a7Xah6QZnLb/f6hcRGSOUvKsiEb3PvMtFM3A2IKgzNHV0oQIaaMsWHC\n",
"XL8yeRLFpkTkWKWvfzaIdYj0VO5KTtsPtiJN4iaToZV/DVQjtADd2GdNRm26FCO4\n",
"8NLt8Z2LUojf/Bv3oQECQQDpPHLCV6CvzKBaFO2XmiN3y3TcGjpBfQ0hp8EnZX0P\n",
"T320exTt5KIoHqTc5tnYyZ6htBsAROjHq0tGn/jz2gjXAkEA45+RLsgae2KETcN9\n",
"F/sgXh46PajO7RRsDR3POdbkRwvYclvaxf6Tu0klY4PBAq6Fs5vC/OzeeaK7WSEg\n",
"rtfXoQJABBFY0wjiNY61ET0iM62thq5WuGwArhm3O+oIFV7Qwo6ZW6d14vxE07xN\n",
"Fck07XH+wUU531RUVv8mzfGGTwJzewJBAJXGYi6JJru3WF0e28oSyPqFI0d9MyNW\n",
"w75htgBWAQEqrzKYdDzBxY1/lOWFRVQxZ/KF9Giep8kbpfEA1lOV3OECQALE07c7\n",
"ZnVyA6D6WQP/gR9KewkQroiksnMYHe3g8j7NStvDaNSDzHtovs37mL08kcpmuxxc\n",
"B6UvxXlwrSOQdEc=\n",
"-----END PRIVATE KEY-----\n",
"\n",
"\n",
"=== Public Key format ===\n",
"Public key (PEM):\n",
" -----BEGIN PUBLIC KEY-----\n",
"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDPYfqTdpP1cq29uLi4fPRPEM6D\n",
"l7MwaZEGFajE52R3C6SWqwHDZpT9eR8emLQ30Fi+OxWqaglgW1K9hIMBYcxWWyM+\n",
"LfA51ETsECwCXLM/2kNM8RCVEvLWjoPaBVLx2IOzHQ9hZxt9LRAUsa6FzE9TLeEY\n",
"cSvWANvtu4BdCB0gNwIDAQAB\n",
"-----END PUBLIC KEY-----\n",
"\n"
]
}
],
"source": [
"from cryptography.hazmat.primitives.asymmetric import rsa\n",
"from cryptography.hazmat.primitives import serialization\n",
"from cryptography.hazmat.primitives.asymmetric import padding\n",
"from cryptography.hazmat.primitives import hashes\n",
"import binascii\n",
"import sys\n",
"from cryptography.hazmat.backends import default_backend\n",
"\n",
"\n",
"size=1024\n",
"message = b\"Hello world\"\n",
"\n",
"\n",
"print(\"Message: \",message)\n",
"print(\"Key size: \",size)\n",
"try:\n",
" private_key = rsa.generate_private_key(public_exponent=65537,key_size=size,backend=default_backend())\n",
"\n",
"\n",
" pub = private_key.public_key()\n",
"\n",
" ciphertext = pub.encrypt(message,padding.OAEP(mgf=padding.MGF1(algorithm=hashes.SHA256()),algorithm=hashes.SHA256(),label=None))\n",
"\n",
" print (\"\\nCiphertext:\\n\",binascii.b2a_hex(ciphertext).decode())\n",
"\n",
" plaintext = private_key.decrypt(ciphertext,padding.OAEP(mgf=padding.MGF1(algorithm=hashes.SHA256()),algorithm=hashes.SHA256(),label=None))\n",
" print(\"\\nDecrypted Message: \",plaintext.decode())\n",
"\n",
" print(\"\\n=== Private Key PEM format ===\")\n",
" pem = private_key.private_bytes(encoding=serialization.Encoding.PEM,format=serialization.PrivateFormat.PKCS8,encryption_algorithm=serialization.NoEncryption())\n",
"\n",
"\n",
" print (\"\\nPrivate key (PEM):\\n\",pem.decode())\n",
"\n",
"\n",
" pem = pub.public_bytes(encoding=serialization.Encoding.PEM,format=serialization.PublicFormat.SubjectPublicKeyInfo).decode(\"utf-8\")\n",
"\n",
"\n",
"\n",
" print(\"\\n=== Public Key format ===\")\n",
" print (\"Public key (PEM):\\n\",pem)\n",
"\n",
"\n",
"except Exception as e:\n",
" print(e)"
]
},
{
"cell_type": "markdown",
"id": "4ecdcc50",
"metadata": {},
"source": [
"## EC Key Generation"
]
},
{
"cell_type": "markdown",
"id": "29e3176f",
"metadata": {},
"source": [
" With Elliptic Curve Cryptography we have a private key value, and where we generate a public key on the point on the curve."
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "873a9bb2",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Private key value: 2043558419001729619814474899588981766865054577966515345132. Number of bits 191\n",
"\n",
"Public key encoded point: 049fe6e8fe419a6b3f815955073a759f9fc0e28e932a568f04cc8e3ce05e188159211fecef2567922028016dedaf8afc37 \n",
"x=9fe6e8fe419a6b3f815955073a759f9fc0e28e932a568f04 \n",
"y=cc8e3ce05e188159211fecef2567922028016dedaf8afc37\n",
"\n",
"Private key (PEM):\n",
" -----BEGIN PRIVATE KEY-----\n",
"MG8CAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQEEVTBTAgEBBBhTV77TSCWX4CwtVKtr\n",
"7i8MjmzmeWNZ1uyhNAMyAASf5uj+QZprP4FZVQc6dZ+fwOKOkypWjwTMjjzgXhiB\n",
"WSEf7O8lZ5IgKAFt7a+K/Dc=\n",
"-----END PRIVATE KEY-----\n",
"\n",
"Private key (DER):\n",
" b'306f020100301306072a8648ce3d020106082a8648ce3d0301010455305302010104185357bed3482597e02c2d54ab6bee2f0c8e6ce6796359d6eca134033200049fe6e8fe419a6b3f815955073a759f9fc0e28e932a568f04cc8e3ce05e188159211fecef2567922028016dedaf8afc37'\n",
"\n",
"Public key (PEM):\n",
" -----BEGIN PUBLIC KEY-----\n",
"MEkwEwYHKoZIzj0CAQYIKoZIzj0DAQEDMgAEn+bo/kGaaz+BWVUHOnWfn8DijpMq\n",
"Vo8EzI484F4YgVkhH+zvJWeSICgBbe2vivw3\n",
"-----END PUBLIC KEY-----\n",
"\n",
"Public key (DER):\n",
" b'3049301306072a8648ce3d020106082a8648ce3d030101033200049fe6e8fe419a6b3f815955073a759f9fc0e28e932a568f04cc8e3ce05e188159211fecef2567922028016dedaf8afc37'\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"/opt/tljh/user/lib/python3.7/site-packages/ipykernel_launcher.py:28: CryptographyDeprecationWarning: encode_point has been deprecated on EllipticCurvePublicNumbers and will be removed in a future version. Please use EllipticCurvePublicKey.public_bytes to obtain both compressed and uncompressed point encoding.\n"
]
}
],
"source": [
"from cryptography.hazmat.primitives.asymmetric import ec\n",
"from cryptography.hazmat.primitives import serialization\n",
"import binascii\n",
"import sys\n",
"from cryptography.hazmat.backends import default_backend\n",
"\n",
"private_key = ec.generate_private_key(ec.SECP384R1(),backend=default_backend())\n",
"type =1\n",
"\n",
"\n",
"if (type==1): private_key = ec.generate_private_key(ec.SECP192R1(),backend=default_backend())\n",
"elif (type==2): private_key = ec.generate_private_key(ec.SECP224R1(),backend=default_backend())\n",
"elif (type==3): private_key = ec.generate_private_key(ec.SECP256K1(),backend=default_backend())\n",
"elif (type==4): private_key = ec.generate_private_key(ec.SECP256R1(),backend=default_backend())\n",
"elif (type==5): private_key = ec.generate_private_key(ec.SECP384R1(),backend=default_backend())\n",
"elif (type==6): private_key = ec.generate_private_key(ec.SECP521R1(),backend=default_backend())\n",
"elif (type==7): private_key = ec.generate_private_key(ec.BrainpoolP256R1(),backend=default_backend())\n",
"elif (type==8): private_key = ec.generate_private_key(ec.BrainpoolP384R1(),backend=default_backend())\n",
"elif (type==9): private_key = ec.generate_private_key(ec.BrainpoolP512R1(),backend=default_backend())\n",
"\n",
"vals = private_key.private_numbers()\n",
"no_bits=vals.private_value.bit_length()\n",
"print (f\"Private key value: {vals.private_value}. Number of bits {no_bits}\")\n",
"\n",
"public_key = private_key.public_key()\n",
"vals=public_key.public_numbers()\n",
"\n",
"enc_point=binascii.b2a_hex(vals.encode_point()).decode()\n",
"\n",
"print (f\"\\nPublic key encoded point: {enc_point} \\nx={enc_point[2:(len(enc_point)-2)//2+2]} \\ny={enc_point[(len(enc_point)-2)//2+2:]}\")\n",
"\n",
"\n",
"pem = private_key.private_bytes(encoding=serialization.Encoding.PEM,format=serialization.PrivateFormat.PKCS8,encryption_algorithm=serialization.NoEncryption())\n",
"\n",
"der = private_key.private_bytes(encoding=serialization.Encoding.DER,format=serialization.PrivateFormat.PKCS8,encryption_algorithm=serialization.NoEncryption())\n",
"\n",
"\n",
"\n",
"print (\"\\nPrivate key (PEM):\\n\",pem.decode())\n",
"print (\"Private key (DER):\\n\",binascii.b2a_hex(der))\n",
"\n",
"pem = public_key.public_bytes(encoding=serialization.Encoding.PEM,format=serialization.PublicFormat.SubjectPublicKeyInfo)\n",
"\n",
"der = public_key.public_bytes(encoding=serialization.Encoding.DER,format=serialization.PublicFormat.SubjectPublicKeyInfo)\n",
"\n",
"print (\"\\nPublic key (PEM):\\n\",pem.decode())\n",
"print (\"Public key (DER):\\n\",binascii.b2a_hex(der))"
]
},
{
"cell_type": "markdown",
"id": "d1f06bfd",
"metadata": {},
"source": [
"## ECDSA"
]
},
{
"cell_type": "markdown",
"id": "37eb6676",
"metadata": {},
"source": [
"With ECDSA (Elliptic Curve Digital Signature Algorithm) we use a private key to sign data, and then the public key can prove it. "
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "b24a1dca",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Private key value: 1520095257287423441745410468085985957586179605404446742156. Number of bits 190\n",
"Name of curve: secp192r1\n",
"Message: test\n",
"Good Signature: 3035021879910e82df6a069d6ab007172d6918daa880e3f218a42079021900b83ff8e14ec7b38c8895897da92f173eecc74f4691efbe39\n",
"Good signature verified\n",
"Bad Signature: 303402183b7c44b272e9c1a2774d6d3f58fa6ea59b12471af019c51702185f142f21ababddfec36d7fcecd131926fac644439ef21596\n",
"A bad signature failed\n",
"\n",
"Private key (PEM):\n",
" -----BEGIN PRIVATE KEY-----\n",
"MG8CAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQEEVTBTAgEBBBg9/oj1rAm7twxSu7fI\n",
"KoQDLwC+8tPR1oyhNAMyAASWY2aP00uyPh0Hu2nx82wwQUnxKbfKIvlJDwb6yAdc\n",
"k/BQmOyP55WPPZZ0tgqMXvk=\n",
"-----END PRIVATE KEY-----\n",
"\n",
"Private key (DER):\n",
" b'306f020100301306072a8648ce3d020106082a8648ce3d0301010455305302010104183dfe88f5ac09bbb70c52bbb7c82a84032f00bef2d3d1d68ca134033200049663668fd34bb23e1d07bb69f1f36c304149f129b7ca22f9490f06fac8075c93f05098ec8fe7958f3d9674b60a8c5ef9'\n",
"\n",
"Public key (PEM):\n",
" -----BEGIN PUBLIC KEY-----\n",
"MEkwEwYHKoZIzj0CAQYIKoZIzj0DAQEDMgAElmNmj9NLsj4dB7tp8fNsMEFJ8Sm3\n",
"yiL5SQ8G+sgHXJPwUJjsj+eVjz2WdLYKjF75\n",
"-----END PUBLIC KEY-----\n",
"\n",
"Public key (DER):\n",
" b'3049301306072a8648ce3d020106082a8648ce3d030101033200049663668fd34bb23e1d07bb69f1f36c304149f129b7ca22f9490f06fac8075c93f05098ec8fe7958f3d9674b60a8c5ef9'\n"
]
}
],
"source": [
"from cryptography.hazmat.primitives.asymmetric import ec\n",
"from cryptography.hazmat.primitives import serialization\n",
"from cryptography.hazmat.primitives import hashes\n",
"from cryptography import exceptions\n",
"import binascii\n",
"import sys\n",
"from cryptography.hazmat.backends import default_backend\n",
"\n",
"private_key = ec.generate_private_key(ec.SECP384R1(),backend=default_backend())\n",
"\n",
"data = b\"test\"\n",
"\n",
"\n",
"\n",
"\n",
"if (type==1): private_key = ec.generate_private_key(ec.SECP192R1(),backend=default_backend())\n",
"elif (type==2): private_key = ec.generate_private_key(ec.SECP224R1(),backend=default_backend())\n",
"elif (type==3): private_key = ec.generate_private_key(ec.SECP256K1(),backend=default_backend())\n",
"elif (type==4): private_key = ec.generate_private_key(ec.SECP256R1(),backend=default_backend())\n",
"elif (type==5): private_key = ec.generate_private_key(ec.SECP384R1(),backend=default_backend())\n",
"elif (type==6): private_key = ec.generate_private_key(ec.SECP521R1(),backend=default_backend())\n",
"elif (type==7): private_key = ec.generate_private_key(ec.BrainpoolP256R1(),backend=default_backend())\n",
"elif (type==8): private_key = ec.generate_private_key(ec.BrainpoolP384R1(),backend=default_backend())\n",
"elif (type==9): private_key = ec.generate_private_key(ec.BrainpoolP512R1(),backend=default_backend())\n",
"elif (type==10): private_key = ec.generate_private_key(ec.SECT163K1(),backend=default_backend())\n",
"elif (type==11): private_key = ec.generate_private_key(ec.SECT163R2(),backend=default_backend())\n",
"elif (type==12): private_key = ec.generate_private_key(ec.SECT233K1(),backend=default_backend())\n",
"elif (type==13): private_key = ec.generate_private_key(ec.SECT233R1(),backend=default_backend())\n",
"elif (type==14): private_key = ec.generate_private_key(ec.SECT283K1(),backend=default_backend())\n",
"elif (type==15): private_key = ec.generate_private_key(ec.SECT233R1(),backend=default_backend())\n",
"\n",
"private_vals = private_key.private_numbers()\n",
"no_bits=private_vals.private_value.bit_length()\n",
"\n",
"print (f\"Private key value: {private_vals.private_value}. Number of bits {no_bits}\")\n",
"\n",
"public_key = private_key.public_key()\n",
"pub=public_key.public_numbers()\n",
"print (\"Name of curve: \",pub.curve.name)\n",
"\n",
"print (\"Message: \",data.decode())\n",
"try:\n",
"\n",
" signature = private_key.sign(data,ec.ECDSA(hashes.SHA256()))\n",
" print (\"Good Signature: \",binascii.b2a_hex(signature).decode())\n",
" public_key.verify(signature, data, ec.ECDSA(hashes.SHA256()))\n",
"except exceptions.InvalidSignature:\n",
" print(\"A bad signature failed\")\n",
"else:\n",
" print(\"Good signature verified\")\n",
"\n",
"try:\n",
"\n",
" signature = private_key.sign(b\"bad message\",ec.ECDSA(hashes.SHA256()))\n",
" print (\"Bad Signature: \",binascii.b2a_hex(signature).decode())\n",
" public_key.verify(signature, data, ec.ECDSA(hashes.SHA256()))\n",
"except exceptions.InvalidSignature:\n",
" print(\"A bad signature failed\")\n",
"else:\n",
" print(\"Good signature verified\")\n",
"\n",
"\n",
"\n",
"pem = private_key.private_bytes(encoding=serialization.Encoding.PEM,format=serialization.PrivateFormat.PKCS8,encryption_algorithm=serialization.NoEncryption())\n",
"\n",
"der = private_key.private_bytes(encoding=serialization.Encoding.DER,format=serialization.PrivateFormat.PKCS8,encryption_algorithm=serialization.NoEncryption())\n",
"\n",
"\n",
"\n",
"print (\"\\nPrivate key (PEM):\\n\",pem.decode())\n",
"print (\"Private key (DER):\\n\",binascii.b2a_hex(der))\n",
"\n",
"pem = public_key.public_bytes(encoding=serialization.Encoding.PEM,format=serialization.PublicFormat.SubjectPublicKeyInfo)\n",
"\n",
"der = public_key.public_bytes(encoding=serialization.Encoding.DER,format=serialization.PublicFormat.SubjectPublicKeyInfo)\n",
"\n",
"print (\"\\nPublic key (PEM):\\n\",pem.decode())\n",
"print (\"Public key (DER):\\n\",binascii.b2a_hex(der))"
]
},
{
"cell_type": "markdown",
"id": "993187c9",
"metadata": {},
"source": [
"## EdDSA"
]
},
{
"cell_type": "markdown",
"id": "e98ebf84",
"metadata": {},
"source": [
"With Ed25519 we use a private key to sign data, and then the public key can prove it. We use Curve 25519 for the generation of the public key and for the signing process. "
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "90b4f801",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Message: -f\n",
"Good Signature: a3ad2f0a47b055120e6b07f1da5c46fcc29290f5eae89d45821a501ceeb7a509db2bfe881e156080511c24d1fdfa6cf58d2caab7eee2764a3502ce9004a0690a\n",
"Good signature verified\n",
"Bad Signature: 54d68b1e1dbcfb26af2b47fbbdecbe7e928c8af26544a3aacde3207cacd4ef0a2a454b3c87e3332c4ff0f352d2d10cfe534f72a4805f1e93476ca1abf9bd710a\n",
"A bad signature failed\n",
"\n",
"Private key (PEM):\n",
" -----BEGIN PRIVATE KEY-----\n",
"MC4CAQAwBQYDK2VwBCIEINmf90gJ2jkVT5AxJtOTLbaXkxe+9IifEjAdzCiEjJ7D\n",
"-----END PRIVATE KEY-----\n",
"\n",
"Private key (DER):\n",
" b'302e020100300506032b657004220420d99ff74809da39154f903126d3932db6979317bef4889f12301dcc28848c9ec3'\n",
"\n",
"Public key (PEM):\n",
" -----BEGIN PUBLIC KEY-----\n",
"MCowBQYDK2VwAyEAf1sbNhi9c3jtiF5dshrMDNEHExVcUC19ikVMofdXpEE=\n",
"-----END PUBLIC KEY-----\n",
"\n",
"Public key (DER):\n",
" b'302a300506032b65700321007f5b1b3618bd7378ed885e5db21acc0cd10713155c502d7d8a454ca1f757a441'\n"
]
}
],
"source": [
"from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey\n",
"from cryptography import exceptions\n",
"from cryptography.hazmat.primitives import serialization\n",
"import binascii\n",
"import sys\n",
"\n",
"data=b\"Test\"\n",
"\n",
"\n",
"private_key = Ed25519PrivateKey.generate()\n",
"public_key = private_key.public_key()\n",
"\n",
"\n",
"public_key = private_key.public_key()\n",
"\n",
"print (\"Message: \",data.decode())\n",
"try:\n",
"\n",
" signature = private_key.sign(data)\n",
" print (\"Good Signature: \",binascii.b2a_hex(signature).decode())\n",
" public_key.verify(signature, data)\n",
"except exceptions.InvalidSignature:\n",
" print(\"A bad signature failed\")\n",
"else:\n",
" print(\"Good signature verified\")\n",
"\n",
"try:\n",
"\n",
" signature = private_key.sign(b\"Bad data\")\n",
" print (\"Bad Signature: \",binascii.b2a_hex(signature).decode())\n",
" public_key.verify(signature, data)\n",
"except exceptions.InvalidSignature:\n",
" print(\"A bad signature failed\")\n",
"else:\n",
" print(\"Good signature verified\")\n",
"\n",
"\n",
"\n",
"pem = private_key.private_bytes(encoding=serialization.Encoding.PEM,format=serialization.PrivateFormat.PKCS8,encryption_algorithm=serialization.NoEncryption())\n",
"\n",
"der = private_key.private_bytes(encoding=serialization.Encoding.DER,format=serialization.PrivateFormat.PKCS8,encryption_algorithm=serialization.NoEncryption())\n",
"\n",
"\n",
"\n",
"print (\"\\nPrivate key (PEM):\\n\",pem.decode())\n",
"print (\"Private key (DER):\\n\",binascii.b2a_hex(der))\n",
"\n",
"pem = public_key.public_bytes(encoding=serialization.Encoding.PEM,format=serialization.PublicFormat.SubjectPublicKeyInfo)\n",
"\n",
"der = public_key.public_bytes(encoding=serialization.Encoding.DER,format=serialization.PublicFormat.SubjectPublicKeyInfo)\n",
"\n",
"print (\"\\nPublic key (PEM):\\n\",pem.decode())\n",
"print (\"Public key (DER):\\n\",binascii.b2a_hex(der))"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "363e239f",
"metadata": {},
"outputs": [],
"source": []
}
],
"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.7.3"
}
},
"nbformat": 4,
"nbformat_minor": 5
}