├── .gitignore ├── LICENSE ├── README.md ├── algorithm ├── __init__.py ├── block_cipher │ ├── aes │ │ ├── aes_file.py │ │ └── aes_string.py │ └── des_cipher.py ├── classical_cipher │ ├── affine_cipher.py │ ├── autokey_ciphertext_cipher.py │ ├── autokey_plaintext_cipher.py │ ├── caesar_cipher.py │ ├── column_permutation_cipher.py │ ├── double_transposition_cipher.py │ ├── keyword_cipher.py │ ├── multilateral_cipher.py │ ├── permutation_cipher.py │ ├── playfair_cipher.py │ └── vigenere_cipher.py ├── hash_algorithm │ ├── md5.py │ ├── md5_file.py │ └── md5_string.py ├── public_cipher │ ├── ecc │ │ ├── ecc.py │ │ ├── func.py │ │ ├── sm3.py │ │ ├── test.rar │ │ └── verifyrandom.py │ └── rsa │ │ ├── _pytest_cache │ │ └── v │ │ │ └── cache │ │ │ ├── lastfailed │ │ │ └── nodeids │ │ └── rsa.py └── stream_cipher │ ├── ca │ ├── ca_file.py │ └── ca_string.py │ ├── rc4_cipher.py │ ├── 加密密钥.txt │ ├── 密文.txt │ └── 明文.txt ├── assets ├── icons │ ├── Hmovetoolbar.png │ ├── Hsepartoolbar.png │ ├── PentestBox.ico │ ├── Vmovetoolbar.png │ ├── Vsepartoolbar.png │ ├── branch_closed-on.png │ ├── branch_closed.png │ ├── branch_open-on.png │ ├── branch_open.png │ ├── checkbox.png │ ├── close.png │ ├── down_arrow.png │ ├── down_arrow_disabled.png │ ├── left_arrow.png │ ├── left_arrow_disabled.png │ ├── right_arrow.png │ ├── right_arrow_disabled.png │ ├── sizegrip.png │ ├── stylesheet-branch-end.png │ ├── stylesheet-branch-more.png │ ├── stylesheet-vline.png │ ├── transparent.png │ ├── undock.png │ ├── up_arrow.png │ └── up_arrow_disabled.png ├── python │ └── qss_reader.py └── qss │ └── darkstyle.qss ├── event ├── configuration.py └── event.py ├── main.py ├── requirements.txt ├── test_file ├── ecc_private_key.txt ├── key_export.txt ├── key_import.txt ├── rsa_private_key.txt ├── to_encrypt_test.docx └── to_encrypt_test.txt └── ui ├── demo.py └── demo.ui /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Python template 3 | # Byte-compiled / optimized / DLL files 4 | __pycache__/ 5 | *.py[cod] 6 | *$py.class 7 | **.pytest_cache/ 8 | venv/ 9 | 10 | # C extensions 11 | *.so 12 | 13 | # Distribution / packaging 14 | .Python 15 | build/ 16 | develop-eggs/ 17 | dist/ 18 | downloads/ 19 | eggs/ 20 | .eggs/ 21 | lib/ 22 | lib64/ 23 | parts/ 24 | sdist/ 25 | var/ 26 | wheels/ 27 | *.egg-info/ 28 | .installed.cfg 29 | *.egg 30 | MANIFEST 31 | 32 | # PyInstaller 33 | # Usually these files are written by a python script from a template 34 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 35 | *.manifest 36 | *.spec 37 | 38 | # Installer logs 39 | pip-log.txt 40 | pip-delete-this-directory.txt 41 | 42 | # Unit test / coverage reports 43 | htmlcov/ 44 | .tox/ 45 | .coverage 46 | .coverage.* 47 | .cache 48 | nosetests.xml 49 | coverage.xml 50 | *.cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | 63 | # Flask stuff: 64 | instance/ 65 | .webassets-cache 66 | 67 | # Scrapy stuff: 68 | .scrapy 69 | 70 | # Sphinx documentation 71 | docs/_build/ 72 | 73 | # PyBuilder 74 | target/ 75 | 76 | # Jupyter Notebook 77 | .ipynb_checkpoints 78 | 79 | # pyenv 80 | .python-version 81 | 82 | # celery beat schedule file 83 | celerybeat-schedule 84 | 85 | # SageMath parsed files 86 | *.sage.py 87 | 88 | # Environments 89 | .env 90 | .venv 91 | env/ 92 | **venv/ 93 | ENV/ 94 | env.bak/ 95 | venv.bak/ 96 | .idea 97 | 98 | # Spyder project settings 99 | .spyderproject 100 | .spyproject 101 | 102 | # Rope project settings 103 | .ropeproject 104 | 105 | # mkdocs documentation 106 | /site 107 | 108 | # mypy 109 | .mypy_cache/ 110 | 111 | **.DS_Store -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Mozilla Public License Version 2.0 2 | ================================== 3 | 4 | 1. Definitions 5 | -------------- 6 | 7 | 1.1. "Contributor" 8 | means each individual or legal entity that creates, contributes to 9 | the creation of, or owns Covered Software. 10 | 11 | 1.2. "Contributor Version" 12 | means the combination of the Contributions of others (if any) used 13 | by a Contributor and that particular Contributor's Contribution. 14 | 15 | 1.3. "Contribution" 16 | means Covered Software of a particular Contributor. 17 | 18 | 1.4. "Covered Software" 19 | means Source Code Form to which the initial Contributor has attached 20 | the notice in Exhibit A, the Executable Form of such Source Code 21 | Form, and Modifications of such Source Code Form, in each case 22 | including portions thereof. 23 | 24 | 1.5. "Incompatible With Secondary Licenses" 25 | means 26 | 27 | (a) that the initial Contributor has attached the notice described 28 | in Exhibit B to the Covered Software; or 29 | 30 | (b) that the Covered Software was made available under the terms of 31 | version 1.1 or earlier of the License, but not also under the 32 | terms of a Secondary License. 33 | 34 | 1.6. "Executable Form" 35 | means any form of the work other than Source Code Form. 36 | 37 | 1.7. "Larger Work" 38 | means a work that combines Covered Software with other material, in 39 | a separate file or files, that is not Covered Software. 40 | 41 | 1.8. "License" 42 | means this document. 43 | 44 | 1.9. "Licensable" 45 | means having the right to grant, to the maximum extent possible, 46 | whether at the time of the initial grant or subsequently, any and 47 | all of the rights conveyed by this License. 48 | 49 | 1.10. "Modifications" 50 | means any of the following: 51 | 52 | (a) any file in Source Code Form that results from an addition to, 53 | deletion from, or modification of the contents of Covered 54 | Software; or 55 | 56 | (b) any new file in Source Code Form that contains any Covered 57 | Software. 58 | 59 | 1.11. "Patent Claims" of a Contributor 60 | means any patent claim(s), including without limitation, method, 61 | process, and apparatus claims, in any patent Licensable by such 62 | Contributor that would be infringed, but for the grant of the 63 | License, by the making, using, selling, offering for sale, having 64 | made, import, or transfer of either its Contributions or its 65 | Contributor Version. 66 | 67 | 1.12. "Secondary License" 68 | means either the GNU General Public License, Version 2.0, the GNU 69 | Lesser General Public License, Version 2.1, the GNU Affero General 70 | Public License, Version 3.0, or any later versions of those 71 | licenses. 72 | 73 | 1.13. "Source Code Form" 74 | means the form of the work preferred for making modifications. 75 | 76 | 1.14. "You" (or "Your") 77 | means an individual or a legal entity exercising rights under this 78 | License. For legal entities, "You" includes any entity that 79 | controls, is controlled by, or is under common control with You. For 80 | purposes of this definition, "control" means (a) the power, direct 81 | or indirect, to cause the direction or management of such entity, 82 | whether by contract or otherwise, or (b) ownership of more than 83 | fifty percent (50%) of the outstanding shares or beneficial 84 | ownership of such entity. 85 | 86 | 2. License Grants and Conditions 87 | -------------------------------- 88 | 89 | 2.1. Grants 90 | 91 | Each Contributor hereby grants You a world-wide, royalty-free, 92 | non-exclusive license: 93 | 94 | (a) under intellectual property rights (other than patent or trademark) 95 | Licensable by such Contributor to use, reproduce, make available, 96 | modify, display, perform, distribute, and otherwise exploit its 97 | Contributions, either on an unmodified basis, with Modifications, or 98 | as part of a Larger Work; and 99 | 100 | (b) under Patent Claims of such Contributor to make, use, sell, offer 101 | for sale, have made, import, and otherwise transfer either its 102 | Contributions or its Contributor Version. 103 | 104 | 2.2. Effective Date 105 | 106 | The licenses granted in Section 2.1 with respect to any Contribution 107 | become effective for each Contribution on the date the Contributor first 108 | distributes such Contribution. 109 | 110 | 2.3. Limitations on Grant Scope 111 | 112 | The licenses granted in this Section 2 are the only rights granted under 113 | this License. No additional rights or licenses will be implied from the 114 | distribution or licensing of Covered Software under this License. 115 | Notwithstanding Section 2.1(b) above, no patent license is granted by a 116 | Contributor: 117 | 118 | (a) for any code that a Contributor has removed from Covered Software; 119 | or 120 | 121 | (b) for infringements caused by: (i) Your and any other third party's 122 | modifications of Covered Software, or (ii) the combination of its 123 | Contributions with other software (except as part of its Contributor 124 | Version); or 125 | 126 | (c) under Patent Claims infringed by Covered Software in the absence of 127 | its Contributions. 128 | 129 | This License does not grant any rights in the trademarks, service marks, 130 | or logos of any Contributor (except as may be necessary to comply with 131 | the notice requirements in Section 3.4). 132 | 133 | 2.4. Subsequent Licenses 134 | 135 | No Contributor makes additional grants as a result of Your choice to 136 | distribute the Covered Software under a subsequent version of this 137 | License (see Section 10.2) or under the terms of a Secondary License (if 138 | permitted under the terms of Section 3.3). 139 | 140 | 2.5. Representation 141 | 142 | Each Contributor represents that the Contributor believes its 143 | Contributions are its original creation(s) or it has sufficient rights 144 | to grant the rights to its Contributions conveyed by this License. 145 | 146 | 2.6. Fair Use 147 | 148 | This License is not intended to limit any rights You have under 149 | applicable copyright doctrines of fair use, fair dealing, or other 150 | equivalents. 151 | 152 | 2.7. Conditions 153 | 154 | Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted 155 | in Section 2.1. 156 | 157 | 3. Responsibilities 158 | ------------------- 159 | 160 | 3.1. Distribution of Source Form 161 | 162 | All distribution of Covered Software in Source Code Form, including any 163 | Modifications that You create or to which You contribute, must be under 164 | the terms of this License. You must inform recipients that the Source 165 | Code Form of the Covered Software is governed by the terms of this 166 | License, and how they can obtain a copy of this License. You may not 167 | attempt to alter or restrict the recipients' rights in the Source Code 168 | Form. 169 | 170 | 3.2. Distribution of Executable Form 171 | 172 | If You distribute Covered Software in Executable Form then: 173 | 174 | (a) such Covered Software must also be made available in Source Code 175 | Form, as described in Section 3.1, and You must inform recipients of 176 | the Executable Form how they can obtain a copy of such Source Code 177 | Form by reasonable means in a timely manner, at a charge no more 178 | than the cost of distribution to the recipient; and 179 | 180 | (b) You may distribute such Executable Form under the terms of this 181 | License, or sublicense it under different terms, provided that the 182 | license for the Executable Form does not attempt to limit or alter 183 | the recipients' rights in the Source Code Form under this License. 184 | 185 | 3.3. Distribution of a Larger Work 186 | 187 | You may create and distribute a Larger Work under terms of Your choice, 188 | provided that You also comply with the requirements of this License for 189 | the Covered Software. If the Larger Work is a combination of Covered 190 | Software with a work governed by one or more Secondary Licenses, and the 191 | Covered Software is not Incompatible With Secondary Licenses, this 192 | License permits You to additionally distribute such Covered Software 193 | under the terms of such Secondary License(s), so that the recipient of 194 | the Larger Work may, at their option, further distribute the Covered 195 | Software under the terms of either this License or such Secondary 196 | License(s). 197 | 198 | 3.4. Notices 199 | 200 | You may not remove or alter the substance of any license notices 201 | (including copyright notices, patent notices, disclaimers of warranty, 202 | or limitations of liability) contained within the Source Code Form of 203 | the Covered Software, except that You may alter any license notices to 204 | the extent required to remedy known factual inaccuracies. 205 | 206 | 3.5. Application of Additional Terms 207 | 208 | You may choose to offer, and to charge a fee for, warranty, support, 209 | indemnity or liability obligations to one or more recipients of Covered 210 | Software. However, You may do so only on Your own behalf, and not on 211 | behalf of any Contributor. You must make it absolutely clear that any 212 | such warranty, support, indemnity, or liability obligation is offered by 213 | You alone, and You hereby agree to indemnify every Contributor for any 214 | liability incurred by such Contributor as a result of warranty, support, 215 | indemnity or liability terms You offer. You may include additional 216 | disclaimers of warranty and limitations of liability specific to any 217 | jurisdiction. 218 | 219 | 4. Inability to Comply Due to Statute or Regulation 220 | --------------------------------------------------- 221 | 222 | If it is impossible for You to comply with any of the terms of this 223 | License with respect to some or all of the Covered Software due to 224 | statute, judicial order, or regulation then You must: (a) comply with 225 | the terms of this License to the maximum extent possible; and (b) 226 | describe the limitations and the code they affect. Such description must 227 | be placed in a text file included with all distributions of the Covered 228 | Software under this License. Except to the extent prohibited by statute 229 | or regulation, such description must be sufficiently detailed for a 230 | recipient of ordinary skill to be able to understand it. 231 | 232 | 5. Termination 233 | -------------- 234 | 235 | 5.1. The rights granted under this License will terminate automatically 236 | if You fail to comply with any of its terms. However, if You become 237 | compliant, then the rights granted under this License from a particular 238 | Contributor are reinstated (a) provisionally, unless and until such 239 | Contributor explicitly and finally terminates Your grants, and (b) on an 240 | ongoing basis, if such Contributor fails to notify You of the 241 | non-compliance by some reasonable means prior to 60 days after You have 242 | come back into compliance. Moreover, Your grants from a particular 243 | Contributor are reinstated on an ongoing basis if such Contributor 244 | notifies You of the non-compliance by some reasonable means, this is the 245 | first time You have received notice of non-compliance with this License 246 | from such Contributor, and You become compliant prior to 30 days after 247 | Your receipt of the notice. 248 | 249 | 5.2. If You initiate litigation against any entity by asserting a patent 250 | infringement claim (excluding declaratory judgment actions, 251 | counter-claims, and cross-claims) alleging that a Contributor Version 252 | directly or indirectly infringes any patent, then the rights granted to 253 | You by any and all Contributors for the Covered Software under Section 254 | 2.1 of this License shall terminate. 255 | 256 | 5.3. In the event of termination under Sections 5.1 or 5.2 above, all 257 | end user license agreements (excluding distributors and resellers) which 258 | have been validly granted by You or Your distributors under this License 259 | prior to termination shall survive termination. 260 | 261 | ************************************************************************ 262 | * * 263 | * 6. Disclaimer of Warranty * 264 | * ------------------------- * 265 | * * 266 | * Covered Software is provided under this License on an "as is" * 267 | * basis, without warranty of any kind, either expressed, implied, or * 268 | * statutory, including, without limitation, warranties that the * 269 | * Covered Software is free of defects, merchantable, fit for a * 270 | * particular purpose or non-infringing. The entire risk as to the * 271 | * quality and performance of the Covered Software is with You. * 272 | * Should any Covered Software prove defective in any respect, You * 273 | * (not any Contributor) assume the cost of any necessary servicing, * 274 | * repair, or correction. This disclaimer of warranty constitutes an * 275 | * essential part of this License. No use of any Covered Software is * 276 | * authorized under this License except under this disclaimer. * 277 | * * 278 | ************************************************************************ 279 | 280 | ************************************************************************ 281 | * * 282 | * 7. Limitation of Liability * 283 | * -------------------------- * 284 | * * 285 | * Under no circumstances and under no legal theory, whether tort * 286 | * (including negligence), contract, or otherwise, shall any * 287 | * Contributor, or anyone who distributes Covered Software as * 288 | * permitted above, be liable to You for any direct, indirect, * 289 | * special, incidental, or consequential damages of any character * 290 | * including, without limitation, damages for lost profits, loss of * 291 | * goodwill, work stoppage, computer failure or malfunction, or any * 292 | * and all other commercial damages or losses, even if such party * 293 | * shall have been informed of the possibility of such damages. This * 294 | * limitation of liability shall not apply to liability for death or * 295 | * personal injury resulting from such party's negligence to the * 296 | * extent applicable law prohibits such limitation. Some * 297 | * jurisdictions do not allow the exclusion or limitation of * 298 | * incidental or consequential damages, so this exclusion and * 299 | * limitation may not apply to You. * 300 | * * 301 | ************************************************************************ 302 | 303 | 8. Litigation 304 | ------------- 305 | 306 | Any litigation relating to this License may be brought only in the 307 | courts of a jurisdiction where the defendant maintains its principal 308 | place of business and such litigation shall be governed by laws of that 309 | jurisdiction, without reference to its conflict-of-law provisions. 310 | Nothing in this Section shall prevent a party's ability to bring 311 | cross-claims or counter-claims. 312 | 313 | 9. Miscellaneous 314 | ---------------- 315 | 316 | This License represents the complete agreement concerning the subject 317 | matter hereof. If any provision of this License is held to be 318 | unenforceable, such provision shall be reformed only to the extent 319 | necessary to make it enforceable. Any law or regulation which provides 320 | that the language of a contract shall be construed against the drafter 321 | shall not be used to construe this License against a Contributor. 322 | 323 | 10. Versions of the License 324 | --------------------------- 325 | 326 | 10.1. New Versions 327 | 328 | Mozilla Foundation is the license steward. Except as provided in Section 329 | 10.3, no one other than the license steward has the right to modify or 330 | publish new versions of this License. Each version will be given a 331 | distinguishing version number. 332 | 333 | 10.2. Effect of New Versions 334 | 335 | You may distribute the Covered Software under the terms of the version 336 | of the License under which You originally received the Covered Software, 337 | or under the terms of any subsequent version published by the license 338 | steward. 339 | 340 | 10.3. Modified Versions 341 | 342 | If you create software not governed by this License, and you want to 343 | create a new license for such software, you may create and use a 344 | modified version of this License if you rename the license and remove 345 | any references to the name of the license steward (except to note that 346 | such modified license differs from this License). 347 | 348 | 10.4. Distributing Source Code Form that is Incompatible With Secondary 349 | Licenses 350 | 351 | If You choose to distribute Source Code Form that is Incompatible With 352 | Secondary Licenses under the terms of this version of the License, the 353 | notice described in Exhibit B of this License must be attached. 354 | 355 | Exhibit A - Source Code Form License Notice 356 | ------------------------------------------- 357 | 358 | This Source Code Form is subject to the terms of the Mozilla Public 359 | License, v. 2.0. If a copy of the MPL was not distributed with this 360 | file, You can obtain one at http://mozilla.org/MPL/2.0/. 361 | 362 | If it is not possible or desirable to put the notice in a particular 363 | file, then You may include the notice in a location (such as a LICENSE 364 | file in a relevant directory) where a recipient would be likely to look 365 | for such a notice. 366 | 367 | You may add additional accurate notices of copyright ownership. 368 | 369 | Exhibit B - "Incompatible With Secondary Licenses" Notice 370 | --------------------------------------------------------- 371 | 372 | This Source Code Form is "Incompatible With Secondary Licenses", as 373 | defined by the Mozilla Public License, v. 2.0. 374 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cryptography-gui-tool 2 | 3 | ## Overview 4 | 5 | A cryptographic tool with a GUI interface that can use keys to encrypt strings and files. 6 | 7 | No performance optimization has been made, encrypting files larger than 1MB may cause the interface to freeze for a long time. 8 | 9 | ## Features 10 | 11 | - Implements 11 classical ciphers, 2 stream ciphers, 2 block ciphers, 2 public key ciphers, and 1 hash algorithm. Can encrypt and decrypt both strings and files. 12 | - Includes a GUI interface implemented with PyQt. 13 | - The cryptographic library is separated from the GUI code and can be used as a standalone cryptographic library. 14 | 15 | The specific implemented ciphers are as follows: 16 | 17 | Classical Ciphers (for string encryption and decryption) 18 | 19 | 1. Monoalphabetic Substitution Ciphers: 20 | 21 | * Caesar Cipher 22 | * Keyword Cipher 23 | * Affine Cipher 24 | * Multilateral Cipher 25 | 26 | 2. Polyalphabetic Ciphers: 27 | 28 | * Vigenere Cipher 29 | * Autokey Ciphertext 30 | * Autokey Plaintext 31 | 32 | 3. Polygram Ciphers: 33 | 34 | * Playfair Cipher 35 | 36 | 4. Transposition Ciphers: 37 | 38 | * Permutation Cipher 39 | * Column Permutation Cipher 40 | * Double-Transposition Cipher 41 | 42 | Stream Ciphers (for encrypting and decrypting strings and files) 43 | 44 | * RC4 45 | * CA 46 | 47 | Block Ciphers (for encrypting and decrypting strings and files) 48 | 49 | * DES-64 50 | * AES-64 51 | 52 | Public Key Ciphers (can generate key pairs, encrypt and decrypt strings and files) 53 | 54 | * RSA 55 | * ECC 56 | 57 | Hash Algorithm (for strings and files) 58 | 59 | * MD5 60 | 61 | ## Environment Dependencies 62 | 63 | Only PyQt5 is required, as listed in `requirement.txt`, generated by `pip freeze`. 64 | 65 | ## Deployment Steps 66 | 67 | It is recommended to create a Python environment using `venv`. In the project directory, execute the following commands: 68 | 69 | ```shell 70 | # 1. Create a virtual environment 71 | python -m venv .env 72 | 73 | # 2. Activate the virtual environment 74 | # cmd 75 | ./.env/Scripts/activate.bat 76 | 77 | # powshell 78 | ./.env/Scripts/Activate.ps1 79 | 80 | # linux or MacOS 81 | source ./.env/Scripts/activate 82 | ``` 83 | 84 | In the created Python environment, run the following commands: 85 | 86 | ```bash 87 | # 1. Install dependencies 88 | pip install -r requirements.txt 89 | 90 | # 2. Start the program 91 | python3 main.py 92 | ``` 93 | 94 | ## Directory Structure Description 95 | 96 | ``` 97 | . 98 | ├── algorithm Cryptographic algorithm implementation 99 | │ ├── block_cipher 100 | │ │ └── aes 101 | │ ├── classical_cipher 102 | │ ├── hash_algorithm 103 | │ ├── public_cipher 104 | │ │ ├── ecc 105 | │ │ └── rsa 106 | │ └── stream_cipher 107 | │ └── ca 108 | ├── assets QSS configuration 109 | │ ├── icons 110 | │ ├── python 111 | │ └── qss 112 | ├── event GUI event binding 113 | └── ui GUI interface definition 114 | ``` 115 | 116 | ## Version Updates 117 | 118 | 1.0 Documentation update 119 | 120 | 1.1 Code standard update 121 | 122 | 1.2 PyQt5 version update; Removed QSS; Test files moved to a separate folder. 123 | 124 | ## Disclaimer 125 | 126 | Please credit the author morsuning if you use this code publicly. 127 | 128 | ## License 129 | 130 | [Mozilla Public License 2.0](https://github.com/morsuning/cryptography-GUItool/blob/master/LICENSE) 131 | 132 | [![Stargazers over time](https://starchart.cc/morsuning/cryptography-GUItool.svg)](https://starchart.cc/morsuning/cryptography-GUItool) 133 | ``` 134 | -------------------------------------------------------------------------------- /algorithm/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/morsuning/cryptography-gui-tool/7e0d58655f6f165f595fac869b98582a9f66448d/algorithm/__init__.py -------------------------------------------------------------------------------- /algorithm/block_cipher/aes/aes_file.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | 4 | class AESE(): 5 | 6 | def __init__(self, blk, key, Nr): 7 | self.blk = blk 8 | self.key = key 9 | self.Nr = Nr 10 | self.sbox = (0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 11 | 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 12 | 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 13 | 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 14 | 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 15 | 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 16 | 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 17 | 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 18 | 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 19 | 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 20 | 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 21 | 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 22 | 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 23 | 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 24 | 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 25 | 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16) 26 | 27 | # xtime process 28 | def xtime(self, x): 29 | if x & 0x80: 30 | return ((x << 1) ^ 0x1b) & 0xff 31 | return x << 1 32 | 33 | # MixColumns: Process the entire block 34 | def MixColumns(self): 35 | tmp = [0 for t in range(4)] 36 | xt = [0 for q in range(4)] 37 | n = 0 38 | for x in range(4): 39 | xt[0] = self.xtime(self.blk[n]) 40 | xt[1] = self.xtime(self.blk[n + 1]) 41 | xt[2] = self.xtime(self.blk[n + 2]) 42 | xt[3] = self.xtime(self.blk[n + 3]) 43 | tmp[0] = xt[0] ^ xt[1] ^ self.blk[n + 1] ^ self.blk[n + 2] ^ self.blk[n + 3] 44 | tmp[1] = self.blk[n] ^ xt[1] ^ xt[2] ^ self.blk[n + 2] ^ self.blk[n + 3] 45 | tmp[2] = self.blk[n] ^ self.blk[n + 1] ^ xt[2] ^ xt[3] ^ self.blk[n + 3] 46 | tmp[3] = xt[0] ^ self.blk[n] ^ self.blk[n + 1] ^ self.blk[n + 2] ^ xt[3] 47 | self.blk[n] = tmp[0] 48 | self.blk[n + 1] = tmp[1] 49 | self.blk[n + 2] = tmp[2] 50 | self.blk[n + 3] = tmp[3] 51 | n = n + 4 52 | 53 | # ShiftRows:Shifts the entire block 54 | def ShiftRows(self): 55 | # 2nd row 56 | t = self.blk[1] 57 | self.blk[1] = self.blk[5] 58 | self.blk[5] = self.blk[9] 59 | self.blk[9] = self.blk[13] 60 | self.blk[13] = t 61 | # 3nd row 62 | t = self.blk[2] 63 | self.blk[2] = self.blk[10] 64 | self.blk[10] = t 65 | t = self.blk[6] 66 | self.blk[6] = self.blk[14] 67 | self.blk[14] = t 68 | # 4nd row 69 | t = self.blk[15] 70 | self.blk[15] = self.blk[11] 71 | self.blk[11] = self.blk[7] 72 | self.blk[7] = self.blk[3] 73 | self.blk[3] = t 74 | 75 | # SubBytes 76 | def SubBytes(self): 77 | for x in range(16): 78 | self.blk[x] = self.sbox[self.blk[x]] 79 | 80 | # AddRoundKey 81 | def AddRoundKey(self, key): 82 | x = 0 83 | k = [0 for m in range(16)] 84 | for c in range(4): 85 | for r in range(4): 86 | k[x] = key[r][c] 87 | x = x + 1 88 | for y in range(16): 89 | self.blk[y] ^= int(k[y]) 90 | 91 | def show(self): 92 | for i in range(16): 93 | print(hex(self.blk[i])) 94 | 95 | # Schedule a secret key for use. 96 | def ScheduleKey(self, w, Nk): 97 | Rcon = [0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36] 98 | for r in range(4): 99 | for c in range(4): 100 | w[0][r][c] = self.key[r + c * 4] 101 | for i in range(1, self.Nr + 1, 1): 102 | for j in range(Nk): 103 | t = [0 for x in range(4)] 104 | for r in range(4): 105 | if j: 106 | t[r] = w[i][r][j - 1] 107 | else: 108 | t[r] = w[i - 1][r][3] 109 | if j == 0: 110 | temp = t[0] 111 | for r in range(3): 112 | t[r] = self.sbox[t[(r + 1) % 4]] 113 | t[3] = self.sbox[temp] 114 | t[0] ^= int(Rcon[i - 1]) 115 | for r in range(4): 116 | w[i][r][j] = w[i - 1][r][j] ^ t[r] 117 | 118 | # 加密函数 119 | def AesEncrypt(self): 120 | outkey = [] 121 | outkey = [[[0 for col in range(4)] for row in range(4)] for s in range(11)] 122 | self.ScheduleKey(outkey, 4) 123 | self.AddRoundKey(outkey[0]) 124 | for x in range(1, self.Nr, 1): 125 | self.SubBytes() 126 | self.ShiftRows() 127 | self.MixColumns() 128 | self.AddRoundKey(outkey[x]) 129 | self.SubBytes() 130 | self.ShiftRows() 131 | self.AddRoundKey(outkey[10]) 132 | cText = "" 133 | return self.blk 134 | 135 | 136 | class AESD(): 137 | def __init__(self, blk, key, Nr): 138 | self.blk = blk 139 | self.key = key 140 | self.Nr = Nr 141 | self.sbox = (0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 142 | 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 143 | 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 144 | 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 145 | 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 146 | 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 147 | 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 148 | 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 149 | 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 150 | 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 151 | 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 152 | 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 153 | 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 154 | 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 155 | 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 156 | 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16) 157 | 158 | def xtime(self, x): 159 | if x & 0x80: 160 | return ((x << 1) ^ 0x1b) & 0xff 161 | return x << 1 162 | 163 | def ReMixColumns(self): 164 | tmp = [0 for q in range(4)] 165 | xt1 = [0 for w in range(4)] 166 | xt2 = [0 for e in range(4)] 167 | xt3 = [0 for r in range(4)] 168 | n = 0 169 | for x in range(4): 170 | xt1[0] = self.xtime(self.blk[n]) 171 | xt1[1] = self.xtime(self.blk[n + 1]) 172 | xt1[2] = self.xtime(self.blk[n + 2]) 173 | xt1[3] = self.xtime(self.blk[n + 3]) 174 | xt2[0] = self.xtime(self.xtime(self.blk[n])) 175 | xt2[1] = self.xtime(self.xtime(self.blk[n + 1])) 176 | xt2[2] = self.xtime(self.xtime(self.blk[n + 2])) 177 | xt2[3] = self.xtime(self.xtime(self.blk[n + 3])) 178 | xt3[0] = self.xtime(self.xtime(self.xtime(self.blk[n]))) 179 | xt3[1] = self.xtime(self.xtime(self.xtime(self.blk[n + 1]))) 180 | xt3[2] = self.xtime(self.xtime(self.xtime(self.blk[n + 2]))) 181 | xt3[3] = self.xtime(self.xtime(self.xtime(self.blk[n + 3]))) 182 | tmp[0] = xt1[0] ^ xt2[0] ^ xt3[0] ^ self.blk[n + 1] ^ xt1[1] ^ xt3[1] ^ self.blk[n + 2] ^ xt2[2] ^ xt3[2] ^ \ 183 | self.blk[n + 3] ^ xt3[3] 184 | tmp[1] = self.blk[n] ^ xt3[0] ^ xt1[1] ^ xt2[1] ^ xt3[1] ^ self.blk[n + 2] ^ xt1[2] ^ xt3[2] ^ self.blk[ 185 | n + 3] ^ xt2[3] ^ xt3[3] 186 | tmp[2] = self.blk[n] ^ xt2[0] ^ xt3[0] ^ self.blk[n + 1] ^ xt3[1] ^ xt1[2] ^ xt2[2] ^ xt3[2] ^ self.blk[ 187 | n + 3] ^ xt1[3] ^ xt3[3] 188 | tmp[3] = self.blk[n] ^ xt1[0] ^ xt3[0] ^ self.blk[n + 1] ^ xt2[1] ^ xt3[1] ^ self.blk[n + 2] ^ xt3[2] ^ xt1[ 189 | 3] ^ xt2[3] ^ xt3[3] 190 | self.blk[n] = tmp[0] 191 | self.blk[n + 1] = tmp[1] 192 | self.blk[n + 2] = tmp[2] 193 | self.blk[n + 3] = tmp[3] 194 | n = n + 4 195 | 196 | def ReShiftRows(self): 197 | # 2nd row 198 | t = self.blk[13] 199 | self.blk[13] = self.blk[9] 200 | self.blk[9] = self.blk[5] 201 | self.blk[5] = self.blk[1] 202 | self.blk[1] = t 203 | # 3rd row 204 | t = self.blk[2] 205 | self.blk[2] = self.blk[10] 206 | self.blk[10] = t 207 | t = self.blk[6] 208 | self.blk[6] = self.blk[14] 209 | self.blk[14] = t 210 | # 4th row 211 | t = self.blk[3] 212 | self.blk[3] = self.blk[7] 213 | self.blk[7] = self.blk[11] 214 | self.blk[11] = self.blk[15] 215 | self.blk[15] = t 216 | 217 | def ReSubBytes(self): 218 | for i in range(16): 219 | for j in range(256): 220 | if self.sbox[j] == self.blk[i]: 221 | self.blk[i] = j 222 | break 223 | 224 | def AddRoundKey(self, key): 225 | x = 0 226 | k = [0 for m in range(16)] 227 | for c in range(4): 228 | for r in range(4): 229 | k[x] = key[r][c] 230 | x = x + 1 231 | for y in range(16): 232 | self.blk[y] ^= k[y] 233 | 234 | def ScheduleKey(self, w, Nk): 235 | Rcon = [0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36] 236 | for r in range(4): 237 | for c in range(4): 238 | w[0][r][c] = self.key[r + c * 4] 239 | for i in range(1, self.Nr + 1, 1): 240 | for j in range(Nk): 241 | t = [0 for x in range(4)] 242 | for r in range(4): 243 | if j: 244 | t[r] = w[i][r][j - 1] 245 | else: 246 | t[r] = w[i - 1][r][3] 247 | if j == 0: 248 | temp = t[0] 249 | for r in range(3): 250 | t[r] = self.sbox[t[(r + 1) % 4]] 251 | t[3] = self.sbox[temp] 252 | t[0] ^= int(Rcon[i - 1]) 253 | for r in range(4): 254 | w[i][r][j] = w[i - 1][r][j] ^ t[r] 255 | 256 | def AesDecrpyt(self): 257 | outkey = [] 258 | outkey = [[[0 for col in range(4)] for row in range(4)] for s in range(11)] 259 | self.ScheduleKey(outkey, 4) 260 | self.AddRoundKey(outkey[10]) 261 | self.ReShiftRows() 262 | self.ReSubBytes() 263 | for x in range(self.Nr - 1, 0, -1): 264 | self.AddRoundKey(outkey[x]) 265 | self.ReMixColumns() 266 | self.ReShiftRows() 267 | self.ReSubBytes() 268 | self.AddRoundKey(outkey[0]) 269 | return self.blk 270 | 271 | 272 | def StringToListN(string): 273 | s = [0 for x in range(16)] 274 | l = len(string) 275 | for x in range(l): 276 | s[x] = int(ord(string[x])) 277 | return s 278 | 279 | 280 | def HexToInt(string): 281 | s = [0 for x in range(16)] 282 | for i in range(16): 283 | s[i] = int(string[2 * i:2 * i + 2], 16) 284 | return s 285 | 286 | 287 | def encrypt(filename, skey, newfilename): 288 | f1 = open(filename, "rb") 289 | data = f1.read() 290 | f1.close() 291 | key = StringToListN(skey) 292 | f2 = open(newfilename, "wb") 293 | number = int(len(data) / 16) 294 | if len(data) % 16 != 0: 295 | number = number + 1 296 | for i in range(0, number): 297 | blk = [0 for x in range(16)] 298 | tmp = data[i * 16:i * 16 + 16] 299 | for j in range(len(tmp)): 300 | blk[j] = int(tmp[j]) 301 | a = AESE(blk, key, 10) 302 | f2.write(bytes(a.AesEncrypt())) 303 | f2.close() 304 | 305 | 306 | def decrypt(filename, skey, newfilename): 307 | f1 = open(filename, "rb") 308 | data = f1.read() 309 | key = StringToListN(skey) 310 | f2 = open(newfilename, "wb") 311 | number = int(len(data) / 16) 312 | if len(data) % 16 != 0: 313 | number = number + 1 314 | for i in range(0, number): 315 | blk = [0 for x in range(16)] 316 | tmp = data[i * 16:i * 16 + 16] 317 | for j in range(len(tmp)): 318 | blk[j] = int(tmp[j]) 319 | a = AESD(blk, key, 10) 320 | f2.write(bytes(a.AesDecrpyt())) 321 | f2.close() 322 | -------------------------------------------------------------------------------- /algorithm/block_cipher/aes/aes_string.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import string 3 | 4 | 5 | class AESE(): 6 | def __init__(self, blk, key, Nr): 7 | self.blk = blk 8 | self.key = key 9 | self.Nr = Nr 10 | self.sbox = (0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 11 | 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 12 | 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 13 | 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 14 | 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 15 | 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 16 | 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 17 | 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 18 | 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 19 | 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 20 | 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 21 | 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 22 | 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 23 | 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 24 | 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 25 | 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16) 26 | 27 | # xtime process 28 | def xtime(self, x): 29 | if (x & 0x80): 30 | return (((x << 1) ^ 0x1b) & 0xff) 31 | return x << 1 32 | 33 | # MixColumns: Process the entire block 34 | def MixColumns(self): 35 | tmp = [0 for t in range(4)] 36 | xt = [0 for q in range(4)] 37 | n = 0 38 | for x in range(4): 39 | xt[0] = self.xtime(self.blk[n]) 40 | xt[1] = self.xtime(self.blk[n + 1]) 41 | xt[2] = self.xtime(self.blk[n + 2]) 42 | xt[3] = self.xtime(self.blk[n + 3]) 43 | tmp[0] = xt[0] ^ xt[1] ^ self.blk[n + 1] ^ self.blk[n + 2] ^ self.blk[n + 3] 44 | tmp[1] = self.blk[n] ^ xt[1] ^ xt[2] ^ self.blk[n + 2] ^ self.blk[n + 3] 45 | tmp[2] = self.blk[n] ^ self.blk[n + 1] ^ xt[2] ^ xt[3] ^ self.blk[n + 3] 46 | tmp[3] = xt[0] ^ self.blk[n] ^ self.blk[n + 1] ^ self.blk[n + 2] ^ xt[3] 47 | self.blk[n] = tmp[0] 48 | self.blk[n + 1] = tmp[1] 49 | self.blk[n + 2] = tmp[2] 50 | self.blk[n + 3] = tmp[3] 51 | n = n + 4 52 | 53 | # ShiftRows:Shifts the entire block 54 | def ShiftRows(self): 55 | # 2nd row 56 | t = self.blk[1] 57 | self.blk[1] = self.blk[5] 58 | self.blk[5] = self.blk[9] 59 | self.blk[9] = self.blk[13] 60 | self.blk[13] = t 61 | # 3nd row 62 | t = self.blk[2] 63 | self.blk[2] = self.blk[10] 64 | self.blk[10] = t 65 | t = self.blk[6] 66 | self.blk[6] = self.blk[14] 67 | self.blk[14] = t 68 | # 4nd row 69 | t = self.blk[15] 70 | self.blk[15] = self.blk[11] 71 | self.blk[11] = self.blk[7] 72 | self.blk[7] = self.blk[3] 73 | self.blk[3] = t 74 | 75 | # SubBytes 76 | def SubBytes(self): 77 | for x in range(16): 78 | self.blk[x] = self.sbox[self.blk[x]] 79 | 80 | # AddRoundKey 81 | def AddRoundKey(self, key): 82 | x = 0 83 | k = [0 for m in range(16)] 84 | for c in range(4): 85 | for r in range(4): 86 | k[x] = key[r][c] 87 | x = x + 1 88 | for y in range(16): 89 | self.blk[y] ^= int(k[y]) 90 | 91 | def show(self): 92 | for i in range(16): 93 | print(hex(self.blk[i])) 94 | 95 | # Schedule a secret key for use. 96 | def ScheduleKey(self, w, Nk): 97 | Rcon = [0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36] 98 | for r in range(4): 99 | for c in range(4): 100 | w[0][r][c] = self.key[r + c * 4] 101 | for i in range(1, self.Nr + 1, 1): 102 | for j in range(Nk): 103 | t = [0 for x in range(4)] 104 | for r in range(4): 105 | if j: 106 | t[r] = w[i][r][j - 1] 107 | else: 108 | t[r] = w[i - 1][r][3] 109 | if j == 0: 110 | temp = t[0] 111 | for r in range(3): 112 | t[r] = self.sbox[t[(r + 1) % 4]] 113 | t[3] = self.sbox[temp] 114 | t[0] ^= int(Rcon[i - 1]) 115 | for r in range(4): 116 | w[i][r][j] = w[i - 1][r][j] ^ t[r] 117 | 118 | # 加密函数 119 | def AesEncrypt(self): 120 | outkey = [] 121 | outkey = [[[0 for col in range(4)] for row in range(4)] for s in range(11)] 122 | self.ScheduleKey(outkey, 4) 123 | self.AddRoundKey(outkey[0]) 124 | for x in range(1, self.Nr, 1): 125 | self.SubBytes() 126 | self.ShiftRows() 127 | self.MixColumns() 128 | self.AddRoundKey(outkey[x]) 129 | self.SubBytes() 130 | self.ShiftRows() 131 | self.AddRoundKey(outkey[10]) 132 | cText = "" 133 | for i in range(16): 134 | xxl = hex(self.blk[i]) 135 | if (len(xxl) == 3): 136 | cText += "0" + xxl[2:] 137 | else: 138 | cText += xxl[2:] 139 | return cText 140 | 141 | 142 | class AESD(): 143 | def __init__(self, blk, key, Nr): 144 | self.blk = blk 145 | self.key = key 146 | self.Nr = Nr 147 | self.sbox = (0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 148 | 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 149 | 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 150 | 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 151 | 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 152 | 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 153 | 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 154 | 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 155 | 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 156 | 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 157 | 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 158 | 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 159 | 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 160 | 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 161 | 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 162 | 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16) 163 | 164 | def xtime(self, x): 165 | if (x & 0x80): 166 | return (((x << 1) ^ 0x1b) & 0xff) 167 | return x << 1 168 | 169 | def ReMixColumns(self): 170 | tmp = [0 for q in range(4)] 171 | xt1 = [0 for w in range(4)] 172 | xt2 = [0 for e in range(4)] 173 | xt3 = [0 for r in range(4)] 174 | n = 0 175 | for x in range(4): 176 | xt1[0] = self.xtime(self.blk[n]) 177 | xt1[1] = self.xtime(self.blk[n + 1]) 178 | xt1[2] = self.xtime(self.blk[n + 2]) 179 | xt1[3] = self.xtime(self.blk[n + 3]) 180 | xt2[0] = self.xtime(self.xtime(self.blk[n])) 181 | xt2[1] = self.xtime(self.xtime(self.blk[n + 1])) 182 | xt2[2] = self.xtime(self.xtime(self.blk[n + 2])) 183 | xt2[3] = self.xtime(self.xtime(self.blk[n + 3])) 184 | xt3[0] = self.xtime(self.xtime(self.xtime(self.blk[n]))) 185 | xt3[1] = self.xtime(self.xtime(self.xtime(self.blk[n + 1]))) 186 | xt3[2] = self.xtime(self.xtime(self.xtime(self.blk[n + 2]))) 187 | xt3[3] = self.xtime(self.xtime(self.xtime(self.blk[n + 3]))) 188 | tmp[0] = xt1[0] ^ xt2[0] ^ xt3[0] ^ self.blk[n + 1] ^ xt1[1] ^ xt3[1] ^ self.blk[n + 2] ^ xt2[2] ^ xt3[2] ^ \ 189 | self.blk[n + 3] ^ xt3[3] 190 | tmp[1] = self.blk[n] ^ xt3[0] ^ xt1[1] ^ xt2[1] ^ xt3[1] ^ self.blk[n + 2] ^ xt1[2] ^ xt3[2] ^ self.blk[ 191 | n + 3] ^ xt2[3] ^ xt3[3] 192 | tmp[2] = self.blk[n] ^ xt2[0] ^ xt3[0] ^ self.blk[n + 1] ^ xt3[1] ^ xt1[2] ^ xt2[2] ^ xt3[2] ^ self.blk[ 193 | n + 3] ^ xt1[3] ^ xt3[3] 194 | tmp[3] = self.blk[n] ^ xt1[0] ^ xt3[0] ^ self.blk[n + 1] ^ xt2[1] ^ xt3[1] ^ self.blk[n + 2] ^ xt3[2] ^ xt1[ 195 | 3] ^ xt2[3] ^ xt3[3] 196 | self.blk[n] = tmp[0] 197 | self.blk[n + 1] = tmp[1] 198 | self.blk[n + 2] = tmp[2] 199 | self.blk[n + 3] = tmp[3] 200 | n = n + 4 201 | 202 | def ReShiftRows(self): 203 | # 2nd row 204 | t = self.blk[13] 205 | self.blk[13] = self.blk[9] 206 | self.blk[9] = self.blk[5] 207 | self.blk[5] = self.blk[1] 208 | self.blk[1] = t 209 | # 3rd row 210 | t = self.blk[2] 211 | self.blk[2] = self.blk[10] 212 | self.blk[10] = t 213 | t = self.blk[6] 214 | self.blk[6] = self.blk[14] 215 | self.blk[14] = t 216 | # 4th row 217 | t = self.blk[3] 218 | self.blk[3] = self.blk[7] 219 | self.blk[7] = self.blk[11] 220 | self.blk[11] = self.blk[15] 221 | self.blk[15] = t 222 | 223 | def ReSubBytes(self): 224 | for i in range(16): 225 | for j in range(256): 226 | if (self.sbox[j] == self.blk[i]): 227 | self.blk[i] = j 228 | break 229 | 230 | def AddRoundKey(self, key): 231 | x = 0 232 | k = [0 for m in range(16)] 233 | for c in range(4): 234 | for r in range(4): 235 | k[x] = key[r][c] 236 | x = x + 1 237 | for y in range(16): 238 | self.blk[y] ^= k[y] 239 | 240 | def ScheduleKey(self, w, Nk): 241 | Rcon = [0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36] 242 | for r in range(4): 243 | for c in range(4): 244 | w[0][r][c] = self.key[r + c * 4] 245 | for i in range(1, self.Nr + 1, 1): 246 | for j in range(Nk): 247 | t = [0 for x in range(4)] 248 | for r in range(4): 249 | if j: 250 | t[r] = w[i][r][j - 1] 251 | else: 252 | t[r] = w[i - 1][r][3] 253 | if j == 0: 254 | temp = t[0] 255 | for r in range(3): 256 | t[r] = self.sbox[t[(r + 1) % 4]] 257 | t[3] = self.sbox[temp] 258 | t[0] ^= int(Rcon[i - 1]) 259 | for r in range(4): 260 | w[i][r][j] = w[i - 1][r][j] ^ t[r] 261 | 262 | def AesDecrpyt(self): 263 | outkey = [] 264 | outkey = [[[0 for col in range(4)] for row in range(4)] for s in range(11)] 265 | self.ScheduleKey(outkey, 4) 266 | self.AddRoundKey(outkey[10]) 267 | self.ReShiftRows() 268 | self.ReSubBytes() 269 | for x in range(self.Nr - 1, 0, -1): 270 | self.AddRoundKey(outkey[x]) 271 | self.ReMixColumns() 272 | self.ReShiftRows() 273 | self.ReSubBytes() 274 | self.AddRoundKey(outkey[0]) 275 | mText = "" 276 | for x in range(16): 277 | mText += chr(self.blk[x]) 278 | return mText.rstrip(chr(0)) 279 | 280 | 281 | def StringToListN(string): 282 | s = [0 for x in range(16)] 283 | l = len(string) 284 | for x in range(l): 285 | s[x] = int(ord(string[x])) 286 | return s 287 | 288 | 289 | def HexToInt(string): 290 | s = [0 for x in range(16)] 291 | for i in range(16): 292 | s[i] = int(string[2 * i:2 * i + 2], 16) 293 | return s 294 | 295 | 296 | def encrypt(plainText, skey): 297 | cText = "" 298 | key = StringToListN(skey) 299 | number = int(len(plainText) / 16) 300 | if (len(plainText) % 16 != 0): 301 | number = number + 1 302 | for i in range(0, number): 303 | blk = StringToListN(plainText[i * 16:i * 16 + 16]) 304 | a = AESE(blk, key, 10) 305 | cText = cText + a.AesEncrypt() 306 | return cText 307 | 308 | 309 | def decrypt(cText, skey): 310 | mText = "" 311 | if (len(cText) % 32 != 0): 312 | print("密文位数错误!") 313 | exit(0) 314 | for i in cText: 315 | if (i not in string.digits + string.ascii_letters): 316 | print("密文格式错误!") 317 | exit(0) 318 | key = StringToListN(skey) 319 | number = int(len(cText) / 32) 320 | for i in range(0, number): 321 | rblk = HexToInt(cText[i * 32:i * 32 + 32]) 322 | b = AESD(rblk, key, 10) 323 | mText = mText + b.AesDecrpyt() 324 | return mText 325 | -------------------------------------------------------------------------------- /algorithm/block_cipher/des_cipher.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | ''' 4 | 常量部分: 5 | IP置换表 逆IP置换表 6 | S盒中的8个盒(substitution box) 7 | P盒(permutation box) 8 | 压缩置换表1-PC1 压缩置换表2-PC2 9 | 拓展置换表E(expansion box) 10 | ''' 11 | # IP置换表 12 | IP = [ 13 | 58, 50, 42, 34, 26, 18, 10, 2, 14 | 60, 52, 44, 36, 28, 20, 12, 4, 15 | 62, 54, 46, 38, 30, 22, 14, 6, 16 | 64, 56, 48, 40, 32, 24, 16, 8, 17 | 57, 49, 41, 33, 25, 17, 9, 1, 18 | 59, 51, 43, 35, 27, 19, 11, 3, 19 | 61, 53, 45, 37, 29, 21, 13, 5, 20 | 63, 55, 47, 39, 31, 23, 15, 7 21 | ] 22 | 23 | # 逆IP置换表 24 | rIP = [ 25 | 40, 8, 48, 16, 56, 24, 64, 32, 26 | 39, 7, 47, 15, 55, 23, 63, 31, 27 | 38, 6, 46, 14, 54, 22, 62, 30, 28 | 37, 5, 45, 13, 53, 21, 61, 29, 29 | 36, 4, 44, 12, 52, 20, 60, 28, 30 | 35, 3, 43, 11, 51, 19, 59, 27, 31 | 34, 2, 42, 10, 50, 18, 58, 26, 32 | 33, 1, 41, 9, 49, 17, 57, 25 33 | ] 34 | 35 | # S盒1-8 36 | S1 = [ 37 | 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7, 38 | 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8, 39 | 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0, 40 | 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13 41 | ] 42 | S2 = [ 43 | 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10, 44 | 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5, 45 | 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15, 46 | 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9 47 | ] 48 | S3 = [ 49 | 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8, 50 | 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1, 51 | 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7, 52 | 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12 53 | ] 54 | S4 = [ 55 | 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15, 56 | 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9, 57 | 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4, 58 | 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14 59 | ] 60 | S5 = [ 61 | 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9, 62 | 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6, 63 | 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14, 64 | 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3 65 | ] 66 | S6 = [ 67 | 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11, 68 | 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8, 69 | 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6, 70 | 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13 71 | ] 72 | S7 = [ 73 | 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1, 74 | 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6, 75 | 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2, 76 | 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12 77 | ] 78 | S8 = [ 79 | 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7, 80 | 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2, 81 | 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8, 82 | 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11 83 | ] 84 | S = [S1, S2, S3, S4, S5, S6, S7, S8] 85 | 86 | # P盒 87 | P = [ 88 | 16, 7, 20, 21, 89 | 29, 12, 28, 17, 90 | 1, 15, 23, 26, 91 | 5, 18, 31, 10, 92 | 2, 8, 24, 14, 93 | 32, 27, 3, 9, 94 | 19, 13, 30, 6, 95 | 22, 11, 4, 25 96 | ] 97 | 98 | # 压缩置换表PC1 99 | PC1 = [ 100 | 57, 49, 41, 33, 25, 17, 9, 101 | 1, 58, 50, 42, 34, 26, 18, 102 | 10, 2, 59, 51, 43, 35, 27, 103 | 19, 11, 3, 60, 52, 44, 36, 104 | 63, 55, 47, 39, 31, 23, 15, 105 | 7, 62, 54, 46, 38, 30, 22, 106 | 14, 6, 61, 53, 45, 37, 29, 107 | 21, 13, 5, 28, 20, 12, 4 108 | ] 109 | 110 | # 压缩置换表PC2 111 | PC2 = [ 112 | 14, 17, 11, 24, 1, 5, 113 | 3, 28, 15, 6, 21, 10, 114 | 23, 19, 12, 4, 26, 8, 115 | 16, 7, 27, 20, 13, 2, 116 | 41, 52, 31, 37, 47, 55, 117 | 30, 40, 51, 45, 33, 48, 118 | 44, 49, 39, 56, 34, 53, 119 | 46, 42, 50, 36, 29, 32 120 | ] 121 | 122 | # 拓展置换表E 123 | E = [ 124 | 32, 1, 2, 3, 4, 5, 125 | 4, 5, 6, 7, 8, 9, 126 | 8, 9, 10, 11, 12, 13, 127 | 12, 13, 14, 15, 16, 17, 128 | 16, 17, 18, 19, 20, 21, 129 | 20, 21, 22, 23, 24, 25, 130 | 24, 25, 26, 27, 28, 29, 131 | 28, 29, 30, 31, 32, 1 132 | ] 133 | 134 | 135 | def table_mapping(table, iput): 136 | result = "" 137 | for i in table: 138 | result += iput[i - 1] 139 | return result 140 | 141 | 142 | class DESCipher: 143 | 144 | def __init__(self): 145 | self.encrypt_result_hex = 0 146 | self.encrypted_file_name = "" 147 | 148 | # 表映射,输入长度必须与表大小一致--- 149 | 150 | # 均分成n部分,传入一个字符串,返回包含n项的列表--- 151 | @staticmethod 152 | def separate(entire, n): 153 | result = [] 154 | per = len(entire) // n 155 | if len(entire) % n != 0: 156 | print("分离错误") 157 | exit(-1) 158 | while len(entire) != 0: 159 | result.append(entire[:per]) 160 | entire = entire[per:] 161 | return result 162 | 163 | # 合并成一部分,传入包含n个字符串的列表,返回一个字符串--- 164 | @staticmethod 165 | def merge(list): 166 | return "".join(i for i in list) 167 | 168 | ''' 169 | 对密钥操作部分 170 | ''' 171 | 172 | # 左/右移n位--- 173 | @staticmethod 174 | def l_or_r_move(stream, n, l_or_r): 175 | if l_or_r == "L": 176 | if n > len(stream) - 1: 177 | print("左移错误") 178 | exit(-1) 179 | tmp = stream[:n] 180 | stream = stream[n:] 181 | result = stream + tmp 182 | else: 183 | if n > len(stream) - 1: 184 | print("右移错误") 185 | exit(-1) 186 | tmp = stream[-n:] 187 | stream = stream[:-n] 188 | result = tmp + stream 189 | return result 190 | 191 | # PC1压缩置换--- 192 | def PC1change(self, key): 193 | result = table_mapping(PC1, key) 194 | return result 195 | 196 | # PC2置换--- 197 | def PC2change(self, endkey): 198 | result = table_mapping(PC2, endkey) 199 | return result 200 | 201 | # 生成密钥1-16--- 202 | def key_generator(self, key): 203 | Key = [] 204 | initedKey = self.PC1change(key) # 对key进行PC1置换 205 | curCandD = self.separate(initedKey, 2) # 将key拆成2部分 206 | for i in range(16): 207 | if i == 0 or i == 1 or i == 8 or i == 15: 208 | curCandD[0] = self.l_or_r_move(curCandD[0], 1, "L") 209 | curCandD[1] = self.l_or_r_move(curCandD[1], 1, "L") 210 | Key.append(self.PC2change(self.merge(curCandD))) 211 | else: 212 | curCandD[0] = self.l_or_r_move(curCandD[0], 2, "L") 213 | curCandD[1] = self.l_or_r_move(curCandD[1], 2, "L") 214 | Key.append(self.PC2change(self.merge(curCandD))) 215 | return Key 216 | 217 | # 初始置换IP输入64位明文--- 218 | def init_permutation(self, block_plain_text): 219 | result = table_mapping(IP, block_plain_text) 220 | return result 221 | 222 | # F函数--- 223 | def func(self, k_per_turn, r_per_turn): 224 | curR = self.Echange(r_per_turn) 225 | beforeS = self.xor(curR, k_per_turn) 226 | toS = self.separate(beforeS, 8) 227 | for i, item in enumerate(toS): 228 | toS[i] = self.Schange(item, i) 229 | tmpResult = self.merge(toS) 230 | result = self.Pchange(tmpResult) 231 | return result 232 | 233 | # S置换--- 234 | def Schange(self, str, turn): 235 | column = int(str[1:5], 2) # 列 236 | row = int((str[0] + str[5]), 2) # 行 237 | tmpresult = S[turn][row * 16 + column] 238 | result = bin(int(tmpresult)).replace("0b", "").zfill(4) 239 | return result 240 | 241 | # P置换--- 242 | def Pchange(self, str): 243 | result = table_mapping(P, str) 244 | return result 245 | 246 | # 16轮加密--- 247 | def turn_operation(self, str, key, EorD): 248 | COUNTTURN = 16 249 | curLandR = self.separate(str, 2) # 将明文拆成2部分 250 | Key = self.key_generator(key) 251 | j = 15 252 | for i in range(COUNTTURN): 253 | nextL = curLandR[1] # 先保存右侧 254 | if EorD == "E": 255 | curLandR[1] = self.func(Key[i], curLandR[1]) # 将右侧和k输入f函数 256 | elif EorD == "D": 257 | curLandR[1] = self.func(Key[j], curLandR[1]) 258 | j -= 1 259 | perR = self.xor(curLandR[0], curLandR[1]) # 将新右侧与左侧异或 260 | curLandR[0] = nextL # 原右侧为新左侧 261 | curLandR[1] = perR # 运算结果为新右侧 262 | tmpresult = self.changeleftandright(curLandR) # 16轮结束后,交换左右 263 | result = self.merge(tmpresult) # 合并结果 264 | return result 265 | 266 | # 交换左右--- 267 | def changeleftandright(self, pair): 268 | tmp = pair[0] 269 | pair[0] = pair[1] 270 | pair[1] = tmp 271 | return pair 272 | 273 | # E置换--- 274 | def Echange(self, tmp): 275 | result = table_mapping(E, tmp) 276 | return result 277 | 278 | # 末(rIP)置换--- 279 | def reinitpermutation(self, tmp): 280 | result = table_mapping(rIP, tmp) 281 | return result 282 | 283 | # 异或操作--- 284 | def xor(self, left, right): 285 | length = len(left) 286 | if length != len(right): 287 | print("异或异常") 288 | exit(-1) 289 | result = int(left, 2) ^ int(right, 2) 290 | return bin(result).replace("0b", "").zfill(length) 291 | 292 | # 采用PKCS7标准填充明文:字节对8取余得r,为0补8个"8",不为0补8-r个8-r 293 | def PKCS7Padding(self, plaintext): 294 | toPaddinglen = 8 - (len(plaintext) % 8) 295 | if toPaddinglen == 8: 296 | result = plaintext 297 | else: 298 | result = plaintext + str(toPaddinglen) * toPaddinglen 299 | return result 300 | 301 | # 将字符串转化为二进制字符串--- 302 | def str2bin(self, str): 303 | result = "" 304 | for i in str: 305 | result += bin(ord(i)).replace('0b', '').zfill(8) 306 | return result 307 | 308 | # 将二进制字符串转化为字符串--- 309 | def bin2str(self, bin): 310 | if len(bin) % 8 != 0: 311 | print("二进制转字符串错误") 312 | exit(-1) 313 | result = "" 314 | while len(bin) != 0: 315 | result += chr(int(bin[:8], 2)) 316 | bin = bin[8:] 317 | return result 318 | 319 | # 对明文分组,每组64位--- 320 | def gruoping(self, plaintext): 321 | result = [] 322 | while len(plaintext) != 0: 323 | result.append(plaintext[:64]) 324 | plaintext = plaintext[64:] 325 | return result 326 | 327 | def inputhandle(self, key): 328 | dic = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!\"#$%&'()*+,-./:;<=>?@[\]^_`{|}~" 329 | if len(key) != 8: 330 | return False 331 | for i in key: 332 | if i not in dic: 333 | return False 334 | return True 335 | 336 | def cryption(self, plaintext, key, EnorDe): 337 | Plaintext = self.gruoping(plaintext) # 将明文分组 338 | cipherText = "" 339 | KEY = self.str2bin(key) # 将密钥转为二进制字符串 340 | for i in Plaintext: # 对每组加密 341 | initedPlaintext = self.init_permutation(i) # IP变换 342 | tmp = self.turn_operation(initedPlaintext, KEY, EnorDe) # 16轮加密 343 | result = self.reinitpermutation(tmp) # IP逆变换 344 | Result = self.bin2str(result) 345 | cipherText += Result 346 | return cipherText 347 | 348 | def encryption(self, plaintext, key): 349 | return self.cryption(plaintext, key, "E") 350 | 351 | def decryption(self, ciphertext, key): 352 | tmp = self.cryption(ciphertext, key, "D") 353 | delete = tmp[-1] 354 | if delete in ["1", "2", "3", "4", "5", "6", "7"]: 355 | return tmp[:-int(delete)] 356 | else: 357 | return tmp 358 | 359 | def new(self, key): 360 | if self.inputhandle(key) == True: 361 | self.Key = key 362 | else: 363 | raise ValueError("密钥输入不符合规范,必须为8位,且为A-Za-z0-9及键盘符号的组合请重新输入") 364 | return self 365 | 366 | def result_to_hex(self, result_string): 367 | encrypt_result_hex = "" 368 | for i in result_string: 369 | encrypt_result_hex.join(hex(int(bin(ord(i)).replace("0b", ""), 2)).replace("0x", "")) 370 | return encrypt_result_hex 371 | 372 | def encrypt_string(self, plain_text): 373 | Plaintext = self.PKCS7Padding(plain_text) 374 | encrypt_result = self.encryption(self.str2bin(Plaintext), self.Key) 375 | self.encrypt_result_hex = self.result_to_hex(encrypt_result) 376 | return encrypt_result 377 | 378 | def decrypt_string(self, cipher_text): 379 | self.plain = self.decryption(self.str2bin(cipher_text), self.Key) 380 | return self.plain 381 | 382 | def encrypt_file(self, file_name, save): 383 | with open(file_name, 'rb') as r: 384 | Plaintext = self.PKCS7Padding(str(r.read())) 385 | encrypt = self.encryption(self.str2bin(Plaintext), self.Key) 386 | self.encrypted_file_name = file_name + ".encrypted" 387 | with open(save, 'wb') as w: 388 | w.write(encrypt.encode('utf-8')) 389 | return self.encrypted_file_name 390 | 391 | def decrypt_file(self, file_name, save): 392 | with open(file_name, 'rb') as r: 393 | decry = self.decryption(self.str2bin(r.read().decode('utf-8')), self.Key) 394 | self.decrypt_file_name = file_name + ".decrypted" 395 | with open(save, 'w') as w: 396 | w.write(decry.strip("b'")) 397 | return self.decrypt_file_name 398 | 399 | 400 | def main(): 401 | """Example""" 402 | des = DESCipher() 403 | des.new("12345678") 404 | encrypt_result = des.encrypt_string("abcdef") 405 | print(encrypt_result) 406 | decrypt_result = des.decrypt_string(encrypt_result) 407 | print(decrypt_result) 408 | 409 | 410 | if __name__ == '__main__': 411 | main() 412 | -------------------------------------------------------------------------------- /algorithm/classical_cipher/affine_cipher.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Date: 2023-02-22 19:36:18 3 | LastEditors: morsuning@gmail.com 4 | LastEditTime: 2023-07-23 00:56:05 5 | ''' 6 | dic = {1: 1, 3: 9, 5: 21, 7: 15, 9: 3, 11: 19, 15: 7, 17: 23, 19: 11, 21: 5, 23: 17, 25: 25} # 模逆 7 | table_encrypt = {'a': 0, 'b': 1, 'c': 2, 'd': 3, 'e': 4, 'f': 5, 8 | 'g': 6, 'h': 7, 'i': 8, 'j': 9, 'k': 10, 'l': 11, 'm': 12, 9 | 'n': 13, 'o': 14, 'p': 15, 'q': 16, 'r': 17, 's': 18, 't': 19, 10 | 'u': 20, 'v': 21, 'w': 22, 'x': 23, 'y': 24, 'z': 25} 11 | table_decrypt = {0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: 'e', 5: 'f', 6: 'g', 12 | 7: 'h', 8: 'i', 9: 'j', 10: 'k', 11: 'l', 12: 'm', 13: 'n', 14: 'o', 15: 'p', 16: 'q', 17: 'r', 13 | 18: 's', 19: 't', 20: 'u', 21: 'v', 22: 'w', 23: 'x', 24: 'y', 25: 'z'} 14 | 15 | # 加密 16 | def encrypt(clear_content, key_a, key_b): 17 | key_a = key_a % 26 18 | key_b = key_b % 26 19 | result = "" 20 | for i in clear_content: 21 | result += table_decrypt.get((key_a * (table_encrypt.get(i)) + key_b) % 26) 22 | return result 23 | 24 | # 解密 25 | def decrypt(cipher, key_a, key_b): 26 | key_a = key_a % 26 27 | key_b = key_b % 26 28 | result = "" 29 | for i in cipher: 30 | result += table_decrypt.get((dic.get(key_a) * table_encrypt.get(i) - (dic.get(key_a) * key_b) % 26) % 26) 31 | return result 32 | 33 | def filter_clear(clear): 34 | result = "" 35 | clear = clear.lower() 36 | for i in clear: 37 | if 97 <= ord(i) <= 122: 38 | result += i 39 | return result 40 | 41 | def main(): 42 | a = 25 43 | b = 13 44 | plaintext = "heljfowejklfg" 45 | ciphertext = encrypt(plaintext, a, b) 46 | print(ciphertext) 47 | print(decrypt(ciphertext, a, b)) 48 | 49 | if __name__ == '__main__': 50 | main() 51 | -------------------------------------------------------------------------------- /algorithm/classical_cipher/autokey_ciphertext_cipher.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: UTF-8 -*- 3 | 4 | def weiji(plain, kkkkey): 5 | # plaintext = 'ThisIsThePlaintext' # 明文 6 | # key = 'hold' # 密钥 7 | plaintext = plain 8 | key = kkkkey 9 | matrix = [([0] * 26) for i in range(26)] 10 | for x in range(26): # 生成加密的26*26矩阵 11 | for y in range(26): 12 | t = 65 + y + x 13 | if t > 90: 14 | matrix[x][y] = chr(t - 26) 15 | if t <= 90: 16 | matrix[x][y] = chr(t) 17 | 18 | # for x in range(26): # 矩阵输出 19 | # for y in range(26): 20 | # print(matrix[x][y], end='') 21 | # if y == 25: 22 | # print(' ') 23 | key1 = '' # 后面的大写密钥 24 | for x in key: # 将密钥全部转化为大写 25 | if ord(x) >= 97: 26 | x = chr(ord(x) - 32) 27 | key1 = key1 + x 28 | # print("明文为:" + plaintext) 29 | # print("密钥为:" + key1) 30 | textsize = len(plaintext) # 明文长度 31 | keysize = len(key) # 密钥长度 32 | pkmat = [([0] * 2) for i in range(textsize)] # 加密一对一对照矩阵 33 | 34 | keytext = '' 35 | t = 0 # 用于密钥和明文匹配时循环判断 36 | for i in range(textsize): 37 | t = t % keysize 38 | pkmat[i][0] = plaintext[i] 39 | pkmat[i][1] = key1[t] 40 | t = t + 1 41 | # print("加密一对一矩阵: ", end='') 42 | # print(pkmat) # 至此,对照表完成,接下来进行转换 43 | for i in range(textsize): 44 | if ord(pkmat[i][0]) >= 97: 45 | t = ord(pkmat[i][0]) - 97 46 | x = ord(pkmat[i][1]) - 65 47 | keytext = keytext + chr(ord(matrix[t][x]) + 32) 48 | if ord(pkmat[i][0]) < 97: 49 | t = ord(pkmat[i][0]) - 65 50 | x = ord(pkmat[i][1]) - 65 51 | keytext = keytext + chr(ord(matrix[t][x])) 52 | return keytext 53 | 54 | def weijijiemi(miwen, kkkkey): 55 | len1 = len(miwen) 56 | len2 = len(kkkkey) 57 | matrix = [([0] * 26) for i in range(26)] 58 | for x in range(26): # 生成加密的26*26矩阵 59 | for y in range(26): 60 | t = 65 + y + x 61 | if t > 90: 62 | matrix[x][y] = chr(t - 26) 63 | if t <= 90: 64 | matrix[x][y] = chr(t) 65 | key = kkkkey 66 | keysize = len(key) 67 | textsize = len(miwen) 68 | kkmat = [([0] * 2) for i in range(textsize)] # 解密一对一对照矩阵 69 | t = 0 # 用于密钥和密文匹配时循环判断 70 | for i in range(textsize): # 生成解密一对一矩阵 71 | t = t % keysize 72 | kkmat[i][0] = miwen[i] 73 | kkmat[i][1] = key[t] 74 | t = t + 1 75 | pptext = '' 76 | for i in range(textsize): # 解密过程,区分大小写的解密 77 | for x in range(26): 78 | # print(ord(kkmat[i][1])) 79 | if ord(kkmat[i][0]) < 97: 80 | if (ord(kkmat[i][1]) <= 90): 81 | y = (ord(kkmat[i][1]) - 65) 82 | else: 83 | y = (ord(kkmat[i][1]) - 97) 84 | if matrix[y][x] == kkmat[i][0]: 85 | pptext = pptext + chr(x + 65) 86 | break 87 | if ord(kkmat[i][0]) >= 97: 88 | if (ord(kkmat[i][1]) <= 90): 89 | y = (ord(kkmat[i][1]) - 65) 90 | else: 91 | y = (ord(kkmat[i][1]) - 97) 92 | if matrix[y][x] == chr(ord(kkmat[i][0]) - 32): 93 | pptext = pptext + chr(x + 97) 94 | break 95 | return pptext 96 | 97 | def encrypt(ppplain, kkkey): 98 | len1 = len(ppplain) 99 | len2 = len(kkkey) 100 | key = kkkey + ppplain[0:len1 - len2] 101 | miwen = weiji(ppplain, key) 102 | return miwen 103 | 104 | def decrypt(ppplain, kkkey): 105 | len1 = len(ppplain) 106 | len2 = len(kkkey) 107 | t = int(len1 / len2) # 循环次数 108 | z = len1 % len2 109 | plaintext = '' 110 | key = kkkey 111 | for i in range(t): 112 | key = weijijiemi(ppplain[i * len2:(i + 1) * len2], key) 113 | print(key) 114 | plaintext = plaintext + key 115 | mmm = weijijiemi(ppplain[len1 - z:len1], key[:z]) 116 | plaintext = plaintext + mmm 117 | return plaintext 118 | 119 | def main(): 120 | # 示例: 121 | print(encrypt("anautokeycipherprovidedesalongkeyword", "cap")) 122 | print(decrypt("cnpugoexmmmnjmgwvfkzrzlhwdpgnryregspz", "cap")) 123 | 124 | if __name__ == "__main__": 125 | main() 126 | -------------------------------------------------------------------------------- /algorithm/classical_cipher/autokey_plaintext_cipher.py: -------------------------------------------------------------------------------- 1 | def encrypt(plainText, key): 2 | alphabet = [chr(65 + x) for x in range(26)] 3 | cipherTable = [] 4 | count1 = 0 5 | for x in range(26): 6 | row = alphabet[count1:] + alphabet[:count1] 7 | cipherTable.append(row) 8 | count1 += 1 9 | plainTextList = [x.upper() for x in plainText if 10 | (ord(x) >= ord("a") and ord(x) <= ord("z")) or (ord(x) >= ord("A") and ord(x) <= ord("Z"))] 11 | keyList = [x.upper() for x in key] 12 | count2 = 0 13 | 14 | cipherTextList, cipherTextPartList = [], [] 15 | for x in plainTextList: 16 | cipherTextPartList.append(cipherTable[ord(keyList[count2]) - ord("A")][ord(x) - ord("A")]) 17 | 18 | count2 += 1 19 | if count2 == len(keyList): 20 | for y in cipherTextPartList: 21 | cipherTextList.append(y) 22 | keyList = [x for x in cipherTextPartList] 23 | cipherTextPartList = [] 24 | count2 = 0 25 | 26 | if count2 != 0: 27 | for x in cipherTextPartList: 28 | cipherTextList.append(x) 29 | else: 30 | pass 31 | cipherText = "" 32 | for x in cipherTextList: 33 | cipherText += x 34 | return cipherText 35 | 36 | def decrypt(cipherText, key): 37 | alphabet = [chr(65 + x) for x in range(26)] 38 | cipherTable = [] 39 | count1 = 0 40 | for x in range(26): 41 | row = alphabet[count1:] + alphabet[:count1] 42 | cipherTable.append(row) 43 | count1 += 1 44 | keyList = [x.upper() for x in key] 45 | cipherTextList = [x.upper() for x in cipherText] 46 | cipherTextList.reverse() 47 | keyList.reverse() 48 | plainTextList, count2 = [], 0 49 | 50 | for x in range(len(cipherTextList)): 51 | plainTextList.append( 52 | chr((cipherTable[ord(cipherTextList[x + len(keyList)]) - ord("A")].index(cipherTextList[x])) + ord("A"))) 53 | count2 += 1 54 | if count2 >= len(cipherTextList) - len(keyList): 55 | break 56 | 57 | for x, y in zip(keyList, cipherTextList[len(cipherTextList) - len(keyList):]): 58 | plainTextList.append(chr(cipherTable[ord(x) - ord("A")].index(y) + ord("A"))) 59 | plainTextList.reverse() 60 | 61 | plainText = "" 62 | for x in plainTextList: 63 | plainText += x 64 | return plainText 65 | 66 | def main(): 67 | plaintext = "hello" 68 | key = "eii" 69 | ciphertext = encrypt(plaintext, key) 70 | print(ciphertext) 71 | print(decrypt(ciphertext, key)) 72 | 73 | if __name__ == "__main__": 74 | main() 75 | -------------------------------------------------------------------------------- /algorithm/classical_cipher/caesar_cipher.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 _*_ 2 | ''' 3 | Caesar cipher加密算法的实现 4 | 凯撒加密(Caesar cipher)是一种简单的消息编码方式, 5 | 根据字母表将消息中的每个字母移动常量位k,默认k为3,例如A转换为D 6 | ''' 7 | 8 | def caesar_encrypt(x, k=3): 9 | """第一个参数为明文字符串,第二个参数为向后移位的位数""" 10 | result = '' 11 | move = k % 26 12 | for i in x: 13 | pass 14 | # 如果是大写 15 | if i.isupper(): 16 | result = result + chr(65 + (ord(i) + move - 65) % 26) 17 | elif i.islower(): 18 | result = result + chr(97 + (ord(i) + move - 97) % 26) 19 | return result 20 | 21 | def caesar_decrypt(x, k=3): 22 | """第一个参数为明文字符串,第二个参数为向后移位的位数""" 23 | result = '' 24 | move = k % 26 25 | for i in x: 26 | # 如果是大写 27 | if i.isupper(): 28 | result = result + chr(65 + (ord(i) - move - 65) % 26) 29 | elif i.islower(): 30 | result = result + chr(97 + (ord(i) - move - 97) % 26) 31 | return result 32 | 33 | def main(): 34 | print('Abcd凯撒加密的密文是:', caesar_encrypt('Abcd', 3)) 35 | print('Defg凯撒加密的明文是:', caesar_decrypt('Defg', 3)) 36 | 37 | if __name__ == "__main__": 38 | main() 39 | -------------------------------------------------------------------------------- /algorithm/classical_cipher/column_permutation_cipher.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Date: 2023-02-22 19:36:18 3 | LastEditors: morsuning@gmail.com 4 | LastEditTime: 2023-07-23 00:57:30 5 | ''' 6 | #! /usr/bin/env python 7 | # -*- coding:UTF-8 -*- 8 | 9 | # 获得读取顺序,返回一个读取列号的列表 10 | def getOrder(key): 11 | result = [] 12 | tmp = [] 13 | for i in key: 14 | tmp.append(ord(i)) 15 | order = tmp.copy() 16 | order.sort() 17 | tmporder = set(order) 18 | for i in tmporder: 19 | if order.count(i) == 1: 20 | result.append(tmp.index(i)) 21 | else: 22 | uniqueindex = unique_index(tmp, i) 23 | for j in uniqueindex: 24 | result.append(j) 25 | return result 26 | 27 | # 输入列表和元素,返回列表中和该元素相等的元素的序号的列表 28 | def unique_index(L, e): 29 | return [i for (i, j) in enumerate(L) if j == e] 30 | 31 | # 向明文尾部填充字符e 32 | def padding(plaintext, m): 33 | while len(plaintext) % m != 0: 34 | plaintext += "e" 35 | return plaintext 36 | 37 | # 加密 38 | def encrypt(plaintext, key): 39 | ciphertext = "" 40 | m = len(key) 41 | Plaintext = padding(plaintext, m) 42 | n = len(Plaintext) // m 43 | order = getOrder(key) 44 | for i in order: 45 | excursion = 0 46 | for j in range(n): 47 | ciphertext += Plaintext[i + excursion] 48 | excursion += m 49 | return ciphertext 50 | 51 | # 解密 52 | def decrypt(ciphertext, key): 53 | plaintext = "" 54 | m = len(key) 55 | Ciphertext = padding(ciphertext, m) 56 | n = len(ciphertext) // m 57 | order = getOrder(key) 58 | readorder = [] 59 | for i in range(len(order)): 60 | readorder.append(order.index(i)) 61 | for i in range(n): 62 | for j in readorder: 63 | plaintext += Ciphertext[i + j * n] 64 | return plaintext 65 | 66 | def main(): 67 | plaintext = input("请输入要加密的密文:\n") 68 | key = input("请输入密钥:\n") 69 | ciphertext = encrypt(plaintext.replace(" ", ""), key) 70 | print("加密后的结果是(明文长模密钥长不为零则用e补充):\n%s" % ciphertext) 71 | choice = input("请输入d解密:\n") 72 | if choice == 'd': 73 | key = input("请输入密钥(如果密钥错误将解出错误的结果):\n") 74 | plain = decrypt(ciphertext, key) 75 | print("原文是(省略所有空格):\n%s" % plain) 76 | else: 77 | print("已退出") 78 | print("实验结束") 79 | 80 | if __name__ == "__main__": 81 | main() 82 | -------------------------------------------------------------------------------- /algorithm/classical_cipher/double_transposition_cipher.py: -------------------------------------------------------------------------------- 1 | def double_transposition(plaintttext, kkkkey): # 此为一次置换,不是两次 2 | plaintext = plaintttext 3 | key = kkkkey 4 | lienum = len(key) 5 | sortmrx = [0 for i in range(lienum)] 6 | plainnum = len(plaintext) 7 | i = plainnum % lienum 8 | if i == 0: # 确定列数 9 | hangnum = int(plainnum / lienum) 10 | if i != 0: 11 | hangnum = int(plainnum / lienum) + 1 12 | matrix = [([0] * lienum) for i in range(hangnum)] 13 | newrix = [([0] * lienum) for i in range(hangnum)] 14 | t = 0 # t用于循环判断,填充矩阵 15 | for x in range(hangnum): # 循环判断,填充矩阵 16 | for y in range(lienum): 17 | if t < plainnum: 18 | matrix[x][y] = plaintext[t] 19 | t = t + 1 20 | if t > plainnum: 21 | matrix[x][y] = '+' 22 | for x in range(lienum): # 对密钥的字母大小进行排序 23 | for y in range(lienum): 24 | if x == y: 25 | sortmrx[x] = sortmrx[x] + 1 26 | continue 27 | if ord(key[x]) > ord(key[y]): 28 | sortmrx[x] = sortmrx[x] + 1 29 | if ord(key[x]) < ord(key[y]): 30 | continue 31 | if (ord(key[x]) == ord(key[y])) & (x > y): 32 | sortmrx[x] = sortmrx[x] + 1 33 | keymrx = [0 for i in range(hangnum * lienum)] # 声明存储加密字符串的数组 34 | t = 0 35 | for i in range(lienum): 36 | for j in range(hangnum): 37 | keymrx[t] = matrix[j][sortmrx[i] - 1] 38 | t = t + 1 39 | t = hangnum * lienum 40 | xxxxxxxxxx = '' 41 | for i in range(len(keymrx)): # 打印输出加密 42 | xxxxxxxxxx = xxxxxxxxxx + str(keymrx[i]) 43 | return xxxxxxxxxx 44 | 45 | def jiemi(keytext, key): # 此为一次解密,不是两次 46 | plaintext = keytext 47 | lienum = len(key) 48 | sortmrx = [0 for i in range(lienum)] 49 | plainnum = len(plaintext) 50 | i = plainnum % lienum 51 | if i == 0: # 确定列数 52 | hangnum = int(plainnum / lienum) 53 | if i != 0: 54 | hangnum = int(plainnum / lienum) + 1 55 | for x in range(lienum): # 对密钥的字母大小进行排序 56 | for y in range(lienum): 57 | if x == y: 58 | sortmrx[x] = sortmrx[x] + 1 59 | continue 60 | if ord(key[x]) > ord(key[y]): 61 | sortmrx[x] = sortmrx[x] + 1 62 | if ord(key[x]) < ord(key[y]): 63 | continue 64 | if (ord(key[x]) == ord(key[y])) & (x > y): 65 | sortmrx[x] = sortmrx[x] + 1 66 | keymrx = [0 for i in range((hangnum) * lienum)] 67 | for i in range(len(keytext)): 68 | keymrx[i] = plaintext[i] 69 | # 解密过程 70 | nnnrix = [([0] * lienum) for i in range(hangnum)] 71 | t = 0 72 | for i in range(lienum): # 解密步骤 73 | for j in range(hangnum): 74 | nnnrix[j][sortmrx[i] - 1] = keymrx[t] 75 | t = t + 1 76 | # print('') 77 | # print("解密结果为:") 78 | tttttt = '' 79 | for i in range(hangnum): # 打印输出解密结果 80 | for j in range(lienum): 81 | tttttt = tttttt + str(nnnrix[i][j]) 82 | # print(nnnrix[i][j], end='') 83 | # if j == lienum - 1: 84 | # print('') 85 | 86 | return tttttt 87 | 88 | def encrypt(mingwen, key1, key2): 89 | xxx = double_transposition(mingwen, key1) 90 | yyy = double_transposition(xxx, key2) 91 | return yyy 92 | 93 | def decrypt(miwem, key2, key1): 94 | xxx = jiemi(miwem, key2) 95 | t = 0 96 | lens = len(xxx) 97 | for i in range(lens): 98 | if xxx[lens - 1 - i] == '0': 99 | t = t + 1 100 | else: 101 | break 102 | xxxx = xxx[0:lens - t] 103 | yyy = jiemi(xxxx, key1) 104 | return yyy.replace('0', '') 105 | 106 | def main(): 107 | plaintext = "encryptionalgorithms" 108 | key = 'dbac' 109 | print(encrypt("encryptionalgorithms", "dbaasdfc", "abcd")) 110 | print(decrypt("yatio0gmni0r0en0tlcohprs", "abcd", "dbaasdfc")) 111 | 112 | if __name__ == "__main__": 113 | main() 114 | -------------------------------------------------------------------------------- /algorithm/classical_cipher/keyword_cipher.py: -------------------------------------------------------------------------------- 1 | import string 2 | 3 | def encrypt(plaintext, ci_key): 4 | plaintext = list(plaintext.lower()) 5 | ciphertext = list(string.ascii_lowercase) 6 | ci_key = list(ci_key.lower()) 7 | key = [] 8 | for i in ci_key: 9 | if i not in key: 10 | key.append(i) 11 | for i in ciphertext: 12 | if i not in key: 13 | key.append(i) 14 | all_letter = list(string.ascii_lowercase) 15 | ciphertext = [] 16 | for i in plaintext: 17 | for j in range(26): 18 | if i == all_letter[j]: 19 | ciphertext.append(key[j]) 20 | return "".join(list(ciphertext)), "".join(list(key)) 21 | 22 | def decrypt(ciphertext, ci_key): 23 | str_ciphertext = list(string.ascii_lowercase) 24 | ci_key = list(ci_key.lower()) 25 | key = [] 26 | for i in ci_key: 27 | if i not in key: 28 | key.append(i) 29 | for i in str_ciphertext: 30 | if i not in key: 31 | key.append(i) 32 | all_letter = string.ascii_lowercase 33 | plaintext = [] 34 | ciphertext = list(ciphertext) 35 | for i in ciphertext: 36 | for j in range(26): 37 | if i == key[j]: 38 | plaintext.append(all_letter[j]) 39 | return "".join(list(plaintext)) 40 | 41 | def main(): 42 | plaintext = input("请输入明文") 43 | ci_key = input("请输入密匙") 44 | ciphertext, key = encrypt(plaintext, ci_key) 45 | plaintext = decrypt(ciphertext, ci_key) 46 | print("解密结果" + plaintext) 47 | 48 | if __name__ == '__main__': 49 | main() 50 | -------------------------------------------------------------------------------- /algorithm/classical_cipher/multilateral_cipher.py: -------------------------------------------------------------------------------- 1 | import collections 2 | 3 | def encrypt(pla, key): 4 | pla = pla.lower() 5 | key = key.lower() 6 | cip = [] 7 | # 定义好矩阵 8 | table = [['', key[0], key[1], key[2], key[3], key[4]], [key[0], 'a', 'b', 'c', 'd', 'e'], 9 | [key[1], 'f', 'g', 'h', 'i', 'k'], [key[2], 'l', 'm', 'n', 'o', 'p'], [key[3], 'q', 'r', 's', 't', 'u'], 10 | [key[4], 'v', 'w', 'x', 'y', 'z']] 11 | for k in pla: 12 | # 当明文中有“j”的时候,当做“i”进行处理 13 | if k == 'j': 14 | k = 'i' 15 | for i in range(1, 6): 16 | for j in range(1, 6): 17 | if k == table[i][j] and k != 'j': 18 | cip.append(table[i][0]) 19 | cip.append(table[0][j]) 20 | cipertext = ''.join(cip) 21 | return cipertext 22 | 23 | 24 | def decrypt(cip, key): 25 | # 将密文拆分,两个两个一组存放 26 | cip = cip.lower() 27 | key = key.lower() 28 | temp = key 29 | cip_res = [] 30 | for i in range(0, len(cip), 2): 31 | cip_res.append(cip[i:i + 2]) 32 | # 存放密文的所有组合 33 | key_res = [] 34 | pla = [] 35 | # 去除重复字母 36 | key = ''.join(collections.OrderedDict.fromkeys(cip)) 37 | for i1 in key: 38 | for i2 in key: 39 | for i3 in key: 40 | for i4 in key: 41 | for i5 in key: 42 | if i1 not in (i2 + i3 + i4 + i5) and i2 not in (i1 + i3 + i4 + i5) and i3 not in ( 43 | i1 + i2 + i4 + i5) and i4 not in (i1 + i2 + i3 + i5) and i5 not in (i1 + i2 + i3 + i4): 44 | key_res.append(i1 + i2 + i3 + i4 + i5) 45 | for z in range(len(key_res)): 46 | key = key_res[z] 47 | table = [['', key[0], key[1], key[2], key[3], key[4]], [key[0], 'a', 'b', 'c', 'd', 'e'], 48 | [key[1], 'f', 'g', 'h', 'i', 'k'], [key[2], 'l', 'm', 'n', 'o', 'p'], 49 | [key[3], 'q', 'r', 's', 't', 'u'], [key[4], 'v', 'w', 'x', 'y', 'z']] 50 | for i in cip_res: 51 | for j in range(len(table[0])): 52 | # 记录第一个下标 53 | if i[0] == table[0][j]: 54 | a = j 55 | # 记录第二个下标 56 | if i[1] == table[0][j]: 57 | b = j 58 | s = table[a][b] 59 | pla.append(s) 60 | j = 0 61 | for i in range(0, len(pla), len(cip_res)): 62 | # f.write("秘钥:" + key_res[j] + " ") 63 | # print(key_res[j]) 64 | flag = ''.join(pla[i:i + len(cip_res)]) 65 | # f.write("明文:" + ''.join(pla[i:i + len(cip_res)])) 66 | if temp == key_res[j]: 67 | break 68 | # f.write('\n') 69 | j = j + 1 70 | return flag 71 | 72 | def main(): 73 | # 只能有英文 74 | pla = input("请输入需要加密的字符串:") 75 | key = input("请输入秘钥:") 76 | # 密钥只能有5位,英文 77 | print(encrypt(pla, key)) 78 | cip = input("请输入需要解密的密文:") 79 | print(decrypt(cip, key)) 80 | 81 | if __name__ == '__main__': 82 | main() 83 | -------------------------------------------------------------------------------- /algorithm/classical_cipher/permutation_cipher.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | def msgToChunks(msg, key): 3 | msg = msg.replace(' ', '') 4 | while len(msg) % len(key) != 0: 5 | msg += ' ' 6 | chunks = [] 7 | for i in range(0, len(msg), len(key)): 8 | chunks.append(msg[i:i + len(key)]) 9 | return chunks 10 | 11 | def transpose(chunks, order): 12 | result = '' 13 | for x in chunks: 14 | for pos in order: 15 | result += x[pos] 16 | return result.replace(' ', '') 17 | 18 | def keyToEncrptyOrder(key): 19 | order = [0] * len(key) 20 | sorted_key = ''.join(sorted(key)) 21 | for i, x in enumerate(key): 22 | order[sorted_key.find(x)] = i 23 | # print(order) 24 | return order 25 | 26 | def keyToDecrptyOrder(key): 27 | order = [0] * len(key) 28 | sorted_key = ''.join(sorted(key)) 29 | for i, x in enumerate(key): 30 | order[i] = sorted_key.find(x) 31 | # print(order) 32 | return order 33 | 34 | def encrypt(msg, key): 35 | msg = msg.replace(' ', '') 36 | chunks = msgToChunks(msg, key) 37 | order = keyToEncrptyOrder(key) 38 | return transpose(chunks, order) 39 | 40 | def decrypt(msg, key): 41 | msg = msg.replace(' ', '') 42 | chunks = msgToChunks(msg, key) 43 | order = keyToDecrptyOrder(key) 44 | return transpose(chunks, order) 45 | 46 | def test(): 47 | print(encrypt('get the ball', '34152')) 48 | print(decrypt('thgetalebl', '34152')) 49 | -------------------------------------------------------------------------------- /algorithm/classical_cipher/playfair_cipher.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import string 3 | 4 | def playfair(key, remaining, encrypting=True): 5 | key = key.lower() 6 | remaining = remaining.lower() 7 | def pos(row, col): # given a row/column, get the position in the table string 8 | return row * 5 + col 9 | def cell(position): # given a position in the table string, get the row/column 10 | row = int(position / 5) 11 | col = position % 5 12 | return row, col 13 | table = "" 14 | # add the key & alphabet to the matrix; ignore duplicates 15 | for c in key.lower() + string.ascii_lowercase: 16 | if c in ['i', 'j']: # treat i/j as the same char 17 | if ('i' not in table) and ('j' not in table): 18 | table = table + 'i' 19 | elif c not in table: 20 | table = table + c 21 | cipher = "" 22 | while remaining != "": 23 | # if only 1 character is left 24 | if len(remaining) == 1: 25 | a = remaining[0] 26 | b = "x" 27 | remaining = "" 28 | # duplicate letter 29 | elif remaining[0] == remaining[1]: 30 | a = remaining[0] 31 | b = "x" 32 | remaining = remaining[1:] 33 | else: 34 | a = remaining[0] 35 | b = remaining[1] 36 | remaining = remaining[2:] 37 | # replace j's with i's 38 | a = "i" if a == "j" else a 39 | b = "i" if b == "j" else b 40 | c1 = cell(table.find(a)) 41 | c2 = cell(table.find(b)) 42 | shift = 1 if encrypting else -1 # for same column/row; if encrypting shift +1, else shift -1 43 | if c1[0] == c2[0]: # same row 44 | cipher = cipher + table[pos(c1[0], (c1[1] + shift) % 5)] + table[pos(c2[0], (c2[1] + shift) % 5)] 45 | elif c1[1] == c2[1]: # same column 46 | cipher = cipher + table[pos((c1[0] + shift) % 5, c1[1])] + table[pos((c2[0] + shift) % 5, c2[1])] 47 | else: 48 | cipher = cipher + table[pos(c1[0], c2[1])] + table[pos(c2[0], c1[1])] 49 | return cipher 50 | 51 | def main(): 52 | # Encrypt foo.txt -> cipher.txt 53 | key = input("请输入key") 54 | plaintext = input("输入明文") 55 | print(playfair(key, plaintext, True).upper()) 56 | key = input("请输入密钥") 57 | ciphertext = input("请输入密文") 58 | print(playfair(key, ciphertext, False).upper()) 59 | 60 | if __name__ == '__main__': 61 | main() 62 | -------------------------------------------------------------------------------- /algorithm/classical_cipher/vigenere_cipher.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | # -*- coding:UTF-8 -*- 3 | # 将字母A-Z转化成0-26的数 4 | def str2ascii2mirr26(str): 5 | if len(str) == 1: 6 | return ord(str) - 65 7 | else: 8 | tmpstr = [] 9 | for i in range(len(str)): 10 | tmpstr.append(ord(str[i]) - 65) 11 | return tmpstr 12 | 13 | # 将0-26的数转化为字母A-Z 14 | def mirr262str(str): 15 | tmpstr = "" 16 | for i in str: 17 | tmpstr += chr(i + 65) 18 | return tmpstr 19 | 20 | # 转化为大写 21 | def strupper(str): 22 | s = "" 23 | s += str 24 | return s.upper() 25 | 26 | # 使得密钥长度和明文一致 27 | def expendkey(key, length): 28 | if len(key) > length: 29 | return key[:length] 30 | elif len(key) == length: 31 | return key 32 | else: 33 | while len(key) < length: 34 | key += key 35 | if len(key) != length: 36 | return key[:length] 37 | else: 38 | return key 39 | 40 | # 加密 41 | def encrypt(plaintext, key): 42 | plaintext = strupper(plaintext) 43 | tmpkey = strupper(key) 44 | Key = expendkey(tmpkey, len(plaintext)) 45 | tmpciphertext = [] 46 | for index, item in enumerate(plaintext): 47 | tmpciphertext.append(((str2ascii2mirr26(Key[index]) + str2ascii2mirr26(item)) % 26)) 48 | return mirr262str(tmpciphertext) 49 | 50 | # 解密 51 | def decrypt(ciphertext, key): 52 | tmpkey = strupper(key) 53 | Key = expendkey(tmpkey, len(ciphertext)) 54 | tmpplaintext = [] 55 | for index, item in enumerate(ciphertext): 56 | tmpplaintext.append(((str2ascii2mirr26(item) - str2ascii2mirr26(Key[index])) % 26)) 57 | return mirr262str(tmpplaintext) 58 | 59 | # 实验主流程 60 | def main(): 61 | print("-------------------------") 62 | print("-----Vigenère Cipher-----") 63 | print("-------------------------") 64 | plaintext = input("请输入要加密的密文:\n") 65 | key = input("请输入密钥:\n") 66 | ciphertext = encrypt(plaintext, key) 67 | print("加密后的结果是:\n%s" % ciphertext) 68 | choice = input("请输入d解密:\n") 69 | if choice == 'd': 70 | key = input("请输入密钥(如果密钥错误将解出错误的结果):\n") 71 | plain = decrypt(ciphertext, key) 72 | print("原文是(全部以小写形式给出):\n%s" % (plain.lower())) 73 | else: 74 | print("已退出") 75 | print("实验结束") 76 | 77 | if __name__ == "__main__": 78 | main() 79 | -------------------------------------------------------------------------------- /algorithm/hash_algorithm/md5.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | class MD5: 5 | 6 | def __init__(self): 7 | super().__init__() 8 | 9 | def md5_file(filename): 10 | 11 | f1 = open(filename, "rb") 12 | p = f1.read() 13 | x = p.__len__() 14 | plaintext = '' 15 | for i in range(x): 16 | plaintext = plaintext + bin(p[i])[2:].zfill(8) 17 | A = 0x67452301 18 | B = 0xefcdab89 19 | C = 0x98badcfe 20 | D = 0x10325476 21 | bintext = plaintext 22 | t = bintext.__len__() % 512 23 | houzhui = bin(bintext.__len__())[2:].zfill(64) 24 | if t < 448: 25 | bintext = bintext + '1' 26 | for i in range(447 - t): 27 | bintext = bintext + '0' 28 | else: 29 | bintext = bintext + '1' 30 | for i in range(959 - t): 31 | bintext = bintext + '0' 32 | 33 | sectext = bintext + houzhui 34 | x = sectext.__len__() / 512 35 | M = [[[0] * 1 for _ in range(16)] for _ in range(int(x))] 36 | M[0][0][0] = 1 37 | for i in range(int(x)): 38 | for j in range(16): 39 | ix = 3 40 | for k in range(1): 41 | x = sectext[i * 512 + j * 32:i * 512 + j * 32 + 32] 42 | y = x[24:32] + x[16:24] + x[8:16] + x[0:8] 43 | M[i][j][k] = int(y, 2) 44 | 45 | def F(x, y, z): 46 | return (x & y) | ((~x) & z) 47 | 48 | def G(x, y, z): 49 | return (x & z) | (y & (~z)) 50 | 51 | def H(x, y, z): 52 | return x ^ y ^ z 53 | 54 | def I(x, y, z): 55 | return y ^ (x | (~z)) 56 | 57 | def yiwei(x, z): 58 | x = x & 0xffffffff 59 | y = bin(x).replace('0b', '') 60 | tt = y.__len__() 61 | if tt < 32: 62 | y = y.zfill(32) 63 | t = y[z:] + y[:z] 64 | return int(t, 2) 65 | else: 66 | x = y[tt - 32:] 67 | t = x[z:] + x[:z] 68 | return int(t, 2) 69 | 70 | def FF(a, b, c, d, M, s, t): 71 | a = b + yiwei((a + F(b, c, d) + M + t), s) 72 | return a & 0xffffffff 73 | 74 | def GG(a, b, c, d, M, s, t): 75 | a = b + yiwei((a + G(b, c, d) + M + t), s) 76 | return a & 0xffffffff 77 | 78 | def HH(a, b, c, d, M, s, t): 79 | a = b + yiwei((a + H(b, c, d) + M + t), s) 80 | return a & 0xffffffff 81 | 82 | def II(a, b, c, d, M, s, t): 83 | a = b + yiwei((a + I(b, c, d) + M + t), s) 84 | return a & 0xffffffff 85 | 86 | for i in range(int(sectext.__len__() / 512)): 87 | a = A 88 | b = B 89 | c = C 90 | d = D 91 | a = FF(a, b, c, d, M[i][0][0], 7, 0xd76aa478) 92 | d = FF(d, a, b, c, M[i][1][0], 12, 0xe8c7b756) 93 | c = FF(c, d, a, b, M[i][2][0], 17, 0x242070db) 94 | b = FF(b, c, d, a, M[i][3][0], 22, 0xc1bdceee) 95 | a = FF(a, b, c, d, M[i][4][0], 7, 0xf57c0faf) 96 | d = FF(d, a, b, c, M[i][5][0], 12, 0x4787c62a) 97 | c = FF(c, d, a, b, M[i][6][0], 17, 0xa8304613) 98 | b = FF(b, c, d, a, M[i][7][0], 22, 0xfd469501) 99 | a = FF(a, b, c, d, M[i][8][0], 7, 0x698098d8) 100 | d = FF(d, a, b, c, M[i][9][0], 12, 0x8b44f7af) 101 | c = FF(c, d, a, b, M[i][10][0], 17, 0xffff5bb1) 102 | b = FF(b, c, d, a, M[i][11][0], 22, 0x895cd7be) 103 | a = FF(a, b, c, d, M[i][12][0], 7, 0x6b901122) 104 | d = FF(d, a, b, c, M[i][13][0], 12, 0xfd987193) 105 | c = FF(c, d, a, b, M[i][14][0], 17, 0xa679438e) 106 | b = FF(b, c, d, a, M[i][15][0], 22, 0x49b40821) 107 | a = GG(a, b, c, d, M[i][1][0], 5, 0xf61e2562) 108 | d = GG(d, a, b, c, M[i][6][0], 9, 0xc040b340) 109 | c = GG(c, d, a, b, M[i][11][0], 14, 0x265e5a51) 110 | b = GG(b, c, d, a, M[i][0][0], 20, 0xe9b6c7aa) 111 | a = GG(a, b, c, d, M[i][5][0], 5, 0xd62f105d) 112 | d = GG(d, a, b, c, M[i][10][0], 9, 0x02441453) 113 | c = GG(c, d, a, b, M[i][15][0], 14, 0xd8a1e681) 114 | b = GG(b, c, d, a, M[i][4][0], 20, 0xe7d3fbc8) 115 | a = GG(a, b, c, d, M[i][9][0], 5, 0x21e1cde6) 116 | d = GG(d, a, b, c, M[i][14][0], 9, 0xc33707d6) 117 | c = GG(c, d, a, b, M[i][3][0], 14, 0xf4d50d87) 118 | b = GG(b, c, d, a, M[i][8][0], 20, 0x455a14ed) 119 | a = GG(a, b, c, d, M[i][13][0], 5, 0xa9e3e905) 120 | d = GG(d, a, b, c, M[i][2][0], 9, 0xfcefa3f8) 121 | c = GG(c, d, a, b, M[i][7][0], 14, 0x676f02d9) 122 | b = GG(b, c, d, a, M[i][12][0], 20, 0x8d2a4c8a) 123 | a = HH(a, b, c, d, M[i][5][0], 4, 0xfffa3942) 124 | d = HH(d, a, b, c, M[i][8][0], 11, 0x8771f681) 125 | c = HH(c, d, a, b, M[i][11][0], 16, 0x6d9d6122) 126 | b = HH(b, c, d, a, M[i][14][0], 23, 0xfde5380c) 127 | a = HH(a, b, c, d, M[i][1][0], 4, 0xa4beea44) 128 | d = HH(d, a, b, c, M[i][4][0], 11, 0x4bdecfa9) 129 | c = HH(c, d, a, b, M[i][7][0], 16, 0xf6bb4b60) 130 | b = HH(b, c, d, a, M[i][10][0], 23, 0xbebfbc70) 131 | a = HH(a, b, c, d, M[i][13][0], 4, 0x289b7ec6) 132 | d = HH(d, a, b, c, M[i][0][0], 11, 0xeaa127fa) 133 | c = HH(c, d, a, b, M[i][3][0], 16, 0xd4ef3085) 134 | b = HH(b, c, d, a, M[i][6][0], 23, 0x04881d05) 135 | a = HH(a, b, c, d, M[i][9][0], 4, 0xd9d4d039) 136 | d = HH(d, a, b, c, M[i][12][0], 11, 0xe6db99e5) 137 | c = HH(c, d, a, b, M[i][15][0], 16, 0x1fa27cf8) 138 | b = HH(b, c, d, a, M[i][2][0], 23, 0xc4ac5665) 139 | 140 | a = II(a, b, c, d, M[i][0][0], 6, 0xf4292244) 141 | d = II(d, a, b, c, M[i][7][0], 10, 0x432aff97) 142 | c = II(c, d, a, b, M[i][14][0], 15, 0xab9423a7) 143 | b = II(b, c, d, a, M[i][5][0], 21, 0xfc93a039) 144 | a = II(a, b, c, d, M[i][12][0], 6, 0x655b59c3) 145 | d = II(d, a, b, c, M[i][3][0], 10, 0x8f0ccc92) 146 | c = II(c, d, a, b, M[i][10][0], 15, 0xffeff47d) 147 | b = II(b, c, d, a, M[i][1][0], 21, 0x85845dd1) 148 | a = II(a, b, c, d, M[i][8][0], 6, 0x6fa87e4f) 149 | d = II(d, a, b, c, M[i][15][0], 10, 0xfe2ce6e0) 150 | c = II(c, d, a, b, M[i][6][0], 15, 0xa3014314) 151 | b = II(b, c, d, a, M[i][13][0], 21, 0x4e0811a1) 152 | a = II(a, b, c, d, M[i][4][0], 6, 0xf7537e82) 153 | d = II(d, a, b, c, M[i][11][0], 10, 0xbd3af235) 154 | c = II(c, d, a, b, M[i][2][0], 15, 0x2ad7d2bb) 155 | b = II(b, c, d, a, M[i][9][0], 21, 0xeb86d391) 156 | A = (A + a) & 0xffffffff 157 | B = (B + b) & 0xffffffff 158 | C = (C + c) & 0xffffffff 159 | D = (D + d) & 0xffffffff 160 | 161 | d = (hex(D)[2:])[6:8] + (hex(D)[2:])[4:6] + (hex(D)[2:])[2:4] + (hex(D)[2:])[0:2] 162 | c = (hex(C)[2:])[6:8] + (hex(C)[2:])[4:6] + (hex(C)[2:])[2:4] + (hex(C)[2:])[0:2] 163 | b = (hex(B)[2:])[6:8] + (hex(B)[2:])[4:6] + (hex(B)[2:])[2:4] + (hex(B)[2:])[0:2] 164 | a = (hex(A)[2:])[6:8] + (hex(A)[2:])[4:6] + (hex(A)[2:])[2:4] + (hex(A)[2:])[0:2] 165 | 166 | return a + b + c + d 167 | 168 | def md5_string(string): 169 | def encode(s): 170 | return ''.join([bin(ord(c)).replace('0b', '').zfill(8) for c in s]) 171 | 172 | def decode(s): 173 | return ''.join([chr(i) for i in [int(b, 2) for b in s.split(' ')]]) 174 | 175 | plaintext = string 176 | # 链接变量 177 | A = 0x67452301 178 | B = 0xefcdab89 179 | C = 0x98badcfe 180 | D = 0x10325476 181 | bintext = encode(plaintext) 182 | # print(encrypt(plaintext)) 183 | # print(encrypt(plaintext).__len__()) 184 | t = bintext.__len__() % 512 185 | # print(t) 186 | houzhui = bin(bintext.__len__())[2:].zfill(64) 187 | # print(houzhui) 188 | if t < 448: # 补齐 189 | bintext = bintext + '1' 190 | for i in range(447 - t): 191 | bintext = bintext + '0' 192 | else: 193 | bintext = bintext + '1' 194 | for i in range(959 - t): 195 | bintext = bintext + '0' 196 | 197 | sectext = bintext + houzhui # 最终的明文 198 | x = sectext.__len__() / 512 199 | M = [[[0] * 1 for _ in range(16)] for _ in range(int(x))] 200 | M[0][0][0] = 1 201 | for i in range(int(x)): 202 | for j in range(16): 203 | ix = 3 204 | for k in range(1): 205 | x = sectext[i * 512 + j * 32:i * 512 + j * 32 + 32] 206 | y = x[24:32] + x[16:24] + x[8:16] + x[0:8] 207 | M[i][j][k] = int(y, 2) 208 | 209 | def F(x, y, z): 210 | return (x & y) | ((~x) & z) 211 | 212 | def G(x, y, z): 213 | return (x & z) | (y & (~z)) 214 | 215 | def H(x, y, z): 216 | return x ^ y ^ z 217 | 218 | def I(x, y, z): 219 | return y ^ (x | (~z)) 220 | 221 | def yiwei(x, z): 222 | x = x & 0xffffffff 223 | y = bin(x).replace('0b', '') 224 | tt = y.__len__() 225 | if tt < 32: 226 | y = y.zfill(32) 227 | t = y[z:] + y[:z] 228 | return int(t, 2) 229 | else: 230 | x = y[tt - 32:] 231 | t = x[z:] + x[:z] 232 | return int(t, 2) 233 | 234 | def FF(a, b, c, d, M, s, t): 235 | a = b + yiwei((a + F(b, c, d) + M + t), s) 236 | return a & 0xffffffff 237 | 238 | def GG(a, b, c, d, M, s, t): 239 | a = b + yiwei((a + G(b, c, d) + M + t), s) 240 | return a & 0xffffffff 241 | 242 | def HH(a, b, c, d, M, s, t): 243 | a = b + yiwei((a + H(b, c, d) + M + t), s) 244 | return a & 0xffffffff 245 | 246 | def II(a, b, c, d, M, s, t): 247 | a = b + yiwei((a + I(b, c, d) + M + t), s) 248 | return a & 0xffffffff 249 | 250 | for i in range(int(sectext.__len__() / 512)): 251 | a = A 252 | b = B 253 | c = C 254 | d = D 255 | # 第一轮循环 256 | a = FF(a, b, c, d, M[i][0][0], 7, 0xd76aa478) 257 | d = FF(d, a, b, c, M[i][1][0], 12, 0xe8c7b756) 258 | c = FF(c, d, a, b, M[i][2][0], 17, 0x242070db) 259 | b = FF(b, c, d, a, M[i][3][0], 22, 0xc1bdceee) 260 | a = FF(a, b, c, d, M[i][4][0], 7, 0xf57c0faf) 261 | d = FF(d, a, b, c, M[i][5][0], 12, 0x4787c62a) 262 | c = FF(c, d, a, b, M[i][6][0], 17, 0xa8304613) 263 | b = FF(b, c, d, a, M[i][7][0], 22, 0xfd469501) 264 | a = FF(a, b, c, d, M[i][8][0], 7, 0x698098d8) 265 | d = FF(d, a, b, c, M[i][9][0], 12, 0x8b44f7af) 266 | c = FF(c, d, a, b, M[i][10][0], 17, 0xffff5bb1) 267 | b = FF(b, c, d, a, M[i][11][0], 22, 0x895cd7be) 268 | a = FF(a, b, c, d, M[i][12][0], 7, 0x6b901122) 269 | d = FF(d, a, b, c, M[i][13][0], 12, 0xfd987193) 270 | c = FF(c, d, a, b, M[i][14][0], 17, 0xa679438e) 271 | b = FF(b, c, d, a, M[i][15][0], 22, 0x49b40821) 272 | # 第二轮循环 273 | a = GG(a, b, c, d, M[i][1][0], 5, 0xf61e2562) 274 | d = GG(d, a, b, c, M[i][6][0], 9, 0xc040b340) 275 | c = GG(c, d, a, b, M[i][11][0], 14, 0x265e5a51) 276 | b = GG(b, c, d, a, M[i][0][0], 20, 0xe9b6c7aa) 277 | a = GG(a, b, c, d, M[i][5][0], 5, 0xd62f105d) 278 | d = GG(d, a, b, c, M[i][10][0], 9, 0x02441453) 279 | c = GG(c, d, a, b, M[i][15][0], 14, 0xd8a1e681) 280 | b = GG(b, c, d, a, M[i][4][0], 20, 0xe7d3fbc8) 281 | a = GG(a, b, c, d, M[i][9][0], 5, 0x21e1cde6) 282 | d = GG(d, a, b, c, M[i][14][0], 9, 0xc33707d6) 283 | c = GG(c, d, a, b, M[i][3][0], 14, 0xf4d50d87) 284 | b = GG(b, c, d, a, M[i][8][0], 20, 0x455a14ed) 285 | a = GG(a, b, c, d, M[i][13][0], 5, 0xa9e3e905) 286 | d = GG(d, a, b, c, M[i][2][0], 9, 0xfcefa3f8) 287 | c = GG(c, d, a, b, M[i][7][0], 14, 0x676f02d9) 288 | b = GG(b, c, d, a, M[i][12][0], 20, 0x8d2a4c8a) 289 | # 第三轮循环 290 | a = HH(a, b, c, d, M[i][5][0], 4, 0xfffa3942) 291 | d = HH(d, a, b, c, M[i][8][0], 11, 0x8771f681) 292 | c = HH(c, d, a, b, M[i][11][0], 16, 0x6d9d6122) 293 | b = HH(b, c, d, a, M[i][14][0], 23, 0xfde5380c) 294 | a = HH(a, b, c, d, M[i][1][0], 4, 0xa4beea44) 295 | d = HH(d, a, b, c, M[i][4][0], 11, 0x4bdecfa9) 296 | c = HH(c, d, a, b, M[i][7][0], 16, 0xf6bb4b60) 297 | b = HH(b, c, d, a, M[i][10][0], 23, 0xbebfbc70) 298 | a = HH(a, b, c, d, M[i][13][0], 4, 0x289b7ec6) 299 | d = HH(d, a, b, c, M[i][0][0], 11, 0xeaa127fa) 300 | c = HH(c, d, a, b, M[i][3][0], 16, 0xd4ef3085) 301 | b = HH(b, c, d, a, M[i][6][0], 23, 0x04881d05) 302 | a = HH(a, b, c, d, M[i][9][0], 4, 0xd9d4d039) 303 | d = HH(d, a, b, c, M[i][12][0], 11, 0xe6db99e5) 304 | c = HH(c, d, a, b, M[i][15][0], 16, 0x1fa27cf8) 305 | b = HH(b, c, d, a, M[i][2][0], 23, 0xc4ac5665) 306 | 307 | # 第四轮循环 308 | a = II(a, b, c, d, M[i][0][0], 6, 0xf4292244) 309 | d = II(d, a, b, c, M[i][7][0], 10, 0x432aff97) 310 | c = II(c, d, a, b, M[i][14][0], 15, 0xab9423a7) 311 | b = II(b, c, d, a, M[i][5][0], 21, 0xfc93a039) 312 | a = II(a, b, c, d, M[i][12][0], 6, 0x655b59c3) 313 | d = II(d, a, b, c, M[i][3][0], 10, 0x8f0ccc92) 314 | c = II(c, d, a, b, M[i][10][0], 15, 0xffeff47d) 315 | b = II(b, c, d, a, M[i][1][0], 21, 0x85845dd1) 316 | a = II(a, b, c, d, M[i][8][0], 6, 0x6fa87e4f) 317 | d = II(d, a, b, c, M[i][15][0], 10, 0xfe2ce6e0) 318 | c = II(c, d, a, b, M[i][6][0], 15, 0xa3014314) 319 | b = II(b, c, d, a, M[i][13][0], 21, 0x4e0811a1) 320 | a = II(a, b, c, d, M[i][4][0], 6, 0xf7537e82) 321 | d = II(d, a, b, c, M[i][11][0], 10, 0xbd3af235) 322 | c = II(c, d, a, b, M[i][2][0], 15, 0x2ad7d2bb) 323 | b = II(b, c, d, a, M[i][9][0], 21, 0xeb86d391) 324 | A = (A + a) & 0xffffffff 325 | B = (B + b) & 0xffffffff 326 | C = (C + c) & 0xffffffff 327 | D = (D + d) & 0xffffffff 328 | 329 | d = (hex(D)[2:])[6:8] + (hex(D)[2:])[4:6] + (hex(D)[2:])[2:4] + (hex(D)[2:])[0:2] 330 | c = (hex(C)[2:])[6:8] + (hex(C)[2:])[4:6] + (hex(C)[2:])[2:4] + (hex(C)[2:])[0:2] 331 | b = (hex(B)[2:])[6:8] + (hex(B)[2:])[4:6] + (hex(B)[2:])[2:4] + (hex(B)[2:])[0:2] 332 | a = (hex(A)[2:])[6:8] + (hex(A)[2:])[4:6] + (hex(A)[2:])[2:4] + (hex(A)[2:])[0:2] 333 | return a + b + c + d 334 | -------------------------------------------------------------------------------- /algorithm/hash_algorithm/md5_file.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | def md5(filename): 4 | f1 = open(filename, "rb") 5 | p = f1.read() 6 | x = p.__len__() 7 | plaintext = '' 8 | for i in range(x): 9 | plaintext = plaintext + bin(p[i])[2:].zfill(8) 10 | A = 0x67452301 11 | B = 0xefcdab89 12 | C = 0x98badcfe 13 | D = 0x10325476 14 | bintext = plaintext 15 | # print(bintext) 16 | # print(encrypt(plaintext)) 17 | # print(encrypt(plaintext).__len__()) 18 | t = bintext.__len__() % 512 19 | # print(t) 20 | houzhui = bin(bintext.__len__())[2:].zfill(64) 21 | # print(houzhui) 22 | if t < 448: # ���� 23 | bintext = bintext + '1' 24 | for i in range(447 - t): 25 | bintext = bintext + '0' 26 | else: 27 | bintext = bintext + '1' 28 | for i in range(959 - t): 29 | bintext = bintext + '0' 30 | 31 | sectext = bintext + houzhui # ���յ����� 32 | # print(sectext) 33 | # print(sectext.__len__()) 34 | x = sectext.__len__() / 512 35 | M = [[[0] * 1 for _ in range(16)] for _ in range(int(x))] 36 | M[0][0][0] = 1 37 | for i in range(int(x)): 38 | for j in range(16): 39 | ix = 3 40 | for k in range(1): 41 | x = sectext[i * 512 + j * 32:i * 512 + j * 32 + 32] 42 | y = x[24:32] + x[16:24] + x[8:16] + x[0:8] 43 | # print(hex(int(y,2))) 44 | M[i][j][k] = int(y, 2) 45 | # print(M)#��ʼ����� 46 | 47 | def F(x, y, z): 48 | return (x & y) | ((~x) & z) 49 | 50 | def G(x, y, z): 51 | return (x & z) | (y & (~z)) 52 | 53 | def H(x, y, z): 54 | return x ^ y ^ z 55 | 56 | def I(x, y, z): 57 | return y ^ (x | (~z)) 58 | 59 | def yiwei(x, z): 60 | x = x & 0xffffffff 61 | y = bin(x).replace('0b', '') 62 | # print(y) 63 | tt = y.__len__() 64 | # print(tt) 65 | if tt < 32: 66 | y = y.zfill(32) 67 | # print(y) 68 | t = y[z:] + y[:z] 69 | return int(t, 2) 70 | else: 71 | x = y[tt - 32:] 72 | # print(x) 73 | t = x[z:] + x[:z] 74 | return int(t, 2) 75 | 76 | def FF(a, b, c, d, M, s, t): 77 | a = b + yiwei((a + F(b, c, d) + M + t), s) 78 | return a & 0xffffffff 79 | 80 | def GG(a, b, c, d, M, s, t): 81 | a = b + yiwei((a + G(b, c, d) + M + t), s) 82 | return a & 0xffffffff 83 | 84 | def HH(a, b, c, d, M, s, t): 85 | a = b + yiwei((a + H(b, c, d) + M + t), s) 86 | return a & 0xffffffff 87 | 88 | def II(a, b, c, d, M, s, t): 89 | a = b + yiwei((a + I(b, c, d) + M + t), s) 90 | return a & 0xffffffff 91 | 92 | for i in range(int(sectext.__len__() / 512)): 93 | a = A 94 | b = B 95 | c = C 96 | d = D 97 | # ��һ��ѭ�� 98 | a = FF(a, b, c, d, M[i][0][0], 7, 0xd76aa478) 99 | d = FF(d, a, b, c, M[i][1][0], 12, 0xe8c7b756) 100 | c = FF(c, d, a, b, M[i][2][0], 17, 0x242070db) 101 | b = FF(b, c, d, a, M[i][3][0], 22, 0xc1bdceee) 102 | a = FF(a, b, c, d, M[i][4][0], 7, 0xf57c0faf) 103 | d = FF(d, a, b, c, M[i][5][0], 12, 0x4787c62a) 104 | c = FF(c, d, a, b, M[i][6][0], 17, 0xa8304613) 105 | b = FF(b, c, d, a, M[i][7][0], 22, 0xfd469501) 106 | a = FF(a, b, c, d, M[i][8][0], 7, 0x698098d8) 107 | d = FF(d, a, b, c, M[i][9][0], 12, 0x8b44f7af) 108 | c = FF(c, d, a, b, M[i][10][0], 17, 0xffff5bb1) 109 | b = FF(b, c, d, a, M[i][11][0], 22, 0x895cd7be) 110 | a = FF(a, b, c, d, M[i][12][0], 7, 0x6b901122) 111 | d = FF(d, a, b, c, M[i][13][0], 12, 0xfd987193) 112 | c = FF(c, d, a, b, M[i][14][0], 17, 0xa679438e) 113 | b = FF(b, c, d, a, M[i][15][0], 22, 0x49b40821) 114 | # �ڶ���ѭ�� 115 | a = GG(a, b, c, d, M[i][1][0], 5, 0xf61e2562) 116 | d = GG(d, a, b, c, M[i][6][0], 9, 0xc040b340) 117 | c = GG(c, d, a, b, M[i][11][0], 14, 0x265e5a51) 118 | b = GG(b, c, d, a, M[i][0][0], 20, 0xe9b6c7aa) 119 | a = GG(a, b, c, d, M[i][5][0], 5, 0xd62f105d) 120 | d = GG(d, a, b, c, M[i][10][0], 9, 0x02441453) 121 | c = GG(c, d, a, b, M[i][15][0], 14, 0xd8a1e681) 122 | b = GG(b, c, d, a, M[i][4][0], 20, 0xe7d3fbc8) 123 | a = GG(a, b, c, d, M[i][9][0], 5, 0x21e1cde6) 124 | d = GG(d, a, b, c, M[i][14][0], 9, 0xc33707d6) 125 | c = GG(c, d, a, b, M[i][3][0], 14, 0xf4d50d87) 126 | b = GG(b, c, d, a, M[i][8][0], 20, 0x455a14ed) 127 | a = GG(a, b, c, d, M[i][13][0], 5, 0xa9e3e905) 128 | d = GG(d, a, b, c, M[i][2][0], 9, 0xfcefa3f8) 129 | c = GG(c, d, a, b, M[i][7][0], 14, 0x676f02d9) 130 | b = GG(b, c, d, a, M[i][12][0], 20, 0x8d2a4c8a) 131 | # ������ѭ�� 132 | a = HH(a, b, c, d, M[i][5][0], 4, 0xfffa3942) 133 | d = HH(d, a, b, c, M[i][8][0], 11, 0x8771f681) 134 | c = HH(c, d, a, b, M[i][11][0], 16, 0x6d9d6122) 135 | b = HH(b, c, d, a, M[i][14][0], 23, 0xfde5380c) 136 | a = HH(a, b, c, d, M[i][1][0], 4, 0xa4beea44) 137 | d = HH(d, a, b, c, M[i][4][0], 11, 0x4bdecfa9) 138 | c = HH(c, d, a, b, M[i][7][0], 16, 0xf6bb4b60) 139 | b = HH(b, c, d, a, M[i][10][0], 23, 0xbebfbc70) 140 | a = HH(a, b, c, d, M[i][13][0], 4, 0x289b7ec6) 141 | d = HH(d, a, b, c, M[i][0][0], 11, 0xeaa127fa) 142 | c = HH(c, d, a, b, M[i][3][0], 16, 0xd4ef3085) 143 | b = HH(b, c, d, a, M[i][6][0], 23, 0x04881d05) 144 | a = HH(a, b, c, d, M[i][9][0], 4, 0xd9d4d039) 145 | d = HH(d, a, b, c, M[i][12][0], 11, 0xe6db99e5) 146 | c = HH(c, d, a, b, M[i][15][0], 16, 0x1fa27cf8) 147 | b = HH(b, c, d, a, M[i][2][0], 23, 0xc4ac5665) 148 | 149 | # ������ѭ�� 150 | a = II(a, b, c, d, M[i][0][0], 6, 0xf4292244) 151 | d = II(d, a, b, c, M[i][7][0], 10, 0x432aff97) 152 | c = II(c, d, a, b, M[i][14][0], 15, 0xab9423a7) 153 | b = II(b, c, d, a, M[i][5][0], 21, 0xfc93a039) 154 | a = II(a, b, c, d, M[i][12][0], 6, 0x655b59c3) 155 | d = II(d, a, b, c, M[i][3][0], 10, 0x8f0ccc92) 156 | c = II(c, d, a, b, M[i][10][0], 15, 0xffeff47d) 157 | b = II(b, c, d, a, M[i][1][0], 21, 0x85845dd1) 158 | a = II(a, b, c, d, M[i][8][0], 6, 0x6fa87e4f) 159 | d = II(d, a, b, c, M[i][15][0], 10, 0xfe2ce6e0) 160 | c = II(c, d, a, b, M[i][6][0], 15, 0xa3014314) 161 | b = II(b, c, d, a, M[i][13][0], 21, 0x4e0811a1) 162 | a = II(a, b, c, d, M[i][4][0], 6, 0xf7537e82) 163 | d = II(d, a, b, c, M[i][11][0], 10, 0xbd3af235) 164 | c = II(c, d, a, b, M[i][2][0], 15, 0x2ad7d2bb) 165 | b = II(b, c, d, a, M[i][9][0], 21, 0xeb86d391) 166 | A = (A + a) & 0xffffffff 167 | B = (B + b) & 0xffffffff 168 | C = (C + c) & 0xffffffff 169 | D = (D + d) & 0xffffffff 170 | 171 | d = (hex(D)[2:])[6:8] + (hex(D)[2:])[4:6] + (hex(D)[2:])[2:4] + (hex(D)[2:])[0:2] 172 | c = (hex(C)[2:])[6:8] + (hex(C)[2:])[4:6] + (hex(C)[2:])[2:4] + (hex(C)[2:])[0:2] 173 | b = (hex(B)[2:])[6:8] + (hex(B)[2:])[4:6] + (hex(B)[2:])[2:4] + (hex(B)[2:])[0:2] 174 | a = (hex(A)[2:])[6:8] + (hex(A)[2:])[4:6] + (hex(A)[2:])[2:4] + (hex(A)[2:])[0:2] 175 | 176 | return a + b + c + d 177 | 178 | 179 | if __name__ == '__main__': 180 | # 测试 181 | x = md5('upload.png') 182 | print(x) 183 | -------------------------------------------------------------------------------- /algorithm/hash_algorithm/md5_string.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | def md5(string): 4 | def encode(s): 5 | return ''.join([bin(ord(c)).replace('0b', '').zfill(8) for c in s]) 6 | 7 | def decode(s): 8 | return ''.join([chr(i) for i in [int(b, 2) for b in s.split(' ')]]) 9 | 10 | plaintext = string 11 | # 链接变量 12 | A = 0x67452301 13 | B = 0xefcdab89 14 | C = 0x98badcfe 15 | D = 0x10325476 16 | bintext = encode(plaintext) 17 | # print(encrypt(plaintext)) 18 | # print(encrypt(plaintext).__len__()) 19 | t = bintext.__len__() % 512 20 | # print(t) 21 | houzhui = bin(bintext.__len__())[2:].zfill(64) 22 | # print(houzhui) 23 | if t < 448: # 补齐 24 | bintext = bintext + '1' 25 | for i in range(447 - t): 26 | bintext = bintext + '0' 27 | else: 28 | bintext = bintext + '1' 29 | for i in range(959 - t): 30 | bintext = bintext + '0' 31 | 32 | sectext = bintext + houzhui # 最终的明文 33 | # print(sectext) 34 | # print(sectext.__len__()) 35 | x = sectext.__len__() / 512 36 | M = [[[0] * 1 for _ in range(16)] for _ in range(int(x))] 37 | M[0][0][0] = 1 38 | for i in range(int(x)): 39 | for j in range(16): 40 | ix = 3 41 | for k in range(1): 42 | x = sectext[i * 512 + j * 32:i * 512 + j * 32 + 32] 43 | y = x[24:32] + x[16:24] + x[8:16] + x[0:8] 44 | # print(hex(int(y,2))) 45 | M[i][j][k] = int(y, 2) 46 | # print(M)#初始化完成 47 | 48 | def F(x, y, z): 49 | return (x & y) | ((~x) & z) 50 | 51 | def G(x, y, z): 52 | return (x & z) | (y & (~z)) 53 | 54 | def H(x, y, z): 55 | return x ^ y ^ z 56 | 57 | def I(x, y, z): 58 | return y ^ (x | (~z)) 59 | 60 | def yiwei(x, z): 61 | x = x & 0xffffffff 62 | y = bin(x).replace('0b', '') 63 | # print(y) 64 | tt = y.__len__() 65 | # print(tt) 66 | if tt < 32: 67 | y = y.zfill(32) 68 | # print(y) 69 | t = y[z:] + y[:z] 70 | return int(t, 2) 71 | else: 72 | x = y[tt - 32:] 73 | # print(x) 74 | t = x[z:] + x[:z] 75 | return int(t, 2) 76 | 77 | def FF(a, b, c, d, M, s, t): 78 | a = b + yiwei((a + F(b, c, d) + M + t), s) 79 | return a & 0xffffffff 80 | 81 | def GG(a, b, c, d, M, s, t): 82 | a = b + yiwei((a + G(b, c, d) + M + t), s) 83 | return a & 0xffffffff 84 | 85 | def HH(a, b, c, d, M, s, t): 86 | a = b + yiwei((a + H(b, c, d) + M + t), s) 87 | return a & 0xffffffff 88 | 89 | def II(a, b, c, d, M, s, t): 90 | a = b + yiwei((a + I(b, c, d) + M + t), s) 91 | return a & 0xffffffff 92 | 93 | for i in range(int(sectext.__len__() / 512)): 94 | a = A 95 | b = B 96 | c = C 97 | d = D 98 | # 第一轮循环 99 | a = FF(a, b, c, d, M[i][0][0], 7, 0xd76aa478) 100 | d = FF(d, a, b, c, M[i][1][0], 12, 0xe8c7b756) 101 | c = FF(c, d, a, b, M[i][2][0], 17, 0x242070db) 102 | b = FF(b, c, d, a, M[i][3][0], 22, 0xc1bdceee) 103 | a = FF(a, b, c, d, M[i][4][0], 7, 0xf57c0faf) 104 | d = FF(d, a, b, c, M[i][5][0], 12, 0x4787c62a) 105 | c = FF(c, d, a, b, M[i][6][0], 17, 0xa8304613) 106 | b = FF(b, c, d, a, M[i][7][0], 22, 0xfd469501) 107 | a = FF(a, b, c, d, M[i][8][0], 7, 0x698098d8) 108 | d = FF(d, a, b, c, M[i][9][0], 12, 0x8b44f7af) 109 | c = FF(c, d, a, b, M[i][10][0], 17, 0xffff5bb1) 110 | b = FF(b, c, d, a, M[i][11][0], 22, 0x895cd7be) 111 | a = FF(a, b, c, d, M[i][12][0], 7, 0x6b901122) 112 | d = FF(d, a, b, c, M[i][13][0], 12, 0xfd987193) 113 | c = FF(c, d, a, b, M[i][14][0], 17, 0xa679438e) 114 | b = FF(b, c, d, a, M[i][15][0], 22, 0x49b40821) 115 | # 第二轮循环 116 | a = GG(a, b, c, d, M[i][1][0], 5, 0xf61e2562) 117 | d = GG(d, a, b, c, M[i][6][0], 9, 0xc040b340) 118 | c = GG(c, d, a, b, M[i][11][0], 14, 0x265e5a51) 119 | b = GG(b, c, d, a, M[i][0][0], 20, 0xe9b6c7aa) 120 | a = GG(a, b, c, d, M[i][5][0], 5, 0xd62f105d) 121 | d = GG(d, a, b, c, M[i][10][0], 9, 0x02441453) 122 | c = GG(c, d, a, b, M[i][15][0], 14, 0xd8a1e681) 123 | b = GG(b, c, d, a, M[i][4][0], 20, 0xe7d3fbc8) 124 | a = GG(a, b, c, d, M[i][9][0], 5, 0x21e1cde6) 125 | d = GG(d, a, b, c, M[i][14][0], 9, 0xc33707d6) 126 | c = GG(c, d, a, b, M[i][3][0], 14, 0xf4d50d87) 127 | b = GG(b, c, d, a, M[i][8][0], 20, 0x455a14ed) 128 | a = GG(a, b, c, d, M[i][13][0], 5, 0xa9e3e905) 129 | d = GG(d, a, b, c, M[i][2][0], 9, 0xfcefa3f8) 130 | c = GG(c, d, a, b, M[i][7][0], 14, 0x676f02d9) 131 | b = GG(b, c, d, a, M[i][12][0], 20, 0x8d2a4c8a) 132 | # 第三轮循环 133 | a = HH(a, b, c, d, M[i][5][0], 4, 0xfffa3942) 134 | d = HH(d, a, b, c, M[i][8][0], 11, 0x8771f681) 135 | c = HH(c, d, a, b, M[i][11][0], 16, 0x6d9d6122) 136 | b = HH(b, c, d, a, M[i][14][0], 23, 0xfde5380c) 137 | a = HH(a, b, c, d, M[i][1][0], 4, 0xa4beea44) 138 | d = HH(d, a, b, c, M[i][4][0], 11, 0x4bdecfa9) 139 | c = HH(c, d, a, b, M[i][7][0], 16, 0xf6bb4b60) 140 | b = HH(b, c, d, a, M[i][10][0], 23, 0xbebfbc70) 141 | a = HH(a, b, c, d, M[i][13][0], 4, 0x289b7ec6) 142 | d = HH(d, a, b, c, M[i][0][0], 11, 0xeaa127fa) 143 | c = HH(c, d, a, b, M[i][3][0], 16, 0xd4ef3085) 144 | b = HH(b, c, d, a, M[i][6][0], 23, 0x04881d05) 145 | a = HH(a, b, c, d, M[i][9][0], 4, 0xd9d4d039) 146 | d = HH(d, a, b, c, M[i][12][0], 11, 0xe6db99e5) 147 | c = HH(c, d, a, b, M[i][15][0], 16, 0x1fa27cf8) 148 | b = HH(b, c, d, a, M[i][2][0], 23, 0xc4ac5665) 149 | 150 | # 第四轮循环 151 | a = II(a, b, c, d, M[i][0][0], 6, 0xf4292244) 152 | d = II(d, a, b, c, M[i][7][0], 10, 0x432aff97) 153 | c = II(c, d, a, b, M[i][14][0], 15, 0xab9423a7) 154 | b = II(b, c, d, a, M[i][5][0], 21, 0xfc93a039) 155 | a = II(a, b, c, d, M[i][12][0], 6, 0x655b59c3) 156 | d = II(d, a, b, c, M[i][3][0], 10, 0x8f0ccc92) 157 | c = II(c, d, a, b, M[i][10][0], 15, 0xffeff47d) 158 | b = II(b, c, d, a, M[i][1][0], 21, 0x85845dd1) 159 | a = II(a, b, c, d, M[i][8][0], 6, 0x6fa87e4f) 160 | d = II(d, a, b, c, M[i][15][0], 10, 0xfe2ce6e0) 161 | c = II(c, d, a, b, M[i][6][0], 15, 0xa3014314) 162 | b = II(b, c, d, a, M[i][13][0], 21, 0x4e0811a1) 163 | a = II(a, b, c, d, M[i][4][0], 6, 0xf7537e82) 164 | d = II(d, a, b, c, M[i][11][0], 10, 0xbd3af235) 165 | c = II(c, d, a, b, M[i][2][0], 15, 0x2ad7d2bb) 166 | b = II(b, c, d, a, M[i][9][0], 21, 0xeb86d391) 167 | A = (A + a) & 0xffffffff 168 | B = (B + b) & 0xffffffff 169 | C = (C + c) & 0xffffffff 170 | D = (D + d) & 0xffffffff 171 | 172 | d = (hex(D)[2:])[6:8] + (hex(D)[2:])[4:6] + (hex(D)[2:])[2:4] + (hex(D)[2:])[0:2] 173 | c = (hex(C)[2:])[6:8] + (hex(C)[2:])[4:6] + (hex(C)[2:])[2:4] + (hex(C)[2:])[0:2] 174 | b = (hex(B)[2:])[6:8] + (hex(B)[2:])[4:6] + (hex(B)[2:])[2:4] + (hex(B)[2:])[0:2] 175 | a = (hex(A)[2:])[6:8] + (hex(A)[2:])[4:6] + (hex(A)[2:])[2:4] + (hex(A)[2:])[0:2] 176 | return a + b + c + d 177 | 178 | 179 | if __name__ == '__main__': 180 | xxxx = md5('128778877') 181 | print(xxxx) 182 | -------------------------------------------------------------------------------- /algorithm/public_cipher/ecc/ecc.py: -------------------------------------------------------------------------------- 1 | # from Crypto.PublicKey import ECC 2 | import collections 3 | import random 4 | 5 | from algorithm.public_cipher.ecc import func 6 | from algorithm.public_cipher.ecc import sm3 7 | 8 | # TODO 支持多种曲线 9 | # TODO 可以以PEM格式导入和导出密钥 10 | 11 | EllipticCurve = collections.namedtuple('EllipticCurve', 'name p a b g n h') 12 | # T=(p,a,b,g,n,h)。 13 | # (p为模 用来将曲线离散化如y^2=x^3+ax+b(mod p)此时称曲线在模p后的取值Fp为有限域 14 | # Fp中只有p(p为素数)个元素0,1,2 …… p-2,p-1; 15 | # Fp 的加法(a+b)法则是 a+b≡c (mod p);即,(a+c)÷p的余数 和c÷p的余数相同。 16 | # Fp 的乘法(a×b)法则是 a×b≡c (mod p); 17 | # Fp 的除法(a÷b)法则是 a/b≡c (mod p);即 a×b-1≡c (mod p);(b-1也是一个0到p-1之间的整数,但满足b×b-1≡1 (mod p);具体求法可以参考初等数论,或我的另一篇文章)。 18 | # Fp 的单位元是1,零元是 0。 19 | # 、a 、b 用来确定一条椭圆曲线, 20 | # g为基点, 21 | # n为点G的阶, 22 | # h 是椭圆曲线上所有点的个数m与n相除的整数部分) 23 | # 这几个参量取值的选择,直接影响了加密的安全性。参量值一般要求满足以下几个条件: 24 | # 1、p 当然越大越安全,但越大,计算速度会变慢,200位左右可以满足一般安全要求; 25 | # 2、p≠n×h; 26 | # 3、pt≠1 (mod n),1≤t<20; 27 | # 4、4a3+27b2≠0 (mod p); 28 | # 5、n 为素数; 29 | # 6、h≤4。 30 | 31 | # 根据国家密码管理局公告 32 | # (第 21 号) 33 | # 推荐曲线 公式:y^2 = x^3 + ax +b 34 | # 各参数如下 35 | curve = EllipticCurve( 36 | "sm2p256v1", 37 | p=0xFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF, 38 | a=0xFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC, 39 | b=0x28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93, 40 | g=(0x32c4ae2c1f1981195f9904466a39c9948fe30bbff2660be1715a4589334c74c7, 41 | 0xbc3736a2f4f6779c59bdcee36b692153d0a9877cc62a474002df32e52139f0a0), 42 | n=0xFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123, 43 | h=1, 44 | ) 45 | 46 | default_ecc_table = { 47 | 'n': 'FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123', 48 | 'p': 'FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF', 49 | 'g': '32c4ae2c1f1981195f9904466a39c9948fe30bbff2660be1715a4589334c74c7' 50 | 'bc3736a2f4f6779c59bdcee36b692153d0a9877cc62a474002df32e52139f0a0', 51 | 'a': 'FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC', 52 | 'b': '28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93', 53 | } 54 | standard_public_key = 'B9C9A6E04E9C91F7BA880429273747D7EF5DDEB0BB2FF6317EB00BEF331A83081A6994B8993F3F5D6EADDDB818' \ 55 | '72266C87C018FB4162F5AF347B483E24620207' 56 | standard_private_key = '00B9AB0B828FF68872F21A837FC303668428DEA11DCD1B24429D0C99E24EED83D5' 57 | 58 | 59 | class EccCipher: 60 | 61 | def __init__(self, private_key=standard_private_key, public_key=standard_public_key, ecc_table=default_ecc_table): 62 | self.private_key = private_key 63 | self.public_key = public_key 64 | self.para_len = len(ecc_table['n']) 65 | self.ecc_table = ecc_table 66 | self.ecc_a3 = ( 67 | int(ecc_table['a'], base=16) + 3) % int(ecc_table['p'], base=16) 68 | 69 | def inverse_mod(self, k, p): 70 | """ 71 | 求k模p的逆元x(x满足(x * k) % p == 1)k必须非零,p必须是素数 72 | """ 73 | if k == 0: 74 | raise ZeroDivisionError('division by zero') 75 | 76 | if k < 0: 77 | # k ** -1 = p - (-k) ** -1 (mod p) 78 | return p - self.inverse_mod(-k, p) 79 | 80 | s, old_s = 0, 1 81 | t, old_t = 1, 0 82 | r, old_r = p, k 83 | 84 | while r != 0: 85 | quotient = old_r // r 86 | old_r, r = r, old_r - quotient * r 87 | old_s, s = s, old_s - quotient * s 88 | old_t, t = t, old_t - quotient * t 89 | 90 | gcd, x, y = old_r, old_s, old_t 91 | assert gcd == 1 92 | assert (k * x) % p == 1 93 | return x % p 94 | 95 | # 判断点是否在曲线上 96 | @staticmethod 97 | def is_on_curve(point): 98 | if point is None: 99 | return True 100 | x, y = point 101 | return (y * y - x * x * x - curve.a * x - curve.b) % curve.p == 0 102 | 103 | # 返回点关于x轴对称的一点 对称映射 104 | def point_neg(self, point): 105 | assert self.is_on_curve(point) 106 | if point is None: 107 | # -0 = 0 108 | return None 109 | 110 | x, y = point 111 | result = (x, -y % curve.p) 112 | 113 | assert self.is_on_curve(result) 114 | 115 | return result 116 | 117 | # 点1和点2相加 根据群论公式 118 | def point_add(self, point1, point2): 119 | assert self.is_on_curve(point1) 120 | assert self.is_on_curve(point2) 121 | 122 | if point1 is None: 123 | # 0 + point2 = point2 124 | return point2 125 | if point2 is None: 126 | # point1 + 0 = point1 127 | return point1 128 | 129 | x1, y1 = point1 130 | x2, y2 = point2 131 | 132 | if x1 == x2 and y1 != y2: 133 | # 即关于x轴对称 134 | return None 135 | 136 | if x1 == x2: 137 | # 即点1和点2重合时,此时直线为曲线的切线,切线斜率则为 138 | m = (3 * x1 * x1 + curve.a) * self.inverse_mod(2 * y1, curve.p) 139 | else: 140 | # 点1和点2不重合 141 | # m = (y2 - y1) * (x2 - x1) ^ (-1) mod p; ^(-1)意为逆元 142 | m = (y1 - y2) * self.inverse_mod(x1 - x2, curve.p) 143 | 144 | x3 = m * m - x1 - x2 145 | y3 = y1 + m * (x3 - x1) 146 | result = (x3 % curve.p, 147 | -y3 % curve.p) 148 | 149 | assert self.is_on_curve(result) 150 | return result 151 | 152 | # 做k * 点运算,生成的点还是在曲线上 153 | def scalar_multiply(self, k, point): 154 | """ 155 | 生成Pa = kG中的Pa 156 | """ 157 | assert self.is_on_curve(point) 158 | 159 | if k % curve.n == 0 or point is None: 160 | return None 161 | 162 | if k < 0: 163 | # k * point = -k * (-point) 164 | return self.scalar_multiply(-k, self.point_neg(point)) 165 | 166 | result = None 167 | addend = point 168 | 169 | while k: 170 | if k == 1: 171 | result = self.point_add(result, addend) 172 | addend = self.point_add(addend, addend) 173 | k >>= 1 174 | 175 | assert self.is_on_curve(result) 176 | 177 | return result 178 | 179 | # 生成ECC公钥和私钥 180 | def make_key_pair(self): 181 | # 生成随机数K用作私钥 公式 Pa = kG中的k 182 | private_key = random.randrange(1, curve.n) 183 | # 计算公钥中的Pa,与G共同组成公钥 184 | # 传入k和基点G:curve.g 185 | public_key = self.scalar_multiply(private_key, curve.g) 186 | return private_key, public_key 187 | 188 | def generate(self): 189 | return self.make_key_pair() 190 | 191 | def _double_point(self, point): 192 | """倍点""" 193 | l = len(point) 194 | len_2 = 2 * self.para_len 195 | if l < self.para_len * 2: 196 | return None 197 | else: 198 | x1 = int(point[0:self.para_len], 16) 199 | y1 = int(point[self.para_len:len_2], 16) 200 | if l == len_2: 201 | z1 = 1 202 | else: 203 | z1 = int(point[len_2:], 16) 204 | 205 | T6 = (z1 * z1) % int(self.ecc_table['p'], base=16) 206 | T2 = (y1 * y1) % int(self.ecc_table['p'], base=16) 207 | T3 = (x1 + T6) % int(self.ecc_table['p'], base=16) 208 | T4 = (x1 - T6) % int(self.ecc_table['p'], base=16) 209 | T1 = (T3 * T4) % int(self.ecc_table['p'], base=16) 210 | T3 = (y1 * z1) % int(self.ecc_table['p'], base=16) 211 | T4 = (T2 * 8) % int(self.ecc_table['p'], base=16) 212 | T5 = (x1 * T4) % int(self.ecc_table['p'], base=16) 213 | T1 = (T1 * 3) % int(self.ecc_table['p'], base=16) 214 | T6 = (T6 * T6) % int(self.ecc_table['p'], base=16) 215 | T6 = (self.ecc_a3 * T6) % int(self.ecc_table['p'], base=16) 216 | T1 = (T1 + T6) % int(self.ecc_table['p'], base=16) 217 | z3 = (T3 + T3) % int(self.ecc_table['p'], base=16) 218 | T3 = (T1 * T1) % int(self.ecc_table['p'], base=16) 219 | T2 = (T2 * T4) % int(self.ecc_table['p'], base=16) 220 | x3 = (T3 - T5) % int(self.ecc_table['p'], base=16) 221 | 222 | if (T5 % 2) == 1: 223 | T4 = (T5 + ((T5 + int(self.ecc_table['p'], base=16)) >> 1) - T3) % int(self.ecc_table['p'], base=16) 224 | else: 225 | T4 = (T5 + (T5 >> 1) - T3) % int(self.ecc_table['p'], base=16) 226 | 227 | T1 = (T1 * T4) % int(self.ecc_table['p'], base=16) 228 | y3 = (T1 - T2) % int(self.ecc_table['p'], base=16) 229 | 230 | form = '%%0%dx' % self.para_len 231 | form = form * 3 232 | return form % (x3, y3, z3) 233 | 234 | def _add_point(self, P1, P2): 235 | """点加函数,P2点为仿射坐标即z=1,P1为Jacobian加重射影坐标""" 236 | len_2 = 2 * self.para_len 237 | l1 = len(P1) 238 | l2 = len(P2) 239 | if (l1 < len_2) or (l2 < len_2): 240 | return None 241 | else: 242 | X1 = int(P1[0:self.para_len], 16) 243 | Y1 = int(P1[self.para_len:len_2], 16) 244 | if l1 == len_2: 245 | Z1 = 1 246 | else: 247 | Z1 = int(P1[len_2:], 16) 248 | x2 = int(P2[0:self.para_len], 16) 249 | y2 = int(P2[self.para_len:len_2], 16) 250 | 251 | T1 = (Z1 * Z1) % int(self.ecc_table['p'], base=16) 252 | T2 = (y2 * Z1) % int(self.ecc_table['p'], base=16) 253 | T3 = (x2 * T1) % int(self.ecc_table['p'], base=16) 254 | T1 = (T1 * T2) % int(self.ecc_table['p'], base=16) 255 | T2 = (T3 - X1) % int(self.ecc_table['p'], base=16) 256 | T3 = (T3 + X1) % int(self.ecc_table['p'], base=16) 257 | T4 = (T2 * T2) % int(self.ecc_table['p'], base=16) 258 | T1 = (T1 - Y1) % int(self.ecc_table['p'], base=16) 259 | Z3 = (Z1 * T2) % int(self.ecc_table['p'], base=16) 260 | T2 = (T2 * T4) % int(self.ecc_table['p'], base=16) 261 | T3 = (T3 * T4) % int(self.ecc_table['p'], base=16) 262 | T5 = (T1 * T1) % int(self.ecc_table['p'], base=16) 263 | T4 = (X1 * T4) % int(self.ecc_table['p'], base=16) 264 | X3 = (T5 - T3) % int(self.ecc_table['p'], base=16) 265 | T2 = (Y1 * T2) % int(self.ecc_table['p'], base=16) 266 | T3 = (T4 - X3) % int(self.ecc_table['p'], base=16) 267 | T1 = (T1 * T3) % int(self.ecc_table['p'], base=16) 268 | Y3 = (T1 - T2) % int(self.ecc_table['p'], base=16) 269 | form = '%%0%dx' % self.para_len 270 | form = form * 3 271 | return form % (X3, Y3, Z3) 272 | 273 | def _convert_jacb_to_nor(self, point): 274 | """Jacobian加重射影坐标转换成仿射坐标""" 275 | len_2 = 2 * self.para_len 276 | x = int(point[0:self.para_len], 16) 277 | y = int(point[self.para_len:len_2], 16) 278 | z = int(point[len_2:], 16) 279 | z_inv = pow(z, int(self.ecc_table['p'], base=16) - 2, int(self.ecc_table['p'], base=16)) 280 | z_invSquar = (z_inv * z_inv) % int(self.ecc_table['p'], base=16) 281 | z_invQube = (z_invSquar * z_inv) % int(self.ecc_table['p'], base=16) 282 | x_new = (x * z_invSquar) % int(self.ecc_table['p'], base=16) 283 | y_new = (y * z_invQube) % int(self.ecc_table['p'], base=16) 284 | z_new = (z * z_inv) % int(self.ecc_table['p'], base=16) 285 | if z_new == 1: 286 | form = '%%0%dx' % self.para_len 287 | form = form * 2 288 | return form % (x_new, y_new) 289 | else: 290 | return None 291 | 292 | def _kg(self, k, point): # kP运算 293 | # 末尾加字符1,表示映射到z轴 294 | point = '%s%s' % (point, '1') 295 | mask_str = '8' 296 | for i in range(self.para_len - 1): 297 | mask_str += '0' 298 | mask = int(mask_str, 16) 299 | temp = point 300 | flag = False 301 | for n in range(self.para_len * 4): 302 | if flag: 303 | temp = self._double_point(temp) 304 | if (k & mask) != 0: 305 | if flag: 306 | temp = self._add_point(temp, point) 307 | else: 308 | flag = True 309 | temp = point 310 | k = k << 1 311 | return self._convert_jacb_to_nor(temp) 312 | 313 | def encrypt(self, data): 314 | # 加密函数,data消息(bytes) 315 | msg = data.hex() # 消息转化为16进制字符串 316 | k = func.random_hex(self.para_len) 317 | c1 = self._kg(int(k, 16), self.ecc_table['g']) 318 | xy = self._kg(int(k, 16), self.public_key) 319 | x2 = xy[0:self.para_len] 320 | y2 = xy[self.para_len:2 * self.para_len] 321 | ml = len(msg) 322 | t = sm3.sm3_kdf(xy.encode('utf8'), ml / 2) 323 | if int(t, 16) == 0: 324 | return None 325 | else: 326 | form = '%%0%dx' % ml 327 | c2 = form % (int(msg, 16) ^ int(t, 16)) 328 | c3 = sm3.sm3_hash([ 329 | i for i in bytes.fromhex('%s%s%s' % (x2, msg, y2)) 330 | ]) 331 | return bytes.fromhex('%s%s%s' % (c1, c3, c2)) 332 | 333 | def decrypt(self, data): 334 | # 解密函数,data密文(bytes) 335 | data = data.hex() 336 | len_2 = 2 * self.para_len 337 | len_3 = len_2 + 64 338 | c1 = data[0:len_2] 339 | c3 = data[len_2:len_3] 340 | c2 = data[len_3:] 341 | xy = self._kg(int(self.private_key, 16), c1) 342 | x2 = xy[0:self.para_len] 343 | y2 = xy[self.para_len:len_2] 344 | cl = len(c2) 345 | t = sm3.sm3_kdf(xy.encode('utf8'), cl / 2) 346 | if int(t, 16) == 0: 347 | return None 348 | else: 349 | form = '%%0%dx' % cl 350 | M = form % (int(c2, 16) ^ int(t, 16)) 351 | u = sm3.sm3_hash([ 352 | i for i in bytes.fromhex('%s%s%s' % (x2, M, y2)) 353 | ]) 354 | return bytes.fromhex(M) 355 | 356 | 357 | def main(): 358 | print('Curve:', curve.name) 359 | c = EccCipher() 360 | private_key, public_key = c.make_key_pair() 361 | 362 | print("生成密钥测试:") 363 | print("私钥d:", private_key) 364 | print("公钥K(x,y):", public_key) 365 | 366 | print("加密字符串测试:") 367 | plain_text = input("请输入要加密的字符串(utf-8字符均可):\n") 368 | cipher_text = c.encrypt(plain_text.encode('utf-8')) 369 | print("加密后的密文是:", cipher_text) 370 | print("解密后的结果是:\n", c.decrypt(cipher_text).decode("utf-8")) 371 | 372 | print("加密文件测试:") 373 | with open("test.rar", 'rb') as f: 374 | cc = c.encrypt(f.read()) 375 | print("加密后的文件:\n", cc) 376 | print("解密后的文件:(应为rar格式)") 377 | print(c.decrypt(cc)) 378 | 379 | print("ECDHE测试:") 380 | alice_private_key, alice_public_key = c.make_key_pair() 381 | print("Alice's private key:", hex(alice_private_key)) 382 | print("Alice's public key: (0x{:x}, 0x{:x})".format(*alice_public_key)) 383 | 384 | bob_private_key, bob_public_key = c.make_key_pair() 385 | print("Bob's private key:", hex(bob_private_key)) 386 | print("Bob's public key: (0x{:x}, 0x{:x})".format(*bob_public_key)) 387 | 388 | s1 = c.scalar_multiply(alice_private_key, bob_public_key) 389 | s2 = c.scalar_multiply(bob_private_key, alice_public_key) 390 | assert s1 == s2 391 | 392 | print('Shared secret in Alice: (0x{:x}, 0x{:x})'.format(*s1)) 393 | print('Shared secret in Bob: (0x{:x}, 0x{:x})'.format(*s2)) 394 | 395 | 396 | if __name__ == '__main__': 397 | main() 398 | -------------------------------------------------------------------------------- /algorithm/public_cipher/ecc/func.py: -------------------------------------------------------------------------------- 1 | from random import choice 2 | 3 | xor = lambda a, b: list(map(lambda x, y: x ^ y, a, b)) 4 | 5 | rotl = lambda x, n: ((x << n) & 0xffffffff) | ((x >> (32 - n)) & 0xffffffff) 6 | 7 | get_uint32_be = lambda key_data: ((key_data[0] << 24) | (key_data[1] << 16) | (key_data[2] << 8) | (key_data[3])) 8 | 9 | put_uint32_be = lambda n: [((n >> 24) & 0xff), ((n >> 16) & 0xff), ((n >> 8) & 0xff), ((n) & 0xff)] 10 | 11 | padding = lambda data, block=16: data + [(16 - len(data) % block) for _ in range(16 - len(data) % block)] 12 | 13 | unpadding = lambda data: data[:-data[-1]] 14 | 15 | list_to_bytes = lambda data: b''.join([bytes((i,)) for i in data]) 16 | 17 | bytes_to_list = lambda data: [i for i in data] 18 | 19 | random_hex = lambda x: ''.join([choice('0123456789abcdef') for _ in range(x)]) 20 | -------------------------------------------------------------------------------- /algorithm/public_cipher/ecc/sm3.py: -------------------------------------------------------------------------------- 1 | import binascii 2 | from math import ceil 3 | 4 | from algorithm.public_cipher.ecc.func import rotl 5 | 6 | IV = [ 7 | 1937774191, 1226093241, 388252375, 3666478592, 8 | 2842636476, 372324522, 3817729613, 2969243214, 9 | ] 10 | 11 | T_j = [ 12 | 2043430169, 2043430169, 2043430169, 2043430169, 2043430169, 2043430169, 13 | 2043430169, 2043430169, 2043430169, 2043430169, 2043430169, 2043430169, 14 | 2043430169, 2043430169, 2043430169, 2043430169, 2055708042, 2055708042, 15 | 2055708042, 2055708042, 2055708042, 2055708042, 2055708042, 2055708042, 16 | 2055708042, 2055708042, 2055708042, 2055708042, 2055708042, 2055708042, 17 | 2055708042, 2055708042, 2055708042, 2055708042, 2055708042, 2055708042, 18 | 2055708042, 2055708042, 2055708042, 2055708042, 2055708042, 2055708042, 19 | 2055708042, 2055708042, 2055708042, 2055708042, 2055708042, 2055708042, 20 | 2055708042, 2055708042, 2055708042, 2055708042, 2055708042, 2055708042, 21 | 2055708042, 2055708042, 2055708042, 2055708042, 2055708042, 2055708042, 22 | 2055708042, 2055708042, 2055708042, 2055708042 23 | ] 24 | 25 | 26 | def sm3_ff_j(x, y, z, j): 27 | if 0 <= j < 16: 28 | ret = x ^ y ^ z 29 | elif 16 <= j < 64: 30 | ret = (x & y) | (x & z) | (y & z) 31 | return ret 32 | 33 | 34 | def sm3_gg_j(x, y, z, j): 35 | if 0 <= j < 16: 36 | ret = x ^ y ^ z 37 | elif 16 <= j < 64: 38 | # ret = (X | Y) & ((2 ** 32 - 1 - X) | Z) 39 | ret = (x & y) | ((~ x) & z) 40 | return ret 41 | 42 | 43 | def sm3_p_0(x): 44 | return x ^ (rotl(x, 9 % 32)) ^ (rotl(x, 17 % 32)) 45 | 46 | 47 | def sm3_p_1(x): 48 | return x ^ (rotl(x, 15 % 32)) ^ (rotl(x, 23 % 32)) 49 | 50 | 51 | def sm3_cf(v_i, b_i): 52 | w = [] 53 | for i in range(16): 54 | weight = 0x1000000 55 | data = 0 56 | for k in range(i * 4, (i + 1) * 4): 57 | data = data + b_i[k] * weight 58 | weight = int(weight / 0x100) 59 | w.append(data) 60 | 61 | for j in range(16, 68): 62 | w.append(0) 63 | w[j] = sm3_p_1(w[j - 16] ^ w[j - 9] ^ (rotl(w[j - 3], 15 % 32))) ^ (rotl(w[j - 13], 7 % 32)) ^ w[j - 6] 64 | str1 = "%08x" % w[j] 65 | w_1 = [] 66 | for j in range(0, 64): 67 | w_1.append(0) 68 | w_1[j] = w[j] ^ w[j + 4] 69 | str1 = "%08x" % w_1[j] 70 | 71 | a, b, c, d, e, f, g, h = v_i 72 | 73 | for j in range(0, 64): 74 | ss_1 = rotl( 75 | ((rotl(a, 12 % 32)) + 76 | e + 77 | (rotl(T_j[j], j % 32))) & 0xffffffff, 7 % 32 78 | ) 79 | ss_2 = ss_1 ^ (rotl(a, 12 % 32)) 80 | tt_1 = (sm3_ff_j(a, b, c, j) + d + ss_2 + w_1[j]) & 0xffffffff 81 | tt_2 = (sm3_gg_j(e, f, g, j) + h + ss_1 + w[j]) & 0xffffffff 82 | d = c 83 | c = rotl(b, 9 % 32) 84 | b = a 85 | a = tt_1 86 | h = g 87 | g = rotl(f, 19 % 32) 88 | f = e 89 | e = sm3_p_0(tt_2) 90 | 91 | a, b, c, d, e, f, g, h = map( 92 | lambda x: x & 0xFFFFFFFF, [a, b, c, d, e, f, g, h]) 93 | 94 | v_j = [a, b, c, d, e, f, g, h] 95 | return [v_j[i] ^ v_i[i] for i in range(8)] 96 | 97 | 98 | def sm3_hash(msg): 99 | # print(msg) 100 | len1 = len(msg) 101 | reserve1 = len1 % 64 102 | msg.append(0x80) 103 | reserve1 = reserve1 + 1 104 | # 56-64, add 64 byte 105 | range_end = 56 106 | if reserve1 > range_end: 107 | range_end = range_end + 64 108 | 109 | for i in range(reserve1, range_end): 110 | msg.append(0x00) 111 | 112 | bit_length = len1 * 8 113 | bit_length_str = [bit_length % 0x100] 114 | for i in range(7): 115 | bit_length = int(bit_length / 0x100) 116 | bit_length_str.append(bit_length % 0x100) 117 | for i in range(8): 118 | msg.append(bit_length_str[7 - i]) 119 | 120 | group_count = round(len(msg) / 64) 121 | 122 | B = [] 123 | for i in range(0, group_count): 124 | B.append(msg[i * 64:(i + 1) * 64]) 125 | 126 | V = [IV] 127 | for i in range(0, group_count): 128 | V.append(sm3_cf(V[i], B[i])) 129 | 130 | y = V[i + 1] 131 | result = "" 132 | for i in y: 133 | result = '%s%08x' % (result, i) 134 | return result 135 | 136 | 137 | def sm3_kdf(z, klen): # z为16进制表示的比特串(str),klen为密钥长度(单位byte) 138 | klen = int(klen) 139 | ct = 0x00000001 140 | rcnt = ceil(klen / 32) 141 | zin = [i for i in bytes.fromhex(z.decode('utf8'))] 142 | ha = "" 143 | for i in range(rcnt): 144 | msg = zin + [i for i in binascii.a2b_hex(('%08x' % ct).encode('utf8'))] 145 | ha = ha + sm3_hash(msg) 146 | ct += 1 147 | return ha[0: klen * 2] 148 | -------------------------------------------------------------------------------- /algorithm/public_cipher/ecc/test.rar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/morsuning/cryptography-gui-tool/7e0d58655f6f165f595fac869b98582a9f66448d/algorithm/public_cipher/ecc/test.rar -------------------------------------------------------------------------------- /algorithm/public_cipher/ecc/verifyrandom.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import collections 4 | import hashlib 5 | 6 | 7 | class VerificationFailed(Exception): 8 | pass 9 | 10 | 11 | EllipticCurve = collections.namedtuple('EllipticCurve', 'seed p a b') 12 | 13 | # 除了最后一条曲线外,下面所有的曲线都来自于OpenSSL 14 | # 源代码(crypto/ec/ec_curv .c)。最后四个是假曲线 15 | # 没有通过种子验证。 16 | 17 | curves = { 18 | 'prime192v1': EllipticCurve( 19 | seed=0x3045ae6fc8422f64ed579528d38120eae12196d5, 20 | p=0xfffffffffffffffffffffffffffffffeffffffffffffffff, 21 | a=0xfffffffffffffffffffffffffffffffefffffffffffffffc, 22 | b=0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1, 23 | ), 24 | 'secp224r1': EllipticCurve( 25 | seed=0xbd71344799d5c7fcdc45b59fa3b9ab8f6a948bc5, 26 | p=0xffffffffffffffffffffffffffffffff000000000000000000000001, 27 | a=0xfffffffffffffffffffffffffffffffefffffffffffffffffffffffe, 28 | b=0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4, 29 | ), 30 | 'secp384r1': EllipticCurve( 31 | seed=0xa335926aa319a27a1d00896a6773a4827acdac73, 32 | p=0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff, 33 | a=0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000fffffffc, 34 | b=0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef, 35 | ), 36 | 'secp521r1': EllipticCurve( 37 | seed=0xd09e8800291cb85396cc6717393284aaa0da64ba, 38 | p=0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff, 39 | a=0x01fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc, 40 | b=0x0051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00, 41 | ), 42 | 'prime192v2': EllipticCurve( 43 | seed=0x31a92ee2029fd10d901b113e990710f0d21ac6b6, 44 | p=0xfffffffffffffffffffffffffffffffeffffffffffffffff, 45 | a=0xfffffffffffffffffffffffffffffffefffffffffffffffc, 46 | b=0xcc22d6dfb95c6b25e49c0d6364a4e5980c393aa21668d953, 47 | ), 48 | 'prime192v3': EllipticCurve( 49 | seed=0xc469684435deb378c4b65ca9591e2a5763059a2e, 50 | p=0xfffffffffffffffffffffffffffffffeffffffffffffffff, 51 | a=0xfffffffffffffffffffffffffffffffefffffffffffffffc, 52 | b=0x22123dc2395a05caa7423daeccc94760a7d462256bd56916, 53 | ), 54 | 'prime239v1': EllipticCurve( 55 | seed=0xe43bb460f0b80cc0c0b075798e948060f8321b7d, 56 | p=0x7fffffffffffffffffffffff7fffffffffff8000000000007fffffffffff, 57 | a=0x7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc, 58 | b=0x6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a, 59 | ), 60 | 'prime239v2': EllipticCurve( 61 | seed=0xe8b4011604095303ca3b8099982be09fcb9ae616, 62 | p=0x7fffffffffffffffffffffff7fffffffffff8000000000007fffffffffff, 63 | a=0x7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc, 64 | b=0x617fab6832576cbbfed50d99f0249c3fee58b94ba0038c7ae84c8c832f2c, 65 | ), 66 | 'prime239v3': EllipticCurve( 67 | seed=0x7d7374168ffe3471b60a857686a19475d3bfa2ff, 68 | p=0x7fffffffffffffffffffffff7fffffffffff8000000000007fffffffffff, 69 | a=0x7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc, 70 | b=0x255705fa2a306654b1f4cb03d6a750a30c250102d4988717d9ba15ab6d3e, 71 | ), 72 | 'prime256v1': EllipticCurve( 73 | seed=0xc49d360886e704936a6678e1139d26b7819f7e90, 74 | p=0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff, 75 | a=0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc, 76 | b=0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b, 77 | ), 78 | 'secp112r1': EllipticCurve( 79 | seed=0x00f50b028e4d696e676875615175290472783fb1, 80 | p=0xdb7c2abf62e35e668076bead208b, 81 | a=0xdb7c2abf62e35e668076bead2088, 82 | b=0x659ef8ba043916eede8911702b22, 83 | ), 84 | 'secp112r2': EllipticCurve( 85 | seed=0x002757a1114d696e6768756151755316c05e0bd4, 86 | p=0xdb7c2abf62e35e668076bead208b, 87 | a=0x6127c24c05f38a0aaaf65c0ef02c, 88 | b=0x51def1815db5ed74fcc34c85d709, 89 | ), 90 | 'secp128r1': EllipticCurve( 91 | seed=0x000e0d4d696e6768756151750cc03a4473d03679, 92 | p=0xfffffffdffffffffffffffffffffffff, 93 | a=0xfffffffdfffffffffffffffffffffffc, 94 | b=0xe87579c11079f43dd824993c2cee5ed3, 95 | ), 96 | 'secp128r2': EllipticCurve( 97 | seed=0x004d696e67687561517512d8f03431fce63b88f4, 98 | p=0xfffffffdffffffffffffffffffffffff, 99 | a=0xd6031998d1b3bbfebf59cc9bbff9aee1, 100 | b=0x5eeefca380d02919dc2c6558bb6d8a5d, 101 | ), 102 | 'secp160r1': EllipticCurve( 103 | seed=0x1053cde42c14d696e67687561517533bf3f83345, 104 | p=0x00ffffffffffffffffffffffffffffffff7fffffff, 105 | a=0x00ffffffffffffffffffffffffffffffff7ffffffc, 106 | b=0x001c97befc54bd7a8b65acf89f81d4d4adc565fa45, 107 | ), 108 | 'secp160r2': EllipticCurve( 109 | seed=0xb99b99b099b323e02709a4d696e6768756151751, 110 | p=0x00fffffffffffffffffffffffffffffffeffffac73, 111 | a=0x00fffffffffffffffffffffffffffffffeffffac70, 112 | b=0x00b4e134d3fb59eb8bab57274904664d5af50388ba, 113 | ), 114 | 'sm2p256v1': EllipticCurve( 115 | seed=0xb99b99b099b323e02709a4d696e6768756151751, 116 | p=0xFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF, 117 | a=0xFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC, 118 | b=0x28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93, 119 | ), 120 | # This is prime192v1 with a wrong value for seed. 121 | 'wrong192v1': EllipticCurve( 122 | seed=0x123, 123 | p=0xfffffffffffffffffffffffffffffffeffffffffffffffff, 124 | a=0xfffffffffffffffffffffffffffffffefffffffffffffffc, 125 | b=0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1, 126 | ), 127 | # This is prime192v1 with a wrong value for p. 128 | 'wrong192v2': EllipticCurve( 129 | seed=0x3045ae6fc8422f64ed579528d38120eae12196d5, 130 | p=0x123, 131 | a=0xfffffffffffffffffffffffffffffffefffffffffffffffc, 132 | b=0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1, 133 | ), 134 | # This is prime192v1 with a wrong value for a. 135 | 'wrong192v3': EllipticCurve( 136 | seed=0x3045ae6fc8422f64ed579528d38120eae12196d5, 137 | p=0xfffffffffffffffffffffffffffffffeffffffffffffffff, 138 | a=0x123, 139 | b=0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1, 140 | ), 141 | # This is prime192v1 with a wrong value for b. 142 | 'wrong192v4': EllipticCurve( 143 | seed=0x3045ae6fc8422f64ed579528d38120eae12196d5, 144 | p=0xfffffffffffffffffffffffffffffffeffffffffffffffff, 145 | a=0xfffffffffffffffffffffffffffffffefffffffffffffffc, 146 | b=0x123, 147 | ), 148 | 149 | } 150 | 151 | 152 | def verify_curve(curve): 153 | """ 154 | Verifies whether the a and b parameters of the given curve were generated 155 | from the seed. 156 | 157 | Raises a VerificationFailed exception in case the verification fails. 158 | """ 159 | # What follows is the implementation of the verification algorithm 160 | # described in "The Elliptic Curve Digital Signature Algorithm (ECDSA)", 161 | # from Certicom. There just a few difference between the original algorithm 162 | # and the implementation: 163 | # 164 | # * a few variable names have been changed for the sake of clarity; 165 | # * the document from Certicom allows arbritrary seeds with bit length 166 | # >= 160; here we only care about seeds that are exactly 160-bit long. 167 | 168 | if curve.seed.bit_length() > 160: 169 | raise VerificationFailed('seed too long') 170 | 171 | seed_bytes = curve.seed.to_bytes(length=160 // 8, byteorder='big') 172 | 173 | # Define t, s and v as specified on the document. 174 | t = curve.p.bit_length() 175 | s = (t - 1) // 160 176 | v = t - 160 * s 177 | 178 | # 1. Compute h = SHA-1(seed_bytes) and let c0 denote the bit string of 179 | # length v bits obtained by taking the v rightmost bits of h. 180 | h = hashlib.sha1(seed_bytes).digest() 181 | h = int.from_bytes(h, byteorder='big') 182 | 183 | c0 = h & ((1 << v) - 1) 184 | 185 | # 2. Let w[0] denote the bit string of length v bits obtained by setting 186 | # the leftmost bit of c0 to 0. 187 | # 188 | # Note: here we use 160 bit instead of v bits, as required by the document. 189 | # We do so to make the code easier, and because it does not make any 190 | # difference (see the step 6). 191 | w0 = c0 & ((1 << v - 1) - 1) 192 | w = [w0.to_bytes(length=160 // 8, byteorder='big')] 193 | 194 | # 3. Let z be the integer whose binary expansion is given by 160-bit string 195 | # seed_bytes. 196 | z = curve.seed 197 | 198 | # 4. For i from 1 to s do: 199 | for i in range(1, s + 1): 200 | # 4.1 Let s_i be 160-bit string which is the binary expansion of the 201 | # integer (z + i) % (2 ** g). 202 | z_i = ((z + i) % (2 ** 160)) 203 | s_i = z_i.to_bytes(length=160 // 8, byteorder='big') 204 | 205 | # 4.2 Compute w_i = SHA-1(s_i). 206 | w_i = hashlib.sha1(s_i).digest() 207 | w.append(w_i) 208 | 209 | # 5. Let w be the bit string obtained by concatenating w_0,w_1,...,w_s. 210 | w = b''.join(w) 211 | 212 | # 6. Let c be the integer whose integer expansion is given by w. 213 | # 214 | # On step 2, we said that we used a longer bit length for the first element 215 | # of w. This is correct because the resulting c does not change: using 160 216 | # bits instead of v bits is equivalent to add some zeroes to the left of c. 217 | c = int.from_bytes(w, 'big') 218 | 219 | # If b ** 2 * c == a ** 3 (mod p) then accept; otherwise reject. 220 | if (curve.b * curve.b * c - curve.a * curve.a * curve.a) % curve.p != 0: 221 | raise VerificationFailed('curve verification failed') 222 | 223 | 224 | # Check all the curves defined above. 225 | # Should produce the following output: 226 | # 227 | # prime192v1: ok 228 | # prime192v2: ok 229 | # ... 230 | # secp384r1: ok 231 | # secp521r1: ok 232 | # wrong192v1: failed 233 | # wrong192v2: failed 234 | # wrong192v3: failed 235 | # wrong192v4: failed 236 | for name in sorted(curves): 237 | curve = curves[name] 238 | print(name, end=': ') 239 | try: 240 | verify_curve(curve) 241 | except VerificationFailed: 242 | print('failed') 243 | else: 244 | print('ok') 245 | -------------------------------------------------------------------------------- /algorithm/public_cipher/rsa/_pytest_cache/v/cache/lastfailed: -------------------------------------------------------------------------------- 1 | { 2 | "rsa.py::test": true 3 | } -------------------------------------------------------------------------------- /algorithm/public_cipher/rsa/_pytest_cache/v/cache/nodeids: -------------------------------------------------------------------------------- 1 | [] -------------------------------------------------------------------------------- /algorithm/public_cipher/rsa/rsa.py: -------------------------------------------------------------------------------- 1 | import binascii # 二进制和ASCII之间转换 2 | from os import urandom # 系统随机的字符 3 | 4 | flag = False 5 | 6 | 7 | # =========================================== 8 | def Mod_1(x, n): 9 | '''取模负1的算法:计算x2= x^-1 (mod n)的值, 10 | r = gcd(a, b) = ia + jb, x与n是互素数''' 11 | x0 = x 12 | y0 = n 13 | x1 = 0 14 | y1 = 1 15 | x2 = 1 16 | y2 = 0 17 | while n != 0: 18 | q = x // n 19 | (x, n) = (n, x % n) 20 | (x1, x2) = ((x2 - (q * x1)), x1) 21 | (y1, y2) = ((y2 - (q * y1)), y1) 22 | if x2 < 0: 23 | x2 += y0 24 | if y2 < 0: 25 | y2 += x0 26 | return x2 27 | 28 | 29 | # =========================================== 30 | def Fast_Mod(a, p, m): 31 | '''快速取模指数算法:计算 (a ^ p) % m 的值,可用pow()代替''' 32 | a, p, m = int(a), int(p), int(m) 33 | if (p == 0): 34 | return 1 35 | r = a % m 36 | k = 1 37 | while (p > 1): 38 | if ((p & 1) != 0): 39 | k = (k * r) % m 40 | r = (r * r) % m 41 | p >>= 1 42 | return (r * k) % m 43 | 44 | 45 | # =========================================== 46 | def randint(n): 47 | '''random是伪随机数,需要更高安全的随机数产生, 48 | 所以使用os.urandom()或者SystmeRandom模块, 49 | 生成n字节的随机数(8位/字节),返回16进制转为10进制整数返回''' 50 | randomdata = urandom(n) 51 | return int(binascii.hexlify(randomdata), 16) 52 | 53 | 54 | # =========================================== 55 | def primality_testing_1(n): 56 | '''测试一,小素数测试,用100以内的小素数检测随机数x, 57 | 可以很大概率排除不是素数,#创建有25个素数的元组''' 58 | Sushubiao = (2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41 59 | , 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97) 60 | for y in Sushubiao: 61 | if n % y == 0: 62 | return False 63 | return True 64 | 65 | 66 | # =========================================== 67 | def primality_testing_2(n, k): 68 | '''测试二,用miller_rabin算法对n进行k次检测''' 69 | if n < 2: 70 | return False 71 | d = n - 1 72 | r = 0 73 | while not (d & 1): 74 | r += 1 75 | d >>= 1 76 | for _ in range(k): 77 | a = randint(120) # 随机数 78 | x = pow(a, d, n) 79 | if x == 1 or x == n - 1: 80 | continue 81 | for _ in range(r - 1): 82 | x = pow(x, 2, n) 83 | if x == 1: 84 | return False 85 | if x == n - 1: 86 | break 87 | else: 88 | return False 89 | return True 90 | 91 | 92 | # =========================================== 93 | def getprime(byte): 94 | while True: 95 | n = randint(byte) 96 | if primality_testing_1(n): 97 | if primality_testing_2(n, 10): 98 | pass 99 | else: 100 | continue 101 | else: 102 | continue 103 | return n 104 | 105 | 106 | # =========================================== 107 | def RSA(): 108 | global flag 109 | message = [] 110 | ciphertext = [] 111 | plaintext = [] 112 | while not flag: 113 | message = [] 114 | ciphertext = [] 115 | plaintext = [] 116 | p = getprime(32) # 1024bit的大整数 117 | q = getprime(32) 118 | while p == q: # 避免p/q值相同 119 | q = getprime(1) 120 | n = p * q # n值公开 121 | OrLa = (p - 1) * (q - 1) # 欧拉函数 122 | e = 524289 123 | '''e取e=524289时,其二进制为10000000000000000001''' 124 | d = Mod_1(e, OrLa) 125 | # print('公钥为({0},{1});\n私钥为({2},{3})'.format(n, e, n, d)) 126 | message = 'theKingOfNight' 127 | # 从标准输入输出流接收数据,数字化再加解密 128 | message = list(map(ord, message)) 129 | # print('ciphertext数字化:', message) 130 | ciphertext = [] 131 | for x in message: 132 | ciphertext.append(pow(x, e, n)) 133 | # print('ciphertext加密:', ciphertext) 134 | message = ciphertext 135 | plaintext = [] 136 | for x in message: 137 | plaintext.append(pow(x, d, n)) 138 | # print('plaintext解密:', plaintext) 139 | if int(plaintext[0]) <= 256: 140 | flag = True 141 | 142 | # print('公钥为({0},{1});\n私钥为({2},{3})'.format(n, e, n, d)) 143 | # print("p:"+str(p)) 144 | # print("q:"+str(q)) 145 | return e, n, d 146 | 147 | 148 | # =================================================== 149 | def encrypt(e, n, message): 150 | temp = '' 151 | # message = input("输入需要加密的密文") 152 | # 从标准输入输出流接收数据,数字化再加解密 153 | message = list(map(ord, message)) 154 | # print('ciphertext数字化:', message) 155 | ciphertext = [] 156 | for x in message: 157 | ciphertext.append(pow(x, e, n)) 158 | for x in ciphertext: 159 | temp = temp + ',' + str(x) 160 | 161 | temp = temp[1:] 162 | # print(temp) 163 | return temp 164 | 165 | 166 | def decrypt(d, n, ciphertext): 167 | message = [] 168 | plaintext = [] 169 | temp = '' 170 | 171 | message = ciphertext.split(',') 172 | for x in message: 173 | plaintext.append(pow(int(x), d, n)) 174 | # print('plaintext解密:', plaintext) 175 | plaintext = list(map(chr, plaintext)) 176 | # print('plaintext字符化:', plaintext) 177 | for i in plaintext: 178 | temp = temp + str(i) 179 | return temp 180 | 181 | 182 | def encode_file(e, n, file_name, encrypted_file_name): 183 | encrpt_file = 'encrpt' 184 | # file_name = input("输入当前路径的文件") 185 | # 文件后缀名检测 186 | decrpt_file_name = file_name.split('.')[1] 187 | # 188 | message = [] 189 | plaintext = [] 190 | ciphertext = [] 191 | with open(file_name, 'rb') as origin_file: 192 | # TODO Wrong Here 193 | for x in origin_file.read(): 194 | # print(int(x)) 195 | message.append(int(x)) 196 | for x in message: 197 | # print(x) 198 | ciphertext.append(pow(int(x), e, n)) 199 | # 写入加密文件 200 | f = open(encrypted_file_name, 'w') 201 | for x in ciphertext: 202 | f.write(str(x) + '\r') 203 | f.close() 204 | return encrpt_file + '.' + file_name.split('.')[1] 205 | 206 | 207 | def decode_file(d, n, encode_file, decrypt_file_name=''): 208 | plaintext = [] 209 | decrpt_file = 'decrpt' 210 | # 文件后缀名检测 211 | decrpt_file_name = encode_file.split('.')[1] 212 | with open(encode_file) as f: 213 | for x in f.readlines(): 214 | plaintext.append(pow(int(x), d, n)) 215 | f = open(decrypt_file_name, 'wb') 216 | f.write(bytes(plaintext)) 217 | f.close() 218 | 219 | 220 | def main(): 221 | e, n, d = RSA() 222 | print(e) 223 | print(n) 224 | print(d) 225 | # public key e,n 226 | # private key d 227 | # encode_file(e,n,file_name) 228 | cipher_text = encrypt(e, n, "1234567") 229 | print(cipher_text) 230 | print(decrypt(d, n, cipher_text)) 231 | # decode_file(d,n,decode_file()) 232 | 233 | 234 | if __name__ == '__main__': 235 | main() 236 | -------------------------------------------------------------------------------- /algorithm/stream_cipher/ca/ca_file.py: -------------------------------------------------------------------------------- 1 | cell = "00010100" 2 | 3 | 4 | def encrypt(filename, rule, newfilename): 5 | if rule < 0 or rule > 255: 6 | return "rule超过范围" 7 | rule = bin(rule)[2:].zfill(8) 8 | f1 = open(filename, "rb") 9 | Plaintext = f1.read() 10 | f1.close() 11 | key = [] 12 | key.append(int(cell, 2)) 13 | for i in range(len(Plaintext)): 14 | new_key = "" 15 | old_key = bin(key[-1])[2:].zfill(8) 16 | for i in range(0, len(old_key)): 17 | tmp = "" 18 | tmp += old_key[i - 1] + old_key[i] 19 | if i == len(old_key) - 1: 20 | tmp += old_key[0] 21 | else: 22 | tmp += old_key[i + 1] 23 | new_key += str(rule[int(tmp, 2)]) 24 | key.append(int(new_key, 2)) 25 | result = [] 26 | for i, j in zip(Plaintext, key): 27 | result.append(i ^ j) 28 | f2 = open(newfilename, "wb") 29 | f2.write(bytes(result)) 30 | f2.close() 31 | 32 | 33 | def decrypt(filename, rule, newfilename): 34 | if rule < 0 or rule > 255: 35 | return "rule超过范围" 36 | rule = bin(rule)[2:].zfill(8) 37 | f1 = open(filename, "rb") 38 | Plaintext = f1.read() 39 | f1.close() 40 | key = [int(cell, 2)] 41 | for i in range(len(Plaintext)): 42 | new_key = "" 43 | old_key = bin(key[-1])[2:].zfill(8) 44 | for i in range(0, len(old_key)): 45 | tmp = "" 46 | tmp += old_key[i - 1] + old_key[i] 47 | if i == len(old_key) - 1: 48 | tmp += old_key[0] 49 | else: 50 | tmp += old_key[i + 1] 51 | new_key += str(rule[int(tmp, 2)]) 52 | key.append(int(new_key, 2)) 53 | result = [] 54 | for i, j in zip(Plaintext, key): 55 | result.append(i ^ j) 56 | f2 = open(newfilename, "wb") 57 | f2.write(bytes(result)) 58 | f2.close() 59 | -------------------------------------------------------------------------------- /algorithm/stream_cipher/ca/ca_string.py: -------------------------------------------------------------------------------- 1 | cell = "00010100" 2 | 3 | 4 | def encrypt(Plaintext, rule): 5 | if rule < 0 or rule > 255: 6 | return "rule超过范围" 7 | Plaintext = Plaintext.encode('utf-8') 8 | rule = bin(rule)[2:].zfill(8) 9 | key = [int(cell, 2)] 10 | for i in range(len(Plaintext)): 11 | new_key = "" 12 | old_key = bin(key[-1])[2:].zfill(8) 13 | for i in range(0, len(old_key)): 14 | tmp = "" 15 | tmp += old_key[i - 1] + old_key[i] 16 | if i == len(old_key) - 1: 17 | tmp += old_key[0] 18 | else: 19 | tmp += old_key[i + 1] 20 | new_key += str(rule[int(tmp, 2)]) 21 | key.append(int(new_key, 2)) 22 | result = [] 23 | for i, j in zip(Plaintext, key): 24 | result.append(i ^ j) 25 | ciphertext = "0x" 26 | for i in result: 27 | ciphertext += hex(i)[2:].zfill(2) 28 | return ciphertext[2:] 29 | 30 | 31 | def decrypt(ciphertext, rule): 32 | if rule < 0 or rule > 255: 33 | return "rule超过范围" 34 | rule = bin(rule)[2:].zfill(8) 35 | if "0x" in ciphertext: 36 | ciphertext = ciphertext[2:] 37 | blk = [] 38 | i = 0 39 | while i + 2 <= len(ciphertext): 40 | blk.append(int(ciphertext[i:i + 2], 16)) 41 | i = i + 2 42 | ciphertext = blk 43 | key = [int(cell, 2)] 44 | for i in range(len(ciphertext)): 45 | new_key = "" 46 | old_key = bin(key[-1])[2:].zfill(8) 47 | for i in range(0, len(old_key)): 48 | tmp = "" 49 | tmp += old_key[i - 1] + old_key[i] 50 | if i == len(old_key) - 1: 51 | tmp += old_key[0] 52 | else: 53 | tmp += old_key[i + 1] 54 | new_key += str(rule[int(tmp, 2)]) 55 | key.append(int(new_key, 2)) 56 | result = [] 57 | for i, j in zip(ciphertext, key): 58 | result.append(i ^ j) 59 | return bytes(result).decode("utf-8") 60 | -------------------------------------------------------------------------------- /algorithm/stream_cipher/rc4_cipher.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import codecs 4 | 5 | 6 | class RC4: 7 | 8 | def KSA(self, key): 9 | # Key Scheduling Algorithm 10 | len_key = len(key) 11 | S = list(range(256)) 12 | # S = [0,1,2, ... , 255] 13 | j = 0 14 | for i in range(256): 15 | j = (j + S[i] + key[i % len_key]) % 256 16 | S[i], S[j] = S[j], S[i] 17 | return S 18 | 19 | def PRGA(self, S): 20 | i = 0 21 | j = 0 22 | K = [] 23 | while True: 24 | i = (i + 1) % 256 25 | j = (j + S[i]) % 256 26 | S[i], S[j] = S[j], S[i] 27 | K = S[(S[i] + S[j]) % 256] 28 | yield K 29 | 30 | def get_keystream(self, key): 31 | S = self.KSA(key) 32 | return self.PRGA(S) 33 | 34 | def encrypt_logic(self, key, text): 35 | key = [ord(c) for c in key] 36 | keystream = self.get_keystream(key) 37 | res = [] 38 | for c in text: 39 | val = ("%02X" % (c ^ next(keystream))) 40 | res.append(val) 41 | return ''.join(res) 42 | 43 | def encrypt(self, key, plaintext): 44 | plaintext = [ord(c) for c in plaintext] 45 | return self.encrypt_logic(key, plaintext) 46 | 47 | def decrypt(self, key, ciphertext): 48 | ciphertext = codecs.decode(ciphertext, 'hex_codec') 49 | res = self.encrypt_logic(key, ciphertext) 50 | return codecs.decode(res, 'hex_codec').decode('utf-8') 51 | 52 | def encrypt_file(self, file_plain, file_ciphered, key): 53 | with open(file_plain, 'r') as myfile: 54 | lines = myfile.readlines() 55 | with open(file_ciphered, 'w') as myfile: 56 | for plaintext in lines: 57 | plaintext = [ord(c) for c in plaintext.replace('\n', '')] 58 | ciphertext = self.encrypt_logic(key, plaintext) 59 | myfile.write(ciphertext + '\n') 60 | 61 | def decrypt_file(self, file_plain, file_ciphered, key): 62 | with open(file_ciphered, 'r') as myfile: 63 | lines = myfile.readlines() 64 | with open(file_plain, 'w') as myfile: 65 | for ciphertext in lines: 66 | ciphertext = codecs.decode(ciphertext.replace('\n', ''), 'hex_codec') 67 | res = self.encrypt_logic(key, ciphertext) 68 | decrptedtext = codecs.decode(res, 'hex_codec').decode('utf-8') 69 | myfile.write(decrptedtext + '\n') 70 | 71 | 72 | def main(): 73 | rc_instance = RC4() 74 | key = 'my-rc4-key' 75 | plaintext = 'An apple a day keeps the doctor away' 76 | ciphertext = rc_instance.encrypt(key, plaintext) 77 | print('明文:', plaintext) 78 | print('加密后的密文:', ciphertext) 79 | print('重新解密得到的明文:', rc_instance.decrypt(key, ciphertext)) 80 | print('从明文.txt开始加密') 81 | rc_instance.encrypt_file('明文.txt', '密文.txt', key) 82 | print('密文.txt生成成功') 83 | print('从密文.txt开始解密') 84 | rc_instance.decrypt_file('明文.txt', '密文.txt', key) 85 | print('明文.txt生成成功') 86 | 87 | 88 | if __name__ == '__main__': 89 | main() 90 | -------------------------------------------------------------------------------- /algorithm/stream_cipher/加密密钥.txt: -------------------------------------------------------------------------------- 1 | my-rc4-key -------------------------------------------------------------------------------- /algorithm/stream_cipher/密文.txt: -------------------------------------------------------------------------------- 1 | E5159BC460605C14A499887EA184698AE3A4F723F69B3C064ED964F2838F92E3FB698D53 2 | -------------------------------------------------------------------------------- /algorithm/stream_cipher/明文.txt: -------------------------------------------------------------------------------- 1 | An apple a day keeps the doctor away 2 | -------------------------------------------------------------------------------- /assets/icons/Hmovetoolbar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/morsuning/cryptography-gui-tool/7e0d58655f6f165f595fac869b98582a9f66448d/assets/icons/Hmovetoolbar.png -------------------------------------------------------------------------------- /assets/icons/Hsepartoolbar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/morsuning/cryptography-gui-tool/7e0d58655f6f165f595fac869b98582a9f66448d/assets/icons/Hsepartoolbar.png -------------------------------------------------------------------------------- /assets/icons/PentestBox.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/morsuning/cryptography-gui-tool/7e0d58655f6f165f595fac869b98582a9f66448d/assets/icons/PentestBox.ico -------------------------------------------------------------------------------- /assets/icons/Vmovetoolbar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/morsuning/cryptography-gui-tool/7e0d58655f6f165f595fac869b98582a9f66448d/assets/icons/Vmovetoolbar.png -------------------------------------------------------------------------------- /assets/icons/Vsepartoolbar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/morsuning/cryptography-gui-tool/7e0d58655f6f165f595fac869b98582a9f66448d/assets/icons/Vsepartoolbar.png -------------------------------------------------------------------------------- /assets/icons/branch_closed-on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/morsuning/cryptography-gui-tool/7e0d58655f6f165f595fac869b98582a9f66448d/assets/icons/branch_closed-on.png -------------------------------------------------------------------------------- /assets/icons/branch_closed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/morsuning/cryptography-gui-tool/7e0d58655f6f165f595fac869b98582a9f66448d/assets/icons/branch_closed.png -------------------------------------------------------------------------------- /assets/icons/branch_open-on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/morsuning/cryptography-gui-tool/7e0d58655f6f165f595fac869b98582a9f66448d/assets/icons/branch_open-on.png -------------------------------------------------------------------------------- /assets/icons/branch_open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/morsuning/cryptography-gui-tool/7e0d58655f6f165f595fac869b98582a9f66448d/assets/icons/branch_open.png -------------------------------------------------------------------------------- /assets/icons/checkbox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/morsuning/cryptography-gui-tool/7e0d58655f6f165f595fac869b98582a9f66448d/assets/icons/checkbox.png -------------------------------------------------------------------------------- /assets/icons/close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/morsuning/cryptography-gui-tool/7e0d58655f6f165f595fac869b98582a9f66448d/assets/icons/close.png -------------------------------------------------------------------------------- /assets/icons/down_arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/morsuning/cryptography-gui-tool/7e0d58655f6f165f595fac869b98582a9f66448d/assets/icons/down_arrow.png -------------------------------------------------------------------------------- /assets/icons/down_arrow_disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/morsuning/cryptography-gui-tool/7e0d58655f6f165f595fac869b98582a9f66448d/assets/icons/down_arrow_disabled.png -------------------------------------------------------------------------------- /assets/icons/left_arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/morsuning/cryptography-gui-tool/7e0d58655f6f165f595fac869b98582a9f66448d/assets/icons/left_arrow.png -------------------------------------------------------------------------------- /assets/icons/left_arrow_disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/morsuning/cryptography-gui-tool/7e0d58655f6f165f595fac869b98582a9f66448d/assets/icons/left_arrow_disabled.png -------------------------------------------------------------------------------- /assets/icons/right_arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/morsuning/cryptography-gui-tool/7e0d58655f6f165f595fac869b98582a9f66448d/assets/icons/right_arrow.png -------------------------------------------------------------------------------- /assets/icons/right_arrow_disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/morsuning/cryptography-gui-tool/7e0d58655f6f165f595fac869b98582a9f66448d/assets/icons/right_arrow_disabled.png -------------------------------------------------------------------------------- /assets/icons/sizegrip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/morsuning/cryptography-gui-tool/7e0d58655f6f165f595fac869b98582a9f66448d/assets/icons/sizegrip.png -------------------------------------------------------------------------------- /assets/icons/stylesheet-branch-end.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/morsuning/cryptography-gui-tool/7e0d58655f6f165f595fac869b98582a9f66448d/assets/icons/stylesheet-branch-end.png -------------------------------------------------------------------------------- /assets/icons/stylesheet-branch-more.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/morsuning/cryptography-gui-tool/7e0d58655f6f165f595fac869b98582a9f66448d/assets/icons/stylesheet-branch-more.png -------------------------------------------------------------------------------- /assets/icons/stylesheet-vline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/morsuning/cryptography-gui-tool/7e0d58655f6f165f595fac869b98582a9f66448d/assets/icons/stylesheet-vline.png -------------------------------------------------------------------------------- /assets/icons/transparent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/morsuning/cryptography-gui-tool/7e0d58655f6f165f595fac869b98582a9f66448d/assets/icons/transparent.png -------------------------------------------------------------------------------- /assets/icons/undock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/morsuning/cryptography-gui-tool/7e0d58655f6f165f595fac869b98582a9f66448d/assets/icons/undock.png -------------------------------------------------------------------------------- /assets/icons/up_arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/morsuning/cryptography-gui-tool/7e0d58655f6f165f595fac869b98582a9f66448d/assets/icons/up_arrow.png -------------------------------------------------------------------------------- /assets/icons/up_arrow_disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/morsuning/cryptography-gui-tool/7e0d58655f6f165f595fac869b98582a9f66448d/assets/icons/up_arrow_disabled.png -------------------------------------------------------------------------------- /assets/python/qss_reader.py: -------------------------------------------------------------------------------- 1 | class QssReader: 2 | def __init__(self): 3 | pass 4 | 5 | # @staticmethod 6 | def read_qss(style): 7 | with open(style, 'r') as f: 8 | return f.read() 9 | -------------------------------------------------------------------------------- /assets/qss/darkstyle.qss: -------------------------------------------------------------------------------- 1 | QProgressBar:horizontal { 2 | border: 1px solid #3A3939; 3 | text-align: center; 4 | padding: 1px; 5 | background: #201F1F; 6 | } 7 | QProgressBar::chunk:horizontal { 8 | background-color: qlineargradient(spread:reflect, x1:1, y1:0.545, x2:1, y2:0, stop:0 rgba(28, 66, 111, 255), stop:1 rgba(37, 87, 146, 255)); 9 | } 10 | 11 | QToolTip 12 | { 13 | border: 1px solid #3A3939; 14 | background-color: rgb(90, 102, 117); 15 | color: white; 16 | padding: 1px; 17 | opacity: 200; 18 | } 19 | 20 | QWidget 21 | { 22 | color: silver; 23 | background-color: #302F2F; 24 | selection-background-color:#78879b; 25 | selection-color: black; 26 | } 27 | 28 | QWidget:item:selected 29 | { 30 | background-color: QLinearGradient( 31 | x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #78879b, stop: 1 #78879b 32 | ); 33 | } 34 | 35 | QMenuBar 36 | { 37 | background-color: #302F2F; 38 | color: silver; 39 | } 40 | 41 | QMenuBar::item 42 | { 43 | background: transparent; 44 | } 45 | 46 | QMenuBar::item:selected 47 | { 48 | background: transparent; 49 | border: 1px solid #3A3939; 50 | } 51 | 52 | QMenuBar::item:pressed 53 | { 54 | border: 1px solid #3A3939; 55 | background-color: #78879b; 56 | color: black; 57 | margin-bottom:-1px; 58 | padding-bottom:1px; 59 | } 60 | 61 | QMenu 62 | { 63 | border: 1px solid #3A3939; 64 | color: silver; 65 | } 66 | 67 | QMenu::item 68 | { 69 | padding: 2px 20px 2px 20px; 70 | } 71 | 72 | QMenu::item:selected 73 | { 74 | color: black; 75 | } 76 | 77 | QWidget:disabled 78 | { 79 | color: #404040; 80 | background-color: #302F2F; 81 | } 82 | 83 | QAbstractItemView 84 | { 85 | alternate-background-color: #3A3939; 86 | color: silver; 87 | border: 1px solid 3A3939; 88 | border-radius: 3px; 89 | padding: 1px; 90 | } 91 | 92 | QWidget:focus, QMenuBar:focus 93 | { 94 | border: 1px solid rgba(48, 86, 111); 95 | } 96 | 97 | QTabWidget:focus, QCheckBox:focus 98 | { 99 | border: none; 100 | } 101 | 102 | QLineEdit 103 | { 104 | background-color: #201F1F; 105 | padding: 2px; 106 | border-style: solid; 107 | border: 1px solid #3A3939; 108 | border-radius: 3px; 109 | color: silver; 110 | } 111 | 112 | QGroupBox { 113 | border:1px solid #3A3939; 114 | border-radius: 7px; 115 | margin-top: 2ex; 116 | } 117 | 118 | QGroupBox::title { 119 | subcontrol-origin: margin; 120 | subcontrol-position: top left; 121 | padding-left: 10px; 122 | padding-right: 10px; 123 | } 124 | 125 | QAbstractScrollArea 126 | { 127 | border-radius: 3px; 128 | border: 1px solid #3A3939; 129 | } 130 | 131 | QScrollBar:horizontal 132 | { 133 | height: 15px; 134 | margin: 0px 11px 0px 11px; 135 | border: 1px solid #3A3939; 136 | border-radius: 6px; 137 | background-color: QLinearGradient( 138 | x1: 0, y1: 1, x2: 0, y2: 0, stop: 0 #302F2F, stop: 1 #484846 139 | ); 140 | } 141 | 142 | QScrollBar::handle:horizontal 143 | { 144 | background-color: QLinearGradient( 145 | x1: 0, y1: 1, x2: 0, y2: 0, stop: 0 #605F5F, stop: 1 #787876 146 | ); 147 | min-width: 5px; 148 | border-radius: 5px; 149 | } 150 | 151 | QScrollBar::sub-line:horizontal 152 | { 153 | border-image: url(icons/right_arrow_disabled.png); 154 | width: 10px; 155 | height: 10px; 156 | subcontrol-position: right; 157 | subcontrol-origin: margin; 158 | } 159 | 160 | QScrollBar::add-line:horizontal 161 | { 162 | border-image: url(icons/left_arrow_disabled.png); 163 | height: 10px; 164 | width: 10px; 165 | subcontrol-position: left; 166 | subcontrol-origin: margin; 167 | } 168 | 169 | QScrollBar::sub-line:horizontal:hover, 170 | QScrollBar::sub-line:horizontal:on 171 | { 172 | border-image: url(icons/right_arrow.png); 173 | height: 10px; 174 | width: 10px; 175 | subcontrol-position: right; 176 | subcontrol-origin: margin; 177 | } 178 | 179 | 180 | QScrollBar::add-line:horizontal:hover, 181 | QScrollBar::add-line:horizontal:on 182 | { 183 | border-image: url(icons/left_arrow.png); 184 | height: 10px; 185 | width: 10px; 186 | subcontrol-position: left; 187 | subcontrol-origin: margin; 188 | } 189 | 190 | QScrollBar::up-arrow:horizontal, 191 | QScrollBar::down-arrow:horizontal 192 | { 193 | background: none; 194 | } 195 | 196 | 197 | QScrollBar::add-page:horizontal, 198 | QScrollBar::sub-page:horizontal 199 | { 200 | background: none; 201 | } 202 | 203 | QScrollBar:vertical 204 | { 205 | background-color: QLinearGradient( 206 | x1: 1, y1: 0, x2: 0, y2: 0, stop: 0 #302F2F, stop: 1 #484846 207 | ); 208 | width: 15px; 209 | margin: 11px 0 11px 0; 210 | border: 1px solid #3A3939; 211 | border-radius: 6px; 212 | } 213 | 214 | QScrollBar::handle:vertical 215 | { 216 | background-color: QLinearGradient( 217 | x1: 1, y1: 0, x2: 0, y2: 0, stop: 0 #605F5F, stop: 1 #787876 218 | ); 219 | min-height: 5px; 220 | border-radius: 5px; 221 | } 222 | 223 | QScrollBar::sub-line:vertical 224 | { 225 | border-image: url(icons/up_arrow_disabled.png); 226 | height: 10px; 227 | width: 10px; 228 | subcontrol-position: top; 229 | subcontrol-origin: margin; 230 | } 231 | 232 | QScrollBar::add-line:vertical 233 | { 234 | border-image: url(icons/down_arrow_disabled.png); 235 | height: 10px; 236 | width: 10px; 237 | subcontrol-position: bottom; 238 | subcontrol-origin: margin; 239 | } 240 | 241 | QScrollBar::sub-line:vertical:hover, 242 | QScrollBar::sub-line:vertical:on 243 | { 244 | 245 | border-image: url(icons/up_arrow.png); 246 | height: 10px; 247 | width: 10px; 248 | subcontrol-position: top; 249 | subcontrol-origin: margin; 250 | } 251 | 252 | 253 | QScrollBar::add-line:vertical:hover, 254 | QScrollBar::add-line:vertical:on 255 | { 256 | border-image: url(icons/down_arrow.png); 257 | height: 10px; 258 | width: 10px; 259 | subcontrol-position: bottom; 260 | subcontrol-origin: margin; 261 | } 262 | 263 | QScrollBar::up-arrow:vertical, 264 | QScrollBar::down-arrow:vertical 265 | { 266 | background: none; 267 | } 268 | 269 | 270 | QScrollBar::add-page:vertical, 271 | QScrollBar::sub-page:vertical 272 | { 273 | background: none; 274 | } 275 | 276 | QTextEdit 277 | { 278 | background-color: #302F2F; 279 | color: silver; 280 | border: 1px solid #3A3939; 281 | } 282 | 283 | QPlainTextEdit 284 | { 285 | background-color: #201F1F;; 286 | color: silver; 287 | border-radius: 3px; 288 | border: 1px solid #3A3939; 289 | } 290 | 291 | QHeaderView::section 292 | { 293 | background-color: #3A3939; 294 | color: silver; 295 | padding-left: 4px; 296 | border: 1px solid #6c6c6c; 297 | } 298 | 299 | QCheckBox:disabled 300 | { 301 | color: #404040; 302 | } 303 | 304 | QSizeGrip { 305 | image: url(icons/sizegrip.png); 306 | width: 12px; 307 | height: 12px; 308 | } 309 | 310 | 311 | QMainWindow::separator 312 | { 313 | background-color: #302F2F; 314 | color: white; 315 | padding-left: 4px; 316 | spacing: 2px; 317 | border: 1px dashed #3A3939; 318 | } 319 | 320 | QMainWindow::separator:hover 321 | { 322 | 323 | background-color: QLinearGradient( 324 | x1:0, y1:0, x2:0, y2:1, stop:0 #58677b, stop:0.5 #78879b stop:1 #58677b 325 | ); 326 | color: white; 327 | padding-left: 4px; 328 | border: 1px solid #3A3939; 329 | spacing: 2px; 330 | } 331 | 332 | 333 | QMenu::separator 334 | { 335 | height: 1px; 336 | background-color: #3A3939; 337 | color: white; 338 | padding-left: 4px; 339 | margin-left: 10px; 340 | margin-right: 5px; 341 | } 342 | 343 | QRadioButton::indicator:checked, 344 | QRadioButton::indicator:unchecked 345 | { 346 | color: #b1b1b1; 347 | background-color: #302F2F; 348 | border: 1px solid silver; 349 | border-radius: 5px; 350 | } 351 | 352 | QRadioButton::indicator:checked 353 | { 354 | background-color: qradialgradient( 355 | cx: 0.5, cy: 0.5, 356 | fx: 0.5, fy: 0.5, 357 | radius: 1.0, 358 | stop: 0.25 #78879b, 359 | stop: 0.3 #302F2F 360 | ); 361 | } 362 | 363 | QCheckBox::indicator{ 364 | color: #b1b1b1; 365 | background-color: #302F2F; 366 | border: 1px solid silver; 367 | width: 9px; 368 | height: 9px; 369 | } 370 | 371 | QRadioButton::indicator 372 | { 373 | border-radius: 7px; 374 | width: 9px; 375 | height: 9px; 376 | } 377 | 378 | QRadioButton::indicator:hover, 379 | QCheckBox::indicator:hover 380 | { 381 | border: 1px solid #78879b; 382 | } 383 | 384 | QCheckBox::indicator:checked 385 | { 386 | image:url(icons/checkbox.png); 387 | } 388 | 389 | QCheckBox::indicator:disabled, 390 | QRadioButton::indicator:disabled 391 | { 392 | border: 1px solid #444; 393 | } 394 | 395 | QFrame 396 | { 397 | border-radius: 3px; 398 | } 399 | 400 | QStackedWidget 401 | { 402 | border: none; 403 | } 404 | 405 | QToolBar 406 | { 407 | border: 1px solid #393838; 408 | background: 1px solid #302F2F; 409 | font-weight: bold; 410 | } 411 | 412 | QToolBar::handle:horizontal 413 | { 414 | image: url(icons/Hmovetoolbar.png); 415 | } 416 | 417 | QToolBar::handle:vertical 418 | { 419 | image: url(icons/Vmovetoolbar.png); 420 | } 421 | 422 | QToolBar::separator:horizontal 423 | { 424 | image: url(icons/Hsepartoolbar.png); 425 | } 426 | 427 | QToolBar::separator:vertical 428 | { 429 | image: url(icons/Vsepartoolbars.png); 430 | } 431 | 432 | QPushButton 433 | { 434 | color: silver; 435 | background-color: QLinearGradient( 436 | x1: 0, y1: 1, x2: 0, y2: 0,stop: 0 #302F2F, stop: 1 #484846 437 | ); 438 | border-width: 1px; 439 | border-color: #4A4949; 440 | border-style: solid; 441 | padding-top: 5px; 442 | padding-bottom: 5px; 443 | padding-left: 5px; 444 | padding-right: 5px; 445 | border-radius: 5px; 446 | } 447 | 448 | QPushButton:disabled 449 | { 450 | background-color: QLinearGradient( 451 | x1: 0, y1: 1, x2: 0, y2: 0, stop: 0 #302F2F, stop: 1 #484846 452 | ); 453 | border-width: 1px; 454 | border-color: #3A3939; 455 | border-style: solid; 456 | padding-top: 5px; 457 | padding-bottom: 5px; 458 | padding-left: 10px; 459 | padding-right: 10px; 460 | /*border-radius: 3px;*/ 461 | color: #3A3939; 462 | } 463 | 464 | QComboBox 465 | { 466 | selection-background-color: #78879b; 467 | background-color: #201F1F; 468 | border-style: solid; 469 | border: 1px solid #3A3939; 470 | border-radius: 3px; 471 | padding: 2px; 472 | } 473 | 474 | QComboBox:hover, 475 | QPushButton:hover, 476 | QAbstractSpinBox:hover, 477 | QLineEdit:hover, 478 | QTextEdit:hover, 479 | QWidget:hover, 480 | QPlainTextEdit:hover, 481 | QAbstractView:hover, 482 | QTreeView:hover 483 | { 484 | border: 1px solid #78879b; 485 | color: silver; 486 | } 487 | 488 | QComboBox:on 489 | { 490 | background-color: #626873; 491 | padding-top: 3px; 492 | padding-left: 4px; 493 | selection-background-color: #4a4a4a; 494 | } 495 | 496 | QComboBox QAbstractItemView 497 | { 498 | background-color: #201F1F; 499 | border-radius: 3px; 500 | border: 1px solid #3A3939; 501 | selection-background-color: QLinearGradient( 502 | x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #78879b, stop: 1 #78879b 503 | ); 504 | } 505 | 506 | QComboBox::drop-down 507 | { 508 | subcontrol-origin: padding; 509 | subcontrol-position: top right; 510 | width: 15px; 511 | border-left-width: 0px; 512 | border-left-color: darkgray; 513 | border-left-style: solid; 514 | border-top-right-radius: 3px; 515 | border-bottom-right-radius: 3px; 516 | } 517 | 518 | QComboBox::down-arrow 519 | { 520 | image: url(icons/down_arrow_disabled.png); 521 | } 522 | 523 | QComboBox::down-arrow:on, 524 | QComboBox::down-arrow:hover, 525 | QComboBox::down-arrow:focus 526 | { 527 | image: url(icons/down_arrow.png); 528 | } 529 | 530 | QPushButton:pressed 531 | { 532 | background-color: QLinearGradient( 533 | x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #302F2F, stop: 1 #484846 534 | ); 535 | } 536 | 537 | QAbstractSpinBox { 538 | padding-top: 2px; 539 | padding-bottom: 2px; 540 | border: 1px solid #3A3939; 541 | background-color: #201F1F; 542 | color: silver; 543 | border-radius: 3px; 544 | } 545 | 546 | QAbstractSpinBox:up-button 547 | { 548 | background-color: transparent; 549 | subcontrol-origin: border; 550 | subcontrol-position: center right; 551 | } 552 | 553 | QAbstractSpinBox:down-button 554 | { 555 | background-color: transparent; 556 | subcontrol-origin: border; 557 | subcontrol-position: center left; 558 | } 559 | 560 | QHeaderView::down-arrow, 561 | QAbstractSpinBox::up-arrow, 562 | QAbstractSpinBox::up-arrow:disabled, 563 | QAbstractSpinBox::up-arrow:off 564 | { 565 | image: url(icons/up_arrow_disabled.png); 566 | width: 10px; 567 | height: 10px; 568 | } 569 | 570 | QHeaderView::down-arrow:hover, 571 | QAbstractSpinBox::up-arrow:hover 572 | 573 | { 574 | image: url(icons/up_arrow.png); 575 | } 576 | 577 | QHeaderView::down-arrow, 578 | QAbstractSpinBox::down-arrow, 579 | QAbstractSpinBox::down-arrow:disabled, 580 | QAbstractSpinBox::down-arrow:off 581 | { 582 | image: url(icons/down_arrow_disabled.png); 583 | width: 10px; 584 | height: 10px; 585 | } 586 | 587 | QHeaderView::up-arrow:hover, 588 | QAbstractSpinBox::down-arrow:hover 589 | { 590 | image: url(icons/down_arrow.png); 591 | } 592 | 593 | QLabel, 594 | QDateEdit::drop-down 595 | { 596 | border: 0px solid black; 597 | } 598 | 599 | QTabBar::tab 600 | { 601 | color: #b1b1b1; 602 | border: 1px solid #3A3939; 603 | background-color: #302F2F; 604 | padding-left: 5px; 605 | padding-right: 5px; 606 | padding-top: 3px; 607 | padding-bottom: 2px; 608 | margin-right: -1px; 609 | } 610 | 611 | 612 | QTabWidget::pane { 613 | border: 1px solid #3A3939; 614 | background-color: QLinearGradient( 615 | x1:0, y1:0, x2:0, y2:1, stop:1 #302F2F, stop:0 #3A3939 616 | ); 617 | } 618 | 619 | QTabBar::tab:last 620 | { 621 | margin-right: 0; 622 | border-top-right-radius: 3px; 623 | } 624 | 625 | QTabBar::tab:first:!selected 626 | { 627 | margin-left: 0px; 628 | border-top-left-radius: 3px; 629 | } 630 | 631 | QTabBar::tab:!selected 632 | { 633 | color: #b1b1b1; 634 | border-bottom-style: solid; 635 | margin-top: 3px; 636 | } 637 | 638 | QTabBar::tab:selected 639 | { 640 | border-top-left-radius: 3px; 641 | border-top-right-radius: 3px; 642 | margin-bottom: 0px; 643 | 644 | background-color: QLinearGradient( 645 | x1:0, y1:0, x2:0, y2:1, stop:1 #302F2F, stop:0 #5A5959 646 | ); 647 | } 648 | 649 | QTabBar::tab:!selected:hover 650 | { 651 | color:white; 652 | } 653 | 654 | QTabBar::tab:selected:hover 655 | { 656 | color:white; 657 | border-top-left-radius: 3px; 658 | border-top-right-radius: 3px; 659 | background-color: QLinearGradient( 660 | x1:0, y1:0, x2:0, y2:1, stop:1 #302F2F, stop:0 #5A5959 661 | ); 662 | } 663 | 664 | QDockWidget 665 | { 666 | color: silver; 667 | titlebar-close-icon: url(icons/close.png); 668 | titlebar-normal-icon: url(icons/undock.png); 669 | } 670 | 671 | QDockWidget::title 672 | { 673 | border: 1px solid #3A3939; 674 | border-bottom: #302F2F; 675 | text-align: left; 676 | spacing: 2px; 677 | background-color: QLinearGradient( 678 | x1:0, y1:0, x2:0, y2:1, stop:1 #302F2F, stop:0 #3A3939 679 | ); 680 | background-image: none; 681 | padding-left: 10px; 682 | } 683 | 684 | QDockWidget { 685 | border: 1px solid lightgray; 686 | titlebar-close-icon: url(icons/close.png); 687 | titlebar-normal-icon: url(icons/undock.png); 688 | } 689 | 690 | QDockWidget::close-button, 691 | QDockWidget::float-button { 692 | border: 1px solid transparent; 693 | border-radius: 5px; 694 | background: transparent; 695 | icon-size: 10px; 696 | } 697 | 698 | QDockWidget::close-button:hover, 699 | QDockWidget::float-button:hover { 700 | background: #3A3939; 701 | } 702 | 703 | QDockWidget::close-button:pressed, 704 | QDockWidget::float-button:pressed { 705 | padding: 1px -1px -1px 1px; 706 | } 707 | 708 | QTreeView, 709 | QListView, 710 | QTableView 711 | { 712 | border: 1px solid #3A3939; 713 | background-color: #201F1F; 714 | } 715 | 716 | QTreeView:branch:selected, 717 | QTreeView:branch:hover 718 | { 719 | background: url(icons/transparent.png); 720 | } 721 | 722 | QTreeView::branch:has-siblings:!adjoins-item 723 | { 724 | border-image: url(icons/transparent.png); 725 | } 726 | 727 | QTreeView::branch:has-siblings:adjoins-item 728 | { 729 | border-image: url(icons/transparent.png); 730 | } 731 | 732 | QTreeView::branch:!has-children:!has-siblings:adjoins-item 733 | { 734 | border-image: url(icons/transparent.png); 735 | } 736 | 737 | QTreeView::branch:has-children:!has-siblings:closed, 738 | QTreeView::branch:closed:has-children:has-siblings 739 | { 740 | image: url(icons/branch_closed.png); 741 | } 742 | 743 | QTreeView::branch:open:has-children:!has-siblings, 744 | QTreeView::branch:open:has-children:has-siblings 745 | { 746 | image: url(icons/branch_open.png); 747 | } 748 | 749 | QTreeView::branch:has-children:!has-siblings:closed:hover, 750 | QTreeView::branch:closed:has-children:has-siblings:hover 751 | { 752 | image: url(icons/branch_closed-on.png); 753 | } 754 | 755 | QTreeView::branch:open:has-children:!has-siblings:hover, 756 | QTreeView::branch:open:has-children:has-siblings:hover 757 | { 758 | image: url(icons/branch_open-on.png); 759 | } 760 | 761 | QSlider::groove:horizontal 762 | { 763 | border: 1px solid #3A3939; 764 | height: 8px; 765 | background: #201F1F; 766 | margin: 2px 0; 767 | border-radius: 4px; 768 | } 769 | 770 | QSlider::handle:horizontal 771 | { 772 | background: QLinearGradient( 773 | x1: 0, y1: 0, x2: 0, y2: 1, stop: 0.0 silver, stop: 0.2 #a8a8a8, stop: 1 #727272 774 | ); 775 | border: 1px solid #3A3939; 776 | width: 14px; 777 | height: 14px; 778 | margin: -4px 0; 779 | border-radius: 7px; 780 | } 781 | 782 | QSlider::groove:vertical 783 | { 784 | border: 1px solid #3A3939; 785 | width: 8px; 786 | background: #201F1F; 787 | margin: 0 0px; 788 | border-radius: 4px; 789 | } 790 | 791 | QSlider::handle:vertical 792 | { 793 | background: QLinearGradient( 794 | x1: 0, y1: 0, x2: 0, y2: 1, stop: 0.0 silver, stop: 0.2 #a8a8a8, stop: 1 #727272 795 | ); 796 | border: 1px solid #3A3939; 797 | width: 14px; 798 | height: 14px; 799 | margin: 0 -4px; 800 | border-radius: 7px; 801 | } 802 | 803 | QToolButton 804 | { 805 | background-color: #302F2F; 806 | } 807 | 808 | QToolButton:pressed 809 | { 810 | background-color: #3A3939; 811 | } 812 | QToolButton:hover 813 | { 814 | background-color: #3A3939; 815 | } 816 | 817 | QTableView#tagView 818 | { 819 | background-color: transparent; 820 | } 821 | 822 | QLabel#inTotalLabel, QLabel#outTotalLabel, QLabel#recordCountLabel 823 | { 824 | font: bold; 825 | } -------------------------------------------------------------------------------- /event/configuration.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/morsuning/cryptography-gui-tool/7e0d58655f6f165f595fac869b98582a9f66448d/event/configuration.py -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | from PyQt5.QtWidgets import QApplication, QMainWindow 4 | 5 | from event import event 6 | 7 | if __name__ == '__main__': 8 | app = QApplication(sys.argv) 9 | MainWindow = QMainWindow() 10 | ui = event.Event(MainWindow) 11 | MainWindow.show() 12 | sys.exit(app.exec_()) 13 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | PyQt5==5.15.10 2 | PyQt5-Qt5==5.15.2 3 | PyQt5-sip==12.13.0 4 | -------------------------------------------------------------------------------- /test_file/ecc_private_key.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/morsuning/cryptography-gui-tool/7e0d58655f6f165f595fac869b98582a9f66448d/test_file/ecc_private_key.txt -------------------------------------------------------------------------------- /test_file/key_export.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/morsuning/cryptography-gui-tool/7e0d58655f6f165f595fac869b98582a9f66448d/test_file/key_export.txt -------------------------------------------------------------------------------- /test_file/key_import.txt: -------------------------------------------------------------------------------- 1 | hello -------------------------------------------------------------------------------- /test_file/rsa_private_key.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/morsuning/cryptography-gui-tool/7e0d58655f6f165f595fac869b98582a9f66448d/test_file/rsa_private_key.txt -------------------------------------------------------------------------------- /test_file/to_encrypt_test.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/morsuning/cryptography-gui-tool/7e0d58655f6f165f595fac869b98582a9f66448d/test_file/to_encrypt_test.docx -------------------------------------------------------------------------------- /test_file/to_encrypt_test.txt: -------------------------------------------------------------------------------- 1 | test --------------------------------------------------------------------------------