├── aes-rijndael ├── aes-impl │ ├── CMakeLists.txt │ ├── aes_traits.h │ ├── structs │ │ └── matrix.h │ ├── aes128.h │ └── aes_transformations.h ├── CMakeLists.txt ├── main.cpp └── CMakeSettings.json ├── README.md ├── LICENSE ├── .gitattributes └── .gitignore /aes-rijndael/aes-impl/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /aes-rijndael/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 3.17) 2 | set(CMAKE_CXX_STANDARD 20) 3 | 4 | project ("aes-rijndael") 5 | add_subdirectory ("aes-impl") 6 | 7 | add_executable (aes-rijndael "main.cpp") -------------------------------------------------------------------------------- /aes-rijndael/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "aes-impl/aes_transformations.h" 4 | #include "aes-impl/aes128.h" 5 | 6 | using namespace std; 7 | 8 | int main() 9 | { 10 | const std::string original_message = "hello world"; 11 | 12 | aes128 aes; 13 | 14 | const auto encrypted_message = aes.encrypt(original_message, "goodby"); 15 | const auto decrypted_message = aes.decrypt(encrypted_message, "goodby"); 16 | 17 | cout << encrypted_message << endl << decrypted_message << endl; 18 | 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /aes-rijndael/aes-impl/aes_traits.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class aes_traits 6 | { 7 | public: 8 | virtual ~aes_traits() = default; 9 | 10 | /** 11 | * \param message message to encryption 12 | * \param key cipher key 13 | * \return encrypted message 14 | */ 15 | virtual std::string encrypt(std::string message, std::string key) = 0; 16 | 17 | /** 18 | * \param message message to decryption 19 | * \param key cipher key 20 | * \return decrypted message 21 | */ 22 | virtual std::string decrypt(std::string message, std::string key) = 0; 23 | }; -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AES | Rijndael algorithm 2 | 3 | ## This rijndael implementation have next features: 4 | - easy to learn 5 | - easy to use 6 | 7 | ## Future changes: 8 | - 192 bit implementation 9 | - 256 bit implementation 10 | - build-in password hashing 11 | 12 | ## Usage 13 | ##### Executing functuions: 14 | ``` cpp 15 | aes128 aes; 16 | 17 | const std::string original_message = "hello world"; 18 | const auto encrypted_message = aes.encrypt(original_message, "goodby"); 19 | const auto decrypted_message = aes.decrypt(encrypted_message, "goodby"); 20 | ``` 21 | 22 | ## Contributing 23 | Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change. 24 | 25 | ## License 26 | [MIT](https://choosealicense.com/licenses/mit/) 27 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Alexandr 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /aes-rijndael/aes-impl/structs/matrix.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include // use std::vector 4 | #include // use std::out_of_range 5 | 6 | template 7 | class matrix final 8 | { 9 | public: 10 | std::vector data_array; 11 | 12 | matrix() : data_array(RowsCount* ColumnsCount) {} 13 | 14 | [[nodiscard]] size_t get_columns_count() const 15 | { 16 | return ColumnsCount; 17 | } 18 | 19 | [[nodiscard]] size_t get_rows_count() const 20 | { 21 | return RowsCount; 22 | } 23 | 24 | [[nodiscard]] T& at(const size_t row, const size_t column) 25 | { 26 | const size_t index = (ColumnsCount * row) + column; 27 | 28 | if (index >= RowsCount * ColumnsCount || 29 | row >= RowsCount || column >= ColumnsCount) 30 | throw std::out_of_range(""); 31 | 32 | return data_array[index]; 33 | } 34 | 35 | [[nodiscard]] T value_at(const size_t row, const size_t column) const 36 | { 37 | const size_t index = (ColumnsCount * row) + column; 38 | 39 | if (index >= RowsCount * ColumnsCount || 40 | row >= RowsCount || column >= ColumnsCount) 41 | throw std::out_of_range(""); 42 | 43 | return data_array[index]; 44 | } 45 | 46 | [[nodiscard]] std::array get_column(const size_t column_number) const 47 | { 48 | std::array column{}; 49 | 50 | for (size_t i = 0; i < RowsCount; i++) 51 | column[i] = this->value_at(i, column_number); 52 | 53 | return column; 54 | } 55 | 56 | auto begin() 57 | { 58 | return this->data_array.begin(); 59 | } 60 | 61 | auto end() 62 | { 63 | return this->data_array.end(); 64 | } 65 | 66 | void set_column(std::array arr, const size_t column_number) 67 | { 68 | for (size_t i = 0; i < RowsCount; i++) 69 | this->at(i, column_number) = arr[i]; 70 | } 71 | }; -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /aes-rijndael/aes-impl/aes128.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "aes_traits.h" 4 | #include "aes_transformations.h" 5 | 6 | #include 7 | #include 8 | 9 | class aes128 : public aes_traits 10 | { 11 | public: 12 | std::string encrypt(std::string message, std::string key) override 13 | { 14 | if (key.size() > 16) 15 | throw std::invalid_argument("key"); 16 | 17 | if (key.size() < 16) 18 | key.resize(16); 19 | 20 | std::vector> states = aes_transformations::message_to_blocks<4, 4>(message); 21 | const aes_block<4, 4> cipher_key = aes_transformations::message_to_block<4, 4>(key); 22 | 23 | const std::array, 10> round_keys = aes_transformations::individual::key_expansion_128(cipher_key); 24 | 25 | for(aes_block<4, 4>& state : states) 26 | { 27 | // initial round 28 | state = aes_transformations::add_round_key(state, cipher_key); 29 | 30 | // first 9 rounds 31 | for(auto round_key_it = round_keys.cbegin(); round_key_it != std::prev(round_keys.cend()); ++round_key_it) 32 | { 33 | state = aes_transformations::sub_bytes(state); 34 | state = aes_transformations::shift_rows(state); 35 | state = aes_transformations::individual::mix_columns_128(state); 36 | state = aes_transformations::add_round_key(state, *round_key_it); 37 | } 38 | 39 | // final 10 round 40 | state = aes_transformations::sub_bytes(state); 41 | state = aes_transformations::shift_rows(state); 42 | state = aes_transformations::add_round_key(state, round_keys.back()); 43 | } 44 | 45 | // build encrypted message 46 | return aes_transformations::blocks_to_message(states); 47 | } 48 | std::string decrypt(std::string message, std::string key) override 49 | { 50 | if (key.size() > 16) 51 | throw std::invalid_argument("key"); 52 | 53 | if (key.size() < 16) 54 | key.resize(16); 55 | 56 | std::vector> states = aes_transformations::message_to_blocks<4, 4>(message); 57 | const aes_block<4, 4> cipher_key = aes_transformations::message_to_block<4, 4>(key); 58 | 59 | const std::array, 10> round_keys = aes_transformations::individual::key_expansion_128(cipher_key); 60 | 61 | for (aes_block<4, 4> & state : states) 62 | { 63 | // initial round 64 | state = aes_transformations::add_round_key(state, round_keys.back()); 65 | 66 | // first 9 rounds 67 | for (auto round_key_it = std::next(round_keys.crbegin()); round_key_it != round_keys.crend(); ++round_key_it) 68 | { 69 | state = aes_transformations::inv_shift_rows(state); 70 | state = aes_transformations::inv_sub_bytes(state); 71 | state = aes_transformations::add_round_key(state, *round_key_it); 72 | state = aes_transformations::individual::inv_mix_columns_128(state); 73 | } 74 | 75 | // final 10 round 76 | state = aes_transformations::inv_shift_rows(state); 77 | state = aes_transformations::inv_sub_bytes(state); 78 | state = aes_transformations::add_round_key(state, cipher_key); 79 | } 80 | 81 | return aes_transformations::blocks_to_message(states); 82 | } 83 | }; -------------------------------------------------------------------------------- /aes-rijndael/CMakeSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": [ 3 | { 4 | "name": "msvc-dbg-x64", 5 | "generator": "Ninja", 6 | "configurationType": "Debug", 7 | "inheritEnvironments": [ "msvc_x64_x64" ], 8 | "buildRoot": "${projectDir}\\out\\build\\${name}", 9 | "installRoot": "${projectDir}\\out\\install\\${name}", 10 | "cmakeCommandArgs": "", 11 | "buildCommandArgs": "", 12 | "ctestCommandArgs": "", 13 | "variables": [] 14 | }, 15 | { 16 | "name": "msvc-rel-x64", 17 | "generator": "Ninja", 18 | "configurationType": "RelWithDebInfo", 19 | "buildRoot": "${projectDir}\\out\\build\\${name}", 20 | "installRoot": "${projectDir}\\out\\install\\${name}", 21 | "cmakeCommandArgs": "", 22 | "buildCommandArgs": "", 23 | "ctestCommandArgs": "", 24 | "inheritEnvironments": [ "msvc_x64_x64" ], 25 | "variables": [] 26 | }, 27 | { 28 | "name": "mingw-dbg-x64", 29 | "generator": "Ninja", 30 | "configurationType": "Debug", 31 | "buildRoot": "${projectDir}\\out\\build\\${name}", 32 | "installRoot": "${projectDir}\\out\\install\\${name}", 33 | "cmakeCommandArgs": "", 34 | "buildCommandArgs": "-v", 35 | "ctestCommandArgs": "", 36 | "inheritEnvironments": [ "mingw_64" ], 37 | "environments": [ 38 | { 39 | "MINGW64_ROOT": "C:\\msys64\\mingw64", 40 | "BIN_ROOT": "${env.MINGW64_ROOT}\\bin", 41 | "FLAVOR": "x86_64-w64-mingw32", 42 | "TOOLSET_VERSION": "7.3.0", 43 | "PATH": "${env.MINGW64_ROOT}\\bin;${env.MINGW64_ROOT}\\..\\usr\\local\\bin;${env.MINGW64_ROOT}\\..\\usr\\bin;${env.MINGW64_ROOT}\\..\\bin;${env.PATH}", 44 | "INCLUDE": "${env.INCLUDE};${env.MINGW64_ROOT}\\include\\c++\\${env.TOOLSET_VERSION};${env.MINGW64_ROOT}\\include\\c++\\${env.TOOLSET_VERSION}\\tr1;${env.MINGW64_ROOT}\\include\\c++\\${env.TOOLSET_VERSION}\\${env.FLAVOR}", 45 | "environment": "mingw_64" 46 | } 47 | ], 48 | "variables": [ 49 | { 50 | "name": "CMAKE_C_COMPILER", 51 | "value": "${env.BIN_ROOT}\\gcc.exe", 52 | "type": "STRING" 53 | }, 54 | { 55 | "name": "CMAKE_CXX_COMPILER", 56 | "value": "${env.BIN_ROOT}\\g++.exe", 57 | "type": "STRING" 58 | } 59 | ], 60 | "intelliSenseMode": "linux-gcc-x64" 61 | }, 62 | { 63 | "name": "mingw-rel-x64", 64 | "generator": "Ninja", 65 | "configurationType": "RelWithDebInfo", 66 | "buildRoot": "${projectDir}\\out\\build\\${name}", 67 | "installRoot": "${projectDir}\\out\\install\\${name}", 68 | "cmakeCommandArgs": "", 69 | "buildCommandArgs": "-v", 70 | "ctestCommandArgs": "", 71 | "inheritEnvironments": [ "mingw_64" ], 72 | "environments": [ 73 | { 74 | "MINGW64_ROOT": "C:\\msys64\\mingw64", 75 | "BIN_ROOT": "${env.MINGW64_ROOT}\\bin", 76 | "FLAVOR": "x86_64-w64-mingw32", 77 | "TOOLSET_VERSION": "7.3.0", 78 | "PATH": "${env.MINGW64_ROOT}\\bin;${env.MINGW64_ROOT}\\..\\usr\\local\\bin;${env.MINGW64_ROOT}\\..\\usr\\bin;${env.MINGW64_ROOT}\\..\\bin;${env.PATH}", 79 | "INCLUDE": "${env.INCLUDE};${env.MINGW64_ROOT}\\include\\c++\\${env.TOOLSET_VERSION};${env.MINGW64_ROOT}\\include\\c++\\${env.TOOLSET_VERSION}\\tr1;${env.MINGW64_ROOT}\\include\\c++\\${env.TOOLSET_VERSION}\\${env.FLAVOR}", 80 | "environment": "mingw_64" 81 | } 82 | ], 83 | "variables": [ 84 | { 85 | "name": "CMAKE_C_COMPILER", 86 | "value": "${env.BIN_ROOT}\\gcc.exe", 87 | "type": "STRING" 88 | }, 89 | { 90 | "name": "CMAKE_CXX_COMPILER", 91 | "value": "${env.BIN_ROOT}\\g++.exe", 92 | "type": "STRING" 93 | } 94 | ], 95 | "intelliSenseMode": "linux-gcc-x64" 96 | }, 97 | { 98 | "name": "win-clang-dbg-x64", 99 | "generator": "Ninja", 100 | "configurationType": "Debug", 101 | "buildRoot": "${projectDir}\\out\\build\\${name}", 102 | "installRoot": "${projectDir}\\out\\install\\${name}", 103 | "cmakeCommandArgs": "", 104 | "buildCommandArgs": "", 105 | "ctestCommandArgs": "", 106 | "inheritEnvironments": [ "clang_cl_x64_x64" ], 107 | "variables": [] 108 | }, 109 | { 110 | "name": "win-clang-rel-x64", 111 | "generator": "Ninja", 112 | "configurationType": "RelWithDebInfo", 113 | "buildRoot": "${projectDir}\\out\\build\\${name}", 114 | "installRoot": "${projectDir}\\out\\install\\${name}", 115 | "cmakeCommandArgs": "", 116 | "buildCommandArgs": "", 117 | "ctestCommandArgs": "", 118 | "inheritEnvironments": [ "clang_cl_x64_x64" ], 119 | "variables": [] 120 | } 121 | ] 122 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Build results 17 | out/ 18 | [Dd]ebug/ 19 | [Dd]ebugPublic/ 20 | [Rr]elease/ 21 | [Rr]eleases/ 22 | x64/ 23 | x86/ 24 | [Aa][Rr][Mm]/ 25 | [Aa][Rr][Mm]64/ 26 | bld/ 27 | [Bb]in/ 28 | [Oo]bj/ 29 | [Ll]og/ 30 | 31 | # Visual Studio 2015/2017 cache/options directory 32 | .vs/ 33 | # Uncomment if you have tasks that create the project's static files in wwwroot 34 | #wwwroot/ 35 | 36 | # Visual Studio 2017 auto generated files 37 | Generated\ Files/ 38 | 39 | # MSTest test Results 40 | [Tt]est[Rr]esult*/ 41 | [Bb]uild[Ll]og.* 42 | 43 | # NUNIT 44 | *.VisualState.xml 45 | TestResult.xml 46 | 47 | # Build Results of an ATL Project 48 | [Dd]ebugPS/ 49 | [Rr]eleasePS/ 50 | dlldata.c 51 | 52 | # Benchmark Results 53 | BenchmarkDotNet.Artifacts/ 54 | 55 | # .NET Core 56 | project.lock.json 57 | project.fragment.lock.json 58 | artifacts/ 59 | 60 | # StyleCop 61 | StyleCopReport.xml 62 | 63 | # Files built by Visual Studio 64 | *_i.c 65 | *_p.c 66 | *_h.h 67 | *.ilk 68 | *.meta 69 | *.obj 70 | *.iobj 71 | *.pch 72 | *.pdb 73 | *.ipdb 74 | *.pgc 75 | *.pgd 76 | *.rsp 77 | *.sbr 78 | *.tlb 79 | *.tli 80 | *.tlh 81 | *.tmp 82 | *.tmp_proj 83 | *_wpftmp.csproj 84 | *.log 85 | *.vspscc 86 | *.vssscc 87 | .builds 88 | *.pidb 89 | *.svclog 90 | *.scc 91 | 92 | # Chutzpah Test files 93 | _Chutzpah* 94 | 95 | # Visual C++ cache files 96 | ipch/ 97 | *.aps 98 | *.ncb 99 | *.opendb 100 | *.opensdf 101 | *.sdf 102 | *.cachefile 103 | *.VC.db 104 | *.VC.VC.opendb 105 | 106 | # Visual Studio profiler 107 | *.psess 108 | *.vsp 109 | *.vspx 110 | *.sap 111 | 112 | # Visual Studio Trace Files 113 | *.e2e 114 | 115 | # TFS 2012 Local Workspace 116 | $tf/ 117 | 118 | # Guidance Automation Toolkit 119 | *.gpState 120 | 121 | # ReSharper is a .NET coding add-in 122 | _ReSharper*/ 123 | *.[Rr]e[Ss]harper 124 | *.DotSettings.user 125 | 126 | # JustCode is a .NET coding add-in 127 | .JustCode 128 | 129 | # TeamCity is a build add-in 130 | _TeamCity* 131 | 132 | # DotCover is a Code Coverage Tool 133 | *.dotCover 134 | 135 | # AxoCover is a Code Coverage Tool 136 | .axoCover/* 137 | !.axoCover/settings.json 138 | 139 | # Visual Studio code coverage results 140 | *.coverage 141 | *.coveragexml 142 | 143 | # NCrunch 144 | _NCrunch_* 145 | .*crunch*.local.xml 146 | nCrunchTemp_* 147 | 148 | # MightyMoose 149 | *.mm.* 150 | AutoTest.Net/ 151 | 152 | # Web workbench (sass) 153 | .sass-cache/ 154 | 155 | # Installshield output folder 156 | [Ee]xpress/ 157 | 158 | # DocProject is a documentation generator add-in 159 | DocProject/buildhelp/ 160 | DocProject/Help/*.HxT 161 | DocProject/Help/*.HxC 162 | DocProject/Help/*.hhc 163 | DocProject/Help/*.hhk 164 | DocProject/Help/*.hhp 165 | DocProject/Help/Html2 166 | DocProject/Help/html 167 | 168 | # Click-Once directory 169 | publish/ 170 | 171 | # Publish Web Output 172 | *.[Pp]ublish.xml 173 | *.azurePubxml 174 | # Note: Comment the next line if you want to checkin your web deploy settings, 175 | # but database connection strings (with potential passwords) will be unencrypted 176 | *.pubxml 177 | *.publishproj 178 | 179 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 180 | # checkin your Azure Web App publish settings, but sensitive information contained 181 | # in these scripts will be unencrypted 182 | PublishScripts/ 183 | 184 | # NuGet Packages 185 | *.nupkg 186 | # The packages folder can be ignored because of Package Restore 187 | **/[Pp]ackages/* 188 | # except build/, which is used as an MSBuild target. 189 | !**/[Pp]ackages/build/ 190 | # Uncomment if necessary however generally it will be regenerated when needed 191 | #!**/[Pp]ackages/repositories.config 192 | # NuGet v3's project.json files produces more ignorable files 193 | *.nuget.props 194 | *.nuget.targets 195 | 196 | # Microsoft Azure Build Output 197 | csx/ 198 | *.build.csdef 199 | 200 | # Microsoft Azure Emulator 201 | ecf/ 202 | rcf/ 203 | 204 | # Windows Store app package directories and files 205 | AppPackages/ 206 | BundleArtifacts/ 207 | Package.StoreAssociation.xml 208 | _pkginfo.txt 209 | *.appx 210 | 211 | # Visual Studio cache files 212 | # files ending in .cache can be ignored 213 | *.[Cc]ache 214 | # but keep track of directories ending in .cache 215 | !?*.[Cc]ache/ 216 | 217 | # Others 218 | ClientBin/ 219 | ~$* 220 | *~ 221 | *.dbmdl 222 | *.dbproj.schemaview 223 | *.jfm 224 | *.pfx 225 | *.publishsettings 226 | orleans.codegen.cs 227 | 228 | # Including strong name files can present a security risk 229 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 230 | #*.snk 231 | 232 | # Since there are multiple workflows, uncomment next line to ignore bower_components 233 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 234 | #bower_components/ 235 | 236 | # RIA/Silverlight projects 237 | Generated_Code/ 238 | 239 | # Backup & report files from converting an old project file 240 | # to a newer Visual Studio version. Backup files are not needed, 241 | # because we have git ;-) 242 | _UpgradeReport_Files/ 243 | Backup*/ 244 | UpgradeLog*.XML 245 | UpgradeLog*.htm 246 | ServiceFabricBackup/ 247 | *.rptproj.bak 248 | 249 | # SQL Server files 250 | *.mdf 251 | *.ldf 252 | *.ndf 253 | 254 | # Business Intelligence projects 255 | *.rdl.data 256 | *.bim.layout 257 | *.bim_*.settings 258 | *.rptproj.rsuser 259 | *- Backup*.rdl 260 | 261 | # Microsoft Fakes 262 | FakesAssemblies/ 263 | 264 | # GhostDoc plugin setting file 265 | *.GhostDoc.xml 266 | 267 | # Node.js Tools for Visual Studio 268 | .ntvs_analysis.dat 269 | node_modules/ 270 | 271 | # Visual Studio 6 build log 272 | *.plg 273 | 274 | # Visual Studio 6 workspace options file 275 | *.opt 276 | 277 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 278 | *.vbw 279 | 280 | # Visual Studio LightSwitch build output 281 | **/*.HTMLClient/GeneratedArtifacts 282 | **/*.DesktopClient/GeneratedArtifacts 283 | **/*.DesktopClient/ModelManifest.xml 284 | **/*.Server/GeneratedArtifacts 285 | **/*.Server/ModelManifest.xml 286 | _Pvt_Extensions 287 | 288 | # Paket dependency manager 289 | .paket/paket.exe 290 | paket-files/ 291 | 292 | # FAKE - F# Make 293 | .fake/ 294 | 295 | # JetBrains Rider 296 | .idea/ 297 | *.sln.iml 298 | 299 | # CodeRush personal settings 300 | .cr/personal 301 | 302 | # Python Tools for Visual Studio (PTVS) 303 | __pycache__/ 304 | *.pyc 305 | 306 | # Cake - Uncomment if you are using it 307 | # tools/** 308 | # !tools/packages.config 309 | 310 | # Tabs Studio 311 | *.tss 312 | 313 | # Telerik's JustMock configuration file 314 | *.jmconfig 315 | 316 | # BizTalk build output 317 | *.btp.cs 318 | *.btm.cs 319 | *.odx.cs 320 | *.xsd.cs 321 | 322 | # OpenCover UI analysis results 323 | OpenCover/ 324 | 325 | # Azure Stream Analytics local run output 326 | ASALocalRun/ 327 | 328 | # MSBuild Binary and Structured Log 329 | *.binlog 330 | 331 | # NVidia Nsight GPU debugger configuration file 332 | *.nvuser 333 | 334 | # MFractors (Xamarin productivity tool) working folder 335 | .mfractor/ 336 | 337 | # Local History for Visual Studio 338 | .localhistory/ 339 | 340 | # BeatPulse healthcheck temp database 341 | healthchecksdb -------------------------------------------------------------------------------- /aes-rijndael/aes-impl/aes_transformations.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "structs/matrix.h" 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | template 10 | using aes_block = matrix; 11 | 12 | struct aes_transformations 13 | { 14 | aes_transformations() = delete; 15 | 16 | // about shift rows step: https://en.wikipedia.org/wiki/Advanced_Encryption_Standard#The_ShiftRows_step 17 | template 18 | static aes_block shift_rows(const aes_block& block) 19 | { 20 | aes_block new_block = block; 21 | 22 | for(size_t row_index = 1; row_index < Height; ++row_index) 23 | { 24 | uint8_t* row = &new_block.at(row_index, 0); 25 | 26 | std::vector buffer(row_index); 27 | 28 | for(size_t i = 0; i < row_index; ++i) 29 | buffer[i] = row[i]; 30 | 31 | for (size_t i = row_index; i < Width; ++i) 32 | row[i - row_index] = row[i]; 33 | 34 | for (size_t i = Width - row_index, j = 0; i < Width; ++i, ++j) 35 | row[i] = buffer[j]; 36 | } 37 | 38 | return block; 39 | } 40 | 41 | // as shift rows step, but conversely 42 | template 43 | static aes_block inv_shift_rows(const aes_block& block) 44 | { 45 | aes_block new_block = block; 46 | 47 | for (size_t row_index = 1; row_index < Height; ++row_index) 48 | { 49 | uint8_t* row = &new_block.at(row_index, 0); 50 | 51 | std::vector buffer(row_index); 52 | 53 | for (size_t i = Width - row_index, j = 0; i < Width; ++i, ++j) 54 | buffer[j] = row[i]; 55 | 56 | for (size_t i = Width - row_index - 1, j = Width - 1; i != std::numeric_limits::max(); --i, --j) 57 | row[j] = row[i]; 58 | 59 | for (size_t i = 0; i < row_index; ++i) 60 | row[i] = buffer[i]; 61 | } 62 | 63 | return block; 64 | } 65 | 66 | // about sub bytes step: https://en.wikipedia.org/wiki/Advanced_Encryption_Standard#The_SubBytes_step 67 | template 68 | static aes_block sub_bytes(const aes_block& block) 69 | { 70 | aes_block new_block = block; 71 | 72 | for (size_t i = 0; i < Height; ++i) 73 | { 74 | for (size_t j = 0; j < Height; ++j) 75 | { 76 | new_block.at(i, j) = s_box[new_block.value_at(i, j)]; 77 | } 78 | } 79 | 80 | return new_block; 81 | } 82 | 83 | // as sub bytes step, but use inverse s_box 84 | template 85 | static aes_block inv_sub_bytes(const aes_block& block) 86 | { 87 | aes_block new_block = block; 88 | 89 | for (size_t i = 0; i < Height; ++i) 90 | { 91 | for (size_t j = 0; j < Height; ++j) 92 | { 93 | new_block.at(i, j) = inv_s_box[new_block.value_at(i, j)]; 94 | } 95 | } 96 | 97 | return new_block; 98 | } 99 | 100 | // about add round key: https://en.wikipedia.org/wiki/Advanced_Encryption_Standard#The_AddRoundKey_step 101 | template 102 | static aes_block add_round_key(const aes_block& state, const aes_block& key) 103 | { 104 | aes_block new_block; 105 | 106 | for (size_t i = 0; i < Height * Width; i++) 107 | new_block.data_array.at(i) = state.data_array.at(i) ^ key.data_array.at(i); 108 | 109 | return new_block; 110 | } 111 | 112 | // converts std::string to one aes-block 113 | template 114 | static aes_block message_to_block(std::string message) 115 | { 116 | aes_block block; 117 | 118 | std::copy(message.begin(), message.end(), block.begin()); 119 | 120 | return block; 121 | } 122 | 123 | // converts std::string to many aes-blocks 124 | template 125 | static std::vector> message_to_blocks(std::string message) 126 | { 127 | const size_t block_size = Height * Width; 128 | 129 | if (message.size() < block_size) 130 | message.resize(block_size); 131 | 132 | if (message.size() % block_size != 0) 133 | message.resize(message.size() + (block_size - message.size() % block_size)); 134 | 135 | std::vector> blocks { message.size() / 16 }; 136 | 137 | for(size_t i = 0; i < blocks.size(); ++i) 138 | { 139 | aes_block& block = blocks[i]; 140 | 141 | std::copy(message.data() + i * block_size, message.data() + i * block_size + block_size, block.begin()); 142 | } 143 | 144 | return blocks; 145 | } 146 | 147 | // converts many aes-blocks to std::string 148 | template 149 | static std::string blocks_to_message(std::vector> blocks) 150 | { 151 | std::string message; 152 | message.reserve(blocks.size() * Height * Width); 153 | 154 | for (aes_block& state : blocks) 155 | for (size_t j = 0; j < Height * Width; j++) 156 | message += state.data_array[j]; 157 | 158 | return message; 159 | } 160 | 161 | struct individual 162 | { 163 | individual() = delete; 164 | 165 | template 166 | static std::array rot_word(const std::array& column) 167 | { 168 | std::array new_column; 169 | 170 | for (size_t i = 1; i < Width; ++i) 171 | new_column[i - 1] = column[i]; 172 | 173 | new_column[Width - 1] = column[0]; 174 | 175 | return new_column; 176 | } 177 | 178 | template 179 | static std::array sub_bytes(const std::array& column) 180 | { 181 | std::array new_column{}; 182 | 183 | for (size_t i = 0; i < Width; i++) 184 | new_column[i] = s_box[column[i]]; 185 | 186 | return new_column; 187 | } 188 | 189 | template 190 | static std::array xor(const std::array& a, const std::array& b) 191 | { 192 | std::array new_column{}; 193 | 194 | for (size_t i = 0; i < Width; i++) 195 | new_column[i] = a[i] ^ b[i]; 196 | 197 | return new_column; 198 | } 199 | 200 | template 201 | static std::array rcon_xor(const std::array& column, size_t rcon_item_n) 202 | { 203 | std::array new_array = column; 204 | 205 | new_array[0] ^= r_con[rcon_item_n]; 206 | 207 | return new_array; 208 | } 209 | 210 | struct gf28 211 | { 212 | gf28() = delete; 213 | 214 | // method: https://en.wikipedia.org/wiki/Finite_field_arithmetic#Multiplication 215 | static uint8_t multiply(uint8_t a, uint8_t b) 216 | { 217 | struct x_time 218 | { 219 | static uint8_t product(const uint8_t x) 220 | { 221 | return (x << 1) ^ ((x >> 7 & 1) * 0x1b); 222 | } 223 | }; 224 | 225 | uint8_t c = 0; 226 | 227 | for (uint32_t i = 0; i < 8; i++) 228 | { 229 | const uint8_t first_bit = b & 1; 230 | if (first_bit != 0) 231 | { 232 | uint8_t d = a; 233 | 234 | for (uint32_t j = 0; j < i; j++) 235 | d = x_time::product(d); 236 | 237 | c ^= d; 238 | } 239 | b >>= 1; 240 | } 241 | 242 | return c; 243 | } 244 | }; 245 | 246 | // about key schedule: https://en.wikipedia.org/wiki/Rijndael_key_schedule#The_key_schedule 247 | static std::array, 10> key_expansion_128(const aes_block<4, 4>& cipher_key) 248 | { 249 | std::array, 11> keys {cipher_key}; 250 | 251 | for(size_t i = 1; i < 11; ++i) 252 | { 253 | const std::array first_column_orig = keys[i - 1].get_column(0); 254 | const std::array fourth_column_orig = keys[i - 1].get_column(3); 255 | 256 | const std::array first_new_column = xor(first_column_orig, rcon_xor(sub_bytes(rot_word(fourth_column_orig)), i)); 257 | const std::array second_new_column = xor(keys[i - 1].get_column(1), first_new_column); 258 | const std::array third_new_column = xor(keys[i - 1].get_column(2), second_new_column); 259 | const std::array fourth_new_column = xor(keys[i - 1].get_column(3), third_new_column); 260 | 261 | aes_block<4, 4> round_key; 262 | round_key.set_column(first_new_column, 0); 263 | round_key.set_column(second_new_column, 1); 264 | round_key.set_column(third_new_column, 2); 265 | round_key.set_column(fourth_new_column, 3); 266 | 267 | keys[i] = round_key; 268 | } 269 | 270 | std::array, 10> round_keys 271 | { 272 | keys[1], keys[2], keys[3], keys[4], keys[5], 273 | keys[6],keys[7], keys[8], keys[9], keys[10] 274 | }; 275 | 276 | return round_keys; 277 | } 278 | 279 | // about mix columns step: https://en.wikipedia.org/wiki/Rijndael_MixColumns 280 | static aes_block<4, 4> mix_columns_128(const aes_block<4, 4>& block) 281 | { 282 | aes_block<4, 4> new_block = block; 283 | 284 | for(size_t i = 0; i < 4; ++i) 285 | { 286 | std::array temp = new_block.get_column(i); 287 | 288 | new_block.at(0, i) = gf28::multiply(2, temp[0]) ^ gf28::multiply(3, temp[1]) ^ temp[2] ^ temp[3]; 289 | new_block.at(1, i) = temp[0] ^ gf28::multiply(2, temp[1]) ^ gf28::multiply(3, temp[2]) ^ temp[3]; 290 | new_block.at(2, i) = temp[0] ^ temp[1] ^ gf28::multiply(2, temp[2]) ^ gf28::multiply(3, temp[3]); 291 | new_block.at(3, i) = gf28::multiply(3, temp[0]) ^ temp[1] ^ temp[2] ^ gf28::multiply(2, temp[3]); 292 | } 293 | 294 | return new_block; 295 | } 296 | 297 | // about inverse mix columns step: https://en.wikipedia.org/wiki/Rijndael_MixColumns#InverseMixColumns 298 | static aes_block<4, 4> inv_mix_columns_128(const aes_block<4, 4>& block) 299 | { 300 | aes_block<4, 4> new_block = block; 301 | 302 | for (size_t i = 0; i < 4; ++i) 303 | { 304 | std::array temp = new_block.get_column(i); 305 | 306 | new_block.at(0, i) = gf28::multiply(14, temp[0]) ^ gf28::multiply(11, temp[1]) ^ gf28::multiply(13, temp[2]) ^ gf28::multiply(9, temp[3]); 307 | new_block.at(1, i) = gf28::multiply(9, temp[0]) ^ gf28::multiply(14, temp[1]) ^ gf28::multiply(11, temp[2]) ^ gf28::multiply(13, temp[3]); 308 | new_block.at(2, i) = gf28::multiply(13, temp[0]) ^ gf28::multiply(9, temp[1]) ^ gf28::multiply(14, temp[2]) ^ gf28::multiply(11, temp[3]); 309 | new_block.at(3, i) = gf28::multiply(11, temp[0]) ^ gf28::multiply(13, temp[1]) ^ gf28::multiply(9, temp[2]) ^ gf28::multiply(14, temp[3]); 310 | } 311 | 312 | return new_block; 313 | } 314 | }; 315 | 316 | // about s_box: https://en.wikipedia.org/wiki/Rijndael_S-box#Forward_S-box 317 | constexpr static uint8_t s_box[] = { 318 | 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 319 | 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 320 | 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 321 | 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 322 | 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 323 | 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 324 | 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 325 | 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 326 | 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 327 | 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 328 | 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 329 | 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 330 | 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 331 | 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 332 | 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 333 | 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 334 | }; 335 | 336 | // about inverse s_box: https://en.wikipedia.org/wiki/Rijndael_S-box#Inverse_S-box 337 | constexpr static uint8_t inv_s_box[] = { 338 | 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB, 339 | 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, 340 | 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E, 341 | 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25, 342 | 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, 343 | 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84, 344 | 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06, 345 | 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, 346 | 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73, 347 | 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E, 348 | 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, 349 | 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4, 350 | 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F, 351 | 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, 352 | 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61, 353 | 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D 354 | }; 355 | 356 | // about round constants: https://en.wikipedia.org/wiki/Rijndael_key_schedule#Round_constants 357 | constexpr static uint8_t r_con[] = { 358 | 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 359 | 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 360 | 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 361 | 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 362 | 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 363 | 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 364 | 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 365 | 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 366 | 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 367 | 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 368 | 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 369 | 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 370 | 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 371 | 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 372 | 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 373 | 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d 374 | }; 375 | }; --------------------------------------------------------------------------------