├── 9781484265857.jpg ├── Chapter 10 - Lattice-based Cryptography └── GGH_encryption.cpp ├── Chapter 12 - Homomorphic Encryption └── SealCPPExample │ ├── .vs │ └── SealCPPExample │ │ └── v16 │ │ ├── .suo │ │ └── Browse.VC.db │ ├── SealCPPExample.sln │ ├── SealCPPExample │ ├── SealCPPExample.vcxproj │ ├── SealCPPExample.vcxproj.filters │ ├── SealCPPExample.vcxproj.user │ ├── SealExample.cpp │ └── x64 │ │ └── Release │ │ ├── SealCPPExample.Build.CppClean.log │ │ ├── SealCPPExample.log │ │ ├── SealCPPExample.tlog │ │ ├── CL.command.1.tlog │ │ ├── CL.read.1.tlog │ │ ├── CL.write.1.tlog │ │ ├── SealCPPExample.lastbuildstate │ │ ├── SealCPPExample.write.1u.tlog │ │ ├── link.command.1.tlog │ │ ├── link.read.1.tlog │ │ └── link.write.1.tlog │ │ ├── SealCPPExample.vcxproj.FileListAbsolute.txt │ │ ├── SealExample.obj │ │ └── vc142.pdb │ └── x64 │ └── Release │ ├── SealCPPExample.exe │ ├── SealCPPExample.iobj │ ├── SealCPPExample.ipdb │ └── SealCPPExample.pdb ├── Chapter 13 - (Ring) Learning with Errors Cryptography ├── LWE_Example.cpp └── LWE_Simple.cpp ├── Chapter 14 - Chaos-based Cryptography ├── ChaosSecureRandomNumberGenerator │ ├── chaos_random.cpp │ ├── dev │ │ └── urandom │ ├── encryption.c │ ├── encryption.h │ ├── generation.c │ ├── generation.h │ └── test.exe └── CipherBasedOnFractals │ ├── FractalCipherCrypto.cpp │ ├── FractalCipherCrypto.h │ └── test.exe ├── Chapter 15 - Big Data Cryptography ├── main.cpp ├── picosha2.h ├── tree.cpp ├── tree.h ├── tree_handling.h ├── tree_node.cpp └── tree_node.h ├── Chapter 16 - Cloud Computing Cryptography ├── cloud_example.cpp ├── openssl-1.0.2d-fips-2.0.10.zip ├── privateKey.pem └── publicKey.pem ├── Chapter 19 - Linear and Differential Cryptanalysis ├── differential_cryptanalysis.cpp ├── differential_cryptanalysis.exe ├── linear_cryptanalysis.cpp └── linear_cryptanalysis.exe ├── Chapter 2 - Cryptography Fundamentals ├── Listing 2-10 - Caesar Cipher.cpp ├── Listing 2-11 - Vigenere.cpp └── Listing 2-9 - SHA-256.cpp ├── Chapter 20 - Integral Cryptanalysis ├── integral.cpp └── integral.exe ├── Chapter 21 - Brute Force and Buffer Overflow Attacks ├── BasicStringGenerationBFAttack │ ├── strings_brute_force.cpp │ └── strings_brute_force.exe ├── BufferOverflowAttack │ ├── buffer_overflow_attack.cpp │ └── buffer_overflow_attack.exe └── CaesarBruteForceAttack │ ├── caesar_brute_force.cpp │ └── caesar_brute_force.exe ├── Chapter 22 - Text Characterization ├── 22-1.cpp ├── 22-1.exe ├── 22-2.cpp ├── 22-2.exe ├── 22-3.cpp ├── 22-3.exe ├── 22-4.cpp ├── 22-4.exe └── bigram.txt ├── Chapter 23 - Implementation of Cryptanalysis Methods ├── random_keys.cpp └── random_keys.exe ├── Chapter 3 - Mathematical Background and Its Applicability ├── CaseStudy1.cpp ├── CaseStudy10.cpp ├── CaseStudy2.cpp ├── CaseStudy3.cpp ├── CaseStudy4.cpp ├── CaseStudy5.cpp ├── CaseStudy6.cpp ├── CaseStudy7_1.cpp ├── CaseStudy7_2.cpp ├── CaseStudy8_1.cpp ├── CaseStudy8_2.cpp └── CaseStudy9.cpp ├── Chapter 4 - Large Integer Arithmetic ├── Listing 4-1.cpp ├── Listing 4-2.cpp ├── Listing 4-3.cpp ├── Listing 4-4.cpp ├── Listing 4-5.cpp ├── Listing 4-6.cpp └── Listing 4-7.cpp ├── Chapter 5 - Floating-point Arithmetic ├── Listing 5-1.cpp ├── Listing 5-2.cpp └── Listing 5-3.cpp ├── Chapter 6 - New Features in C++20 └── FormatHeader.cpp ├── Chapter 9 - Elliptic-curve Cryptography ├── FFE_Engine.hpp ├── main.cpp └── main.exe ├── Contributing.md ├── LICENSE.txt ├── README.md └── errata.md /9781484265857.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/pro-cryptography-cryptanalysis-cpp20/462331a454e32be1c768c7aee079b335510adcef/9781484265857.jpg -------------------------------------------------------------------------------- /Chapter 10 - Lattice-based Cryptography/GGH_encryption.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "math.h" 3 | 4 | using namespace std; 5 | 6 | void encrypt(double message[100], double public_B[100][100], double error_vals[100], int dimension, double output_encrypted_text[100]); 7 | void decrypt(int dimension, double encrypted_message[100], double private_basis[100][100], double unimodular_matrix[100][100], double output_message[100]); 8 | double matrix_determinant(double square_matrix[100][100], int dimension); 9 | void matrix_inverse(double matrix[100][100], int dimension, double output_inverse[100][100]); 10 | void matrix_multiplication(double matrix1[100][100], double matrix2[100][100], double output[100][100], int dimension) ; 11 | void matrix_addition(double matrix1[100][100], double matrix2[100][100], double output_sum[100][100], int dimension); 12 | void get_cofactor(double matrix[100][100], double aux[100][100], int p, int q, int n); 13 | void adjoint_matrix(double matrix[100][100], double adjoint[100][100], int dimension); 14 | bool inverse_matrix(double matrix[100][100], double inv_matrix[100][100], int dimension); 15 | void vector_to_matrix(double v[100], int dimension, double output_matrix[100][100]); 16 | void matrix_to_vector(double matrix[100][100], double output_v[100], int dimension); 17 | void print_matrix(double matrix[100][100], int n, string message); 18 | void print_vector(double vect[100], int n, string message); 19 | void print_message(string message); 20 | 21 | int main() 22 | { 23 | int message_length = 2; 24 | 25 | double b[100][100] = {{17.0, 0.0}, {0.0, 19.0}}; // the private basis -> b 26 | double b_inverse[100][100]; 27 | 28 | inverse_matrix(b, b_inverse, message_length); 29 | 30 | double A[100][100] = {{2.0, 3.0}, {3.0, 5.0}}; // the private unimodular matrix -> A 31 | double A_inverse[100][100]; 32 | inverse_matrix(A, A_inverse, message_length); 33 | 34 | double B[100][100]; // the public key -> B 35 | matrix_multiplication(A, b, B, message_length); 36 | 37 | // Encryption 38 | double enc_message[100]; // stores the encryption of the message -> c 39 | double message[100] = {2, -5}; // the message -> m 40 | double error_vals[100] = {1, -1}; // the error values -> e 41 | 42 | print_vector(message, message_length, "message"); 43 | encrypt(message, B, error_vals, message_length, enc_message); 44 | print_vector(enc_message, message_length, "encrypted message"); 45 | 46 | // Decryption 47 | double recovered_message[100]; 48 | decrypt(message_length, enc_message, b, A, recovered_message); 49 | print_vector(recovered_message, message_length, "recovered message"); 50 | } 51 | 52 | // Auxiliary function that prints a matrix on the console 53 | void print_matrix(double matrix[100][100], int n, string message) 54 | { 55 | cout< aux_enc_message 94 | matrix_multiplication(aux_message, public_B, aux_enc_message, dimension); 95 | vector_to_matrix(error_vals, dimension, aux_error_vals); 96 | 97 | // Compute m∙B+e -> output_encrypted_text 98 | matrix_addition(aux_enc_message, aux_error_vals, aux_enc_message, dimension); 99 | matrix_to_vector(aux_enc_message, output_encrypted_text, dimension); 100 | } 101 | 102 | void decrypt(int dimension, double encrypted_message[100], double private_basis[100][100], double unimodular_matrix[100][100], double output_message[100]) 103 | { 104 | // (1) Compute c * (b^(-1)) 105 | // (2) Remove e * (b^(-1)) 106 | // (3) Compute m * A * (A^(-1)) 107 | double aux_enc_message[100][100], aux_message[100][100]; 108 | double recovered_message[100][100]; 109 | 110 | // Compute the inverse of the basis -> b_inverse 111 | double b_inverse[100][100]; 112 | inverse_matrix(private_basis, b_inverse, dimension); 113 | 114 | // Compute the inverse of the unimodular matrix -> A_inverse 115 | double A_inverse[100][100]; 116 | inverse_matrix(unimodular_matrix, A_inverse, dimension); 117 | 118 | // (1) Compute c * (b^(-1)) -> aux_enc_message 119 | vector_to_matrix(encrypted_message, dimension, aux_enc_message); 120 | matrix_multiplication(aux_enc_message, b_inverse, aux_message, dimension); 121 | 122 | // (2) Remove e * (b^(-1)) from aux_enc_message 123 | // Basically, the value aux_message[i][j] is rounded to the neareast integer 124 | for (int i=0; i<2; i++) 125 | { 126 | for (int j=0; j<2; j++) 127 | aux_message[i][j] = round(aux_message[i][j]); 128 | } 129 | 130 | // (3) Compute m * A * (A^(-1)) 131 | matrix_multiplication(aux_message, A_inverse, recovered_message, dimension); 132 | matrix_to_vector(recovered_message, output_message, dimension); 133 | } 134 | 135 | // Computes the matrix multiplication between two matrices 136 | void matrix_multiplication(double matrix1[100][100], double matrix2[100][100], double output[100][100], int dimension) 137 | { 138 | for (int i = 0; i < dimension; i++) 139 | { 140 | for (int j = 0; j < dimension; j++) 141 | { 142 | output[i][j] = 0; 143 | for (int k = 0; k < dimension; k++) 144 | output[i][j] += matrix1[i][k] * matrix2[k][j]; 145 | } 146 | } 147 | } 148 | 149 | // Computes the matrix sum between two matrices 150 | void matrix_addition(double matrix1[100][100], double matrix2[100][100], double output_sum[100][100], int dimension) 151 | { 152 | for(int i = 0; i < dimension; ++i) 153 | for(int j = 0; j < dimension; ++j) 154 | output_sum[i][j] = matrix1[i][j] + matrix2[i][j]; 155 | } 156 | 157 | // Computes the cofactor of the element matrix[p][q] 158 | void get_cofactor(double matrix[100][100], double aux[100][100], int p, int q, int n) 159 | { 160 | int i = 0, j = 0; 161 | 162 | for (int row = 0; row < n; row++) 163 | { 164 | for (int col = 0; col < n; col++) 165 | { 166 | if (row != p && col != q) 167 | { 168 | aux[i][j++] = matrix[row][col]; 169 | 170 | if (j == n - 1) 171 | { 172 | j = 0; 173 | i++; 174 | } 175 | } 176 | } 177 | } 178 | } 179 | 180 | // computes the determinant of a square matrix 181 | double matrix_determinant(double square_matrix[100][100], int dimension) 182 | { 183 | double matrix_det = 0.0; 184 | double aux_matrix[100][100]; 185 | 186 | if (dimension == 1) 187 | return square_matrix[0][0]; 188 | 189 | if (dimension == 2) 190 | return ((square_matrix[0][0] * square_matrix[1][1]) - (square_matrix[1][0] * square_matrix[0][1])); 191 | else 192 | { 193 | for (int k = 0; k < dimension; k++) { 194 | int aux_i = 0; 195 | for (int i = 1; i < dimension; i++) { 196 | int aux_j = 0; 197 | for (int j = 0; j < dimension; j++) { 198 | if (j == k) 199 | continue; 200 | aux_matrix[aux_i][aux_j] = square_matrix[i][j]; 201 | aux_j++; 202 | } 203 | aux_i++; 204 | } 205 | matrix_det = matrix_det + (pow(-1.0, k) * square_matrix[0][k] * matrix_determinant( aux_matrix, dimension - 1 )); 206 | } 207 | } 208 | return matrix_det; 209 | } 210 | 211 | // Computes the adjoint of a matrix 212 | void adjoint_matrix(double matrix[100][100], double adjoint[100][100], int dimension) 213 | { 214 | if (dimension == 1) 215 | { 216 | adjoint[0][0] = 1; 217 | return; 218 | } 219 | 220 | int sign = 1; 221 | double aux[100][100]; 222 | 223 | for (int i=0; i 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 16.0 23 | Win32Proj 24 | {f24a2a9f-0123-469b-a789-db53b06b8397} 25 | SealCPPExample 26 | 10.0 27 | 28 | 29 | 30 | Application 31 | true 32 | v142 33 | Unicode 34 | 35 | 36 | Application 37 | false 38 | v142 39 | true 40 | Unicode 41 | 42 | 43 | Application 44 | true 45 | v142 46 | Unicode 47 | 48 | 49 | Application 50 | false 51 | v142 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | true 75 | 76 | 77 | false 78 | 79 | 80 | true 81 | 82 | 83 | false 84 | 85 | 86 | 87 | Level3 88 | true 89 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 90 | true 91 | C:\libs\SEAL-master\native\src 92 | stdcpp17 93 | 94 | 95 | Console 96 | true 97 | C:\libs\SEAL-master\lib\$(Platform)\$(Configuration) 98 | seal.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 99 | 100 | 101 | 102 | 103 | Level3 104 | true 105 | true 106 | true 107 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 108 | true 109 | C:\libs\SEAL-master\native\src 110 | stdcpp17 111 | 112 | 113 | Console 114 | true 115 | true 116 | true 117 | C:\libs\SEAL-master\lib\$(Platform)\$(Configuration) 118 | seal.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 119 | 120 | 121 | 122 | 123 | Level3 124 | true 125 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 126 | true 127 | C:\libs\SEAL-master\native\src 128 | stdcpp17 129 | 130 | 131 | Console 132 | true 133 | C:\libs\SEAL-master\lib\$(Platform)\$(Configuration) 134 | seal.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 135 | 136 | 137 | 138 | 139 | Level3 140 | true 141 | true 142 | true 143 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 144 | true 145 | C:\libs\SEAL-master\native\src 146 | stdcpp17 147 | 148 | 149 | Console 150 | true 151 | true 152 | true 153 | C:\libs\SEAL-master\lib\$(Platform)\$(Configuration) 154 | seal.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | -------------------------------------------------------------------------------- /Chapter 12 - Homomorphic Encryption/SealCPPExample/SealCPPExample/SealCPPExample.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | -------------------------------------------------------------------------------- /Chapter 12 - Homomorphic Encryption/SealCPPExample/SealCPPExample/SealCPPExample.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /Chapter 12 - Homomorphic Encryption/SealCPPExample/SealCPPExample/SealExample.cpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "seal/seal.h" 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | using namespace std; 22 | using namespace seal; 23 | 24 | void seal_example_bfv() 25 | { 26 | EncryptionParameters BFV_parameters(scheme_type::BFV); 27 | 28 | size_t polynomial_degree = 4096; 29 | BFV_parameters.set_poly_modulus_degree(polynomial_degree); 30 | BFV_parameters.set_coeff_modulus(CoeffModulus::BFVDefault(polynomial_degree)); 31 | BFV_parameters.set_plain_modulus(1024); 32 | 33 | auto seal_context = SEALContext::Create(BFV_parameters); 34 | 35 | KeyGenerator keygen(seal_context); 36 | PublicKey encryption_key = keygen.public_key(); 37 | SecretKey decryption_key = keygen.secret_key(); 38 | Encryptor bfv_encrypt(seal_context, encryption_key); 39 | Evaluator bfv_evaluate(seal_context); 40 | Decryptor bfv_decrypt(seal_context, decryption_key); 41 | 42 | 43 | int value_x = 3; 44 | Plaintext x_plaintext(to_string(value_x)); 45 | cout << "The value x = " + to_string(value_x) + " is expressed as a plaintext polynomial 0x" + x_plaintext.to_string() + "." << endl; 46 | 47 | Ciphertext x_ciphertext; 48 | cout << "Encrypting x_plaintext to x_ciphertext..." << endl; 49 | bfv_encrypt.encrypt(x_plaintext, x_ciphertext); 50 | 51 | cout << " - the size of the x_ciphertext (freshly encrypted) is : " << x_ciphertext.size() << endl; 52 | cout << " - the noise budget for x_ciphertext is : " << bfv_decrypt.invariant_noise_budget(x_ciphertext) << " bits" 53 | << endl; 54 | 55 | Plaintext value_x_decrypted; 56 | cout << " - decryption of x_encrypted: "; 57 | bfv_decrypt.decrypt(x_ciphertext, value_x_decrypted); 58 | cout << "0x" << value_x_decrypted.to_string() << endl; 59 | 60 | cout << "Computing (x^2+2)..." << endl; 61 | Ciphertext square_x_plus_two; 62 | bfv_evaluate.square(x_ciphertext, square_x_plus_two); 63 | Plaintext plain_value_two("2"); 64 | bfv_evaluate.add_plain_inplace(square_x_plus_two, plain_value_two); 65 | 66 | cout << " - the size of the square_x_plus_two is: " << square_x_plus_two.size() << endl; 67 | cout << " - the noise budget for square_x_plus_two is: " << bfv_decrypt.invariant_noise_budget(square_x_plus_two) << " bits" 68 | << endl; 69 | 70 | Plaintext decrypted_result; 71 | cout << " - decryption of square_x_plus_two: "; 72 | bfv_decrypt.decrypt(square_x_plus_two, decrypted_result); 73 | cout << "0x" << decrypted_result.to_string() << endl; 74 | 75 | 76 | cout << "Computing (x+1)^2..." << endl; 77 | Ciphertext x_plus_one_square; 78 | Plaintext plain_value_one("1"); 79 | bfv_evaluate.add_plain(x_ciphertext, plain_value_one, x_plus_one_square); 80 | bfv_evaluate.square_inplace(x_plus_one_square); 81 | cout << " - the size of x_plus_one_square is: " << x_plus_one_square.size() << endl; 82 | cout << " - the noise budget in x_plus_one_square is: " << bfv_decrypt.invariant_noise_budget(x_plus_one_square) << " bits" 83 | << endl; 84 | cout << " - decryption of x_plus_one_square: "; 85 | bfv_decrypt.decrypt(x_plus_one_square, decrypted_result); 86 | cout << "0x" << decrypted_result.to_string() << endl; 87 | 88 | 89 | cout << "Compute [3(x^2+2)(x+1)^2]." << endl; 90 | Ciphertext enc_result; 91 | Plaintext plain_value_three("3"); 92 | bfv_evaluate.multiply_plain_inplace(square_x_plus_two, plain_value_three); 93 | bfv_evaluate.multiply(square_x_plus_two, x_plus_one_square, enc_result); 94 | cout << " - the size of encrypted_result: " << enc_result.size() << endl; 95 | cout << " - the noise budget for encrypted_result: " << bfv_decrypt.invariant_noise_budget(enc_result) << " bits" 96 | << endl; 97 | cout << "NOTE: If the noise budget is zero, the decryption can be incorrect." << endl; 98 | cout << " - decryption of enc_result: "; 99 | bfv_decrypt.decrypt(enc_result, decrypted_result); 100 | cout << "0x" << decrypted_result.to_string() << endl; 101 | } 102 | 103 | int main() 104 | { 105 | seal_example_bfv(); 106 | return 0; 107 | } -------------------------------------------------------------------------------- /Chapter 12 - Homomorphic Encryption/SealCPPExample/SealCPPExample/x64/Release/SealCPPExample.Build.CppClean.log: -------------------------------------------------------------------------------- 1 | c:\users\stefania\source\repos\sealcppexample\sealcppexample\x64\release\vc142.pdb 2 | c:\users\stefania\source\repos\sealcppexample\sealcppexample\x64\release\sealexample.obj 3 | c:\users\stefania\source\repos\sealcppexample\x64\release\sealcppexample.exe 4 | c:\users\stefania\source\repos\sealcppexample\x64\release\sealcppexample.pdb 5 | c:\users\stefania\source\repos\sealcppexample\x64\release\sealcppexample.ipdb 6 | c:\users\stefania\source\repos\sealcppexample\x64\release\sealcppexample.iobj 7 | c:\users\stefania\source\repos\sealcppexample\sealcppexample\x64\release\sealcppexample.tlog\cl.command.1.tlog 8 | c:\users\stefania\source\repos\sealcppexample\sealcppexample\x64\release\sealcppexample.tlog\cl.read.1.tlog 9 | c:\users\stefania\source\repos\sealcppexample\sealcppexample\x64\release\sealcppexample.tlog\cl.write.1.tlog 10 | c:\users\stefania\source\repos\sealcppexample\sealcppexample\x64\release\sealcppexample.tlog\link.command.1.tlog 11 | c:\users\stefania\source\repos\sealcppexample\sealcppexample\x64\release\sealcppexample.tlog\link.read.1.tlog 12 | c:\users\stefania\source\repos\sealcppexample\sealcppexample\x64\release\sealcppexample.tlog\link.write.1.tlog 13 | c:\users\stefania\source\repos\sealcppexample\sealcppexample\x64\release\sealcppexample.tlog\sealcppexample.write.1u.tlog 14 | -------------------------------------------------------------------------------- /Chapter 12 - Homomorphic Encryption/SealCPPExample/SealCPPExample/x64/Release/SealCPPExample.log: -------------------------------------------------------------------------------- 1 |  SealExample.cpp 2 | Generating code 3 | 1 of 3694 functions (<0.1%) were compiled, the rest were copied from previous compilation. 4 | 0 functions were new in current compilation 5 | 7 functions had inline decision re-evaluated but remain unchanged 6 | Finished generating code 7 | SealCPPExample.vcxproj -> C:\Users\Stefania\source\repos\SealCPPExample\x64\Release\SealCPPExample.exe 8 | -------------------------------------------------------------------------------- /Chapter 12 - Homomorphic Encryption/SealCPPExample/SealCPPExample/x64/Release/SealCPPExample.tlog/CL.command.1.tlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/pro-cryptography-cryptanalysis-cpp20/462331a454e32be1c768c7aee079b335510adcef/Chapter 12 - Homomorphic Encryption/SealCPPExample/SealCPPExample/x64/Release/SealCPPExample.tlog/CL.command.1.tlog -------------------------------------------------------------------------------- /Chapter 12 - Homomorphic Encryption/SealCPPExample/SealCPPExample/x64/Release/SealCPPExample.tlog/CL.read.1.tlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/pro-cryptography-cryptanalysis-cpp20/462331a454e32be1c768c7aee079b335510adcef/Chapter 12 - Homomorphic Encryption/SealCPPExample/SealCPPExample/x64/Release/SealCPPExample.tlog/CL.read.1.tlog -------------------------------------------------------------------------------- /Chapter 12 - Homomorphic Encryption/SealCPPExample/SealCPPExample/x64/Release/SealCPPExample.tlog/CL.write.1.tlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/pro-cryptography-cryptanalysis-cpp20/462331a454e32be1c768c7aee079b335510adcef/Chapter 12 - Homomorphic Encryption/SealCPPExample/SealCPPExample/x64/Release/SealCPPExample.tlog/CL.write.1.tlog -------------------------------------------------------------------------------- /Chapter 12 - Homomorphic Encryption/SealCPPExample/SealCPPExample/x64/Release/SealCPPExample.tlog/SealCPPExample.lastbuildstate: -------------------------------------------------------------------------------- 1 | PlatformToolSet=v142:VCToolArchitecture=Native32Bit:VCToolsVersion=14.26.28801:TargetPlatformVersion=10.0.18362.0: 2 | Release|x64|C:\Users\Stefania\source\repos\SealCPPExample\| 3 | -------------------------------------------------------------------------------- /Chapter 12 - Homomorphic Encryption/SealCPPExample/SealCPPExample/x64/Release/SealCPPExample.tlog/SealCPPExample.write.1u.tlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/pro-cryptography-cryptanalysis-cpp20/462331a454e32be1c768c7aee079b335510adcef/Chapter 12 - Homomorphic Encryption/SealCPPExample/SealCPPExample/x64/Release/SealCPPExample.tlog/SealCPPExample.write.1u.tlog -------------------------------------------------------------------------------- /Chapter 12 - Homomorphic Encryption/SealCPPExample/SealCPPExample/x64/Release/SealCPPExample.tlog/link.command.1.tlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/pro-cryptography-cryptanalysis-cpp20/462331a454e32be1c768c7aee079b335510adcef/Chapter 12 - Homomorphic Encryption/SealCPPExample/SealCPPExample/x64/Release/SealCPPExample.tlog/link.command.1.tlog -------------------------------------------------------------------------------- /Chapter 12 - Homomorphic Encryption/SealCPPExample/SealCPPExample/x64/Release/SealCPPExample.tlog/link.read.1.tlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/pro-cryptography-cryptanalysis-cpp20/462331a454e32be1c768c7aee079b335510adcef/Chapter 12 - Homomorphic Encryption/SealCPPExample/SealCPPExample/x64/Release/SealCPPExample.tlog/link.read.1.tlog -------------------------------------------------------------------------------- /Chapter 12 - Homomorphic Encryption/SealCPPExample/SealCPPExample/x64/Release/SealCPPExample.tlog/link.write.1.tlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/pro-cryptography-cryptanalysis-cpp20/462331a454e32be1c768c7aee079b335510adcef/Chapter 12 - Homomorphic Encryption/SealCPPExample/SealCPPExample/x64/Release/SealCPPExample.tlog/link.write.1.tlog -------------------------------------------------------------------------------- /Chapter 12 - Homomorphic Encryption/SealCPPExample/SealCPPExample/x64/Release/SealCPPExample.vcxproj.FileListAbsolute.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/pro-cryptography-cryptanalysis-cpp20/462331a454e32be1c768c7aee079b335510adcef/Chapter 12 - Homomorphic Encryption/SealCPPExample/SealCPPExample/x64/Release/SealCPPExample.vcxproj.FileListAbsolute.txt -------------------------------------------------------------------------------- /Chapter 12 - Homomorphic Encryption/SealCPPExample/SealCPPExample/x64/Release/SealExample.obj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/pro-cryptography-cryptanalysis-cpp20/462331a454e32be1c768c7aee079b335510adcef/Chapter 12 - Homomorphic Encryption/SealCPPExample/SealCPPExample/x64/Release/SealExample.obj -------------------------------------------------------------------------------- /Chapter 12 - Homomorphic Encryption/SealCPPExample/SealCPPExample/x64/Release/vc142.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/pro-cryptography-cryptanalysis-cpp20/462331a454e32be1c768c7aee079b335510adcef/Chapter 12 - Homomorphic Encryption/SealCPPExample/SealCPPExample/x64/Release/vc142.pdb -------------------------------------------------------------------------------- /Chapter 12 - Homomorphic Encryption/SealCPPExample/x64/Release/SealCPPExample.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/pro-cryptography-cryptanalysis-cpp20/462331a454e32be1c768c7aee079b335510adcef/Chapter 12 - Homomorphic Encryption/SealCPPExample/x64/Release/SealCPPExample.exe -------------------------------------------------------------------------------- /Chapter 12 - Homomorphic Encryption/SealCPPExample/x64/Release/SealCPPExample.iobj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/pro-cryptography-cryptanalysis-cpp20/462331a454e32be1c768c7aee079b335510adcef/Chapter 12 - Homomorphic Encryption/SealCPPExample/x64/Release/SealCPPExample.iobj -------------------------------------------------------------------------------- /Chapter 12 - Homomorphic Encryption/SealCPPExample/x64/Release/SealCPPExample.ipdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/pro-cryptography-cryptanalysis-cpp20/462331a454e32be1c768c7aee079b335510adcef/Chapter 12 - Homomorphic Encryption/SealCPPExample/x64/Release/SealCPPExample.ipdb -------------------------------------------------------------------------------- /Chapter 12 - Homomorphic Encryption/SealCPPExample/x64/Release/SealCPPExample.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/pro-cryptography-cryptanalysis-cpp20/462331a454e32be1c768c7aee079b335510adcef/Chapter 12 - Homomorphic Encryption/SealCPPExample/x64/Release/SealCPPExample.pdb -------------------------------------------------------------------------------- /Chapter 13 - (Ring) Learning with Errors Cryptography/LWE_Example.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | int main() 7 | { 8 | srand(time(0)); 9 | 10 | int numberOfRandVals = 20; 11 | int values_A [20]; //** values_A is a set of random numbers; represents the public key 12 | int secretValue = 5; //** represents the secret key 13 | int values_error [numberOfRandVals]; //** represents the error values 14 | int values_B [numberOfRandVals]; //** values_B is computed based on values_A, secretValue, values_error; represents the public key 15 | 16 | int q = 97; //** q is a prime number 17 | 18 | //** generate random values 19 | //** the number of random values is numberOfRandVals = 20 20 | //** the range is 0 - q=97 21 | for(int i=0; i < numberOfRandVals; i++) 22 | { 23 | //** to generate a random value in a range MIN - MAX, 24 | //** we proceed as folloes: val = rand() % (MAX + 1 - MIN) + MIN; 25 | 26 | //** generate random values between 0 - 97 27 | values_A[i] = rand() % (q + 1 - 0) + 0; 28 | //** generate small error values, between 1 - 4 29 | values_error[i] = rand() % (4 + 1 - 1) + 1; 30 | //** compute values_B using the formula B_i = A_i*s + e_i 31 | values_B[i] = values_A[i]*secretValue + values_error[i]; 32 | } 33 | 34 | cout<<"--------- The parameters and the keys ---------" << endl; 35 | cout<<"--Prime number (q)--" << endl; 36 | cout<<"q = " << q << endl; 37 | cout<<"--Public key (A, B)--" << endl; 38 | cout<<"A = [ "; 39 | for (int i=0; i < numberOfRandVals; i++) 40 | { 41 | cout << values_A[i] << " "; 42 | } 43 | cout<<"]" << endl; 44 | 45 | cout<<"B = [ "; 46 | for (int i=0; i < numberOfRandVals; i++) 47 | { 48 | cout << values_B[i] << " "; 49 | } 50 | cout<<"]" << endl; 51 | cout<<"--Secret key (s)--" << endl; 52 | cout<<"s = " << secretValue << endl; 53 | cout<<"--Random error (e)--" << endl; 54 | cout<<"e = [ "; 55 | for (int i=0; i < numberOfRandVals; i++) 56 | { 57 | cout << values_error[i] << " "; 58 | } 59 | cout<<"]" << endl; 60 | 61 | cout<< endl << endl << "--------- Getting samples from the public key... ---------"; 62 | int noOfSamples = floor(numberOfRandVals / 4); //** represents the number of samples from the public key 63 | int samples [noOfSamples]; 64 | for(int i=0; i < noOfSamples; i++) 65 | { 66 | //** generate a number of 5 random indices between 0 and 19 67 | samples[i] = rand() % ((numberOfRandVals-1) + 1 - 0) + 0; 68 | } 69 | cout< q/2) 114 | decryption = 1; 115 | else 116 | decryption = 0; 117 | cout< 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | int main() 7 | { 8 | srand(time(0)); 9 | 10 | int no_of_values = 10; 11 | int public_key [no_of_values]; 12 | int values [no_of_values]; 13 | int secret_key = 5; 14 | int error_value = 12; 15 | int message = 1; 16 | 17 | int value = 0; 18 | 19 | for (int i = 0; i < no_of_values; i++) 20 | { 21 | //** generate random values between 0 and 23 22 | values[i] = rand() % (23 + 1 - 0) + 0; 23 | //** compute the public key 24 | public_key[i] = values[i] * secret_key + error_value; 25 | } 26 | 27 | cout<<"--Message: "<< message<<"--"; 28 | cout< 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | using namespace std; 14 | 15 | const size_t MESSAGE_LENGTH = 2000000000; 16 | 17 | uint64_t generateStringOfBytes() 18 | { 19 | int folder = 0; 20 | ssize_t resourceFile = 0; 21 | uint64_t buffer = 0; 22 | 23 | if((folder = open("D:/Apps C++/Chapter 14 - Chaos-based Cryptography/ChaosSecureRandomNumberGenerator/dev/urandom", O_RDONLY)) == -1) 24 | exit(-1); 25 | 26 | if((resourceFile = read(folder, &buffer, sizeof buffer)) < 0) 27 | exit(-1); 28 | 29 | buffer &= ((1ULL << 53) - 1); 30 | close(folder); 31 | return buffer; 32 | } 33 | 34 | int main(void) 35 | { 36 | struct generation gen; 37 | uint64_t key[3] = {generateStringOfBytes()+rand()%3000, generateStringOfBytes()+rand()%5000, generateStringOfBytes()+rand()%8000}; 38 | cout<<"Key 1 -> "< "< "< 5 | 6 | using namespace std; 7 | 8 | // performing the encryption operation 9 | void encryption(struct generation *g, uint8_t *buffer, size_t length) 10 | { 11 | uint32_t position_in_stream; 12 | size_t number_of_calls = length >> 2; 13 | size_t l_neighbour = length & 3; 14 | uint8_t *temporary = (uint8_t *)&position_in_stream; 15 | 16 | for(size_t index = 0; index < number_of_calls; ++index) 17 | { 18 | position_in_stream = generation32(g); 19 | buffer[(index<<2)] ^= temporary[0]; 20 | buffer[(index<<2)+1] ^= temporary[1]; 21 | buffer[(index<<2)+2] ^= temporary[2]; 22 | buffer[(index<<2)+3] ^= temporary[3]; 23 | } 24 | 25 | if(l_neighbour != 0) 26 | { 27 | position_in_stream = generation32(g); 28 | for(size_t index = 0; index < l_neighbour; ++index) 29 | buffer[(number_of_calls<<2)+index] ^= temporary[index]; 30 | } 31 | 32 | std::cout<<"The position with the stream is -> "< 6 | 7 | void encryption(struct generation *g, uint8_t *buffer, size_t length); 8 | 9 | #endif -------------------------------------------------------------------------------- /Chapter 14 - Chaos-based Cryptography/ChaosSecureRandomNumberGenerator/generation.c: -------------------------------------------------------------------------------- 1 | #include "generation.h" 2 | 3 | static void initialization(struct generation *gen, double initValueX, double initValueY, double initValueZ) 4 | { 5 | gen->x.d = initValueX; 6 | gen->y.d = initValueY; 7 | gen->z.d = initValueZ; 8 | } 9 | 10 | static void perform_iteration(struct generation *gen) 11 | { 12 | gen->x.d = gen->x.d + APPROXIMATION * (-gen->y.d - gen->z.d); 13 | gen->y.d = gen->y.d + APPROXIMATION * (gen->x.d + A_Coordinate * gen->y.d); 14 | gen->z.d = gen->z.d + APPROXIMATION * (B_Coordinate + gen->z.d * (gen->x.d - C_Coordinate)); 15 | } 16 | 17 | void generation_initialization(struct generation *gen, uint64_t keyValue[3]) 18 | { 19 | initialization(gen, 20 | (double)keyValue[0] / 9007199254740992, 21 | (double)keyValue[1] / 8674747684896687, 22 | (double)keyValue[2] / 6758675765879568); 23 | 24 | for(uint8_t index = 0; index < REMOVE_NOISE - 1; ++index) 25 | perform_iteration(gen); 26 | } 27 | 28 | uint32_t generation32(struct generation *gen) 29 | { 30 | uint32_t message[6]; 31 | message[0] = (uint32_t)(gen->x.rb.mantisa >> 32); 32 | message[1] = (uint32_t)(gen->x.rb.mantisa); 33 | message[2] = (uint32_t)(gen->y.rb.mantisa >> 32); 34 | message[3] = (uint32_t)(gen->y.rb.mantisa); 35 | message[4] = (uint32_t)(gen->z.rb.mantisa >> 32); 36 | message[5] = (uint32_t)(gen->z.rb.mantisa); 37 | perform_iteration(gen); 38 | 39 | message[0] += message[1]; 40 | message[2] += message[3]; 41 | message[4] += message[5]; 42 | 43 | for(uint8_t index = 0; index < 4; ++index) 44 | { 45 | ROSSLER(message[0],7); ROSSLER(message[3],13); 46 | message[5] ^= (message[4] + message[3]); 47 | message[1] ^= (message[2] + message[0]); 48 | message[2] = message[2] ^ message[0] ^ message[5]; 49 | message[4] = message[4] ^ message[3] ^ message[1]; 50 | } 51 | 52 | message[2] += message[4]; 53 | return message[2]; 54 | } -------------------------------------------------------------------------------- /Chapter 14 - Chaos-based Cryptography/ChaosSecureRandomNumberGenerator/generation.h: -------------------------------------------------------------------------------- 1 | #ifndef GENERATION_H 2 | #define GENERATION_H 3 | 4 | #include 5 | #include 6 | 7 | // the Rossler (ROL) attractor definition for plane (x,n) 8 | #define ROSSLER(x,n) ((x = ((x << n) | (x >> (32 - n))))) 9 | 10 | // the attractor variables (coordinates) - for this example Rossler is chosen 11 | #define A_Coordinate 0.5273 12 | #define B_Coordinate 3 13 | #define C_Coordinate 6 14 | 15 | // constant for integral approximation as a step size 16 | #define APPROXIMATION 0.01 17 | 18 | // constant used for removing the initial noise 19 | #define REMOVE_NOISE 64 20 | 21 | void generation_initialization(struct generation *g, uint64_t k[3]); 22 | uint32_t generation32(struct generation *g); 23 | 24 | // the normalization form of a real number 25 | union realbits 26 | { 27 | double d; 28 | struct 29 | { 30 | uint64_t mantisa: 52; 31 | uint64_t exponent: 11; 32 | uint64_t sign: 1; 33 | } rb; 34 | }; 35 | 36 | struct generation 37 | { 38 | union realbits x, y, z; 39 | }; 40 | 41 | #endif -------------------------------------------------------------------------------- /Chapter 14 - Chaos-based Cryptography/ChaosSecureRandomNumberGenerator/test.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/pro-cryptography-cryptanalysis-cpp20/462331a454e32be1c768c7aee079b335510adcef/Chapter 14 - Chaos-based Cryptography/ChaosSecureRandomNumberGenerator/test.exe -------------------------------------------------------------------------------- /Chapter 14 - Chaos-based Cryptography/CipherBasedOnFractals/FractalCipherCrypto.cpp: -------------------------------------------------------------------------------- 1 | #include "FractalCipherCrypto.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | // implementing bitCodeEncryptedMessageA from FractalCipherCrypto.h file 10 | unsigned int CryptoFractalCipher::bitCodeEncryptedMessageA(unsigned int bit_from_plaintext) 11 | { 12 | // below we will create a cryptographic strem from the clear stream 13 | int crypto_bit=0; 14 | { 15 | identifyFirstRoot(); 16 | 17 | // quadratic value 18 | unsigned long quadraticValue = PerformProjectionFor_X(z_yCoordinatePoint); 19 | 20 | // Do the encoding process and provide the 21 | // cryptographic stream from the clear stream 22 | // Variables used: 23 | // - iV: the input value 24 | // - oV: the output value 25 | // - rV: the route value in the expansion of the fractal 26 | unsigned int iV, oV, rV; 27 | { 28 | unsigned int result1, result2, result3; 29 | iV=(bit_from_plaintext) & 1; 30 | 31 | // obtained from the iteration of the quadratic value 32 | result1=quadraticValue; 33 | 34 | // input value 35 | result2=iV; 36 | 37 | // we will copy the bits if it is set in one operand but not both 38 | result3=result1^result2; 39 | 40 | // the final output value 41 | oV=result3; 42 | 43 | // the route value that need to be followed within the expansion of the fractal 44 | rV=result2; 45 | } 46 | crypto_bit=(oV); 47 | 48 | if ((rV) != 0) 49 | { 50 | // use the route on the second root point 51 | z_xCoordinatePoint=-z_xCoordinatePoint; 52 | z_yCoordinatePoint=-z_yCoordinatePoint; 53 | } 54 | } 55 | return crypto_bit; 56 | }; 57 | 58 | unsigned int CryptoFractalCipher::bitCodeDecryptedMessageB(unsigned int bit_from_encoding) 59 | { 60 | // decode the clear value from the cryptographic stream 61 | int bit_from_plaintext=0; 62 | { 63 | identifyFirstRoot(); 64 | 65 | // computing the quadratic value 66 | unsigned long quadraticValue = PerformProjectionFor_X(z_yCoordinatePoint); 67 | 68 | // decoding process for obtaining the clearstream from the cryptographic stream 69 | // Variables used: 70 | // - iV: the input value 71 | // - oV: the output value 72 | // - rV: the route value in the expansion of the fractal 73 | unsigned int iV, oV, rV; 74 | { 75 | unsigned int result1,result2,result3; 76 | 77 | iV=(bit_from_encoding) & 1; 78 | 79 | // obtained from the iteration of the quadratic value 80 | result1=quadraticValue & 1; 81 | 82 | // input value 83 | result3=iV; 84 | 85 | // we will copy the bits if it is set in one operand but not both 86 | result2=result1^result3; 87 | 88 | // the output value 89 | oV=result2; 90 | 91 | // the route value that need to be followed within the expansion of the fractal 92 | rV=result2; 93 | } 94 | bit_from_plaintext=(oV); 95 | 96 | if ((rV) != 0) 97 | { 98 | // use the route on the second root point 99 | z_xCoordinatePoint=-z_xCoordinatePoint; 100 | z_yCoordinatePoint=-z_yCoordinatePoint; 101 | } 102 | } 103 | return bit_from_plaintext; 104 | }; 105 | 106 | unsigned int CryptoFractalCipher::bitCodeEncryptedMessageC(unsigned int bit_from_stream) 107 | { 108 | // generate the cryptographic stream from the clear stream 109 | int bit_from_coding=0; 110 | { 111 | identifyFirstRoot(); 112 | 113 | unsigned long quadraticValueForY = PerformProjectionFor_X(z_yCoordinatePoint); 114 | unsigned long quadraticValueForX = PerformProjectionFor_X(z_xCoordinatePoint); 115 | 116 | // encoding process 117 | unsigned int iV, oV, rV; 118 | 119 | { unsigned int result1, result2, result3, result4; 120 | iV=(bit_from_stream); 121 | 122 | // from the iteration of the 'y' quadratic 123 | result1=quadraticValueForY; 124 | 125 | // from the iteration of the 'x' quadratic 126 | result2=quadraticValueForX; 127 | 128 | // we will copy the bits if it is set in one operand but not both 129 | result3=iV^result1; 130 | result4=iV^result2; 131 | 132 | // the output value 133 | oV=result3; 134 | rV=result4; // branch in path to follow through IIM 135 | } 136 | bit_from_coding=(oV); 137 | 138 | if ((rV) != 0) 139 | { 140 | // use the route on the second root point 141 | z_xCoordinatePoint=-z_xCoordinatePoint; 142 | z_yCoordinatePoint=-z_yCoordinatePoint; 143 | } 144 | } 145 | return bit_from_coding; 146 | }; 147 | 148 | unsigned int CryptoFractalCipher::bitCodeDecryptedMessageD(unsigned int bit_from_stream) 149 | { 150 | // generate the cryptographic stream from the clear stream 151 | int bit_from_coding = 0; 152 | { 153 | identifyFirstRoot(); 154 | 155 | unsigned long quadraticValueForY = PerformProjectionFor_X(z_yCoordinatePoint); 156 | unsigned long quadraticValueForX = PerformProjectionFor_X(z_xCoordinatePoint); 157 | 158 | // encoding process 159 | unsigned int iV, oV, rV; 160 | { 161 | unsigned int result1, result2, result3, result4; 162 | iV=(bit_from_stream) & 1; 163 | 164 | // from iterated quadratic y and x 165 | result1=quadraticValueForY; 166 | result2=quadraticValueForX; 167 | 168 | // we will copy the bits if it is set in one operand but not both 169 | result3=iV^result1; 170 | result4=result3^result2; 171 | 172 | // output value 173 | oV=result3; 174 | 175 | // the route value 176 | rV=result4; 177 | } 178 | bit_from_coding=(oV); 179 | 180 | if ((rV) != 0) 181 | { //take branch to second root 182 | z_xCoordinatePoint=-z_xCoordinatePoint; 183 | z_yCoordinatePoint=-z_yCoordinatePoint; 184 | } 185 | } 186 | return bit_from_coding; 187 | }; 188 | 189 | unsigned int CryptoFractalCipher::getEncryptedMessageA(unsigned int clearstream) 190 | { 191 | // for creating the cryptographic stream from the clear stream 192 | int cryptographic_stream=0; 193 | 194 | for (int iterationIndex=0; iterationIndex<32; (iterationIndex++)) 195 | { 196 | 197 | // encoding process for obtaining cryptographic stream from clear stream 198 | unsigned int iV,oV; 199 | iV=(clearstream>>iterationIndex) & 1; 200 | oV=bitCodeEncryptedMessageA(iV); 201 | cryptographic_stream+=((oV)<>iterationIndex) & 1; 218 | oV=bitCodeDecryptedMessageB(iV); 219 | clearstream+=((oV)<>iterationIndex) & 1; 235 | oV=bitCodeEncryptedMessageC(iV); 236 | cV+=((oV)<>iterationIndex) & 1; 252 | oV=bitCodeDecryptedMessageD(iV); 253 | cV+=((oV)< First Method (A) = "< Second Method (B) = "< A with B = "< B with A = "< 5 | #include 6 | #include 7 | 8 | class CryptoFractalCipher 9 | { 10 | // point C = (x, y) - the representation in the xOy system of point C 11 | double c_xCoordinatePoint, c_yCoordinatePoint; 12 | 13 | // point Z = (x,y) - the representation in the xOy system of point Z 14 | double z_xCoordinatePoint, z_yCoordinatePoint; //Zx,Zy; 15 | 16 | // get the sign of a double number 17 | inline double getSign(double number) 18 | { 19 | // in case that d is less than 0, return -1.0, making the number negative 20 | // contrary make the number positive 21 | if (number<0) 22 | return(-1.0); 23 | else 24 | return(1.0); 25 | }; 26 | 27 | // Value 'yValue' will be projected over an integer matrix or grid. 28 | // We have choose this for achieving the scaling goal and performing tests. 29 | // The projection process is a matter of personal choice, any other idea or 30 | // solution can be implemented by reader. 31 | inline unsigned int PerformProjectionFor_Y(double yValue) 32 | { 33 | unsigned long q; 34 | const double scale=(32768.0/2.0); 35 | const double offset=(32768.0); 36 | 37 | // do the projection as a positive integerproject to positive integer 38 | q=(yValue*scale)+offset; 39 | 40 | //getting the LSB (least significant bit) 41 | q&=1; 42 | return q; 43 | } 44 | 45 | // Value 'xValue' will be projected over an integer matrix or grid. 46 | // We have choose this for achieving the scaling goal and performing tests. 47 | // The projection process is a matter of personal choice, any other idea or 48 | // solution can be implemented by reader. 49 | inline unsigned int PerformProjectionFor_X(double xValue) 50 | { 51 | // used for storing the decomposition value 52 | double decompositionValue; 53 | 54 | // power value (exponent) 55 | int n; 56 | 57 | // with frexp() we will decompose the double point (xValue) as 58 | // argument into a normalized fraction and an integral power 59 | decompositionValue = frexp (xValue , &n); 60 | 61 | // with ldexp() we will return the result of multiplying 'decompositionValue' 62 | // (the significand) with 2 and raised to the power '51' (exponent) 63 | decompositionValue = ldexp(decompositionValue,51); 64 | 65 | // Test if the difference between 'decompositionValue' and 66 | // floor(decompositionValue) is less than 0.5 67 | // if yes return '1', otherwise '0'. 68 | // With floor() we round 'decompositionValue', returning the largest 69 | // integral value that is not greater than 'decompositionValue' 70 | return (((decompositionValue-floor(decompositionValue))<0.5)?1:0); 71 | } 72 | 73 | inline void identifyFirstRoot() 74 | { 75 | /* Zn*Zn=Z(n+1)-c */ 76 | z_xCoordinatePoint=z_xCoordinatePoint-c_xCoordinatePoint; 77 | z_yCoordinatePoint=z_yCoordinatePoint-c_yCoordinatePoint; 78 | 79 | // r represents the length of the vector from the origin to the point 80 | // r = |z| = sqrt(x*x+y*y) 81 | double r; 82 | 83 | // the new point z = (x,y) 84 | double z_xNewPointValue, z_yNewPointValue; //NewZx, NewZy 85 | r=sqrt(z_xCoordinatePoint*z_xCoordinatePoint+z_yCoordinatePoint*z_yCoordinatePoint); 86 | 87 | // the below code sequence represents the implementation of the algorithm presented in [17], from page 361 to 362. 88 | // case 1: z>0 89 | if (z_xCoordinatePoint>0) 90 | { 91 | z_xNewPointValue=sqrt(0.5*(z_xCoordinatePoint+r)); 92 | z_yNewPointValue=z_yCoordinatePoint/(2*z_xNewPointValue); 93 | } 94 | 95 | // for cases when z<0 and z=0 96 | else 97 | { 98 | // case 2: z<0 99 | if (z_xCoordinatePoint<0) 100 | { 101 | z_yNewPointValue=getSign(z_yCoordinatePoint)*sqrt(0.5*(-z_xCoordinatePoint+r)); 102 | z_xNewPointValue=z_yCoordinatePoint/(2*z_yNewPointValue); 103 | } 104 | 105 | //case 3: z=0 106 | else 107 | { 108 | z_xNewPointValue=sqrt(0.5*fabs(z_yCoordinatePoint)); 109 | if (z_xNewPointValue>0) z_yNewPointValue=z_yCoordinatePoint/(2*z_xNewPointValue); 110 | else z_yNewPointValue=0; 111 | } 112 | }; 113 | // end of the implementation 114 | 115 | // the values for x and y coordinates 116 | z_xCoordinatePoint=z_xNewPointValue; 117 | z_yCoordinatePoint=z_yNewPointValue; 118 | }; 119 | 120 | public: 121 | // gets the encrypted value 122 | unsigned int getEncryptedMessageA(unsigned int plainValue); 123 | unsigned int getDecryptedMessageB(unsigned int encryptedValue); 124 | unsigned int getEncryptedMessageC(unsigned int stream); 125 | unsigned int getDecryptedMessageD(unsigned int stream); 126 | 127 | // gets the single bit 128 | unsigned int bitCodeEncryptedMessageA(unsigned int plainValue); 129 | unsigned int bitCodeDecryptedMessageB(unsigned int encryptedValue); 130 | unsigned int bitCodeEncryptedMessageC(unsigned int stream); 131 | unsigned int bitCodeDecryptedMessageD(unsigned int stream); 132 | 133 | // constructor 134 | CryptoFractalCipher(double cx,double cy); 135 | 136 | // destructor 137 | virtual ~CryptoFractalCipher(); 138 | }; 139 | #endif -------------------------------------------------------------------------------- /Chapter 14 - Chaos-based Cryptography/CipherBasedOnFractals/test.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/pro-cryptography-cryptanalysis-cpp20/462331a454e32be1c768c7aee079b335510adcef/Chapter 14 - Chaos-based Cryptography/CipherBasedOnFractals/test.exe -------------------------------------------------------------------------------- /Chapter 15 - Big Data Cryptography/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "tree.h" 3 | 4 | using namespace std; 5 | 6 | 7 | int main() { 8 | vector nodes_set; 9 | 10 | //create sample data 11 | nodes_set.push_back(new tree_node(compute_sha256("Merkle "))); 12 | nodes_set.push_back(new tree_node(compute_sha256("tree "))); 13 | nodes_set.push_back(new tree_node(compute_sha256("node "))); 14 | nodes_set.push_back(new tree_node(compute_sha256("example."))); 15 | nodes_set.push_back(new tree_node(compute_sha256("This is an example of merkle tree."))); 16 | 17 | // initialize leaves 18 | for (unsigned int i = 0; i < nodes_set.size(); i++) { 19 | nodes_set[i]->l_neighbour = NULL; 20 | nodes_set[i]->r_neighbour = NULL; 21 | } 22 | 23 | merkle_tree *hash_tree = new merkle_tree(nodes_set); 24 | std::cout << hash_tree->tree_root->hash_value << std::endl; 25 | hash_tree->print_merkle_tree(hash_tree->tree_root, 0); 26 | 27 | for (int k = 0; k < nodes_set.size(); k++) { 28 | delete nodes_set[k]; 29 | } 30 | 31 | delete hash_tree; 32 | 33 | return 0; 34 | } -------------------------------------------------------------------------------- /Chapter 15 - Big Data Cryptography/picosha2.h: -------------------------------------------------------------------------------- 1 | /* 2 | The MIT License (MIT) 3 | Copyright (C) 2017 okdshin 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 15 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 17 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 18 | THE SOFTWARE. 19 | */ 20 | #ifndef PICOSHA2_H 21 | #define PICOSHA2_H 22 | // picosha2:20140213 23 | 24 | #ifndef PICOSHA2_BUFFER_SIZE_FOR_INPUT_ITERATOR 25 | #define PICOSHA2_BUFFER_SIZE_FOR_INPUT_ITERATOR \ 26 | 1048576 //=1024*1024: default is 1MB memory 27 | #endif 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | namespace picosha2 { 36 | typedef unsigned long word_t; 37 | typedef unsigned char byte_t; 38 | 39 | static const size_t k_digest_size = 32; 40 | 41 | namespace detail { 42 | inline byte_t mask_8bit(byte_t x) { return x & 0xff; } 43 | 44 | inline word_t mask_32bit(word_t x) { return x & 0xffffffff; } 45 | 46 | const word_t add_constant[64] = { 47 | 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 48 | 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 49 | 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, 50 | 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 51 | 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 52 | 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 53 | 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, 54 | 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 55 | 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 56 | 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 57 | 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2}; 58 | 59 | const word_t initial_message_digest[8] = {0x6a09e667, 0xbb67ae85, 0x3c6ef372, 60 | 0xa54ff53a, 0x510e527f, 0x9b05688c, 61 | 0x1f83d9ab, 0x5be0cd19}; 62 | 63 | inline word_t ch(word_t x, word_t y, word_t z) { return (x & y) ^ ((~x) & z); } 64 | 65 | inline word_t maj(word_t x, word_t y, word_t z) { 66 | return (x & y) ^ (x & z) ^ (y & z); 67 | } 68 | 69 | inline word_t rotr(word_t x, std::size_t n) { 70 | assert(n < 32); 71 | return mask_32bit((x >> n) | (x << (32 - n))); 72 | } 73 | 74 | inline word_t bsig0(word_t x) { return rotr(x, 2) ^ rotr(x, 13) ^ rotr(x, 22); } 75 | 76 | inline word_t bsig1(word_t x) { return rotr(x, 6) ^ rotr(x, 11) ^ rotr(x, 25); } 77 | 78 | inline word_t shr(word_t x, std::size_t n) { 79 | assert(n < 32); 80 | return x >> n; 81 | } 82 | 83 | inline word_t ssig0(word_t x) { return rotr(x, 7) ^ rotr(x, 18) ^ shr(x, 3); } 84 | 85 | inline word_t ssig1(word_t x) { return rotr(x, 17) ^ rotr(x, 19) ^ shr(x, 10); } 86 | 87 | template 88 | void hash256_block(RaIter1 message_digest, RaIter2 first, RaIter2 last) { 89 | assert(first + 64 == last); 90 | static_cast(last); // for avoiding unused-variable warning 91 | word_t w[64]; 92 | std::fill(w, w + 64, 0); 93 | for (std::size_t i = 0; i < 16; ++i) { 94 | w[i] = (static_cast(mask_8bit(*(first + i * 4))) << 24) | 95 | (static_cast(mask_8bit(*(first + i * 4 + 1))) << 16) | 96 | (static_cast(mask_8bit(*(first + i * 4 + 2))) << 8) | 97 | (static_cast(mask_8bit(*(first + i * 4 + 3)))); 98 | } 99 | for (std::size_t i = 16; i < 64; ++i) { 100 | w[i] = mask_32bit(ssig1(w[i - 2]) + w[i - 7] + ssig0(w[i - 15]) + 101 | w[i - 16]); 102 | } 103 | 104 | word_t a = *message_digest; 105 | word_t b = *(message_digest + 1); 106 | word_t c = *(message_digest + 2); 107 | word_t d = *(message_digest + 3); 108 | word_t e = *(message_digest + 4); 109 | word_t f = *(message_digest + 5); 110 | word_t g = *(message_digest + 6); 111 | word_t h = *(message_digest + 7); 112 | 113 | for (std::size_t i = 0; i < 64; ++i) { 114 | word_t temp1 = h + bsig1(e) + ch(e, f, g) + add_constant[i] + w[i]; 115 | word_t temp2 = bsig0(a) + maj(a, b, c); 116 | h = g; 117 | g = f; 118 | f = e; 119 | e = mask_32bit(d + temp1); 120 | d = c; 121 | c = b; 122 | b = a; 123 | a = mask_32bit(temp1 + temp2); 124 | } 125 | *message_digest += a; 126 | *(message_digest + 1) += b; 127 | *(message_digest + 2) += c; 128 | *(message_digest + 3) += d; 129 | *(message_digest + 4) += e; 130 | *(message_digest + 5) += f; 131 | *(message_digest + 6) += g; 132 | *(message_digest + 7) += h; 133 | for (std::size_t i = 0; i < 8; ++i) { 134 | *(message_digest + i) = mask_32bit(*(message_digest + i)); 135 | } 136 | } 137 | 138 | } // namespace detail 139 | 140 | template 141 | void output_hex(InIter first, InIter last, std::ostream& os) { 142 | os.setf(std::ios::hex, std::ios::basefield); 143 | while (first != last) { 144 | os.width(2); 145 | os.fill('0'); 146 | os << static_cast(*first); 147 | ++first; 148 | } 149 | os.setf(std::ios::dec, std::ios::basefield); 150 | } 151 | 152 | template 153 | void bytes_to_hex_string(InIter first, InIter last, std::string& hex_str) { 154 | std::ostringstream oss; 155 | output_hex(first, last, oss); 156 | hex_str.assign(oss.str()); 157 | } 158 | 159 | template 160 | void bytes_to_hex_string(const InContainer& bytes, std::string& hex_str) { 161 | bytes_to_hex_string(bytes.begin(), bytes.end(), hex_str); 162 | } 163 | 164 | template 165 | std::string bytes_to_hex_string(InIter first, InIter last) { 166 | std::string hex_str; 167 | bytes_to_hex_string(first, last, hex_str); 168 | return hex_str; 169 | } 170 | 171 | template 172 | std::string bytes_to_hex_string(const InContainer& bytes) { 173 | std::string hex_str; 174 | bytes_to_hex_string(bytes, hex_str); 175 | return hex_str; 176 | } 177 | 178 | class hash256_one_by_one { 179 | public: 180 | hash256_one_by_one() { init(); } 181 | 182 | void init() { 183 | buffer_.clear(); 184 | std::fill(data_length_digits_, data_length_digits_ + 4, 0); 185 | std::copy(detail::initial_message_digest, 186 | detail::initial_message_digest + 8, h_); 187 | } 188 | 189 | template 190 | void process(RaIter first, RaIter last) { 191 | add_to_data_length(std::distance(first, last)); 192 | std::copy(first, last, std::back_inserter(buffer_)); 193 | std::size_t i = 0; 194 | for (; i + 64 <= buffer_.size(); i += 64) { 195 | detail::hash256_block(h_, buffer_.begin() + i, 196 | buffer_.begin() + i + 64); 197 | } 198 | buffer_.erase(buffer_.begin(), buffer_.begin() + i); 199 | } 200 | 201 | void finish() { 202 | byte_t temp[64]; 203 | std::fill(temp, temp + 64, 0); 204 | std::size_t remains = buffer_.size(); 205 | std::copy(buffer_.begin(), buffer_.end(), temp); 206 | temp[remains] = 0x80; 207 | 208 | if (remains > 55) { 209 | std::fill(temp + remains + 1, temp + 64, 0); 210 | detail::hash256_block(h_, temp, temp + 64); 211 | std::fill(temp, temp + 64 - 4, 0); 212 | } else { 213 | std::fill(temp + remains + 1, temp + 64 - 4, 0); 214 | } 215 | 216 | write_data_bit_length(&(temp[56])); 217 | detail::hash256_block(h_, temp, temp + 64); 218 | } 219 | 220 | template 221 | void get_hash_bytes(OutIter first, OutIter last) const { 222 | for (const word_t* iter = h_; iter != h_ + 8; ++iter) { 223 | for (std::size_t i = 0; i < 4 && first != last; ++i) { 224 | *(first++) = detail::mask_8bit( 225 | static_cast((*iter >> (24 - 8 * i)))); 226 | } 227 | } 228 | } 229 | 230 | private: 231 | void add_to_data_length(word_t n) { 232 | word_t carry = 0; 233 | data_length_digits_[0] += n; 234 | for (std::size_t i = 0; i < 4; ++i) { 235 | data_length_digits_[i] += carry; 236 | if (data_length_digits_[i] >= 65536u) { 237 | carry = data_length_digits_[i] >> 16; 238 | data_length_digits_[i] &= 65535u; 239 | } else { 240 | break; 241 | } 242 | } 243 | } 244 | void write_data_bit_length(byte_t* begin) { 245 | word_t data_bit_length_digits[4]; 246 | std::copy(data_length_digits_, data_length_digits_ + 4, 247 | data_bit_length_digits); 248 | 249 | // convert byte length to bit length (multiply 8 or shift 3 times left) 250 | word_t carry = 0; 251 | for (std::size_t i = 0; i < 4; ++i) { 252 | word_t before_val = data_bit_length_digits[i]; 253 | data_bit_length_digits[i] <<= 3; 254 | data_bit_length_digits[i] |= carry; 255 | data_bit_length_digits[i] &= 65535u; 256 | carry = (before_val >> (16 - 3)) & 65535u; 257 | } 258 | 259 | // write data_bit_length 260 | for (int i = 3; i >= 0; --i) { 261 | (*begin++) = static_cast(data_bit_length_digits[i] >> 8); 262 | (*begin++) = static_cast(data_bit_length_digits[i]); 263 | } 264 | } 265 | std::vector buffer_; 266 | word_t data_length_digits_[4]; // as 64bit integer (16bit x 4 integer) 267 | word_t h_[8]; 268 | }; 269 | 270 | inline void get_hash_hex_string(const hash256_one_by_one& hasher, 271 | std::string& hex_str) { 272 | byte_t hash[k_digest_size]; 273 | hasher.get_hash_bytes(hash, hash + k_digest_size); 274 | return bytes_to_hex_string(hash, hash + k_digest_size, hex_str); 275 | } 276 | 277 | inline std::string get_hash_hex_string(const hash256_one_by_one& hasher) { 278 | std::string hex_str; 279 | get_hash_hex_string(hasher, hex_str); 280 | return hex_str; 281 | } 282 | 283 | namespace impl { 284 | template 285 | void hash256_impl(RaIter first, RaIter last, OutIter first2, OutIter last2, int, 286 | std::random_access_iterator_tag) { 287 | hash256_one_by_one hasher; 288 | // hasher.init(); 289 | hasher.process(first, last); 290 | hasher.finish(); 291 | hasher.get_hash_bytes(first2, last2); 292 | } 293 | 294 | template 295 | void hash256_impl(InputIter first, InputIter last, OutIter first2, 296 | OutIter last2, int buffer_size, std::input_iterator_tag) { 297 | std::vector buffer(buffer_size); 298 | hash256_one_by_one hasher; 299 | // hasher.init(); 300 | while (first != last) { 301 | int size = buffer_size; 302 | for (int i = 0; i != buffer_size; ++i, ++first) { 303 | if (first == last) { 304 | size = i; 305 | break; 306 | } 307 | buffer[i] = *first; 308 | } 309 | hasher.process(buffer.begin(), buffer.begin() + size); 310 | } 311 | hasher.finish(); 312 | hasher.get_hash_bytes(first2, last2); 313 | } 314 | } 315 | 316 | template 317 | void hash256(InIter first, InIter last, OutIter first2, OutIter last2, 318 | int buffer_size = PICOSHA2_BUFFER_SIZE_FOR_INPUT_ITERATOR) { 319 | picosha2::impl::hash256_impl( 320 | first, last, first2, last2, buffer_size, 321 | typename std::iterator_traits::iterator_category()); 322 | } 323 | 324 | template 325 | void hash256(InIter first, InIter last, OutContainer& dst) { 326 | hash256(first, last, dst.begin(), dst.end()); 327 | } 328 | 329 | template 330 | void hash256(const InContainer& src, OutIter first, OutIter last) { 331 | hash256(src.begin(), src.end(), first, last); 332 | } 333 | 334 | template 335 | void hash256(const InContainer& src, OutContainer& dst) { 336 | hash256(src.begin(), src.end(), dst.begin(), dst.end()); 337 | } 338 | 339 | template 340 | void hash256_hex_string(InIter first, InIter last, std::string& hex_str) { 341 | byte_t hashed[k_digest_size]; 342 | hash256(first, last, hashed, hashed + k_digest_size); 343 | std::ostringstream oss; 344 | output_hex(hashed, hashed + k_digest_size, oss); 345 | hex_str.assign(oss.str()); 346 | } 347 | 348 | template 349 | std::string hash256_hex_string(InIter first, InIter last) { 350 | std::string hex_str; 351 | hash256_hex_string(first, last, hex_str); 352 | return hex_str; 353 | } 354 | 355 | inline void hash256_hex_string(const std::string& src, std::string& hex_str) { 356 | hash256_hex_string(src.begin(), src.end(), hex_str); 357 | } 358 | 359 | template 360 | void hash256_hex_string(const InContainer& src, std::string& hex_str) { 361 | hash256_hex_string(src.begin(), src.end(), hex_str); 362 | } 363 | 364 | template 365 | std::string hash256_hex_string(const InContainer& src) { 366 | return hash256_hex_string(src.begin(), src.end()); 367 | } 368 | 369 | } // namespace picosha2 370 | 371 | #endif // PICOSHA2_H -------------------------------------------------------------------------------- /Chapter 15 - Big Data Cryptography/tree.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "tree.h" 4 | 5 | using namespace std; 6 | 7 | merkle_tree::merkle_tree(vector vector_nodes) 8 | { 9 | vector aux_nodes; 10 | while (vector_nodes.size() != 1) 11 | { 12 | print_hash_values(vector_nodes); 13 | for (int i = 0, n = 0; i < vector_nodes.size(); i = i + 2, n++) { 14 | if (i != vector_nodes.size() - 1) // check if there is a neighbour block 15 | { 16 | // merges the neighbour nodes and computes the hash value of the new node 17 | aux_nodes.push_back(new tree_node(compute_sha256(vector_nodes[i]->hash_value + vector_nodes[i + 1]->hash_value))); 18 | // link the new node with the left neighbour and the right neighbour 19 | aux_nodes[n]->l_neighbour = vector_nodes[i]; 20 | aux_nodes[n]->r_neighbour = vector_nodes[i + 1]; 21 | } else 22 | { 23 | aux_nodes.push_back(vector_nodes[i]); 24 | } 25 | } 26 | cout << "\n"; 27 | vector_nodes = aux_nodes; 28 | aux_nodes.clear(); 29 | } 30 | 31 | // picks the first node as the root of the tree 32 | this->tree_root = vector_nodes[0]; 33 | } 34 | 35 | merkle_tree::~merkle_tree() 36 | { 37 | delete_merkle_tree(tree_root); 38 | cout << "The tree was deleted." << endl; 39 | } 40 | 41 | void merkle_tree::print_merkle_tree(tree_node *node, int index) 42 | { 43 | if (node) { 44 | if (node->l_neighbour) { 45 | print_merkle_tree(node->l_neighbour, index + 4); 46 | } 47 | if (node->r_neighbour) { 48 | print_merkle_tree(node->r_neighbour, index + 4); 49 | } 50 | if (index) { 51 | cout << setw(index) << ' '; 52 | } 53 | cout << node->hash_value[0] << "\n "; 54 | } 55 | } 56 | 57 | void merkle_tree::delete_merkle_tree(tree_node *node) 58 | { 59 | if (node) { 60 | delete_merkle_tree(node->l_neighbour); 61 | delete_merkle_tree(node->r_neighbour); 62 | node = NULL; 63 | delete node; 64 | } 65 | } -------------------------------------------------------------------------------- /Chapter 15 - Big Data Cryptography/tree.h: -------------------------------------------------------------------------------- 1 | #ifndef MERKLE_TREE 2 | #define MERKLE_TREE 3 | 4 | #include "tree_node.h" 5 | #include "picosha2.h" 6 | #include "tree_handling.h" 7 | #include 8 | #include 9 | 10 | using namespace std; 11 | 12 | 13 | struct merkle_tree { 14 | tree_node* tree_root; 15 | merkle_tree(vector vector_nodes); 16 | ~merkle_tree(); 17 | void print_merkle_tree(tree_node *node, int index); 18 | void delete_merkle_tree(tree_node *node); 19 | }; 20 | 21 | 22 | #endif -------------------------------------------------------------------------------- /Chapter 15 - Big Data Cryptography/tree_handling.h: -------------------------------------------------------------------------------- 1 | #ifndef TREE_MISC 2 | #define TREE_MISC 3 | 4 | #include 5 | #include 6 | #include "tree.h" 7 | #include "picosha2.h" 8 | 9 | using namespace std; 10 | 11 | // computes the hash value of the input using SHA256 12 | inline string compute_sha256(string input_string) 13 | { 14 | string hash_string = picosha2::hash256_hex_string(input_string); 15 | return hash_string; 16 | } 17 | 18 | // display the hash values from a vector of tree nodes 19 | inline void print_hash_values(vector vector_nodes) 20 | { 21 | for (int i = 0; i < vector_nodes.size(); i++) 22 | { 23 | cout << vector_nodes[i]->hash_value << endl; 24 | } 25 | } 26 | 27 | #endif -------------------------------------------------------------------------------- /Chapter 15 - Big Data Cryptography/tree_node.cpp: -------------------------------------------------------------------------------- 1 | #include "tree_node.h" 2 | using namespace std; 3 | 4 | // assigns the input hash value to the hash_value attribute of the tree node 5 | tree_node::tree_node(string value) 6 | { 7 | this->hash_value = value; 8 | } 9 | 10 | -------------------------------------------------------------------------------- /Chapter 15 - Big Data Cryptography/tree_node.h: -------------------------------------------------------------------------------- 1 | #ifndef TREE_NODE 2 | #define TREE_NODE 3 | 4 | #include 5 | using namespace std; 6 | 7 | // define the node of the merkle tree 8 | struct tree_node 9 | { 10 | string hash_value; // the hash value 11 | tree_node *l_neighbour; // the left neighbour 12 | tree_node *r_neighbour; // the right neighbour 13 | 14 | // instantiates the hash value within the node 15 | // see the corresponding .cpp file 16 | tree_node(string value); 17 | }; 18 | 19 | #endif -------------------------------------------------------------------------------- /Chapter 16 - Cloud Computing Cryptography/cloud_example.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | // the encryption scheme is a simple XOR-ing process 6 | // XOR-ing is used for both encryption and decryption 7 | // parameter "message" can be the plain message or the encrypted message, according to user's needs 8 | string xor_string(string message, string key) 9 | { 10 | string out_message(message); 11 | unsigned int key_len(key.length()), message_len(message.length()), pos(0); 12 | for(unsigned int index = 0; index < message_len; index++) 13 | { 14 | out_message[index] = message[index] ^ key[pos]; 15 | if(++pos == key_len){ pos = 0; } 16 | } 17 | return out_message; 18 | } 19 | 20 | int main() 21 | { 22 | // read the message to be encrypted from the console 23 | string plain_text; 24 | cout<<"Enter the message: "; 25 | getline (cin, plain_text); 26 | 27 | // the public key is read from the .pem corresponding file 28 | string row1; 29 | string public_key = ""; 30 | ifstream public_key_file ("publicKey.pem"); 31 | if (public_key_file.is_open()) 32 | { 33 | while (getline (public_key_file, row1) ) 34 | { 35 | public_key += row1; 36 | } 37 | public_key_file.close(); 38 | } 39 | // to check that the public key is read correctly, it is dispalyed on the console 40 | cout<<"Public key:"< 2 | #include 3 | #include 4 | 5 | //** variables 6 | int theSBox[16] = {3, 14, 1, 10, 4, 9, 5, 6, 8, 11, 15, 2, 13, 12, 0, 7}; 7 | //int theSBox[16] = {14, 2, 11, 0, 4, 6, 7, 15, 8, 5, 3, 9, 13, 12, 1, 10}; 8 | int characters[16][16]; 9 | int known_plaintext_0[10000]; 10 | int known_plaintext_1[10000]; 11 | int known_ciphertext_0[10000]; 12 | int known_ciphertext_1[10000]; 13 | int good_plaintext_0, good_plaintext_1, good_ciphertext_0, good_ciphertext_1; 14 | int pairs_of_numbers; 15 | int characters_dataSet_0[16]; 16 | int characters_data_max = 0; 17 | 18 | 19 | int round_function(int integer_input, int cryptoKey) 20 | { 21 | return theSBox[cryptoKey ^ integer_input]; 22 | } 23 | 24 | int encryption(int integer_input, int key_0, int key_1) 25 | { 26 | int x_value_0 = round_function(integer_input, key_0); 27 | return x_value_0 ^ key_1; 28 | } 29 | 30 | void find_differences() 31 | { 32 | printf("\nXOR Differential Structure:\n"); 33 | 34 | int a, b, c, f; //c, d, e, f 35 | 36 | for(a = 0; a < 16; a++) 37 | { 38 | for(b = 0; b < 16; b++) 39 | { 40 | characters[a ^ b][theSBox[a] ^ theSBox[b]]++; 41 | } 42 | } 43 | 44 | for(a = 0; a < 16; a++) 45 | { 46 | for(b = 0; b < 16; b++) 47 | printf(" %x ", characters[a][b]); 48 | printf("\n"); 49 | } 50 | 51 | printf("\nShowing the most important differences:\n"); 52 | 53 | for(a = 0; a < 16; a++) 54 | { 55 | for(b = 0; b < 16; b++) 56 | { 57 | if (characters[a][b] == 6) 58 | { 59 | printf(" 6/16: %i {--} %i\n", a, b); 60 | } 61 | } 62 | } 63 | } 64 | 65 | void generate_characters_data(int input_differences, int output_differences) 66 | { 67 | printf("\nIntermediate values generated using the differentials(%i --> %i):\n", input_differences, output_differences); 68 | 69 | characters_data_max = 0; 70 | int f; 71 | for(f = 0; f < 16; f++) 72 | { 73 | int computations = f ^ input_differences; 74 | 75 | if ((theSBox[f] ^ theSBox[computations]) == output_differences) 76 | { 77 | printf(" The possibility: %i + %i {--} %i + %i\n", f, computations, theSBox[f], theSBox[computations]); 78 | characters_dataSet_0[characters_data_max] = f; 79 | characters_data_max++; 80 | } 81 | } 82 | } 83 | 84 | void generate_pairs(int input_differences) 85 | { 86 | printf("\nKnown pairs %i generated. The pairs are based on the differentials served as input of %i.\n", pairs_of_numbers, input_differences); 87 | 88 | //** generate substitution keys 89 | int real_key_0 = rand() % 16; 90 | int real_key_1 = rand() % 16; 91 | 92 | printf(" Real Key 0 = %i\n", real_key_0); 93 | printf(" Real Key 1 = %i\n", real_key_1); 94 | 95 | int c; 96 | 97 | //** using XOR, pairs for plaintexts and ciphertexts are generated 98 | for(c = 0; c < pairs_of_numbers; c++) 99 | { 100 | known_plaintext_0[c] = rand() % 16; 101 | known_plaintext_1[c] = known_plaintext_0[c] ^ input_differences; 102 | known_ciphertext_0[c] = encryption(known_plaintext_0[c], real_key_0, real_key_1); 103 | known_ciphertext_1[c] = encryption(known_plaintext_1[c], real_key_0, real_key_1); 104 | } 105 | } 106 | 107 | void identifying_good_pair(int output_differences) 108 | { 109 | printf("\nLooking for good pair:\n"); 110 | int c; 111 | 112 | //** test if the pair of ciphertexts meet the characteristics 113 | for(c = 0; c < pairs_of_numbers; c++) 114 | { 115 | if ((known_ciphertext_0[c] ^ known_ciphertext_1[c]) == output_differences) 116 | { 117 | good_ciphertext_0 = known_ciphertext_0[c]; 118 | good_ciphertext_1 = known_ciphertext_1[c]; 119 | good_plaintext_0 = known_plaintext_0[c]; 120 | good_plaintext_1 = known_plaintext_1[c]; 121 | printf(" A good pair has been found: (P0 = %i, P1 = %i) {--} (C0 = %i, C1 = %i)\n", good_plaintext_0, good_plaintext_1, good_ciphertext_0, good_ciphertext_1); 122 | return; 123 | } 124 | } 125 | printf("There was no good pair found!\n"); 126 | } 127 | 128 | int key_testing(int key_test_0, int key_test_1) 129 | { 130 | int c; 131 | int crap = 0; 132 | for(c = 0; c < pairs_of_numbers; c++) 133 | { 134 | if ((encryption(known_plaintext_0[c], key_test_0, key_test_1) 135 | != known_ciphertext_0[c]) || (encryption(known_plaintext_1[c], key_test_0, key_test_1) != known_ciphertext_1[c])) 136 | { 137 | crap = 1; 138 | break; 139 | } 140 | } 141 | 142 | if (crap == 0) 143 | return 1; 144 | else 145 | return 0; 146 | } 147 | 148 | void brute_cracking() 149 | { 150 | printf("\nReducing the space of the key using brute force:\n"); 151 | 152 | int f; 153 | 154 | //** based on the characteristics, we will test each of the possible value 155 | for(f = 0; f < characters_data_max; f++) 156 | { 157 | int key_test_0 = characters_dataSet_0[f] ^ good_plaintext_0; 158 | int key_test_1 = theSBox[characters_dataSet_0[f]] ^ good_ciphertext_0 ; 159 | 160 | if (key_testing(key_test_0, key_test_1) == 1) 161 | printf("\n\nThe Key! (%i, %i), ", key_test_0, key_test_1); 162 | else 163 | printf(" (%i, %i), ", key_test_0, key_test_1); 164 | } 165 | } 166 | 167 | int main() 168 | { 169 | //** generate random value once the program is run 170 | srand(time(NULL)); 171 | 172 | //** look in the s-boxes for good differences 173 | find_differences(); 174 | 175 | //** define number of known pairs 176 | pairs_of_numbers = 8; 177 | 178 | //** look for inputs that meet specific characteristics 179 | generate_characters_data(4, 7); 180 | 181 | //** let's generate pairs of chosen-plaintext 182 | generate_pairs(4); 183 | 184 | //** pick a pair which meet the characteristic 185 | identifying_good_pair(7); 186 | 187 | //** find the key 188 | brute_cracking(); 189 | } 190 | -------------------------------------------------------------------------------- /Chapter 19 - Linear and Differential Cryptanalysis/differential_cryptanalysis.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/pro-cryptography-cryptanalysis-cpp20/462331a454e32be1c768c7aee079b335510adcef/Chapter 19 - Linear and Differential Cryptanalysis/differential_cryptanalysis.exe -------------------------------------------------------------------------------- /Chapter 19 - Linear and Differential Cryptanalysis/linear_cryptanalysis.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int sBox_content[16] = {9, 11, 12, 4, 10, 1, 2, 6, 13, 7, 3, 8, 15, 14, 0, 5}; 6 | int sBox_content_revision[16] = {14, 5, 6, 10, 3, 15, 7, 9, 11, 0, 4, 1, 2, 8, 13, 12}; 7 | int approximation_array[16][16]; 8 | int known_plaintext[500]; 9 | int known_ciphertext[500]; 10 | int numbers_known = 0; 11 | 12 | int using_mask(int inputValue, int mask_value) 13 | { 14 | int value = inputValue & mask_value; 15 | int total = 0; 16 | 17 | while(value > 0) 18 | { 19 | int temporary = value % 2; 20 | value /= 2; 21 | 22 | if (temporary == 1) 23 | { 24 | total = total ^ 1; 25 | } 26 | } 27 | return total; 28 | } 29 | 30 | void looking_for_approximation() 31 | { 32 | int a, b, c; 33 | 34 | //** the output of mask value 35 | for(a = 1; a < 16; a++) 36 | { 37 | //** the input of mask value 38 | for(b = 1; b < 16; b++) 39 | { 40 | //** input 41 | for(c = 0; c < 16; c++) 42 | { 43 | if (using_mask(c, b) == using_mask(sBox_content[c], a)) 44 | { 45 | approximation_array[b][a]++; 46 | } 47 | } 48 | } 49 | } 50 | } 51 | 52 | void display_approximation() 53 | { 54 | printf("Linear Approximations Values: \n"); 55 | 56 | int a, b, c; 57 | for(a = 1; a < 16; a++) 58 | for(b = 1; b < 16; b++) 59 | if (approximation_array[a][b] == 14) 60 | printf(" %i : %i {--} %i\n", approximation_array[a][b], a, b); 61 | 62 | printf("\n"); 63 | } 64 | 65 | int round_function(int inputValue, int substitution_key) 66 | { 67 | return sBox_content[inputValue ^ substitution_key]; 68 | } 69 | 70 | void filling_known_numbers() 71 | { 72 | int substitution_key_1 = rand() % 16; 73 | int substitution_key_2 = rand() % 16; 74 | 75 | printf("Generating data: Key_1 = %i, Key_2 = %i\n", substitution_key_1, substitution_key_2); 76 | 77 | int total = 0; 78 | 79 | int c; 80 | for(c = 0; c < numbers_known; c++) 81 | { 82 | known_plaintext[c] = rand() % 16; 83 | known_ciphertext[c] = round_function(round_function(known_plaintext[c], substitution_key_1), substitution_key_2); 84 | } 85 | 86 | printf("Generating Data: We have %i known pairs generated\n\n", numbers_known); 87 | 88 | } 89 | 90 | void keys_testing(int key_1, int key_2) //testKeys 91 | { 92 | int c; 93 | for(c = 0; c < numbers_known; c++) 94 | { 95 | if (round_function(round_function(known_plaintext[c], key_1), key_2) != known_ciphertext[c]) 96 | { 97 | break; 98 | } 99 | } 100 | 101 | printf("# "); 102 | } 103 | 104 | int main() 105 | { 106 | printf("Linear Cryptanalysis\n\n"); 107 | 108 | srand(time(NULL)); 109 | 110 | looking_for_approximation(); 111 | display_approximation(); 112 | 113 | int input_approximation = 11; 114 | int output_approximation = 11; 115 | 116 | //** how many numbers we known 117 | numbers_known = 16; 118 | filling_known_numbers(); 119 | 120 | int cryptographic_key_score[16]; 121 | int reaching_threshold = 0; //sofar1 122 | 123 | printf("Proceeding with Linear Attack"); 124 | printf("\tLinear Approximation = %i -> %i\n", input_approximation, output_approximation); 125 | printf("\n\n"); 126 | 127 | int b, h; 128 | for(b = 0; b < 16; b++) 129 | { 130 | cryptographic_key_score[b] = 0; 131 | for(h = 0; h < numbers_known; h++) 132 | { 133 | reaching_threshold++; 134 | int middle_round = round_function(known_plaintext[h], b); //Find Xi by guessing at K1 135 | 136 | if ((using_mask(middle_round, input_approximation) == using_mask(known_ciphertext[h], output_approximation))) 137 | cryptographic_key_score[b]++; 138 | else 139 | cryptographic_key_score[b]--; 140 | 141 | } 142 | } 143 | 144 | int maximum_score_value = 0; 145 | 146 | for(b = 0; b < 16; b++) 147 | { 148 | int score_value = cryptographic_key_score[b] * cryptographic_key_score[b]; 149 | if (score_value > maximum_score_value) maximum_score_value = score_value; 150 | } 151 | 152 | int good_cryptographic_keys[16]; 153 | 154 | for(h = 0; h < 16; h++) 155 | good_cryptographic_keys[h] = -1; 156 | 157 | h = 0; 158 | 159 | printf("Linear Attack:\n"); 160 | for(b = 0; b < 16; b++) 161 | { 162 | if ((cryptographic_key_score[b] * cryptographic_key_score[b]) == maximum_score_value) 163 | { 164 | good_cryptographic_keys[h] = b; 165 | printf("\tPotential Value Candidate for Cryptography Key 1 = %i\n", good_cryptographic_keys[h]); 166 | h++; 167 | } 168 | } 169 | 170 | int guessing_cryptographic_key_1; 171 | int guessing_cryptographic_key_2; 172 | 173 | for(h = 0; h < 16; h++) 174 | { 175 | if (good_cryptographic_keys[h] != -1) 176 | { 177 | int cryptography_key_test_1 = round_function(known_plaintext[0], good_cryptographic_keys[h]) ^ sBox_content_revision[known_ciphertext[0]]; 178 | 179 | int tested = 0; 180 | int e; 181 | int bad = 0; 182 | for(e = 0;e < numbers_known; e++) 183 | { 184 | reaching_threshold += 2; 185 | int testOut = round_function(round_function(known_plaintext[e], good_cryptographic_keys[h]), cryptography_key_test_1); 186 | if (testOut != known_ciphertext[e]) 187 | bad = 1; 188 | } 189 | if (bad == 0) 190 | { 191 | printf("\tFound Keys! K1 = %i, K2 = %i\n", good_cryptographic_keys[h], cryptography_key_test_1); 192 | guessing_cryptographic_key_1 = good_cryptographic_keys[h]; 193 | guessing_cryptographic_key_2 = cryptography_key_test_1; 194 | printf("\tComputations Until Key Found = %i\n", reaching_threshold); 195 | 196 | } 197 | } 198 | } 199 | 200 | printf("\tThe total value of computations = %i\n\n", reaching_threshold); 201 | reaching_threshold = 0; 202 | 203 | printf("Brute Force Attack\n"); 204 | for(h = 0; h < 16; h++) 205 | { 206 | for(b = 0; b < 16; b++) 207 | { 208 | int e; 209 | int bad = 0; 210 | for(e = 0;e < numbers_known; e++) 211 | { 212 | reaching_threshold += 2; 213 | int testOut = round_function(round_function(known_plaintext[e], h), b); 214 | if (testOut != known_ciphertext[e]) 215 | bad = 1; 216 | } 217 | if (bad == 0) 218 | { 219 | printf("\tCryptographic Keys Found with Success! K1 = %i, K2 = %i\n", h, b); 220 | printf("\tThe number of computations computed until the cryptography key(s) were found = %i\n", reaching_threshold); 221 | } 222 | } 223 | } 224 | 225 | printf("\tComputations Total = %i\n", reaching_threshold); 226 | } -------------------------------------------------------------------------------- /Chapter 19 - Linear and Differential Cryptanalysis/linear_cryptanalysis.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/pro-cryptography-cryptanalysis-cpp20/462331a454e32be1c768c7aee079b335510adcef/Chapter 19 - Linear and Differential Cryptanalysis/linear_cryptanalysis.exe -------------------------------------------------------------------------------- /Chapter 2 - Cryptography Fundamentals/Listing 2-10 - Caesar Cipher.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | // This function receives text and shift and 5 | // returns the encrypted text 6 | string encrypt(string text, int s) 7 | { 8 | string result = ""; 9 | 10 | // traverse text 11 | for (int i=0;i 2 | #include 3 | using namespace std; 4 | class Vigenere { 5 | public: 6 | //** represents the key 7 | string key; 8 | 9 | //** the constructor of the class 10 | //** the chosen key 11 | Vigenere(string chosenKey) { 12 | for (int i = 0; i < chosenKey.size(); ++i) { 13 | if (chosenKey[i] >= 'A' && chosenKey[i] <= 'Z') 14 | this->key += chosenKey[i]; 15 | else if (chosenKey[i] >= 'a' && chosenKey[i] <= 'z') 16 | this->key += chosenKey[i] + 'A' - 'a'; 17 | } 18 | } 19 | string encrypt(string t) 20 | { 21 | string encryptedOutput; 22 | for (int i = 0, j = 0; i < t.length(); ++i) { 23 | char c = t[i]; 24 | if (c >= 'a' && c <= 'z') 25 | c += 'A' - 'a'; 26 | else if (c < 'A' || c > 'Z') 27 | continue; 28 | encryptedOutput += (c + key[j] - 2 * 'A') % 26 + 'A'; //added 'A' to bring it in range of ASCII alphabet [ 65-90 | A-Z ] 29 | j = (j + 1) % key.length(); 30 | } 31 | return encryptedOutput; 32 | } 33 | string decrypt(string t) { 34 | string decryptedOutput; 35 | for (int i = 0, j = 0; i < t.length(); ++i) { 36 | char c = t[i]; 37 | if (c >= 'a' && c <= 'z') 38 | c += 'A' - 'a'; 39 | else if (c < 'A' || c > 'Z') 40 | continue; 41 | decryptedOutput += (c - key[j] + 26) % 26 + 'A';//added 'A' to bring it in range of ASCII alphabet [ 65-90 | A-Z ] 42 | j = (j + 1) % key.length(); 43 | } 44 | return decryptedOutput; 45 | } 46 | }; 47 | 48 | int main() { 49 | 50 | Vigenere myVigenere("APRESS!WELCOME"); 51 | string originalMessage ="ThisisanexampleofvigenerecipherforApress"; 52 | string enc = myVigenere.encrypt(originalMessage); 53 | string dec = myVigenere.decrypt(enc); 54 | cout << "Original Message: "< 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace std; 10 | vector binaryConversion(const string); 11 | vector addPadOf512Bits(const vector); 12 | vector resizingTheBlock(vector); 13 | string computingTheHash(const vector); 14 | 15 | string displayAsHex(unsigned long); 16 | void outputTheBlockState(vector); 17 | string displayAsBinary(unsigned long); 18 | const bool displayBlockStateAddOne = 0; 19 | const bool displayDistanceFrom512Bit = 0; 20 | const bool displayResultsOfPadding = false; 21 | const bool displayWorkVariablesForT = 0; 22 | const bool displayT1Computation = false; 23 | const bool displayT2Computation = false; 24 | const bool displayTheHashSegments = false; 25 | const bool displayWt = false; 26 | 27 | //** definite in acord cu specificatiile NIST 28 | #define ROTRIGHT(word,bits) (((word) >> (bits)) | ((word) << (32-(bits)))) 29 | #define SSIG0(x) (ROTRIGHT(x,7) ^ ROTRIGHT(x,18) ^ ((x) >> 3)) 30 | #define SSIG1(x) (ROTRIGHT(x,17) ^ ROTRIGHT(x,19) ^ ((x) >> 10)) 31 | #define CH(x,y,z) (((x) & (y)) ^ (~(x) & (z))) 32 | #define MAJ(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) 33 | 34 | //** conform cu ultimele actualizari facute de catre NIST 35 | //** BSIG0 este inlocuit cu EP0 si BSIG1 cu EP0 in implementarea noastra 36 | 37 | #define BSIG0(x) (ROTRIGHT(x,7) ^ ROTRIGHT(x,18) ^ ((x) >> 3)) 38 | #define BSIG1(x) (ROTRIGHT(x,17) ^ ROTRIGHT(x,19) ^ ((x) >> 10)) 39 | 40 | #define EP0(x) (ROTRIGHT(x,2) ^ ROTRIGHT(x,13) ^ ROTRIGHT(x,22)) 41 | #define EP1(x) (ROTRIGHT(x,6) ^ ROTRIGHT(x,11) ^ ROTRIGHT(x,25)) 42 | 43 | int main(int argc, char* argv[]) 44 | { 45 | string theMessage = ""; 46 | bool testing = 0; 47 | 48 | switch (argc) { 49 | case 1: 50 | cout << "The is no input string found. The test will be run using random first three letters abc.\n"; 51 | theMessage = "abc"; 52 | testing = true; 53 | break; 54 | case 2: 55 | if (strlen(argv[1]) > 55) 56 | { 57 | cout << "The string provided is biger than 55 characters length. Enter a shorter string" 58 | << " or message!\n"; 59 | return 0; 60 | } 61 | theMessage = argv[1]; 62 | break; 63 | default: 64 | cout << "There are too many items in the command line."; 65 | exit(-1); 66 | break; 67 | } 68 | 69 | 70 | vector theBlocksArray; 71 | 72 | theBlocksArray = binaryConversion(theMessage); 73 | 74 | theBlocksArray = addPadOf512Bits(theBlocksArray); 75 | 76 | theBlocksArray = resizingTheBlock(theBlocksArray); 77 | 78 | string myHash = computingTheHash(theBlocksArray); 79 | 80 | if (testing) 81 | { 82 | const string theCorrectHashForABC = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"; 83 | if (theCorrectHashForABC.compare(myHash) != 0) { 84 | cout << "\tThe test has failed!\n"; 85 | return(1); 86 | } 87 | else { 88 | cout << "\tThe test has passed!\n"; 89 | return(0); 90 | } 91 | } 92 | 93 | cout << myHash << endl; 94 | return 0; 95 | } 96 | 97 | vector resizingTheBlock(vector inputOf8BitAsciiValues) 98 | { 99 | vector outputOf32BitWordsCombinedAsAsciiValues(16); 100 | 101 | for(int i = 0; i < 64; i = i + 4) 102 | { 103 | bitset<32> temporary32BitSection(0); 104 | 105 | temporary32BitSection = (unsigned long) inputOf8BitAsciiValues[i] << 24; 106 | temporary32BitSection |= (unsigned long) inputOf8BitAsciiValues[i + 1] << 16; 107 | temporary32BitSection |= (unsigned long) inputOf8BitAsciiValues[i + 2] << 8; 108 | temporary32BitSection |= (unsigned long) inputOf8BitAsciiValues[i + 3]; 109 | 110 | outputOf32BitWordsCombinedAsAsciiValues[i/4] = temporary32BitSection.to_ulong(); 111 | } 112 | 113 | return outputOf32BitWordsCombinedAsAsciiValues; 114 | } 115 | 116 | void outputTheBlockState(vector vectorOfCurrentBlocks) 117 | { 118 | cout << "---- The current State of the Block ----\n"; 119 | for (int i = 0; i < vectorOfCurrentBlocks.size(); i++) 120 | { 121 | cout << "block[" << i << "] binary: " << displayAsBinary(vectorOfCurrentBlocks[i]) 122 | << " hex y: 0x" << displayAsHex(vectorOfCurrentBlocks[i]) << endl; 123 | } 124 | } 125 | 126 | string displayAsHex(unsigned long input32BitBlock) 127 | { 128 | bitset<32> theBitSet(input32BitBlock); 129 | unsigned number = theBitSet.to_ulong(); 130 | 131 | stringstream theStringStream; 132 | theStringStream << std::hex << std::setw(8) << std::setfill('0') << number; 133 | string temporary; 134 | theStringStream >> temporary; 135 | 136 | return temporary; 137 | } 138 | 139 | string displayAsBinary(unsigned long input32OrLessBitBlock) 140 | { 141 | bitset<8> theBitSet(input32OrLessBitBlock); 142 | return theBitSet.to_string(); 143 | } 144 | 145 | vector binaryConversion(const string inputOfAnyLength) 146 | { 147 | vector vectorBlockHoldingAsciiCharacters; 148 | 149 | for (int i = 0; i < inputOfAnyLength.size(); ++i) 150 | { 151 | bitset<8> bitSetOf8Bits(inputOfAnyLength.c_str()[i]); 152 | vectorBlockHoldingAsciiCharacters.push_back(bitSetOf8Bits.to_ulong()); 153 | } 154 | 155 | return vectorBlockHoldingAsciiCharacters; 156 | } 157 | 158 | vector addPadOf512Bits(vector vectorBlockHoldingAsciiCharacters) 159 | { 160 | int lengthOfMessageInBits = vectorBlockHoldingAsciiCharacters.size() * 8; 161 | 162 | int zeroesToAdd = 447 - lengthOfMessageInBits; 163 | 164 | if(displayBlockStateAddOne) 165 | outputTheBlockState(vectorBlockHoldingAsciiCharacters); 166 | 167 | unsigned long t1Block = 0x80; 168 | vectorBlockHoldingAsciiCharacters.push_back(t1Block); 169 | 170 | if(displayBlockStateAddOne) 171 | outputTheBlockState(vectorBlockHoldingAsciiCharacters); 172 | outputTheBlockState(vectorBlockHoldingAsciiCharacters); 173 | 174 | zeroesToAdd = zeroesToAdd - 7; 175 | 176 | if (displayDistanceFrom512Bit) 177 | { 178 | cout << "lengthOfMessageInBits = " << lengthOfMessageInBits << endl; 179 | cout << "zeroesToAdd = " << zeroesToAdd + 7 << endl; // Plus 7 so this follows the paper. 180 | } 181 | 182 | if (displayDistanceFrom512Bit) 183 | cout << "adding " << zeroesToAdd / 8 << " empty eight bit blocks!\n"; 184 | 185 | for(int i = 0; i < zeroesToAdd / 8; i++) 186 | vectorBlockHoldingAsciiCharacters.push_back(0x00000000); 187 | 188 | bitset<64> theBig64BlobBit(lengthOfMessageInBits); 189 | if (displayDistanceFrom512Bit) 190 | cout << "l in a 64 bit binary blob: \n\t" << theBig64BlobBit << endl; 191 | 192 | string big_64bit_string = theBig64BlobBit.to_string(); 193 | 194 | bitset<8> temp_string_holder1(big_64bit_string.substr(0,8)); 195 | vectorBlockHoldingAsciiCharacters.push_back(temp_string_holder1.to_ulong()); 196 | 197 | for(int i = 8; i < 63; i=i+8) 198 | { 199 | bitset<8> temporaryStringHolder2(big_64bit_string.substr(i,8)); 200 | vectorBlockHoldingAsciiCharacters.push_back(temporaryStringHolder2.to_ulong()); 201 | } 202 | 203 | if (displayResultsOfPadding) 204 | { 205 | cout << "Current 512 bit pre-processed hash in binary: \n"; 206 | for(int i = 0; i < vectorBlockHoldingAsciiCharacters.size(); i=i+4) 207 | cout << i << ": " << displayAsBinary(vectorBlockHoldingAsciiCharacters[i]) << " " 208 | << i + 1 << ": " << displayAsBinary(vectorBlockHoldingAsciiCharacters[i+1]) << " " 209 | << i + 2 << ": " << displayAsBinary(vectorBlockHoldingAsciiCharacters[i+2]) << " " 210 | << i + 3 << ": " << displayAsBinary(vectorBlockHoldingAsciiCharacters[i+3]) << endl; 211 | 212 | cout << "Current 512 bit pre-processed hash in hex: \n"; 213 | for(int i = 0; i < vectorBlockHoldingAsciiCharacters.size(); i=i+4) 214 | cout << i << ": " << "0x" + displayAsHex(vectorBlockHoldingAsciiCharacters[i]) << " " 215 | << i + 1 << ": " << "0x" + displayAsHex(vectorBlockHoldingAsciiCharacters[i+1]) << " " 216 | << i + 2 << ": " << "0x" + displayAsHex(vectorBlockHoldingAsciiCharacters[i+2]) << " " 217 | << i + 3 << ": " << "0x" + displayAsHex(vectorBlockHoldingAsciiCharacters[i+3]) << endl; 218 | } 219 | return vectorBlockHoldingAsciiCharacters; 220 | } 221 | 222 | string computingTheHash(const vector blockOf512BitPaddedMessage) 223 | { 224 | unsigned long constantOf32BitWords[64] = { 225 | 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1, 226 | 0x923f82a4,0xab1c5ed5,0xd807aa98,0x12835b01,0x243185be,0x550c7dc3, 227 | 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174,0xe49b69c1,0xefbe4786, 228 | 0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da, 229 | 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147, 230 | 0x06ca6351,0x14292967,0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13, 231 | 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85,0xa2bfe8a1,0xa81a664b, 232 | 0xc24b8b70,0xc76c51a3,0xd192e819,0xd6990624,0xf40e3585,0x106aa070, 233 | 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a, 234 | 0x5b9cca4f,0x682e6ff3,0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208, 235 | 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 236 | }; 237 | 238 | unsigned long static InitialHashValueFor32Bit_0 = 0x6a09e667; 239 | unsigned long static InitialHashValueFor32Bit_1 = 0xbb67ae85; 240 | unsigned long static InitialHashValueFor32Bit_2 = 0x3c6ef372; 241 | unsigned long static InitialHashValueFor32Bit_3 = 0xa54ff53a; 242 | unsigned long static InitialHashValueFor32Bit_4 = 0x510e527f; 243 | unsigned long static InitialHashValueFor32Bit_5 = 0x9b05688c; 244 | unsigned long static InitialHashValueFor32Bit_6 = 0x1f83d9ab; 245 | unsigned long static InitialHashValueFor32Bit_7 = 0x5be0cd19; 246 | 247 | unsigned long Word[64]; 248 | 249 | for(int t = 0; t <= 15; t++) 250 | { 251 | Word[t] = blockOf512BitPaddedMessage[t] & 0xFFFFFFFF; 252 | 253 | if (displayWt) 254 | cout << "Word[" << t << "]: 0x" << displayAsHex(Word[t]) << endl; 255 | } 256 | 257 | for(int t = 16; t <= 63; t++) 258 | { 259 | Word[t] = SSIG1(Word[t-2]) + Word[t-7] + SSIG0(Word[t-15]) + Word[t-16]; 260 | 261 | Word[t] = Word[t] & 0xFFFFFFFF; 262 | 263 | if (displayWt) 264 | cout << "Word[" << t << "]: " << Word[t]; 265 | } 266 | 267 | unsigned long temporary_1; 268 | unsigned long temporary_2; 269 | unsigned long a = InitialHashValueFor32Bit_0; 270 | unsigned long b = InitialHashValueFor32Bit_1; 271 | unsigned long c = InitialHashValueFor32Bit_2; 272 | unsigned long d = InitialHashValueFor32Bit_3; 273 | unsigned long e = InitialHashValueFor32Bit_4; 274 | unsigned long f = InitialHashValueFor32Bit_5; 275 | unsigned long g = InitialHashValueFor32Bit_6; 276 | unsigned long h = InitialHashValueFor32Bit_7; 277 | 278 | if(displayWorkVariablesForT) 279 | cout << " A B C D " 280 | << "E F G H T1 T2\n"; 281 | 282 | for( int t = 0; t < 64; t++) 283 | { 284 | temporary_1 = h + EP1(e) + CH(e,f,g) + constantOf32BitWords[t] + Word[t]; 285 | if ((t == 20) & displayT1Computation) 286 | { 287 | cout << "h: 0x" << hex << h << " dec:" << dec << h 288 | << " sign:" << dec << (int)h << endl; 289 | cout << "EP1(e): 0x" << hex << EP1(e) << " dec:" 290 | << dec << EP1(e) << " sign:" << dec << (int)EP1(e) 291 | << endl; 292 | cout << "CH(e,f,g): 0x" << hex << CH(e,f,g) << " dec:" 293 | << dec << CH(e,f,g) << " sign:" << dec 294 | << (int)CH(e,f,g) << endl; 295 | cout << "constantOf32BitWords[t]: 0x" << hex << constantOf32BitWords[t] << " dec:" << dec 296 | << constantOf32BitWords[t] << " sign:" << dec << (int)constantOf32BitWords[t] << endl; 297 | cout << "Word[t]: 0x" << hex << Word[t] << " dec:" << dec 298 | << Word[t] << " sign:" << dec << (int)Word[t] << endl; 299 | cout << "temporary_1 = 0x" << hex << temporary_1 << " dec:" << dec 300 | << temporary_1 << " sign:" << dec << (int)temporary_1 << endl; 301 | } 302 | 303 | temporary_2 = EP0(a) + MAJ(a,b,c); 304 | 305 | if ((t == 20) & displayT2Computation) 306 | { 307 | cout << "a: 0x" << hex << a << " dec:" << dec << a 308 | << " sign:" << dec << (int)a << endl; 309 | cout << "b: 0x" << hex << b << " dec:" << dec << b 310 | << " sign:" << dec << (int)b << endl; 311 | cout << "c: 0x" << hex << c << " dec:" << dec << c 312 | << " sign:" << dec << (int)c << endl; 313 | cout << "EP0(a): 0x" << hex << EP0(a) << " dec:" 314 | << dec << EP0(a) << " sign:" << dec << (int)EP0(a) 315 | << endl; 316 | cout << "MAJ(a,b,c): 0x" << hex << MAJ(a,b,c) << " dec:" 317 | << dec << MAJ(a,b,c) << " sign:" << dec 318 | << (int)MAJ(a,b,c) << endl; 319 | cout << "temporary_2 = 0x" << hex << temporary_2 << " dec:" << dec 320 | << temporary_2 << " sign:" << dec << (int)temporary_2 << endl; 321 | } 322 | 323 | h = g; 324 | g = f; 325 | f = e; 326 | e = (d + temporary_1) & 0xFFFFFFFF; // Makes sure that we are still using 32 bits. 327 | d = c; 328 | c = b; 329 | b = a; 330 | a = (temporary_1 + temporary_2) & 0xFFFFFFFF; // Makes sure that we are still using 32 bits. 331 | 332 | if (displayWorkVariablesForT) 333 | { 334 | cout << "t= " << t << " "; 335 | cout << displayAsHex (a) << " " << displayAsHex (b) << " " 336 | << displayAsHex (c) << " " << displayAsHex (d) << " " 337 | << displayAsHex (e) << " " << displayAsHex (f) << " " 338 | << displayAsHex (g) << " " << displayAsHex (h) << " " 339 | << endl; 340 | } 341 | } 342 | 343 | if(displayTheHashSegments) 344 | { 345 | cout << "InitialHashValueFor32Bit_0 = " << displayAsHex (InitialHashValueFor32Bit_0) << " + " << displayAsHex (a) 346 | << " " << displayAsHex (InitialHashValueFor32Bit_0 + a) << endl; 347 | cout << "InitialHashValueFor32Bit_1 = " << displayAsHex (InitialHashValueFor32Bit_1) << " + " << displayAsHex (b) 348 | << " " << displayAsHex (InitialHashValueFor32Bit_1 + b) << endl; 349 | cout << "InitialHashValueFor32Bit_2 = " << displayAsHex (InitialHashValueFor32Bit_2) << " + " << displayAsHex (c) 350 | << " " << displayAsHex (InitialHashValueFor32Bit_2 + c) << endl; 351 | cout << "InitialHashValueFor32Bit_3 = " << displayAsHex (InitialHashValueFor32Bit_3) << " + " << displayAsHex (d) 352 | << " " << displayAsHex (InitialHashValueFor32Bit_3 + d) << endl; 353 | cout << "InitialHashValueFor32Bit_4 = " << displayAsHex (InitialHashValueFor32Bit_4) << " + " << displayAsHex (e) 354 | << " " << displayAsHex (InitialHashValueFor32Bit_4 + e) << endl; 355 | cout << "InitialHashValueFor32Bit_5 = " << displayAsHex (InitialHashValueFor32Bit_5) << " + " << displayAsHex (f) 356 | << " " << displayAsHex (InitialHashValueFor32Bit_5 + f) << endl; 357 | cout << "InitialHashValueFor32Bit_6 = " << displayAsHex (InitialHashValueFor32Bit_6) << " + " << displayAsHex (g) 358 | << " " << displayAsHex (InitialHashValueFor32Bit_6 + g) << endl; 359 | cout << "InitialHashValueFor32Bit_7 = " << displayAsHex (InitialHashValueFor32Bit_7) << " + " << displayAsHex (h) 360 | << " " << displayAsHex (InitialHashValueFor32Bit_7 + h) << endl; 361 | } 362 | 363 | InitialHashValueFor32Bit_0 = (InitialHashValueFor32Bit_0 + a) & 0xFFFFFFFF; 364 | InitialHashValueFor32Bit_1 = (InitialHashValueFor32Bit_1 + b) & 0xFFFFFFFF; 365 | InitialHashValueFor32Bit_2 = (InitialHashValueFor32Bit_2 + c) & 0xFFFFFFFF; 366 | InitialHashValueFor32Bit_3 = (InitialHashValueFor32Bit_3 + d) & 0xFFFFFFFF; 367 | InitialHashValueFor32Bit_4 = (InitialHashValueFor32Bit_4 + e) & 0xFFFFFFFF; 368 | InitialHashValueFor32Bit_5 = (InitialHashValueFor32Bit_5 + f) & 0xFFFFFFFF; 369 | InitialHashValueFor32Bit_6 = (InitialHashValueFor32Bit_6 + g) & 0xFFFFFFFF; 370 | InitialHashValueFor32Bit_7 = (InitialHashValueFor32Bit_7 + h) & 0xFFFFFFFF; 371 | 372 | return displayAsHex(InitialHashValueFor32Bit_0) + displayAsHex(InitialHashValueFor32Bit_1) + displayAsHex(InitialHashValueFor32Bit_2) + 373 | displayAsHex(InitialHashValueFor32Bit_3) + displayAsHex(InitialHashValueFor32Bit_4) + displayAsHex(InitialHashValueFor32Bit_5) + 374 | displayAsHex(InitialHashValueFor32Bit_6) + displayAsHex(InitialHashValueFor32Bit_7); 375 | } -------------------------------------------------------------------------------- /Chapter 20 - Integral Cryptanalysis/integral.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | //** VARIABLES 6 | //** the sBox structure 7 | int sboxValue[16] = {9, 11, 12, 4, 10, 1, 2, 6, 13, 7, 3, 8, 15, 14, 0, 5}; 8 | //** the revision sBox value structure 9 | int revision_sbox_value[16] = {14, 5, 6, 10, 3, 15, 7, 9, 11, 0, 4, 1, 2, 8, 13, 12}; 10 | //** an approximation array 11 | int approximation_array_structure[16][16]; 12 | //** the maximum score which will need to be compared with the "score" variable 13 | int maximum_score = 0; 14 | //** the total value 15 | int total_value = 0; 16 | //** control counters, 1 and 2 17 | int counter1; 18 | int counter2; 19 | //** generating known plaintext 20 | int known_plaintext[500]; 21 | //** generating known ciphertext 22 | int known_ciphertext[500]; 23 | //** number of generated known pairs 24 | int known_numbers = 0; 25 | //** approximation values, for input and output 26 | int approximation_for_input = 11; 27 | int approximation_for_output = 11; 28 | //** score value for the cryptography key 29 | int cryptographyKey_score_value[16]; 30 | //** the threshold level. used for identitying the step until we reached for finding the cryptography keys 31 | int threshold_level = 0; 32 | //** good reliable cryptography key 33 | int reliable_crypto_keys[16]; 34 | //** the values for the guessed cryptography key 35 | int guessing_crypto_key1, guessing_crypto_key2; 36 | //** testing control variable for cryptography key 37 | int cryptoKey1_testing; 38 | 39 | //** apply the mask 40 | int applying_the_mask(int theValue, int mask_value) 41 | { 42 | int internal_value = theValue & mask_value; 43 | int total_value = 0; 44 | 45 | while(internal_value > 0) 46 | { 47 | int temporary = internal_value % 2; 48 | internal_value /= 2; 49 | 50 | if (temporary == 1) 51 | total_value = total_value ^ 1; 52 | } 53 | return total_value; 54 | } 55 | 56 | //** detecting the approximation 57 | void detect_the_approximation() 58 | { 59 | int a, b, c; 60 | 61 | //** parsing for the output mask. 16 represents the size of the s-Box 62 | for(a = 1; a < 16; a++) 63 | { 64 | //** parsing for the input mask 65 | for(b = 1; b < 16; b++) 66 | { 67 | //** parsing the input 68 | for(c = 0; c < 16; c++) 69 | { 70 | if (applying_the_mask(c, b) == applying_the_mask(sboxValue[c], a)) 71 | approximation_array_structure[b][a]++; 72 | } 73 | } 74 | } 75 | } 76 | 77 | //** show and display the approximation 78 | void display_the_approximation() 79 | { 80 | printf("Integral Values Approximations: \n"); 81 | int a, b, c; 82 | for(a = 1; a < 16; a++) 83 | { 84 | for(b = 1; b < 16; b++) 85 | { 86 | if (approximation_array_structure[a][b] == 14) 87 | printf(" %i : %i {<-->} %i\n", approximation_array_structure[a][b], a, b); 88 | } 89 | } 90 | 91 | printf("\n"); 92 | } 93 | 94 | //** round function for s 95 | int rounding_procedure(int dataInput, int substitution_key) 96 | { 97 | return sboxValue[dataInput ^ substitution_key]; 98 | } 99 | 100 | //** filling the knowings possible key values 101 | void filling_up_the_knowings() 102 | { 103 | 104 | int substitution_key_1 = rand() % 16; 105 | int substitution_key_2 = rand() % 16; 106 | 107 | printf("Generating Data: Key 1 = %i, Key 2 = %i\n", substitution_key_1, substitution_key_2); 108 | 109 | //** parse each known value and for each known plaintext and ciphertext compute the proper values 110 | for(counter1 = 0; counter1 < known_numbers; counter1++) 111 | { 112 | known_plaintext[counter1] = rand() % 16; 113 | known_ciphertext[counter1] = rounding_procedure(rounding_procedure(known_plaintext[counter1], substitution_key_1), substitution_key_2); 114 | } 115 | 116 | printf("Generating Data: We have generated %i known pairs\n\n", known_numbers); 117 | } 118 | 119 | //** verify and test the cryptography keys 120 | void testing_the_keys(int key_1, int key_2) 121 | { 122 | for(counter2 = 0; counter2 < known_numbers; counter2++) 123 | if (rounding_procedure(rounding_procedure(known_plaintext[counter2], key_1), key_2) != known_ciphertext[counter2]) 124 | break; 125 | 126 | printf("* "); 127 | } 128 | 129 | int main() 130 | { 131 | printf("Testing Program for Integral Cryptanalysis\n\n"); 132 | 133 | srand(time(NULL)); 134 | 135 | detect_the_approximation(); 136 | display_the_approximation(); 137 | 138 | known_numbers = 16; 139 | filling_up_the_knowings(); 140 | 141 | printf("Integral Cryptanalysis Attack --> Based on Linear Approximation = %i {<-->} %i\n", approximation_for_input, approximation_for_output); 142 | 143 | int c, d; 144 | for(c = 0; c < 16; c++) 145 | { 146 | cryptographyKey_score_value[c] = 0; 147 | for(d = 0; d < known_numbers; d++) 148 | { 149 | threshold_level++; 150 | int midRound = rounding_procedure(known_plaintext[d], c); //Find Xi by guessing at K1 151 | 152 | if ((applying_the_mask(midRound, approximation_for_input) == applying_the_mask(known_ciphertext[d], approximation_for_output))) 153 | cryptographyKey_score_value[c]++; 154 | else 155 | cryptographyKey_score_value[c]--; 156 | } 157 | } 158 | 159 | for(c = 0; c < 16; c++) 160 | { 161 | int score = cryptographyKey_score_value[c] * cryptographyKey_score_value[c]; 162 | if (score > maximum_score) maximum_score = score; 163 | } 164 | 165 | for(d = 0; d < 16; d++) 166 | { 167 | reliable_crypto_keys[d] = -1; 168 | } 169 | 170 | d = 0; 171 | 172 | for(c = 0; c < 16; c++) 173 | { 174 | if ((cryptographyKey_score_value[c] * cryptographyKey_score_value[c]) == maximum_score) 175 | { 176 | reliable_crypto_keys[d] = c; 177 | printf("Integral Cryptanalysis Attack --> Candidate for K1 = %i\n", reliable_crypto_keys[d]); 178 | d++; 179 | } 180 | } 181 | 182 | for(d = 0; d < 16; d++) 183 | { 184 | if (reliable_crypto_keys[d] != -1) 185 | { 186 | cryptoKey1_testing = rounding_procedure(known_plaintext[0], reliable_crypto_keys[d]) ^ revision_sbox_value[known_ciphertext[0]]; 187 | 188 | int tested = 0; 189 | int e; 190 | int bad = 0; 191 | for(e = 0;e < known_numbers; e++) 192 | { 193 | threshold_level += 2; 194 | int testOut = rounding_procedure(rounding_procedure(known_plaintext[e], reliable_crypto_keys[d]), cryptoKey1_testing); 195 | if (testOut != known_ciphertext[e]) 196 | bad = 1; 197 | } 198 | if (bad == 0) 199 | { 200 | printf("Integral Cryptanalysis Attack --> We have found the cryptography keys! Crypto Key 1 = %i, Crypto Key 2 = %i\n", reliable_crypto_keys[d], cryptoKey1_testing); 201 | guessing_crypto_key1 = reliable_crypto_keys[d]; 202 | guessing_crypto_key2 = cryptoKey1_testing; 203 | printf("Integral Cryptanalysis Attack --> Number of computations for reaching the cryptography key = %i\n", threshold_level); 204 | 205 | } 206 | 207 | } 208 | } 209 | 210 | printf("Integral Cryptanalysis Attack --> Computations Total = %i\n\n", threshold_level); 211 | 212 | threshold_level = 0; 213 | 214 | for(d = 0; d < 16; d++) 215 | { 216 | for(c = 0; c < 16; c++) 217 | { 218 | 219 | int e; 220 | int bad = 0; 221 | for(e = 0;e < known_numbers; e++) 222 | { 223 | threshold_level += 2; 224 | int testOut = rounding_procedure(rounding_procedure(known_plaintext[e], d), c); 225 | if (testOut != known_ciphertext[e]) 226 | bad = 1; 227 | } 228 | if (bad == 0) 229 | { 230 | printf("Brute Force --> We have found the cryptography keys! Crypto Key 1 = %i, Crypto Key 2 = %i\n", d, c); 231 | printf("Brute Force --> Number of computations for reaching the cryptography key = %i\n", threshold_level); 232 | } 233 | } 234 | 235 | } 236 | 237 | printf("Brute Force --> Total computations number = %i\n", threshold_level); 238 | 239 | //while(1){} 240 | } -------------------------------------------------------------------------------- /Chapter 20 - Integral Cryptanalysis/integral.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/pro-cryptography-cryptanalysis-cpp20/462331a454e32be1c768c7aee079b335510adcef/Chapter 20 - Integral Cryptanalysis/integral.exe -------------------------------------------------------------------------------- /Chapter 21 - Brute Force and Buffer Overflow Attacks/BasicStringGenerationBFAttack/strings_brute_force.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | // We are using a linked list data structure. 6 | // The reasong is to avoid some of the restrictions 7 | // based on the generation of the string length. 8 | // Our list has to be converted to string in 9 | // such way that it can be used. The current conversion 10 | // might be a little slower comparing with other methods 11 | // due to the fact that the conversion is happening with 12 | // each cycle. 13 | 14 | // Another solution consists in implementing a solution based 15 | // on the generation of the allocation for the string with 16 | // a fixed size equal with 20 characters (which is more than 17 | // enough. 18 | 19 | // the structure definition for holding the characters (strings) 20 | typedef struct charactersList charlist_t; 21 | struct charactersList 22 | { 23 | // the character 24 | unsigned char character; 25 | // the next character 26 | charlist_t* nextCharacter; 27 | }; 28 | 29 | // The method will return a new initialized charlist_t element. 30 | // The element returned is charlist_t 31 | charlist_t* new_characterList_element() 32 | { 33 | charlist_t* elementFromTheList; 34 | 35 | if ((elementFromTheList = (charlist_t*) malloc(sizeof(charlist_t))) != 0) 36 | { 37 | elementFromTheList->character = 0; 38 | elementFromTheList->nextCharacter = NULL; 39 | } 40 | else 41 | { 42 | perror("The allocation using malloc() has failed."); 43 | } 44 | 45 | return elementFromTheList; 46 | } 47 | 48 | // allocation free memory by the characters list 49 | // listOfCharacters - represents a pointer for the first element within the list 50 | void freeAllocation_CharactersList(charlist_t* listOfCharacters) 51 | { 52 | charlist_t* currentCharacter = listOfCharacters; 53 | charlist_t* nextCharacter; 54 | 55 | while (currentCharacter != NULL) 56 | { 57 | nextCharacter = currentCharacter->nextCharacter; 58 | free(currentCharacter); 59 | currentCharacter = nextCharacter; 60 | } 61 | } 62 | 63 | 64 | // the function display the current list of characters 65 | // the function will iterate through the whole list and it will print all the characters 66 | void showCharactersList(charlist_t* list) 67 | { 68 | charlist_t* nextCharacter = list; 69 | while (nextCharacter != NULL) 70 | { 71 | printf("%d ", nextCharacter->character); 72 | nextCharacter = nextCharacter->nextCharacter; 73 | } 74 | printf("\n"); 75 | } 76 | 77 | // the function will return the next sequence of characters. 78 | // the characters are treated as numbers 0-255 79 | // the function proceeds by incrementation of the character from the first position 80 | void nextCharactersSequence(charlist_t* listOfCharacters) 81 | { 82 | listOfCharacters->character++; 83 | if (listOfCharacters->character == 0) 84 | { 85 | if (listOfCharacters->nextCharacter == NULL) 86 | { 87 | listOfCharacters->nextCharacter = new_characterList_element(); 88 | } 89 | else 90 | { 91 | nextCharactersSequence(listOfCharacters->nextCharacter); 92 | } 93 | } 94 | } 95 | 96 | int main() 97 | { 98 | charlist_t* sequenceOfCharacters; 99 | sequenceOfCharacters = new_characterList_element(); 100 | 101 | // this while will work for all possibles combinations 102 | // this has to be stopped manually 103 | while (1) 104 | { 105 | nextCharactersSequence(sequenceOfCharacters); 106 | showCharactersList(sequenceOfCharacters); 107 | } 108 | 109 | freeAllocation_CharactersList(sequenceOfCharacters); 110 | } -------------------------------------------------------------------------------- /Chapter 21 - Brute Force and Buffer Overflow Attacks/BasicStringGenerationBFAttack/strings_brute_force.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/pro-cryptography-cryptanalysis-cpp20/462331a454e32be1c768c7aee079b335510adcef/Chapter 21 - Brute Force and Buffer Overflow Attacks/BasicStringGenerationBFAttack/strings_brute_force.exe -------------------------------------------------------------------------------- /Chapter 21 - Brute Force and Buffer Overflow Attacks/BufferOverflowAttack/buffer_overflow_attack.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(int argc, char *argv[]) 6 | { 7 | // We allocate a buffer of 5 bytes which includes also the termination, NULL. 8 | // The allocation should be done as 8 bytes which is two double words. 9 | // For overflowing process we will need more than 8 bytes. 10 | 11 | // if the user provides more than 8 characters for the input, 12 | // an access violation and fault segmentation 13 | char buffer_test_example[5]; 14 | // execution of the program 15 | if (argc < 2) 16 | { 17 | printf("Function strcpy() will not be executed...\n"); 18 | printf("The syntax: %s \n", argv[0]); 19 | exit(0); 20 | } 21 | 22 | // Take the input from the user and copy it to the buffer. 23 | // The process is done without verifying the bound 24 | strcpy(buffer_test_example, argv[1]); 25 | printf("The content of thebuffer -> %s\n", buffer_test_example); 26 | 27 | printf("The function strcpy() is being executed...\n"); 28 | 29 | return 0; 30 | } -------------------------------------------------------------------------------- /Chapter 21 - Brute Force and Buffer Overflow Attacks/BufferOverflowAttack/buffer_overflow_attack.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/pro-cryptography-cryptanalysis-cpp20/462331a454e32be1c768c7aee079b335510adcef/Chapter 21 - Brute Force and Buffer Overflow Attacks/BufferOverflowAttack/buffer_overflow_attack.exe -------------------------------------------------------------------------------- /Chapter 21 - Brute Force and Buffer Overflow Attacks/CaesarBruteForceAttack/caesar_brute_force.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | // the function will be used to encrypt the plaintext 5 | // string msg - the message 6 | // int keytValue - the key 7 | string encrypt(string msg,int keyValue) 8 | { 9 | // variable used to hold the cipher value of the plaintext 10 | string cipher=""; 11 | 12 | // parse the string 13 | for(int i=0;i " << keyTry << " :- " << plaintext << endl; 66 | } 67 | } 68 | 69 | int main() 70 | { 71 | int encKey; 72 | string cleartext; 73 | cout << "ENCRYPTION - Enter the text for encryption -> "; 74 | getline(cin,cleartext); 75 | 76 | cout << "Enter the key for encryption the text -> "; 77 | cin >> encKey; 78 | 79 | string encryptedMessage = encrypt(cleartext,encKey); 80 | cout << "ENCRYPTED MESSAGE - The encrypted message is -> " << encryptedMessage << endl << endl; 81 | 82 | //** brute force attack 83 | decrypt(encryptedMessage); 84 | } -------------------------------------------------------------------------------- /Chapter 21 - Brute Force and Buffer Overflow Attacks/CaesarBruteForceAttack/caesar_brute_force.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/pro-cryptography-cryptanalysis-cpp20/462331a454e32be1c768c7aee079b335510adcef/Chapter 21 - Brute Force and Buffer Overflow Attacks/CaesarBruteForceAttack/caesar_brute_force.exe -------------------------------------------------------------------------------- /Chapter 22 - Text Characterization/22-1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() 5 | { 6 | const int number_of_experiments=10000; 7 | const int number_of_stars_distribution=100; // maximum number of stars to distribute 8 | 9 | std::default_random_engine theGenerator; 10 | std::chi_squared_distribution theDistribution(6.0); 11 | 12 | int p[10]={}; 13 | 14 | for (int i=0; i=0.0)&&(no<10.0)) ++p[int(no)]; 18 | } 19 | 20 | std::cout << "chi_squared_distribution (6.0):" << std::endl; 21 | 22 | for (int i=0; i<10; ++i) { 23 | std::cout << i << "-" << (i+1) << ": "; 24 | std::cout << std::string(p[i]*number_of_stars_distribution/number_of_experiments,'*') << std::endl; 25 | } 26 | 27 | return 0; 28 | } -------------------------------------------------------------------------------- /Chapter 22 - Text Characterization/22-1.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/pro-cryptography-cryptanalysis-cpp20/462331a454e32be1c768c7aee079b335510adcef/Chapter 22 - Text Characterization/22-1.exe -------------------------------------------------------------------------------- /Chapter 22 - Text Characterization/22-2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(void) 4 | { 5 | int alphabet_counting['z' - 'a' + 1]['z' - 'a' + 1] = {{ 0 }}; 6 | int character0 = EOF, character1; 7 | FILE *fileBigramSampleText = fopen("bigram.txt", "r"); 8 | 9 | if (fileBigramSampleText != NULL) 10 | { 11 | while ((character1 = getc(fileBigramSampleText)) != EOF) 12 | { 13 | if (character1 >= 'a' && character1 <= 'z' && character0 >= 'a' && character0 <= 'z') 14 | { 15 | alphabet_counting[character0 - 'a'][character1 - 'a']++; 16 | } 17 | character0 = character1; 18 | } 19 | fclose(fileBigramSampleText); 20 | for (character0 = 'a'; character0 <= 'z'; character0++) 21 | { 22 | for (character1 = 'a'; character1 <= 'z'; character1++) 23 | { 24 | int number = alphabet_counting[character0 - 'a'][character1 - 'a']; 25 | if (number) 26 | { 27 | printf("%c%c: %d\n", character0, character1, number); 28 | } 29 | } 30 | } 31 | } 32 | return 0; 33 | } -------------------------------------------------------------------------------- /Chapter 22 - Text Characterization/22-2.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/pro-cryptography-cryptanalysis-cpp20/462331a454e32be1c768c7aee079b335510adcef/Chapter 22 - Text Characterization/22-2.exe -------------------------------------------------------------------------------- /Chapter 22 - Text Characterization/22-3.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(void) 5 | { 6 | // the last five bytes corresponds to ISO/IEC 8859-9 7 | const char alphabet[] = "abcdefghijklmnopqrstuvwxyz\xFD\xFxE7\xF6\xFC"; 8 | const int length_of_alphabet = (sizeof(alphabet) - 1); 9 | int count[length_of_alphabet][length_of_alphabet]; 10 | char *position0 = NULL; 11 | int character1; 12 | FILE *fileTextForCountingBigrams = fopen("bigram.txt", "r"); 13 | 14 | memset(count, 0, sizeof(count)); 15 | 16 | if (fileTextForCountingBigrams != NULL) 17 | { 18 | while ((character1 = getc(fileTextForCountingBigrams)) != EOF) 19 | { 20 | char *p1 = (char*)memchr(alphabet, character1, length_of_alphabet); 21 | if (p1 != NULL && position0 != NULL) 22 | { 23 | count[position0 - alphabet][p1 - alphabet]++; 24 | } 25 | position0 = p1; 26 | } 27 | fclose(fileTextForCountingBigrams); 28 | for (size_t i = 0; i < length_of_alphabet; i++) 29 | { 30 | for (size_t j = 0; j < length_of_alphabet; j++) 31 | { 32 | int n = count[i][j]; 33 | if (n > 0) 34 | { 35 | printf("%c%c: %d\n", alphabet[i], alphabet[j], n); 36 | } 37 | } 38 | } 39 | } 40 | return 0; 41 | } -------------------------------------------------------------------------------- /Chapter 22 - Text Characterization/22-3.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/pro-cryptography-cryptanalysis-cpp20/462331a454e32be1c768c7aee079b335510adcef/Chapter 22 - Text Characterization/22-3.exe -------------------------------------------------------------------------------- /Chapter 22 - Text Characterization/22-4.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | void printTrigramOccurance(string fullText, string trigramPattern) 5 | { 6 | int occurance = fullText.find(trigramPattern); 7 | while (occurance!= string::npos) 8 | { 9 | cout << "Pattern found at index " << occurance << endl; 10 | occurance = fullText.find(trigramPattern, occurance + 1); 11 | } 12 | } 13 | int main() 14 | { 15 | string fullText = "Welcome to Apress."; 16 | string trigramPattern = "Apr"; 17 | printTrigramOccurance(fullText, trigramPattern); 18 | } 19 | -------------------------------------------------------------------------------- /Chapter 22 - Text Characterization/22-4.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/pro-cryptography-cryptanalysis-cpp20/462331a454e32be1c768c7aee079b335510adcef/Chapter 22 - Text Characterization/22-4.exe -------------------------------------------------------------------------------- /Chapter 22 - Text Characterization/bigram.txt: -------------------------------------------------------------------------------- 1 | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. -------------------------------------------------------------------------------- /Chapter 23 - Implementation of Cryptanalysis Methods/random_keys.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | //** generate an integer that is situated between 1 to 4 8 | int generateInteger() 9 | { 10 | //** pseudo-random generator (srand). time(NULL) represents the seed 11 | srand(time(NULL)); 12 | 13 | //** generate a random value and store the remainder of rand() to 5 14 | int randomValue = rand() % 5; 15 | 16 | //** if the value is equal with 0, move to the next value of i and return that value 17 | if (randomValue == 0) 18 | randomValue++; 19 | return randomValue; 20 | } 21 | 22 | //** the function will generate randomly an integer situated between 0 and 25 23 | int generateRandomlyInteger() 24 | { 25 | //** pseudo-random generator (srand). time(NULL) represents the seed 26 | srand(time(NULL)); 27 | 28 | //** generate a random value and store the remainder of rand() with 26 29 | int random_key = rand() % 26; 30 | return random_key; 31 | } 32 | 33 | //** based on the length provided, the function will generate a cryptographic key 34 | void generate_crypto_key(int length) 35 | { 36 | //** create a string variable for cryptography key and initialize it with NULL 37 | string crypto_key = ""; 38 | 39 | //** variable used for cryptography key generation 40 | string alphabet_lower_case = "abcdefghijklmnopqrstuvwxyz"; 41 | string alphabet_upper_case = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 42 | string special_symbols = "!@#$%&"; 43 | string digits_and_numbers = "0123456789"; 44 | 45 | //** local variables and their initializations 46 | int key_seed; 47 | int lowerCase_Alphabet_Count = 0; 48 | int upperCase_Alphabet_Count = 0; 49 | int digits_And_numbers_count = 0; 50 | int special_symbols_count = 0; 51 | 52 | //** the variable count will save the length of the cryptography key. initially we will set it to zero 53 | int countingLengthCryptoKey = 0; 54 | while (countingLengthCryptoKey < length) 55 | { 56 | //** generateInteger() function will return a number that is situated between 1 and 4. 57 | //** The number that is generated will be used in assignation with one of the strings that has been defined above (for example: alphabet_lower_case, alphabet_upper_case, special_symbols, and digits_and_numbers). 58 | //** This being said, the following correspondence will be applied: (1) for alphabet_lower_case, (2) for alphabet_upper_case, (3) for special_symbols, and (4) digits_and_numbers 59 | int string_type = generateInteger(); 60 | 61 | //** For the first character of the cryptography key we will put a rule in such way that it should be a letter, in such way that the string that will be selected will be an lower case alphabet or an upper case alphabet. The IF condition is quite vital as the switch is based on it and the value that string_type variable will have. 62 | if (countingLengthCryptoKey == 0) 63 | { 64 | string_type = string_type % 3; 65 | if (string_type == 0) 66 | string_type++; 67 | } 68 | 69 | switch (string_type) 70 | { 71 | case 1: 72 | //** based on the IF condition, it is necessary to check the minimum requirements of the lower case alphabet characters if they have been accomplished and fulfilled. If we are dealing with the situation in which the requirement has not been achieved we will situate ourself in the break phase. 73 | if ((lowerCase_Alphabet_Count == 2) 74 | && (digits_And_numbers_count == 0 75 | || upperCase_Alphabet_Count == 0 76 | || upperCase_Alphabet_Count == 1 77 | || special_symbols_count == 0)) 78 | break; 79 | 80 | key_seed = generateRandomlyInteger(); 81 | crypto_key = crypto_key + alphabet_lower_case[key_seed]; 82 | lowerCase_Alphabet_Count++; 83 | countingLengthCryptoKey++; 84 | break; 85 | 86 | case 2: 87 | //** based on the IF condition, it is necessary to check the minimum requirements of the upper case alphabet characters if they have been accomplished and fulfilled. If we are dealing with the situation in which the requirement has not been achieved we will situate ourself in the break phase. 88 | if ((upperCase_Alphabet_Count == 2) 89 | && (digits_And_numbers_count == 0 90 | || lowerCase_Alphabet_Count == 0 91 | || lowerCase_Alphabet_Count == 1 92 | || special_symbols_count == 0)) 93 | break; 94 | key_seed = generateRandomlyInteger(); 95 | crypto_key = crypto_key + alphabet_upper_case[key_seed]; 96 | upperCase_Alphabet_Count++; 97 | countingLengthCryptoKey++; 98 | break; 99 | 100 | case 3: 101 | //** based on the IF condition, it is necessary to check the minimum requirements of the numbers if they have been accomplished and fulfilled. If we are dealing with the situation in which the requirement has not been achieved we will situate ourself in the break phase. 102 | if ((digits_And_numbers_count == 1) 103 | && (lowerCase_Alphabet_Count == 0 104 | || lowerCase_Alphabet_Count == 1 105 | || upperCase_Alphabet_Count == 1 106 | || upperCase_Alphabet_Count == 0 107 | || special_symbols_count == 0)) 108 | break; 109 | 110 | key_seed = generateRandomlyInteger(); 111 | key_seed = key_seed % 10; 112 | crypto_key = crypto_key + digits_and_numbers[key_seed]; 113 | digits_And_numbers_count++; 114 | countingLengthCryptoKey++; 115 | break; 116 | 117 | case 4: 118 | //** based on the IF condition, it is necessary to check the minimum requirements of the special characters if they have been accomplished and fulfilled. If we are dealing with the situation in which the requirement has not been achieved we will situate ourself in the break phase. 119 | if ((special_symbols_count == 1) 120 | && (lowerCase_Alphabet_Count == 0 121 | || lowerCase_Alphabet_Count == 1 122 | || upperCase_Alphabet_Count == 0 123 | || upperCase_Alphabet_Count == 1 124 | || digits_And_numbers_count == 0)) 125 | break; 126 | 127 | key_seed = generateRandomlyInteger(); 128 | key_seed = key_seed % 6; 129 | crypto_key = crypto_key + special_symbols[key_seed]; 130 | special_symbols_count++; 131 | countingLengthCryptoKey++; 132 | break; 133 | } 134 | } 135 | 136 | cout << "\n-----------------------------\n"; 137 | cout << " Cryptography Key \n"; 138 | cout << "------------------------------\n\n"; 139 | cout << " " << crypto_key; 140 | cout << "\n\nPress any key to continue... \n"; 141 | getchar(); 142 | } 143 | 144 | int main() 145 | { 146 | int option; 147 | int desired_length; 148 | 149 | //** designing the menu 150 | do 151 | { 152 | cout << "\n-------------------------------------\n"; 153 | cout << " Random Cryptography Key Generator \n"; 154 | cout << "-------------------------------------\n\n"; 155 | cout << " 1 --> Generate a Cryptography Key" 156 | << "\n"; 157 | cout << " 2 --> Quit the program" 158 | << "\n\n"; 159 | cout << "Enter 1 for Generating Cryptograpy Key or 2 to quit the program : "; 160 | cin >> option; 161 | 162 | switch (option) 163 | { 164 | case 1: 165 | cout << "Set the length to : "; 166 | cin >> desired_length; 167 | 168 | //** if the length entered is less than 7, an error will be shown 169 | if (desired_length < 7) 170 | { 171 | cout << "\nError Mode : The Cryptography Key Length hould be at least 7\n"; 172 | cout << "Press a key and try again \n"; 173 | getchar(); 174 | } 175 | //** The desired length should bot be bigger than 100, otherwise an error will be shown 176 | else if (desired_length > 100) 177 | { 178 | cout << "\nError Mode : The maximum length of the cryptography key should be 100\n"; 179 | cout << "Press a key and try again \n"; 180 | getchar(); 181 | } 182 | 183 | //** in ohter cases, call generate_crypto_key() function to generate a cryptography key 184 | else 185 | generate_crypto_key(desired_length); 186 | break; 187 | 188 | default: 189 | //** in case if an invalid option is entered, show to the user an error message 190 | if (option != 2) 191 | { 192 | printf("\nOups! You have entered a choice that doesn't exist\n"); 193 | printf("Enter ( 1 ) to generate cryptography key and ( 2 ) to quit the program.\n"); 194 | cout << "Enter a key and try again \n"; 195 | getchar(); 196 | } 197 | break; 198 | } 199 | } while (option != 2); 200 | 201 | return 0; 202 | } -------------------------------------------------------------------------------- /Chapter 23 - Implementation of Cryptanalysis Methods/random_keys.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/pro-cryptography-cryptanalysis-cpp20/462331a454e32be1c768c7aee079b335510adcef/Chapter 23 - Implementation of Cryptanalysis Methods/random_keys.exe -------------------------------------------------------------------------------- /Chapter 3 - Mathematical Background and Its Applicability/CaseStudy1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | enum ColorTypes { 7 | Blue, 8 | NotBlue } ; 9 | 10 | //** create a sequence container 11 | typedef std::vector backpack; 12 | 13 | backpack initializeBackpack(unsigned blue_balls, unsigned differentBalls) 14 | { 15 | backpack backpackOfBalls ; 16 | for (unsigned i=0; i(theFirstIsBlue) / theTotalOfSamples; 69 | 70 | float probabilityForBothBallsToBeBlue = 71 | static_cast(bothAreBlue) / theTotalOfSamples; 72 | 73 | float probabilityForSecondBallToBeRed = 74 | static_cast(theSecondIsBlue) / theTotalOfSamples; 75 | 76 | std::cout << "Probability for the first ball to be blue: " 77 | << probabilityOfFirstBallToBeBlue * 100.0 << "%\n" ; 78 | 79 | std::cout << "Probability for the second ball to be blue: " 80 | << probabilityForSecondBallToBeRed * 100.0 << "%\n" ; 81 | 82 | std::cout << "Probability for both balls to be blue: " 83 | << probabilityForBothBallsToBeBlue * 100.0 << "%\n" ; 84 | } -------------------------------------------------------------------------------- /Chapter 3 - Mathematical Background and Its Applicability/CaseStudy10.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "legendre.h" 3 | 4 | using namespace std ; 5 | using namespace LegendreStorage::Legendre ; 6 | 7 | int main() 8 | { 9 | double p_n; 10 | 11 | cout.precision(5) ; 12 | for (unsigned int v = 0 ; v <= 5 ; v++) 13 | { 14 | for (double b = -1.0 ; b <= 1.0 ; b = b + 0.1) 15 | { 16 | p_n = Polynom_n(v, b) ; 17 | cout << "P" << v << "(" << b << ") = " << p_n << endl ; 18 | } 19 | cout << endl ; 20 | } 21 | 22 | return 0 ; 23 | } -------------------------------------------------------------------------------- /Chapter 3 - Mathematical Background and Its Applicability/CaseStudy2.cpp: -------------------------------------------------------------------------------- 1 | //** this will be used for computing the distribution 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | int main() 8 | { 9 | //** declare default_random_engine object 10 | //** we will use it as a random number 11 | //** we will provide a seed for default_random_engine 12 | //** if a pseudo random is necessary 13 | default_random_engine gen; 14 | 15 | double x=0.0, y=1.0; 16 | 17 | // Initializing of uniform_real_distribution class 18 | uniform_real_distribution dist(x, y); 19 | 20 | //** the number of experiments 21 | const int numberOfExperiments = 10000000; 22 | 23 | //** the number of ranges 24 | int numberOfRanges = 100; 25 | int probability[numberOfRanges] = {}; 26 | for (int k = 0; k < numberOfExperiments; ++k) { 27 | 28 | // using operator() function 29 | // to give random values 30 | double no = dist(gen); 31 | ++probability[int(no * numberOfRanges)]; 32 | } 33 | 34 | cout << "Probability of some ranges" << endl; 35 | // Displaying the probability of some ranges 36 | // after generating values 10000 times. 37 | cout << "0.50-0.51" 38 | << " " << (float)probability[50]/(float)numberOfExperiments< 2 | #include 3 | #include 4 | 5 | int main() 6 | { 7 | //** the constant represents the number of experiments 8 | const int numberOfExperiments=10000; 9 | //** the constant represents the 10 | //** maximum number of stars to distribute 11 | const int numberOfStarsToDistribute=100; 12 | 13 | std::default_random_engine g; 14 | std::normal_distribution dist(6.0,3.0); 15 | 16 | int prob[10]={}; 17 | 18 | for (int k=0; k=0.0)&&(no<10.0)) ++prob[int(no)]; 21 | } 22 | 23 | std::cout << "the mean distribution (6.0,3.0):" << std::endl; 24 | 25 | for (int l=0; l<10; ++l) { 26 | std::cout << l << "-" << (l+1) << ": "; 27 | std::cout << std::string(prob[l]*numberOfStarsToDistribute/numberOfExperiments,'*') << std::endl; 28 | } 29 | 30 | return 0; 31 | } -------------------------------------------------------------------------------- /Chapter 3 - Mathematical Background and Its Applicability/CaseStudy4.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | //** the below function is used 6 | //** for computing the variance 7 | int computingVariance(int n[], int h) //**a=n, n=h 8 | { 9 | //** will compute the mean 10 | //** average of the elements 11 | int sum = 0; 12 | for (int k = 0; k < h; k++) 13 | sum += n[k]; 14 | double theMean = (double)sum / 15 | (double)h; 16 | 17 | //** calculate the sum squared 18 | //** differences with the mean 19 | double squared_differences = 0; 20 | for (int t=0; t 2 | #include 3 | 4 | using namespace std; 5 | 6 | float computeStandardDeviation(float data[]); 7 | 8 | int main() 9 | { 10 | int n; 11 | float elements_array[10]; 12 | 13 | cout << "Add 10 elements: "; 14 | for(n = 0; n < 10; ++n) 15 | cin >> elements_array[n]; 16 | 17 | cout << endl << "The Standard Deviation is = " << computeStandardDeviation(elements_array); 18 | 19 | return 0; 20 | } 21 | 22 | float computeStandardDeviation(float elements_array[]) 23 | { 24 | float theSum = 0.0, theMean, theStandardDeviation = 0.0; 25 | 26 | int j,k; 27 | 28 | for(j = 0; j < 10; ++j) 29 | { 30 | theSum += elements_array[j]; 31 | } 32 | 33 | theMean = theSum/10; 34 | 35 | for(k = 0; k < 10; ++k) 36 | theStandardDeviation += pow(elements_array[k] - theMean, 2); 37 | 38 | return sqrt(theStandardDeviation / 10); 39 | } -------------------------------------------------------------------------------- /Chapter 3 - Mathematical Background and Its Applicability/CaseStudy6.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | int main(int argc, const char *argv[]) 8 | { 9 | const int processes = 15000; 10 | short int no_of_birthdays[365]; 11 | int processesWithSuccess; 12 | bool IsSharedBirthday; 13 | 14 | //** we will time(NULL) as seed to be used for the 15 | //** pseudo-random number generator srand() 16 | srand(time(NULL)); 17 | 18 | for (int no_of_people = 2; no_of_people < 45; ++no_of_people) 19 | { 20 | processesWithSuccess = 0; 21 | for (int i = 0; i < processes; ++i) 22 | { 23 | //** all birthdays will be set to 0 24 | for (int j = 0; j < 365; no_of_birthdays[j++] = 0); 25 | IsSharedBirthday = false; 26 | for (int j = 0; j < no_of_people; ++j) 27 | { 28 | //** if our given birthday is shared (this means that is assigned for more than one person) 29 | //** this will be a shared birthday and we will need to stop verifying. 30 | if (++no_of_birthdays[rand() % 365] > 1) 31 | { 32 | IsSharedBirthday = true; 33 | break; 34 | } 35 | } 36 | if (IsSharedBirthday) ++processesWithSuccess; 37 | } 38 | 39 | cout << "The probability for " << no_of_people << " people from the same room to share the same birthday is \t" 40 | << ( float(processesWithSuccess) / float(processes) ) << endl; 41 | } 42 | return 0; 43 | } -------------------------------------------------------------------------------- /Chapter 3 - Mathematical Background and Its Applicability/CaseStudy7_1.cpp: -------------------------------------------------------------------------------- 1 | //** NOTE: bits/stdc++ does not represent 2 | //** a standard header file of GNU C++ library. 3 | //** If the code will be compiled with other 4 | //** compilers than GCC it will fail 5 | #include 6 | 7 | using namespace std; 8 | 9 | //** the function will compute 10 | //** the GCD for two number 11 | int g(int x, int y) 12 | { 13 | if (x == 0) 14 | return y; 15 | return g(y % x, x); 16 | } 17 | 18 | 19 | int main() 20 | { 21 | int x = 10, y = 15; 22 | cout << "Euclid GCD(" << x << ", " 23 | << y << ") = " << g(x, y) 24 | << endl; 25 | x = 35, y = 10; 26 | cout << "Euclid GCD(" << x << ", " 27 | << y << ") = " << g(x, y) 28 | << endl; 29 | x = 31, y = 2; 30 | cout << " EuclidGCD(" << x << ", " 31 | << y << ") = " << g(x, y) 32 | << endl; 33 | return 0; 34 | } -------------------------------------------------------------------------------- /Chapter 3 - Mathematical Background and Its Applicability/CaseStudy7_2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | //** computing extended euclidean algorithm 5 | int g_e(int x, int y, int *w, int *y) 6 | { 7 | //** this is the basic or ideal case 8 | if (x == 0) 9 | { 10 | *w = 0; 11 | *y = 1; 12 | return y; 13 | } 14 | 15 | //** variables for storing the results 16 | //** for the recursive call 17 | int a1, b1; 18 | int g = g_e(y%x, x, &a1, &b1); 19 | 20 | //** with help of the recursive call 21 | //** update a and b with the results 22 | *w = b1 - (y/x) * a1; 23 | *y = a1; 24 | 25 | return g; 26 | } 27 | 28 | // Driver Code 29 | int main() 30 | { 31 | int a, b, w = 35, y = 15; 32 | int g = g_e(w, y, &a, &b); 33 | cout << "g_e(" << w << ", " << y 34 | << ") = " << g << endl; 35 | return 0; 36 | } -------------------------------------------------------------------------------- /Chapter 3 - Mathematical Background and Its Applicability/CaseStudy8_1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | //** this represents the basic method or tricky method 5 | //** for finding modulo multiplicative inverse of 6 | //** x under modulo m 7 | int modulo_inverse(int x, int m) 8 | { 9 | x = x%m; 10 | for (int y=1; y 2 | using namespace std; 3 | 4 | //** function for computing extended 5 | //** euclidean algorithm 6 | int gcd_e(int x, int y, int *w, int *z); //a=x, b=y, *x=*w, *y=*z, gcdExtended=gcd_e 7 | 8 | void modulo_inverse(int h, int modulo) //a = h, m=modulo 9 | { 10 | int i, j; //x=i, y=j 11 | int g = gcd_e(h, modulo, &i, &j); 12 | if (g != 1) 13 | cout << "There is no inverse."; 14 | else 15 | { 16 | //** we add the modulo in 17 | //** order to handle negative i 18 | int result = (i%modulo + modulo) % modulo; 19 | cout << "The modular multiplicative inverse is " << result; 20 | } 21 | } 22 | 23 | // C function for extended Euclidean Algorithm 24 | int gcd_e(int h, int k, int *w, int *z) //** a=h, b=k, *x=*w, *y=*z 25 | { 26 | //** the "happy" case 27 | if (h == 0) 28 | { 29 | *w = 0, *z = 1; 30 | return k; 31 | } 32 | 33 | //** storing results of our recurive invoke 34 | int a1, b1; //** x1=a1, y1=b1 35 | int g = gcd_e(k%h, h, &a1, &b1); 36 | 37 | //** with recursive invocation results 38 | //** we will update x and y 39 | *w = b1 - (k/h) * a1; 40 | *z = a1; 41 | 42 | return g; 43 | } 44 | 45 | 46 | int main() 47 | { 48 | int x = 3, modulo = 11; 49 | modulo_inverse(x, modulo); 50 | return 0; 51 | } 52 | -------------------------------------------------------------------------------- /Chapter 3 - Mathematical Background and Its Applicability/CaseStudy9.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | int inverse(int x, int modulo) //** a=x, m=modulo 6 | { 7 | int modulo0 = modulo, k, quotient; //** m0 = modulo0, t=k, q=l 8 | int a0 = 0, a1 = 1; //** x0=a0, x1=a1 9 | 10 | if (modulo == 1) 11 | return 0; 12 | 13 | //** we will apply extended euclidean algorithm 14 | while (x > 1) 15 | { 16 | quotient = x / modulo; 17 | 18 | k = modulo; 19 | 20 | //** modulo represents the remainder 21 | //** continue with the process same as 22 | //** euclid's algorithm 23 | modulo = x%modulo, x=k; 24 | 25 | k = a0; 26 | 27 | a0 = a1 - quotient * a0; 28 | 29 | a1 = k; 30 | } 31 | 32 | //** make a1 positive 33 | if (a1 < 0) 34 | a1 += modulo0; 35 | 36 | return a1; 37 | } 38 | 39 | int lookForMinX(int numbers[], int remainders[], int l) //num=numbers rem=remainders, k=l 40 | { 41 | //** computing the product for all the numbers 42 | int product = 1; 43 | for (int j = 0; j < l; j++) 44 | product *= numbers[j]; 45 | 46 | //** we initialize the result with 0 47 | int result = 0; 48 | 49 | //** apply the formula mentioned above 50 | for (int j = 0; j < l; j++) 51 | { 52 | int pp = product / numbers[j]; 53 | result += remainders[j] * inverse(pp, numbers[j]) * pp; 54 | } 55 | 56 | return result % product; 57 | } 58 | 59 | 60 | int main(void) 61 | { 62 | int numbers[] = {3, 4, 5}; 63 | int remainders[] = {2, 3, 1}; 64 | int k = sizeof(numbers)/sizeof(numbers[0]); 65 | cout << "x is " << lookForMinX(numbers, remainders, k); 66 | return 0; 67 | } -------------------------------------------------------------------------------- /Chapter 4 - Large Integer Arithmetic/Listing 4-1.cpp: -------------------------------------------------------------------------------- 1 | void transformIntToBigInt(int BigNo[], int number) 2 | { 3 | int k; 4 | int bitSign; 5 | int BASE; 6 | 7 | //** start indexing with 0 position 8 | k = 0; 9 | 10 | //** if we still have something left 11 | //** within the number, continue 12 | while (number) { 13 | //** insert the digit that is least significant 14 | //** into BigNo[k] number 15 | BigNo[k++] = number % bitSign; 16 | 17 | //** we don't need the least significant bit 18 | number /= BASE; 19 | } 20 | 21 | //** complete the remain of the array with zeroes 22 | while (k < N) 23 | BigNo[k++] = 0; 24 | } 25 | -------------------------------------------------------------------------------- /Chapter 4 - Large Integer Arithmetic/Listing 4-2.cpp: -------------------------------------------------------------------------------- 1 | void increment (int BigNo []) 2 | { 3 | int i; 4 | int N; 5 | int BASE; 6 | 7 | //* start indexing with least significant digit 8 | 9 | i = 0; 10 | while (i < N) 11 | { 12 | 13 | //* increment the digit 14 | BigNo[i]++; 15 | 16 | //** if it overflows 17 | if (BigNo[i] == BASE) 18 | { 19 | 20 | //** make it zero and move the index to next 21 | BigNo[i] = 0; 22 | i++; 23 | } 24 | else 25 | //** else, we are done! 26 | break; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Chapter 4 - Large Integer Arithmetic/Listing 4-3.cpp: -------------------------------------------------------------------------------- 1 | void addition(int BigNo1[], int BigNo2[], int BigNo3[]) 2 | { 3 | int j, overflowCarry, sum; 4 | int carry, N, BASE; 5 | 6 | //** There is no need to carry yet 7 | carry = 0; 8 | 9 | //** move from the least to the most significant digit 10 | for (j=0; j= BASE) 20 | { 21 | carry = 1; 22 | 23 | //** adjust in such way that 24 | //** the sum will fit within a digit 25 | sum -= BASE; 26 | } 27 | else 28 | //** otherwise no carryOverflow 29 | carry = 0; 30 | 31 | //** add the result in the same sum variable 32 | BigNo3[j] = sum; 33 | } 34 | 35 | //** if we are getting to the 36 | //** end we can expect an overflow 37 | if (carry) 38 | printf ("There is an overflow in the addition!\n"); 39 | } 40 | -------------------------------------------------------------------------------- /Chapter 4 - Large Integer Arithmetic/Listing 4-4.cpp: -------------------------------------------------------------------------------- 1 | void multiply (int BigInt1[], int BigInt2[], int BigInt3[]) 2 | { 3 | int length_of_integer; 4 | int x, y, P[length_of_integer]; 5 | 6 | //** C will store the sum of 7 | //** partial products. It's initially 0. 8 | transformIntToBigInt(BigInt3, 0); 9 | 10 | //* for each digit in BigInt1 11 | for (x=0; x= BASE) { 23 | //** handle the overflow 24 | carryOverflow = B[k] / BASE; 25 | BigOne2[k] %= BASE; 26 | } 27 | else 28 | //** no overflow 29 | carryOverflow = 0; 30 | } 31 | if (carryOverflow) 32 | printf ("During the multiplication we experienced an overflow!\n"); 33 | } 34 | -------------------------------------------------------------------------------- /Chapter 4 - Large Integer Arithmetic/Listing 4-6.cpp: -------------------------------------------------------------------------------- 1 | void leftShifting (int BigInt1[], int number) { 2 | int i; 3 | int N; 4 | 5 | //** moving starting from left to right, 6 | //** we will move anything with left n spaces 7 | for (i=N-1; i>= number; i--) 8 | BigInt1[i] = BigInt1[i- number]; 9 | 10 | //** complete the last n digits with zeros 11 | while (i >= 0) BigInt1[i--] = 0; 12 | } 13 | -------------------------------------------------------------------------------- /Chapter 4 - Large Integer Arithmetic/Listing 4-7.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() 5 | { 6 | ttmath::UInt<2> firstA, secondB, thirdC; 7 | 8 | a = "8765"; 9 | b = 3456; 10 | c = a*b; 11 | 12 | std::cout << thirdC << std::endl; 13 | } 14 | -------------------------------------------------------------------------------- /Chapter 5 - Floating-point Arithmetic/Listing 5-1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | int main() 6 | { 7 | cout << 5.0 << endl; 8 | cout << 6.7f << endl; 9 | cout << 9876543.21 << endl; 10 | } 11 | -------------------------------------------------------------------------------- /Chapter 5 - Floating-point Arithmetic/Listing 5-2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | int main() 6 | { 7 | cout << 7.56756767f << endl; 8 | cout << 765.657667f << endl; 9 | cout << 345543.564f << endl; 10 | cout << 9976544.43f << endl; 11 | cout << 0.00043534345f << endl; 12 | 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /Chapter 5 - Floating-point Arithmetic/Listing 5-3.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | int main() 7 | { 8 | std::cout << std::setprecision(16); 9 | std::cout << 3.333333333333333333333333333333333f < 2 | #include 3 | 4 | //** let’s define a wrapper for class AESCryptography 5 | template 6 | struct Encryption { 7 | AESCryptography value; 8 | }; 9 | 10 | template 11 | 12 | struct 13 | std::formatter, 14 | CharAESCryptography>: 15 | std::formatter 16 | { 17 | template 18 | auto format(Encryption 19 | encAESCrypto, FormatContext& theFormatContext) 20 | { 21 | return std::formatter::format 23 | (encAESCrypto.value, theFormatContext); 24 | } 25 | }; 26 | 27 | int main() 28 | { 29 | Encryption encrypted = { 32 }; 30 | std::cout << std::format("{:#x}", encrypted); 31 | } 32 | -------------------------------------------------------------------------------- /Chapter 9 - Elliptic-curve Cryptography/FFE_Engine.hpp: -------------------------------------------------------------------------------- 1 | namespace EllipticCurveCryptography 2 | { 3 | //** basic functions for 4 | //** Finite Field Elements (FFE) 5 | namespace HelperFunctionFFE 6 | { 7 | //** Computing Extended GCD gives g = a*u + b*v 8 | int ExtendedGreatestCommonDivisor(int a, int b, int& u, int &v) 9 | { 10 | u = 1; 11 | v = 0; 12 | int g = a; 13 | int u1 = 0; 14 | int v1 = 1; 15 | int g1 = b; 16 | while (g1 != 0) 17 | { 18 | //** division using integers 19 | int q = g/g1; 20 | int t1 = u - q*u1; 21 | int t2 = v - q*v1; 22 | int t3 = g - q*g1; 23 | u = u1; v = v1; g = g1; 24 | u1 = t1; v1 = t2; g1 = t3; 25 | } 26 | 27 | return g; 28 | } 29 | 30 | //** providing solution and solving 31 | //** the linear congruence equation 32 | //** x * z == 1 (mod n) for z 33 | int InverseModular(int x, int n) 34 | { 35 | //** "%" represents the remainder 36 | //** function, 0 <= x % n < |n| 37 | x = x % n; 38 | int u,v,g,z; 39 | g = ExtendedGreatestCommonDivisor(x, n, u,v); 40 | if (g != 1) 41 | { 42 | //** x and n has to be primes 43 | //** in order to exist an x^-1 mod n 44 | z = 0; 45 | } 46 | else 47 | { 48 | z = u % n; 49 | } 50 | return z; 51 | } 52 | } 53 | 54 | //** represents the element from a Galois field 55 | //** we will use a specific behaviour for the 56 | //** modular function in which (-n) mod m will 57 | //** return a negative number. 58 | //** The implementation is done in such way that 59 | //** it will offer a support for the basic 60 | //** arithmetic operations, such as: 61 | //** + (addition), - (subtraction), / (division) 62 | //** and scalar multiplication. 63 | //** The P served as an argument represents the 64 | //** order for the field. 65 | template 66 | class FFE 67 | { 68 | int i_; 69 | 70 | void assign(int i) 71 | { 72 | i_ = i; 73 | if ( i<0 ) 74 | { 75 | //** The correction behaviour is important. 76 | //** Using (-i) mod p we will make sure 77 | //** that the behaviour is the proper one. 78 | i_ = (i%P) + 2*P; 79 | } 80 | 81 | i_ %= P; 82 | } 83 | 84 | public: 85 | //** the constructor 86 | FFE() 87 | : i_(0) 88 | {} 89 | 90 | //** another constructor 91 | explicit FFE(int i) 92 | { 93 | assign(i); 94 | } 95 | 96 | //** copying the constructor 97 | FFE(const FFE

& rhs) 98 | : i_(rhs.i_) 99 | { 100 | } 101 | 102 | //** providing access to 103 | //** the raw integer 104 | int i() const { return i_; } 105 | 106 | //** implementation for negation operator 107 | FFE operator-() const 108 | { 109 | return FFE(-i_); 110 | } 111 | 112 | //** assignation with an integer 113 | FFE& operator=(int i) 114 | { 115 | assign(i); 116 | return *this; 117 | } 118 | 119 | //** assignation from field element 120 | FFE

& operator=(const FFE

& rhs) 121 | { 122 | i_ = rhs.i_; 123 | return *this; 124 | } 125 | 126 | //** implementation of "*=" operator 127 | FFE

& operator*=(const FFE

& rhs) 128 | { 129 | i_ = (i_*rhs.i_) % P; 130 | return *this; 131 | } 132 | 133 | //** implementation of "==" operator 134 | friend bool operator==(const FFE

& lhs, const FFE

& rhs) 135 | { 136 | return (lhs.i_ == rhs.i_); 137 | } 138 | 139 | //** implementation of "==" operator 140 | friend bool operator==(const FFE

& lhs, int rhs) 141 | { 142 | return (lhs.i_ == rhs); 143 | } 144 | 145 | //** implementation of "!=" operator 146 | friend bool operator!=(const FFE

& lhs, int rhs) 147 | { 148 | return (lhs.i_ != rhs); 149 | } 150 | 151 | // implementation of "a/b" operator 152 | friend FFE

operator/(const FFE

& lhs, const FFE

& rhs) 153 | { 154 | return FFE

( lhs.i_ * HelperFunctionFFE::InverseModular(rhs.i_,P)); 155 | } 156 | 157 | //** implementation of "a+b" operator 158 | friend FFE

operator+(const FFE

& lhs, const FFE

& rhs) 159 | { 160 | return FFE

( lhs.i_ + rhs.i_); 161 | } 162 | 163 | //** implementation of "a-b" operator 164 | friend FFE

operator-(const FFE

& lhs, const FFE

& rhs) 165 | { 166 | return FFE

(lhs.i_ - rhs.i_); 167 | } 168 | 169 | // implementation of "a + int" operator 170 | friend FFE

operator+(const FFE

& lhs, int i) 171 | { 172 | return FFE

( lhs.i_+i); 173 | } 174 | 175 | //** implementation of "int + a" operator 176 | friend FFE

operator+(int i, const FFE

& rhs) 177 | { 178 | return FFE

( rhs.i_+i); 179 | } 180 | 181 | //** implementation of "int * a" operator 182 | friend FFE

operator*(int n, const FFE

& rhs) 183 | { 184 | return FFE

( n*rhs.i_); 185 | } 186 | 187 | //** implementation of "a * b" 188 | friend FFE

operator*(const FFE

& lhs, const FFE

& rhs) 189 | { 190 | return FFE

( lhs.i_ * rhs.i_); 191 | } 192 | 193 | //** the operator ostream for 194 | //** showing and displaying in 195 | //** readable format 196 | template 197 | friend ostream& operator<<(ostream& os, const FFE& g) 198 | { 199 | return os << g.i_; 200 | } 201 | }; 202 | } 203 | 204 | 205 | -------------------------------------------------------------------------------- /Chapter 9 - Elliptic-curve Cryptography/main.cpp: -------------------------------------------------------------------------------- 1 | //** Leave everything as it is. 2 | //** Don't change the order of the inputs or namespaces. 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | #include 11 | #include "FFE_Engine.hpp" 12 | 13 | namespace EllipticCurveCryptography 14 | { 15 | //** Elliptic Curve over a finite field of order P: 16 | //** y^2 mod P = x^3 + ax + b mod P 17 | template class EllipticCurve 18 | { 19 | public: 20 | // this curve is defined over the finite field (Galois field) Fp, this is the 21 | // typedef of elements in it 22 | typedef FFE ffe_element; 23 | 24 | //** Any point on elliptic curve is formed 25 | //** from two elements that are within Fp 26 | //** field (Galois Field). The points are 27 | //** created once we declare an instance of 28 | //** Elliptic Curve itself. 29 | class EllipticCurvePoint 30 | { 31 | friend class EllipticCurve; 32 | typedef FFE ffe_element; 33 | ffe_element xCoordValue_; 34 | ffe_element yCoordValue_; 35 | EllipticCurve *ellipticCurve_; 36 | 37 | // core of the doubling multiplier algorithm (see below) 38 | // multiplies acc by m as a series of "2*accumulatorContainer's" 39 | void DoublingMultiplierAlgorithm(int multiplier, EllipticCurvePoint& accumulatorContainer) 40 | { 41 | if (multiplier > 0) 42 | { 43 | EllipticCurvePoint doublingValue = accumulatorContainer; 44 | for (int counter=0; counter < multiplier; ++counter) 45 | { 46 | doublingValue += doublingValue; // doubling step 47 | } 48 | accumulatorContainer = doublingValue; 49 | } 50 | } 51 | 52 | //** Implementation of doubling multiplier algorithm. 53 | //** The process stands on multiplying 54 | //** intermediateResultAccumulator for 55 | //** storing the intermediate results with inputScalar. 56 | //** This is done through expansion in multipliple 57 | //** by 2 between the first of the binary represtantion of inputScalar. 58 | EllipticCurvePoint MultiplyUsingScalar(int inputScalar, const EllipticCurvePoint& intermediateResultAccumulator) 59 | { 60 | EllipticCurvePoint accumulatorContainer = intermediateResultAccumulator; 61 | EllipticCurvePoint outputResult = EllipticCurvePoint(0,0,*ellipticCurve_); 62 | int i = 0, j = 0; 63 | int iS = inputScalar; 64 | 65 | while(iS) 66 | { 67 | if (iS&1) 68 | { 69 | 70 | //** Setting up the bit. 71 | //** The computation is done by following the formula: 72 | //** accumulatorContainer = 2^(i-j)*accumulatorContainer 73 | DoublingMultiplierAlgorithm(i-j,accumulatorContainer); 74 | outputResult += accumulatorContainer; 75 | 76 | //** last setting for the bit 77 | j = i; 78 | } 79 | iS >>= 1; 80 | ++i; 81 | } 82 | return outputResult; 83 | } 84 | 85 | //** the function deals with 86 | //** adding two points on the curve 87 | 88 | //** xCoord1, yCoord1, xCoord2=x2, yCoord2=y2 89 | void ECTwoPointsAddition(ffe_element xCoord1, ffe_element yCoord1, ffe_element xCoord2, ffe_element yCoord2, ffe_element & xCoordR, ffe_element & yCoordR) const 90 | { 91 | //** dealing with sensitives cases 92 | //** for implying addition identity 93 | if (xCoord1==0 && yCoord1==0) 94 | { 95 | xCoordR = xCoord2; 96 | yCoordR = yCoord2; 97 | return; 98 | } 99 | if (xCoord2==0 && yCoord2==0) 100 | { 101 | xCoordR = xCoord1; 102 | yCoordR = yCoord1; 103 | return; 104 | } 105 | if (yCoord1==-yCoord2) 106 | { 107 | xCoordR = yCoordR = 0; 108 | return; 109 | } 110 | 111 | //** deal with the additions 112 | ffe_element s; 113 | if (xCoord1 == xCoord2 && yCoord1 == yCoord2) 114 | { 115 | //** computing 2*P 116 | s = (3*(xCoord1.i()*xCoord1.i()) + ellipticCurve_->a()) / (2*yCoord1); 117 | xCoordR = ((s*s) - 2*xCoord1); 118 | } 119 | else 120 | { 121 | //** computing P+Q 122 | s = (yCoord1 - yCoord2) / (xCoord1 - xCoord2); 123 | xCoordR = ((s*s) - xCoord1 - xCoord2); 124 | } 125 | 126 | if (s!=0) 127 | { 128 | yCoordR = (-yCoord1 + s*(xCoord1 - xCoordR)); 129 | } 130 | else 131 | { 132 | xCoordR = yCoordR = 0; 133 | } 134 | } 135 | 136 | EllipticCurvePoint(int xPoint, int yPoint) 137 | : xCoordValue_(xPoint), 138 | yCoordValue_(yPoint), 139 | ellipticCurve_(0) 140 | {} 141 | 142 | EllipticCurvePoint(int xPoint, int yPoint, EllipticCurve & EllipticCurve) 143 | : xCoordValue_(xPoint), 144 | yCoordValue_(yPoint), 145 | ellipticCurve_(&EllipticCurve) 146 | {} 147 | 148 | EllipticCurvePoint(const ffe_element& xPoint, const ffe_element& yPoint, EllipticCurve & EllipticCurve) 149 | : xCoordValue_(xPoint), 150 | yCoordValue_(yPoint), 151 | ellipticCurve_(&EllipticCurve) 152 | {} 153 | 154 | public: 155 | static EllipticCurvePoint ONE; 156 | 157 | //** constructor 158 | EllipticCurvePoint(const EllipticCurvePoint& rhsPoint) 159 | { 160 | xCoordValue_ = rhsPoint.xCoordValue_; 161 | yCoordValue_ = rhsPoint.yCoordValue_; 162 | ellipticCurve_ = rhsPoint.ellipticCurve_; 163 | } 164 | 165 | //** the assignment process 166 | EllipticCurvePoint& operator=(const EllipticCurvePoint& rhsPoint) 167 | { 168 | xCoordValue_ = rhsPoint.xCoordValue_; 169 | yCoordValue_ = rhsPoint.yCoordValue_; 170 | ellipticCurve_ = rhsPoint.ellipticCurve_; 171 | return *this; 172 | } 173 | 174 | //** access x component as element of Fp 175 | ffe_element GetX() const { return xCoordValue_; } 176 | 177 | //** access y component as element of Fp 178 | ffe_element GetY() const { return yCoordValue_; } 179 | 180 | //** calculate the order of this point by brute-force additions 181 | unsigned int ComputingOrderBruteForceAddition(unsigned int maximum_period = ~0) const //** order() 182 | { 183 | EllipticCurvePoint ecPoint = *this; 184 | unsigned int order = 0; 185 | while(ecPoint.xCoordValue_ != 0 && ecPoint.yCoordValue_ != 0) 186 | { 187 | ++order; 188 | ecPoint += *this; 189 | if (order > maximum_period) break; 190 | } 191 | return order; 192 | } 193 | 194 | //** negation operator (-) that gives the inverse of a point 195 | EllipticCurvePoint operator-() 196 | { 197 | return EllipticCurvePoint(xCoordValue_,-yCoordValue_); 198 | } 199 | 200 | //** equal (==) operator 201 | friend bool operator==(const EllipticCurvePoint& lhsPoint, const EllipticCurvePoint& rhsPoint) 202 | { 203 | return (lhsPoint.ec_ == rhsPoint.ec_) && (lhsPoint.x_ == rhsPoint.x_) && (lhsPoint.y_ == rhsPoint.y_); 204 | } 205 | 206 | //** different (!=) operator 207 | friend bool operator!=(const EllipticCurvePoint& lhsPoint, const EllipticCurvePoint& rhsPoint) 208 | { 209 | return (lhsPoint.ec_ != rhsPoint.ec_) || (lhsPoint.x_ != rhsPoint.x_) || (lhsPoint.y_ != rhsPoint.y_); 210 | } 211 | 212 | //** Implementation of a + b operator 213 | friend EllipticCurvePoint operator+(const EllipticCurvePoint& lhsPoint, const EllipticCurvePoint& rhsPoint) 214 | { 215 | ffe_element xResult, yResult; 216 | lhsPoint.ECTwoPointsAddition(lhsPoint.xCoordValue_,lhsPoint.yCoordValue_,rhsPoint.xCoordValue_,rhsPoint.yCoordValue_,xResult,yResult); 217 | return EllipticCurvePoint(xResult,yResult,*lhsPoint.ellipticCurve_); 218 | } 219 | 220 | //** multiplying with scalar * int 221 | friend EllipticCurvePoint operator*(int scalar, const EllipticCurvePoint& rhsPoint) 222 | { 223 | return EllipticCurvePoint(rhsPoint).operator*=(scalar); 224 | } 225 | 226 | //** Implementation of += operator 227 | EllipticCurvePoint& operator+=(const EllipticCurvePoint& rhsPoint) 228 | { 229 | ECTwoPointsAddition(xCoordValue_,yCoordValue_,rhsPoint.xCoordValue_,rhsPoint.yCoordValue_,xCoordValue_,yCoordValue_); 230 | return *this; 231 | } 232 | 233 | //** Implementation of *= int operator 234 | EllipticCurvePoint& operator*=(int scalar) 235 | { 236 | return (*this = MultiplyUsingScalar(scalar,*this)); 237 | } 238 | 239 | //** display and print the point using ostream 240 | friend ostream& operator <<(ostream& os, const EllipticCurvePoint& p) 241 | { 242 | return (os << "(" << p.xCoordValue_ << ", " << p.yCoordValue_ << ")"); 243 | } 244 | }; 245 | 246 | 247 | //** performing the elliptic curve implementation 248 | typedef EllipticCurve this_t; 249 | typedef class EllipticCurve::EllipticCurvePoint point_t; 250 | 251 | //** the Weierstrass equation as y^2 = x^3 + ax + b 252 | EllipticCurve(int CoefA, int CoefB) 253 | : ECParameterA(CoefA), 254 | ECParameterB(CoefB), 255 | tableOfPoints(), 256 | tableFilledComputated(false) 257 | { 258 | } 259 | 260 | //** compute all the points (from the group of elements) for 261 | //** Weierstrass equation. Note the fact that if we are 262 | //** having a high order for the curve, the computation process 263 | //** will take some time 264 | void CalculatePoints() 265 | { 266 | int x_val[OrderFFE_EC]; 267 | int y_val[OrderFFE_EC]; 268 | for (int counter = 0; counter < OrderFFE_EC; ++counter) 269 | { 270 | int nsq = counter*counter; 271 | x_val[counter] = ((counter*nsq) + ECParameterA.i() * counter + ECParameterB.i()) % OrderFFE_EC; 272 | y_val[counter] = nsq % OrderFFE_EC; 273 | } 274 | 275 | for (int counter1 = 0; counter1 < OrderFFE_EC; ++counter1) 276 | { 277 | for (int counter2 = 0; counter2 < OrderFFE_EC; ++counter2) 278 | { 279 | if (x_val[counter1] == y_val[counter2]) 280 | { 281 | tableOfPoints.push_back(EllipticCurvePoint(counter1,counter2,*this)); 282 | } 283 | } 284 | } 285 | 286 | tableFilledComputated = true; 287 | } 288 | 289 | //** obtain the point (from the group of elements) for the curve 290 | EllipticCurvePoint operator[](int n) 291 | { 292 | if ( !tableFilledComputated ) 293 | { 294 | CalculatePoints(); 295 | } 296 | 297 | return tableOfPoints[n]; 298 | } 299 | 300 | //** the number og the elements in the group 301 | size_t Size() const { return tableOfPoints.size(); } 302 | 303 | //** the degree of the point for the elliptic curve 304 | int Degree() const { return OrderFFE_EC; } 305 | 306 | //** the "a" parameter, as an element of Fp 307 | FFE a() const { return ECParameterA; } 308 | 309 | //** the "b" paramter, as an element of Fp 310 | FFE b() const { return ECParameterB; } 311 | 312 | //** print and show the elliptic curve in a readable format using ostream human readable form 313 | template 314 | friend ostream& operator <<(ostream& os, const EllipticCurve& EllipticCurve); 315 | 316 | //** print and display all the elements of the elliptic curve group 317 | ostream& PrintTable(ostream &os, int columns=4); 318 | 319 | private: 320 | typedef std::vector TableWithPoints; 321 | 322 | //** table with the points 323 | TableWithPoints tableOfPoints; 324 | 325 | //** first parameter of the elliptic curve equation 326 | FFE ECParameterA; 327 | 328 | //** second parameter of the elliptic curve equation 329 | FFE ECParameterB; 330 | 331 | //** boolean value to show if the table has been computed 332 | bool tableFilledComputated; 333 | }; 334 | 335 | template 336 | typename EllipticCurve::EllipticCurvePoint EllipticCurve::EllipticCurvePoint::ONE(0,0); 337 | 338 | template 339 | ostream& operator <<(ostream& os, const EllipticCurve& EllipticCurve) 340 | { 341 | os << "y^2 mod " << ECT << " = (x^3" << showpos; 342 | if ( EllipticCurve.ECParameterA != 0 ) 343 | { 344 | os << EllipticCurve.ECParameterA << "x"; 345 | } 346 | 347 | if ( EllipticCurve.ECParameterB.i() != 0 ) 348 | { 349 | os << EllipticCurve.ECParameterB; 350 | } 351 | 352 | os << noshowpos << ") mod " << ECT; 353 | return os; 354 | } 355 | 356 | template 357 | ostream& EllipticCurve

::PrintTable(ostream &os, int columns) 358 | { 359 | if (tableFilledComputated) 360 | { 361 | int col = 0; 362 | typename EllipticCurve

::TableWithPoints::iterator iter = tableOfPoints.begin(); 363 | for ( ; iter!=tableOfPoints.end(); ++iter ) 364 | { 365 | os << "(" << (*iter).xCoordValue_.i() << ", " << (*iter).yCoordValue_.i() << ") "; 366 | if ( ++col > columns ) 367 | { 368 | os << "\n"; 369 | col = 0; 370 | } 371 | } 372 | } 373 | else 374 | { 375 | os << "EllipticCurve, F_" << P; 376 | } 377 | return os; 378 | } 379 | } 380 | 381 | namespace utils 382 | { 383 | float frand() 384 | { 385 | static float norm = 1.0f / (float)RAND_MAX; 386 | return (float)rand()*norm; 387 | } 388 | 389 | int irand(int min, int max) 390 | { 391 | return min+(int)(frand()*(float)(max-min)); 392 | } 393 | } 394 | 395 | using namespace EllipticCurveCryptography; 396 | using namespace utils; 397 | 398 | int main(int argc, char *argv[]) 399 | { 400 | typedef EllipticCurve<163> elliptic_curve; 401 | elliptic_curve myEllipticCurve(1,1); 402 | 403 | cout << "Basic Example of using Elliptic Curve Cryptography using C++20. Apress, 2020\n\n"; 404 | 405 | //** display some informations about the 406 | //** elliptic curve and display some of the properties 407 | cout << "Equation of the elliptic curve: " << myEllipticCurve << "\n"; 408 | 409 | //** compute the points for the elliptic 410 | //** curve for equation from the above 411 | myEllipticCurve.CalculatePoints(); 412 | 413 | cout << "\nList of the points (x,Y) for the curve (i.e. the group elements):\n"; 414 | myEllipticCurve.PrintTable(cout,5); 415 | cout << "\n\n"; 416 | 417 | elliptic_curve::EllipticCurvePoint P = myEllipticCurve[2]; 418 | cout << "Randomly - Point P = " << P << ", 2P = " << (P+P) << "\n"; 419 | 420 | elliptic_curve::EllipticCurvePoint Q = myEllipticCurve[3]; 421 | cout << "Randomly - Point Q = " << Q << ", P+Q = " << (P+Q) << "\n"; 422 | 423 | elliptic_curve::EllipticCurvePoint R = P; 424 | R += Q; 425 | cout << "P += Q = " << R << "\n"; 426 | 427 | R = P; 428 | R += R; 429 | cout << "P += P = 2P = " << R << "\n"; 430 | 431 | cout << "\nEncryption of the message using elliptic curve principles\n\n"; 432 | 433 | //** as an example we will use Menes-Vanstone scheme that is 434 | //** based on elliptic curve for message encryption 435 | elliptic_curve::EllipticCurvePoint G = myEllipticCurve[0]; 436 | while( (G.GetY() == 0 || G.GetX() == 0) || (G.ComputingOrderBruteForceAddition()<2) ) 437 | { 438 | int n = (int)(frand()*myEllipticCurve.Size()); 439 | G = myEllipticCurve[n]; 440 | } 441 | 442 | cout << "G = " << G << ", order(G) is " << G.ComputingOrderBruteForceAddition() << "\n"; 443 | 444 | //** Suppose that Alice wish to communicate with Bob 445 | //** Alice and its public key 446 | int a = irand(1,myEllipticCurve.Degree()-1); 447 | //** generating the public key 448 | elliptic_curve::EllipticCurvePoint Pa = a*G; 449 | cout << "Alice - Public key (Pa) = " << a << "*" << G << " = " << Pa << endl; 450 | 451 | //** Bob and is public key 452 | int b = irand(1,myEllipticCurve.Degree()-1); 453 | //** the public key 454 | elliptic_curve::EllipticCurvePoint Pb = b*G; 455 | cout << "Bob - Public key (Pb) = " << b << "*" << G << " = " << Pb << endl; 456 | 457 | //** Oscar - the eavesdropper and attacker 458 | int o = irand(1,myEllipticCurve.Degree()-1);; 459 | elliptic_curve::EllipticCurvePoint Po = o*G; 460 | cout << "Oscar - Public key (Po) = " << o << "*" << G << " = " << Po << endl; 461 | 462 | cout << "\n\n"; 463 | 464 | //** Alice proceed with the encryption 465 | //** for her message and send it to Bob. 466 | //** To achieve this, the first step is 467 | //** to split the message into multiple 468 | //** parts which are encoded using Galois 469 | //** field (Fp), which is also the domain 470 | //** elliptic curve. 471 | int m1 = 19; 472 | int m2 = 72; 473 | 474 | cout << "The clear text message send by Alice to Bob: (" << m1 << ", " << m2 << ")\n"; 475 | 476 | //** proceed with encryption using the key of Bob 477 | elliptic_curve::EllipticCurvePoint Pk = a*Pb; 478 | elliptic_curve::ffe_element c1(m1*Pk.GetX()); 479 | elliptic_curve::ffe_element c2(m2*Pk.GetY()); 480 | 481 | //** the message that is encrypted is composed from: 482 | //** Pa - Alice public key 483 | //** c1,c2 484 | cout << "The message encrypted from Alice for Bob is represented as {Pa,c1,c2} and its content is = {" << Pa << ", " << c1 << ", " << c2 << "}\n\n"; 485 | 486 | //** Bob compute the decryption for the message 487 | //** received from Alice, using her public key 488 | //** and the session value (integer b) 489 | Pk = b*Pa; 490 | elliptic_curve::ffe_element m1d = c1/Pk.GetX(); 491 | elliptic_curve::ffe_element m2d = c2/Pk.GetY(); 492 | 493 | cout << "\tThe message decrypted by Bob from Alice is = (" << m1d << ", " << m2d << ")" << endl; 494 | 495 | //** Oscar will intercept the message and 496 | //** and he/she will try to decrypt it 497 | //** using his/her key 498 | Pk = o*Pa; 499 | m1d = c1/Pk.GetX(); 500 | m2d = c2/Pk.GetY(); 501 | 502 | cout << "\nOscar decrypt the message from Alice = (" << m1d << ", " << m2d << ")" << endl; 503 | 504 | cout << endl; 505 | 506 | } 507 | -------------------------------------------------------------------------------- /Chapter 9 - Elliptic-curve Cryptography/main.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/pro-cryptography-cryptanalysis-cpp20/462331a454e32be1c768c7aee079b335510adcef/Chapter 9 - Elliptic-curve Cryptography/main.exe -------------------------------------------------------------------------------- /Contributing.md: -------------------------------------------------------------------------------- 1 | # Contributing to Apress Source Code 2 | 3 | Copyright for Apress source code belongs to the author(s). However, under fair use you are encouraged to fork and contribute minor corrections and updates for the benefit of the author(s) and other readers. 4 | 5 | ## How to Contribute 6 | 7 | 1. Make sure you have a GitHub account. 8 | 2. Fork the repository for the relevant book. 9 | 3. Create a new branch on which to make your change, e.g. 10 | `git checkout -b my_code_contribution` 11 | 4. Commit your change. Include a commit message describing the correction. Please note that if your commit message is not clear, the correction will not be accepted. 12 | 5. Submit a pull request. 13 | 14 | Thank you for your contribution! -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Freeware License, some rights reserved 2 | 3 | Copyright (c) 2021 Marius Iulian Mihailescu and Stefania Loredana Nita 4 | 5 | Permission is hereby granted, free of charge, to anyone obtaining a copy 6 | of this software and associated documentation files (the "Software"), 7 | to work with the Software within the limits of freeware distribution and fair use. 8 | This includes the rights to use, copy, and modify the Software for personal use. 9 | Users are also allowed and encouraged to submit corrections and modifications 10 | to the Software for the benefit of other users. 11 | 12 | It is not allowed to reuse, modify, or redistribute the Software for 13 | commercial use in any way, or for a user’s educational materials such as books 14 | or blog articles without prior permission from the copyright holder. 15 | 16 | The above copyright notice and this permission notice need to be included 17 | in all copies or substantial portions of the software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | AUTHORS OR COPYRIGHT HOLDERS OR APRESS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 | SOFTWARE. 26 | 27 | 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Apress Source Code 2 | 3 | This repository accompanies [*Pro Cryptography and Cryptanalysis with C++20*](https://www.apress.com/9781484265857) by Marius Iulian Mihailescu and Stefania Loredana Nita (Apress, 2021). 4 | 5 | [comment]: #cover 6 | ![Cover image](9781484265857.jpg) 7 | 8 | Download the files as a zip using the green button, or clone the repository to your machine using Git. 9 | 10 | ## Releases 11 | 12 | Release v1.0 corresponds to the code in the published book, without corrections or updates. 13 | 14 | ## Contributions 15 | 16 | See the file Contributing.md for more information on how you can contribute to this repository. -------------------------------------------------------------------------------- /errata.md: -------------------------------------------------------------------------------- 1 | # Errata for *Pro Cryptography and Cryptanalysis with C++20* 2 | 3 | On **page xx** [Summary of error]: 4 | 5 | Details of error here. Highlight key pieces in **bold**. 6 | 7 | *** 8 | 9 | On **page xx** [Summary of error]: 10 | 11 | Details of error here. Highlight key pieces in **bold**. 12 | 13 | *** --------------------------------------------------------------------------------