mirror of
https://github.com/billbuchanan/appliedcrypto.git
synced 2026-02-20 13:50:42 +00:00
979 lines
31 KiB
Plaintext
979 lines
31 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "509b908c",
|
|
"metadata": {},
|
|
"source": [
|
|
"# Fundamentals\n",
|
|
"Within cryptography our aim is often to secure a message between Bob and Alice, and so that Eve - the adversory - cannot view or change a message that is passed between them. Along with Bob and Alice, we have other cybersecurity actors, such as Peggy (the prover) and Victor (the verifier):\n",
|
|
"\n",
|
|
"\n",
|
|
"\n",
|
|
"This workbook outlines of the key fundamentals that are used in cryptography, including the usage of binary operators, ciphertext representation, Boolean operators and prime numbers. "
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "e8a9af38",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Introduction\n",
|
|
"\n",
|
|
"In order to implement security, we often take plaintext and convert it into ciphertext:\n",
|
|
"\n",
|
|
"\n",
|
|
"\n",
|
|
"With a program, we often have numerical values (integers or floating point) or characters and strings. So, while the plaintext can contain characters that can be viewable, with binary we often have to represent the byte values with Base64 or in a hexadecimal form.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "37c0d953",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Hex, binary, decimal and Base64\n",
|
|
"The conversion of byte values into a hexademical form involves us breaking the byte vakues into 4 bit nibbles, and then representing each of these values with a hexadecimal value. For example, if we have a byte pattern of\n",
|
|
"\n",
|
|
"```\n",
|
|
"01111111 01010001\n",
|
|
"```\n",
|
|
"We can then split up the byte values to give:\n",
|
|
"\n",
|
|
"```\n",
|
|
"0111 1111 0101 0001\n",
|
|
"7 F 5 1\n",
|
|
"```\n",
|
|
"An example of this is:\n",
|
|
"\n",
|
|
"\n",
|
|
"\n",
|
|
"Another typical format is Base64, and where we take 6 bits at a time and represent it with a Base64 character:\n",
|
|
"\n",
|
|
"\n",
|
|
"\n",
|
|
"For a pattern of:\n",
|
|
"\n",
|
|
"```\n",
|
|
"01000001 01000010 \n",
|
|
"```\n",
|
|
"We can then split up the byte values to give:\n",
|
|
"\n",
|
|
"```\n",
|
|
"010000 010100 0010 [00] \n",
|
|
"Q U I =\n",
|
|
"```\n",
|
|
"This gives us \"QUI=\", and where we pad with zeros to fill up slots of six bits, and then pad with \"=\" characters to give a multiple of four characters within the Base64 string. In Python, we can represent a hex, octal and binary value with 0x, 0o and 0b at the start of the value. We can then convert into decimal, hex, octal and binary with the int(), hex(), oct() and bin() methods:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 1,
|
|
"id": "8c8fae3f",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"21 Int=21, Hex=0x15, Oct=0o25\n",
|
|
"34 Bin=0b100010, Hex=0x22, Oct=0o42, Dec=34\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"val1=0b10101\n",
|
|
"val2=int(val1)\n",
|
|
"val3=hex(val1)\n",
|
|
"val4=oct(val1)\n",
|
|
"\n",
|
|
"print(f\"{val1} Int={val2}, Hex={val3}, Oct={val4}\")\n",
|
|
"\n",
|
|
"val1=0o42\n",
|
|
"val2=bin(val1)\n",
|
|
"val3=hex(val1)\n",
|
|
"val4=oct(val1)\n",
|
|
"val5=int(val1)\n",
|
|
"\n",
|
|
"print(f\"{val1} Bin={val2}, Hex={val3}, Oct={val4}, Dec={val5}\")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "5f33519c",
|
|
"metadata": {},
|
|
"source": [
|
|
"> Modify the program so that you can determine the hex, octal and binary value for the decimal value of 42.\n",
|
|
"\n",
|
|
"> Modify the program so that you can determine the decimal, octal and binary value for the hex value of 0x42.\n",
|
|
"\n",
|
|
"> Modify the program so that you can determine the hex, decimal, and binary value for the octal value of 0o42.\n",
|
|
"\n",
|
|
"> Modify the program so that is shows the following table (note: use for \"i in range()\"):\n",
|
|
"\n",
|
|
"```\n",
|
|
"Val Hex Oct Binary\n",
|
|
"0 0x0 0o0 0b0\n",
|
|
"1 0x1 0o1 0b1\n",
|
|
"2 0x2 0o2 0b10\n",
|
|
"3 0x3 0o3 0b11\n",
|
|
"4 0x4 0o4 0b100\n",
|
|
"5 0x5 0o5 0b101\n",
|
|
"6 0x6 0o6 0b110\n",
|
|
"7 0x7 0o7 0b111\n",
|
|
"8 0x8 0o10 0b1000\n",
|
|
"9 0x9 0o11 0b1001\n",
|
|
"10 0xa 0o12 0b1010\n",
|
|
"11 0xb 0o13 0b1011\n",
|
|
"12 0xc 0o14 0b1100\n",
|
|
"13 0xd 0o15 0b1101\n",
|
|
"14 0xe 0o16 0b1110\n",
|
|
"15 0xf 0o17 0b1111 \n",
|
|
"```"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "73426b52",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Byte conversions\n",
|
|
"In cryptography, we often operate on byte arrays and need to convert from byte array formats into other formats, such as for ASCII string values. For this, we can use the binascii library, such as using hexlify() to convert a hex string into a into a byte array, and with b2a_hex() to perform the reverse operation: "
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 49,
|
|
"id": "9129b9e6",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"String abcdefg is b'61626364656667' in bytes\n",
|
|
"Bytes b'3631363236333634363536363637' is 3631363236333634363536363637 as a string\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"import binascii\n",
|
|
"\n",
|
|
"a=\"abcdefg\"\n",
|
|
"b=binascii.hexlify(a.encode())\n",
|
|
"\n",
|
|
"print(f\"String {a} is {b} in bytes\")\n",
|
|
"\n",
|
|
"\n",
|
|
"c=binascii.b2a_hex(b)\n",
|
|
"\n",
|
|
"print(f\"Bytes {c} is {c.decode()} as a string\")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "b72f269f",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Bit operations\n",
|
|
"While we mostly deal with bytes in cryptography, we might also modify bit values. For this we can use the bitwise AND, OR and XOR operations. For this we get:\n",
|
|
"```\n",
|
|
"a b AND(a,b) OR(a,b) XOR(a,b)\n",
|
|
"0 0 0 0 0\n",
|
|
"0 1 0 1 1\n",
|
|
"1 0 0 1 1\n",
|
|
"1 1 1 1 0\n",
|
|
"```\n",
|
|
"\n",
|
|
"We can then use the bitwise operations of & (AND), | (OR) and ^ (XOR). For example we can specify in binary, and then perform bitwise operations. In this case we will display the results in a binary format:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 55,
|
|
"id": "8eaccf0e",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"0x32 AND 0b1000011 = 0b10\n",
|
|
"0b110010 OR 0b1000011 = 0b1110011\n",
|
|
"0b110010 XOR 0b1000011 = 0b1110001\n",
|
|
"0 0b0 0b10101010 0b10101010\n",
|
|
"1 0b0 0b10101011 0b10101011\n",
|
|
"2 0b10 0b10101010 0b10101000\n",
|
|
"3 0b10 0b10101011 0b10101001\n",
|
|
"4 0b0 0b10101110 0b10101110\n",
|
|
"5 0b0 0b10101111 0b10101111\n",
|
|
"6 0b10 0b10101110 0b10101100\n",
|
|
"7 0b10 0b10101111 0b10101101\n",
|
|
"8 0b1000 0b10101010 0b10100010\n",
|
|
"9 0b1000 0b10101011 0b10100011\n",
|
|
"10 0b1010 0b10101010 0b10100000\n",
|
|
"11 0b1010 0b10101011 0b10100001\n",
|
|
"12 0b1000 0b10101110 0b10100110\n",
|
|
"13 0b1000 0b10101111 0b10100111\n",
|
|
"14 0b1010 0b10101110 0b10100100\n",
|
|
"15 0b1010 0b10101111 0b10100101\n",
|
|
"16 0b0 0b10111010 0b10111010\n",
|
|
"17 0b0 0b10111011 0b10111011\n",
|
|
"18 0b10 0b10111010 0b10111000\n",
|
|
"19 0b10 0b10111011 0b10111001\n",
|
|
"20 0b0 0b10111110 0b10111110\n",
|
|
"21 0b0 0b10111111 0b10111111\n",
|
|
"22 0b10 0b10111110 0b10111100\n",
|
|
"23 0b10 0b10111111 0b10111101\n",
|
|
"24 0b1000 0b10111010 0b10110010\n",
|
|
"25 0b1000 0b10111011 0b10110011\n",
|
|
"26 0b1010 0b10111010 0b10110000\n",
|
|
"27 0b1010 0b10111011 0b10110001\n",
|
|
"28 0b1000 0b10111110 0b10110110\n",
|
|
"29 0b1000 0b10111111 0b10110111\n",
|
|
"30 0b1010 0b10111110 0b10110100\n",
|
|
"31 0b1010 0b10111111 0b10110101\n",
|
|
"32 0b100000 0b10101010 0b10001010\n",
|
|
"33 0b100000 0b10101011 0b10001011\n",
|
|
"34 0b100010 0b10101010 0b10001000\n",
|
|
"35 0b100010 0b10101011 0b10001001\n",
|
|
"36 0b100000 0b10101110 0b10001110\n",
|
|
"37 0b100000 0b10101111 0b10001111\n",
|
|
"38 0b100010 0b10101110 0b10001100\n",
|
|
"39 0b100010 0b10101111 0b10001101\n",
|
|
"40 0b101000 0b10101010 0b10000010\n",
|
|
"41 0b101000 0b10101011 0b10000011\n",
|
|
"42 0b101010 0b10101010 0b10000000\n",
|
|
"43 0b101010 0b10101011 0b10000001\n",
|
|
"44 0b101000 0b10101110 0b10000110\n",
|
|
"45 0b101000 0b10101111 0b10000111\n",
|
|
"46 0b101010 0b10101110 0b10000100\n",
|
|
"47 0b101010 0b10101111 0b10000101\n",
|
|
"48 0b100000 0b10111010 0b10011010\n",
|
|
"49 0b100000 0b10111011 0b10011011\n",
|
|
"50 0b100010 0b10111010 0b10011000\n",
|
|
"51 0b100010 0b10111011 0b10011001\n",
|
|
"52 0b100000 0b10111110 0b10011110\n",
|
|
"53 0b100000 0b10111111 0b10011111\n",
|
|
"54 0b100010 0b10111110 0b10011100\n",
|
|
"55 0b100010 0b10111111 0b10011101\n",
|
|
"56 0b101000 0b10111010 0b10010010\n",
|
|
"57 0b101000 0b10111011 0b10010011\n",
|
|
"58 0b101010 0b10111010 0b10010000\n",
|
|
"59 0b101010 0b10111011 0b10010001\n",
|
|
"60 0b101000 0b10111110 0b10010110\n",
|
|
"61 0b101000 0b10111111 0b10010111\n",
|
|
"62 0b101010 0b10111110 0b10010100\n",
|
|
"63 0b101010 0b10111111 0b10010101\n",
|
|
"64 0b0 0b11101010 0b11101010\n",
|
|
"65 0b0 0b11101011 0b11101011\n",
|
|
"66 0b10 0b11101010 0b11101000\n",
|
|
"67 0b10 0b11101011 0b11101001\n",
|
|
"68 0b0 0b11101110 0b11101110\n",
|
|
"69 0b0 0b11101111 0b11101111\n",
|
|
"70 0b10 0b11101110 0b11101100\n",
|
|
"71 0b10 0b11101111 0b11101101\n",
|
|
"72 0b1000 0b11101010 0b11100010\n",
|
|
"73 0b1000 0b11101011 0b11100011\n",
|
|
"74 0b1010 0b11101010 0b11100000\n",
|
|
"75 0b1010 0b11101011 0b11100001\n",
|
|
"76 0b1000 0b11101110 0b11100110\n",
|
|
"77 0b1000 0b11101111 0b11100111\n",
|
|
"78 0b1010 0b11101110 0b11100100\n",
|
|
"79 0b1010 0b11101111 0b11100101\n",
|
|
"80 0b0 0b11111010 0b11111010\n",
|
|
"81 0b0 0b11111011 0b11111011\n",
|
|
"82 0b10 0b11111010 0b11111000\n",
|
|
"83 0b10 0b11111011 0b11111001\n",
|
|
"84 0b0 0b11111110 0b11111110\n",
|
|
"85 0b0 0b11111111 0b11111111\n",
|
|
"86 0b10 0b11111110 0b11111100\n",
|
|
"87 0b10 0b11111111 0b11111101\n",
|
|
"88 0b1000 0b11111010 0b11110010\n",
|
|
"89 0b1000 0b11111011 0b11110011\n",
|
|
"90 0b1010 0b11111010 0b11110000\n",
|
|
"91 0b1010 0b11111011 0b11110001\n",
|
|
"92 0b1000 0b11111110 0b11110110\n",
|
|
"93 0b1000 0b11111111 0b11110111\n",
|
|
"94 0b1010 0b11111110 0b11110100\n",
|
|
"95 0b1010 0b11111111 0b11110101\n",
|
|
"96 0b100000 0b11101010 0b11001010\n",
|
|
"97 0b100000 0b11101011 0b11001011\n",
|
|
"98 0b100010 0b11101010 0b11001000\n",
|
|
"99 0b100010 0b11101011 0b11001001\n",
|
|
"100 0b100000 0b11101110 0b11001110\n",
|
|
"101 0b100000 0b11101111 0b11001111\n",
|
|
"102 0b100010 0b11101110 0b11001100\n",
|
|
"103 0b100010 0b11101111 0b11001101\n",
|
|
"104 0b101000 0b11101010 0b11000010\n",
|
|
"105 0b101000 0b11101011 0b11000011\n",
|
|
"106 0b101010 0b11101010 0b11000000\n",
|
|
"107 0b101010 0b11101011 0b11000001\n",
|
|
"108 0b101000 0b11101110 0b11000110\n",
|
|
"109 0b101000 0b11101111 0b11000111\n",
|
|
"110 0b101010 0b11101110 0b11000100\n",
|
|
"111 0b101010 0b11101111 0b11000101\n",
|
|
"112 0b100000 0b11111010 0b11011010\n",
|
|
"113 0b100000 0b11111011 0b11011011\n",
|
|
"114 0b100010 0b11111010 0b11011000\n",
|
|
"115 0b100010 0b11111011 0b11011001\n",
|
|
"116 0b100000 0b11111110 0b11011110\n",
|
|
"117 0b100000 0b11111111 0b11011111\n",
|
|
"118 0b100010 0b11111110 0b11011100\n",
|
|
"119 0b100010 0b11111111 0b11011101\n",
|
|
"120 0b101000 0b11111010 0b11010010\n",
|
|
"121 0b101000 0b11111011 0b11010011\n",
|
|
"122 0b101010 0b11111010 0b11010000\n",
|
|
"123 0b101010 0b11111011 0b11010001\n",
|
|
"124 0b101000 0b11111110 0b11010110\n",
|
|
"125 0b101000 0b11111111 0b11010111\n",
|
|
"126 0b101010 0b11111110 0b11010100\n",
|
|
"127 0b101010 0b11111111 0b11010101\n",
|
|
"128 0b10000000 0b10101010 0b101010\n",
|
|
"129 0b10000000 0b10101011 0b101011\n",
|
|
"130 0b10000010 0b10101010 0b101000\n",
|
|
"131 0b10000010 0b10101011 0b101001\n",
|
|
"132 0b10000000 0b10101110 0b101110\n",
|
|
"133 0b10000000 0b10101111 0b101111\n",
|
|
"134 0b10000010 0b10101110 0b101100\n",
|
|
"135 0b10000010 0b10101111 0b101101\n",
|
|
"136 0b10001000 0b10101010 0b100010\n",
|
|
"137 0b10001000 0b10101011 0b100011\n",
|
|
"138 0b10001010 0b10101010 0b100000\n",
|
|
"139 0b10001010 0b10101011 0b100001\n",
|
|
"140 0b10001000 0b10101110 0b100110\n",
|
|
"141 0b10001000 0b10101111 0b100111\n",
|
|
"142 0b10001010 0b10101110 0b100100\n",
|
|
"143 0b10001010 0b10101111 0b100101\n",
|
|
"144 0b10000000 0b10111010 0b111010\n",
|
|
"145 0b10000000 0b10111011 0b111011\n",
|
|
"146 0b10000010 0b10111010 0b111000\n",
|
|
"147 0b10000010 0b10111011 0b111001\n",
|
|
"148 0b10000000 0b10111110 0b111110\n",
|
|
"149 0b10000000 0b10111111 0b111111\n",
|
|
"150 0b10000010 0b10111110 0b111100\n",
|
|
"151 0b10000010 0b10111111 0b111101\n",
|
|
"152 0b10001000 0b10111010 0b110010\n",
|
|
"153 0b10001000 0b10111011 0b110011\n",
|
|
"154 0b10001010 0b10111010 0b110000\n",
|
|
"155 0b10001010 0b10111011 0b110001\n",
|
|
"156 0b10001000 0b10111110 0b110110\n",
|
|
"157 0b10001000 0b10111111 0b110111\n",
|
|
"158 0b10001010 0b10111110 0b110100\n",
|
|
"159 0b10001010 0b10111111 0b110101\n",
|
|
"160 0b10100000 0b10101010 0b1010\n",
|
|
"161 0b10100000 0b10101011 0b1011\n",
|
|
"162 0b10100010 0b10101010 0b1000\n",
|
|
"163 0b10100010 0b10101011 0b1001\n",
|
|
"164 0b10100000 0b10101110 0b1110\n",
|
|
"165 0b10100000 0b10101111 0b1111\n",
|
|
"166 0b10100010 0b10101110 0b1100\n",
|
|
"167 0b10100010 0b10101111 0b1101\n",
|
|
"168 0b10101000 0b10101010 0b10\n",
|
|
"169 0b10101000 0b10101011 0b11\n",
|
|
"170 0b10101010 0b10101010 0b0\n",
|
|
"171 0b10101010 0b10101011 0b1\n",
|
|
"172 0b10101000 0b10101110 0b110\n",
|
|
"173 0b10101000 0b10101111 0b111\n",
|
|
"174 0b10101010 0b10101110 0b100\n",
|
|
"175 0b10101010 0b10101111 0b101\n",
|
|
"176 0b10100000 0b10111010 0b11010\n",
|
|
"177 0b10100000 0b10111011 0b11011\n",
|
|
"178 0b10100010 0b10111010 0b11000\n",
|
|
"179 0b10100010 0b10111011 0b11001\n",
|
|
"180 0b10100000 0b10111110 0b11110\n",
|
|
"181 0b10100000 0b10111111 0b11111\n",
|
|
"182 0b10100010 0b10111110 0b11100\n",
|
|
"183 0b10100010 0b10111111 0b11101\n",
|
|
"184 0b10101000 0b10111010 0b10010\n",
|
|
"185 0b10101000 0b10111011 0b10011\n",
|
|
"186 0b10101010 0b10111010 0b10000\n",
|
|
"187 0b10101010 0b10111011 0b10001\n",
|
|
"188 0b10101000 0b10111110 0b10110\n",
|
|
"189 0b10101000 0b10111111 0b10111\n",
|
|
"190 0b10101010 0b10111110 0b10100\n",
|
|
"191 0b10101010 0b10111111 0b10101\n",
|
|
"192 0b10000000 0b11101010 0b1101010\n",
|
|
"193 0b10000000 0b11101011 0b1101011\n",
|
|
"194 0b10000010 0b11101010 0b1101000\n",
|
|
"195 0b10000010 0b11101011 0b1101001\n",
|
|
"196 0b10000000 0b11101110 0b1101110\n",
|
|
"197 0b10000000 0b11101111 0b1101111\n",
|
|
"198 0b10000010 0b11101110 0b1101100\n",
|
|
"199 0b10000010 0b11101111 0b1101101\n",
|
|
"200 0b10001000 0b11101010 0b1100010\n",
|
|
"201 0b10001000 0b11101011 0b1100011\n",
|
|
"202 0b10001010 0b11101010 0b1100000\n",
|
|
"203 0b10001010 0b11101011 0b1100001\n",
|
|
"204 0b10001000 0b11101110 0b1100110\n",
|
|
"205 0b10001000 0b11101111 0b1100111\n",
|
|
"206 0b10001010 0b11101110 0b1100100\n",
|
|
"207 0b10001010 0b11101111 0b1100101\n",
|
|
"208 0b10000000 0b11111010 0b1111010\n",
|
|
"209 0b10000000 0b11111011 0b1111011\n",
|
|
"210 0b10000010 0b11111010 0b1111000\n",
|
|
"211 0b10000010 0b11111011 0b1111001\n",
|
|
"212 0b10000000 0b11111110 0b1111110\n",
|
|
"213 0b10000000 0b11111111 0b1111111\n",
|
|
"214 0b10000010 0b11111110 0b1111100\n",
|
|
"215 0b10000010 0b11111111 0b1111101\n",
|
|
"216 0b10001000 0b11111010 0b1110010\n",
|
|
"217 0b10001000 0b11111011 0b1110011\n",
|
|
"218 0b10001010 0b11111010 0b1110000\n",
|
|
"219 0b10001010 0b11111011 0b1110001\n",
|
|
"220 0b10001000 0b11111110 0b1110110\n",
|
|
"221 0b10001000 0b11111111 0b1110111\n",
|
|
"222 0b10001010 0b11111110 0b1110100\n",
|
|
"223 0b10001010 0b11111111 0b1110101\n",
|
|
"224 0b10100000 0b11101010 0b1001010\n",
|
|
"225 0b10100000 0b11101011 0b1001011\n",
|
|
"226 0b10100010 0b11101010 0b1001000\n",
|
|
"227 0b10100010 0b11101011 0b1001001\n",
|
|
"228 0b10100000 0b11101110 0b1001110\n",
|
|
"229 0b10100000 0b11101111 0b1001111\n",
|
|
"230 0b10100010 0b11101110 0b1001100\n",
|
|
"231 0b10100010 0b11101111 0b1001101\n",
|
|
"232 0b10101000 0b11101010 0b1000010\n",
|
|
"233 0b10101000 0b11101011 0b1000011\n",
|
|
"234 0b10101010 0b11101010 0b1000000\n",
|
|
"235 0b10101010 0b11101011 0b1000001\n",
|
|
"236 0b10101000 0b11101110 0b1000110\n",
|
|
"237 0b10101000 0b11101111 0b1000111\n",
|
|
"238 0b10101010 0b11101110 0b1000100\n",
|
|
"239 0b10101010 0b11101111 0b1000101\n",
|
|
"240 0b10100000 0b11111010 0b1011010\n",
|
|
"241 0b10100000 0b11111011 0b1011011\n",
|
|
"242 0b10100010 0b11111010 0b1011000\n",
|
|
"243 0b10100010 0b11111011 0b1011001\n",
|
|
"244 0b10100000 0b11111110 0b1011110\n",
|
|
"245 0b10100000 0b11111111 0b1011111\n",
|
|
"246 0b10100010 0b11111110 0b1011100\n",
|
|
"247 0b10100010 0b11111111 0b1011101\n",
|
|
"248 0b10101000 0b11111010 0b1010010\n",
|
|
"249 0b10101000 0b11111011 0b1010011\n",
|
|
"250 0b10101010 0b11111010 0b1010000\n",
|
|
"251 0b10101010 0b11111011 0b1010001\n",
|
|
"252 0b10101000 0b11111110 0b1010110\n",
|
|
"253 0b10101000 0b11111111 0b1010111\n",
|
|
"254 0b10101010 0b11111110 0b1010100\n",
|
|
"255 0b10101010 0b11111111 0b1010101\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"\n",
|
|
"a=0x32\n",
|
|
"b=0x43\n",
|
|
"\n",
|
|
"c=a & b\n",
|
|
"d=a | b\n",
|
|
"e=a ^ b\n",
|
|
"\n",
|
|
"print(f\"{hex(a)} AND {bin(b)} = {bin(c)}\")\n",
|
|
"print(f\"{bin(a)} OR {bin(b)} = {bin(d)}\")\n",
|
|
"print(f\"{bin(a)} XOR {bin(b)} = {bin(e)}\")\n",
|
|
"\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "fb34d492",
|
|
"metadata": {},
|
|
"source": [
|
|
"> Check the Boolean operations to see that the program works.\n",
|
|
"\n",
|
|
"> Using the program, determine the result of 0b10101010 XOR 0b10101010.\n",
|
|
"\n",
|
|
"> Modify the program so that you can specify hexademical values, and then display in a hexademical format.\n",
|
|
"\n",
|
|
"> Modify the program so that we have a loop from 0 to 255 (note: use for \"i in range()\"), and AND, OR and XOR is a value of 0b10101010. A sample run for the first few outputs is:\n",
|
|
"\n",
|
|
"```\n",
|
|
"i& AND\tOR\t XOR\n",
|
|
"0b0 0b0\t0b10101010\t0b10101010\n",
|
|
"0b1 0b0\t0b10101011\t0b10101011\n",
|
|
"0b10 0b10\t0b10101010\t0b10101000\n",
|
|
"0b11 0b10\t0b10101011\t0b10101001\n",
|
|
"0b100 0b0\t0b10101110\t0b10101110\n",
|
|
"0b101 0b0\t0b10101111\t0b10101111\n",
|
|
"0b110 0b10\t0b10101110\t0b10101100\n",
|
|
"0b111 0b10\t0b10101111\t0b10101101\n",
|
|
"0b1000 0b1000\t0b10101010\t0b10100010\n",
|
|
"0b1001 0b1000\t0b10101011\t0b10100011\n",
|
|
"0b1010 0b1010\t0b10101010\t0b10100000\n",
|
|
"0b1011 0b1010\t0b10101011\t0b10100001\n",
|
|
"0b1100 0b1000\t0b10101110\t0b10100110\n",
|
|
"0b1101 0b1000\t0b10101111\t0b10100111\n",
|
|
"0b1110 0b1010\t0b10101110\t0b10100100\n",
|
|
"0b1111 0b1010\t0b10101111\t0b10100101\n",
|
|
"0b10000 0b0\t0b10111010\t0b10111010\n",
|
|
"0b10001 0b0\t0b10111011\t0b10111011\n",
|
|
"0b10010 0b10\t0b10111010\t0b10111000\n",
|
|
"0b10011 0b10\t0b10111011\t0b10111001\n",
|
|
"0b10100 0b0\t0b10111110\t0b10111110\n",
|
|
"```"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "3634d7ce",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Modulo operation\n",
|
|
"\n",
|
|
"One of the most basic operations in cryptography is to use the modulo operation, and which gives the remainder of an integer division. For 17 modulo 5, we get 2. In most cases, with cryptography, we use the modulo of a prime number (p), and use (mod p) operation, such as:\n",
|
|
"\n",
|
|
"```\n",
|
|
"A = B (mod p)\n",
|
|
"```\n",
|
|
"\n",
|
|
"The operator for modulo operations is defined with \"%\". "
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 57,
|
|
"id": "e870306b",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"15434 (mod 127) = 67\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"a=15434\n",
|
|
"p=127\n",
|
|
"\n",
|
|
"b = a%p\n",
|
|
"\n",
|
|
"print(f\"{a} (mod {p}) = {b}\")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "29be2ce3",
|
|
"metadata": {},
|
|
"source": [
|
|
"> Verify that the program is working correctly. Then determine the following:\n",
|
|
"```\n",
|
|
"15434 (mod 127) = ?\n",
|
|
"546324 (mod 997) = ?\n",
|
|
"905463124 (mod 524287) = ?\n",
|
|
"```"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "b0d38eae",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Prime numbers\n",
|
|
"\n",
|
|
"Many areas of cryptography use prime numbers, and which are integer values which can only be divisable by itself and 1. Every other integer - known as composite numbers - can be made up of a multiplication of prime numbers. Examples of prime numbers are 13, 97 and 997. The following composite numbers can be factorized into the multiplication of prime numbers:\n",
|
|
"\n",
|
|
"```\n",
|
|
"33 = 3 x 11\n",
|
|
"532 = 2 x 2 x 7 x 19\n",
|
|
"2,542 = 2 x 31 x 41\n",
|
|
"743,243 = 193 x 3,851\n",
|
|
"1,234,567,890 = 2 x 3 x 3 x 5 x 3,607 x 3,803\n",
|
|
"\n",
|
|
"```"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "0b9e3720",
|
|
"metadata": {},
|
|
"source": [
|
|
"In the following, we will use the libnum library to generate a random prime number with a given number of bits:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 85,
|
|
"id": "fd09fcb6",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Random: 812768180957 Length: 40\n",
|
|
"\n",
|
|
"Prime (p): 560263049029. Length: 40 bits, Digits: 12\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"import libnum\n",
|
|
"\n",
|
|
"bitsize=40\n",
|
|
"\n",
|
|
"r=libnum.randint_bits(bitsize)\n",
|
|
"\n",
|
|
"print (\"Random: %d Length: %d\" % (r,libnum.len_in_bits(r)))\n",
|
|
"\n",
|
|
"\n",
|
|
"p=libnum.generate_prime(bitsize)\n",
|
|
"\n",
|
|
"print (\"\\nPrime (p): %d. Length: %d bits, Digits: %d\" % (p,libnum.len_in_bits(p), len(str(p)) )) "
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "5a1a3c85",
|
|
"metadata": {},
|
|
"source": [
|
|
"another library is Crypto:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 94,
|
|
"id": "6ec3d9cb",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"No of bits in prime is 64\n",
|
|
"\n",
|
|
"Random n-bit Prime (p): 11916865567959269669\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"import Crypto.Util.number\n",
|
|
"\n",
|
|
"import sys\n",
|
|
"\n",
|
|
"bits=64\n",
|
|
"\n",
|
|
"print (\"No of bits in prime is \",bits)\n",
|
|
"\n",
|
|
"p=Crypto.Util.number.getPrime(bits, randfunc=Crypto.Random.get_random_bytes)\n",
|
|
"print (\"\\nRandom n-bit Prime (p): \",p)\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "dc11d9d0",
|
|
"metadata": {},
|
|
"source": [
|
|
"> Generate a 64-bit random prime number. And use this page to determine if it is prime [here](https://asecuritysite.com/primes/testprime).\n",
|
|
"\n",
|
|
"> Generate a 256-bit random prime number. And use this page to determine if it is prime [here](https://asecuritysite.com/primes/testprime).\n",
|
|
"\n",
|
|
"> By observing the last few digits of a number, which numbers are obviously not prime numbers?"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "d2d3bd5d",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Finite Fields\n",
|
|
"Within cryptography, we typically constrain our operations within a finite field. This is normally defined by a prime number (p), and where we have values between 0 and (p-1). This can be defined with the (mod p) operator. For this, we need to define a mapping from A to B, and which can be reversed back from B to A. For the add operation with a (mod p) operation, we can reverse with a subtraction:\n",
|
|
"\n",
|
|
"\n",
|
|
"\n",
|
|
"For a logarithmic operation, we should be able to map all the values in A to B:\n",
|
|
"\n",
|
|
"\n",
|
|
"\n",
|
|
"In the following, we will determine the mapping of values when we add and subtract 5 using the (mod p) operation:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 39,
|
|
"id": "d4b145d0",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"0+5 (mod 7)=5\n",
|
|
"0-5 (mod 7)=2\n",
|
|
"1+5 (mod 7)=6\n",
|
|
"1-5 (mod 7)=3\n",
|
|
"2+5 (mod 7)=0\n",
|
|
"2-5 (mod 7)=4\n",
|
|
"3+5 (mod 7)=1\n",
|
|
"3-5 (mod 7)=5\n",
|
|
"4+5 (mod 7)=2\n",
|
|
"4-5 (mod 7)=6\n",
|
|
"5+5 (mod 7)=3\n",
|
|
"5-5 (mod 7)=0\n",
|
|
"6+5 (mod 7)=4\n",
|
|
"6-5 (mod 7)=1\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"\n",
|
|
"b=5\n",
|
|
"p=7\n",
|
|
"\n",
|
|
"for a in range(p):\n",
|
|
" c=(a+b) % p\n",
|
|
" d=(a-b) % p\n",
|
|
" print(f\"{a}+{b} (mod {p})={c}\")\n",
|
|
" print(f\"{a}-{b} (mod {p})={d}\")\n",
|
|
" "
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "6867a166",
|
|
"metadata": {},
|
|
"source": [
|
|
"\n",
|
|
"> Verify that for each value of a, that we get a unique mapping to a value in the range of 0 to p-1.\n",
|
|
"> Verify that we can add a given value to a number, and then subtract the same value to get the original value back. Note the value should be between 0 and p-1."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "528f0427",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Inverse mod\n",
|
|
"As we are using integer values, the perform a division by finding the inverse mod of a value, and then multiplying it with another value. For a divided by b, we get:\n",
|
|
"\n",
|
|
"```\n",
|
|
"Inv_b = pow(b,-1,p)\n",
|
|
"a_b = a * Inv_b\n",
|
|
"```\n",
|
|
"\n",
|
|
"In the following, we will multiply a by b, and then reverse by dividing by b:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 95,
|
|
"id": "dcb77c31",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"a=13, b=6\n",
|
|
"13 times 6 (mod p)=2\n",
|
|
"Inverse 6 (mod 19)=16\n",
|
|
"2 divided by 6 (mod 19)=13\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"a = 13\n",
|
|
"b= 6\n",
|
|
"p=19\n",
|
|
"\n",
|
|
"c=a*b % p\n",
|
|
"\n",
|
|
"print(f\"a={a}, b={b}\")\n",
|
|
"\n",
|
|
"print(f\"{a} times {b} (mod p)={c}\")\n",
|
|
"\n",
|
|
"Inv_b=pow(b,-1,p)\n",
|
|
"\n",
|
|
"print(f\"Inverse {b} (mod {p})={Inv_b}\")\n",
|
|
"\n",
|
|
"d = c*Inv_b %p\n",
|
|
"print(f\"{c} divided by {b} (mod {p})={d}\")\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "4127f768",
|
|
"metadata": {},
|
|
"source": [
|
|
"> For a prime number of 19, determine the inverse mod of 6?\n",
|
|
"\n",
|
|
"> For a prime number of 97, determine the inverse mod of 6?\n",
|
|
"\n",
|
|
"> For a prime number of 997, a=101 and b=97. Compute c = a times b (mod p), and show that c divided by b (mod p) will give a."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "d4676b59",
|
|
"metadata": {},
|
|
"source": [
|
|
"We can also use the libnum library to compute the inverse mod value, such as:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 41,
|
|
"id": "349b3ff1",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Result=54\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"import libnum\n",
|
|
"\n",
|
|
"p=997\n",
|
|
"a=54\n",
|
|
"b=62\n",
|
|
"\n",
|
|
"c= a*b %p\n",
|
|
"\n",
|
|
"Inv_b = libnum.invmod(b,p)\n",
|
|
"\n",
|
|
"res = (c* Inv_b) % p\n",
|
|
"\n",
|
|
"print(f\"Result={res}\")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "b24407b8",
|
|
"metadata": {},
|
|
"source": [
|
|
"## GCD (Greatest Common Divisor)\n",
|
|
"Another basic operator in cryptography is GCD, and which returns the largest value that can be divided into a defined value. For example, the GCD(60, 12) is 12, as 12 is the largest divider of 60 and 12. In the following we will use the libnum library to determine the GCD of two numbers:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 99,
|
|
"id": "3565fb67",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"GCD(802,72)=2\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"from libnum import gcd\n",
|
|
"a=56\n",
|
|
"b=72\n",
|
|
"\n",
|
|
"print(f\"GCD({a},{b})={gcd(a,b)}\")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "9c647834",
|
|
"metadata": {},
|
|
"source": [
|
|
"> Run the program, and verify its operation with a few examples.\n",
|
|
"\n",
|
|
"> What is the result of GCD(802,72)?\n",
|
|
"\n",
|
|
"> What is the result of GCD(997,81)?"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "ee22a1f0",
|
|
"metadata": {},
|
|
"source": [
|
|
"Overall, we tend to use this operation to determine when two values do not share the same factor, and thus often look for:\n",
|
|
"\n",
|
|
"GCD(a,b)==1"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "f5e2f3fc",
|
|
"metadata": {
|
|
"vscode": {
|
|
"languageId": "html"
|
|
}
|
|
},
|
|
"source": [
|
|
"> Determine if 91 and 27 share any factors"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "84b8a11d",
|
|
"metadata": {},
|
|
"source": [
|
|
"# Exponentiation cipher\n",
|
|
"Exponentiation ciphers use a form of C=M^e (mod p) to encrypt and decrypt a message (M) using an encryption key of e and a prime number p. It is used in Pohlig-Hellman and RSA. In the following, we use two methods of computing the exponentiation:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "d8e266cc",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Cipher = M^e (mod p)\n",
|
|
"\n",
|
|
"M=1234567890\n",
|
|
"e=65537\n",
|
|
"p=2**255-1\n",
|
|
"\n",
|
|
"C=M**e % p # Slow for large values\n",
|
|
"print (f\"Cipher = {C}\")\n",
|
|
"\n",
|
|
"C=pow(M,e,p) # Much faster\n",
|
|
"print (f\"Cipher = {C}\")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "4c49a2c7",
|
|
"metadata": {},
|
|
"source": [
|
|
"> Which of the two methods is the fastest?\n",
|
|
"> Make the message value much larger, what effect does it have on the computation?\n",
|
|
"> Why is the pow() method faster?\n",
|
|
"> If you create d=pow(e,-1,p), and then try M=pow(C,d,p), what is the result?"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "4c083835",
|
|
"metadata": {},
|
|
"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.8.3"
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 5
|
|
}
|