├── LICENSE ├── Main.cpp ├── Mnemonic_C++.entitlements ├── Mnemonic_C++.sln ├── Mnemonic_C++.vcxproj ├── Mnemonic_C++.vcxproj.filters ├── Mnemonic_C++.vcxproj.user ├── Mnemonic_C++.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcshareddata │ │ └── IDEWorkspaceChecks.plist │ └── xcuserdata │ │ └── xopmc.xcuserdatad │ │ └── UserInterfaceState.xcuserstate ├── xcshareddata │ └── xcschemes │ │ └── Mnemonic_C++.xcscheme └── xcuserdata │ └── xopmc.xcuserdatad │ └── xcschemes │ └── xcschememanagement.plist ├── README.md ├── add_scalar.c ├── dict.hpp ├── ed25519.h ├── fe.c ├── fe.h ├── fixedint.h ├── ge.c ├── ge.h ├── install_openssl_macos.sh ├── key_exchange.c ├── keypair.c ├── makefile ├── precomp_data.h ├── sc.c ├── sc.h ├── seed.c ├── sha512.c ├── sha512.h ├── sign.c └── verify.c /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Михаил Х. (XopMC) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Main.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XopMC/Mnemonic_CPP/4127df062974bbb7d6ca1b15bf7d5e59d4d282e4/Main.cpp -------------------------------------------------------------------------------- /Mnemonic_C++.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.cs.allow-unsigned-executable-memory 6 | 7 | com.apple.security.cs.disable-library-validation 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Mnemonic_C++.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.7.34018.315 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Mnemonic_C++", "Mnemonic_C++.vcxproj", "{D56F6A13-D091-42BF-B20D-A46ADF85D961}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {D56F6A13-D091-42BF-B20D-A46ADF85D961}.Debug|x64.ActiveCfg = Debug|x64 17 | {D56F6A13-D091-42BF-B20D-A46ADF85D961}.Debug|x64.Build.0 = Debug|x64 18 | {D56F6A13-D091-42BF-B20D-A46ADF85D961}.Debug|x86.ActiveCfg = Debug|Win32 19 | {D56F6A13-D091-42BF-B20D-A46ADF85D961}.Debug|x86.Build.0 = Debug|Win32 20 | {D56F6A13-D091-42BF-B20D-A46ADF85D961}.Release|x64.ActiveCfg = Release|x64 21 | {D56F6A13-D091-42BF-B20D-A46ADF85D961}.Release|x64.Build.0 = Release|x64 22 | {D56F6A13-D091-42BF-B20D-A46ADF85D961}.Release|x86.ActiveCfg = Release|Win32 23 | {D56F6A13-D091-42BF-B20D-A46ADF85D961}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {EF49F77C-86BE-4409-A950-A352315DAE52} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /Mnemonic_C++.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 17.0 23 | Win32Proj 24 | {d56f6a13-d091-42bf-b20d-a46adf85d961} 25 | Mnemonic_C++ 26 | 10.0 27 | MnemonicC 28 | 29 | 30 | 31 | Application 32 | true 33 | v143 34 | Unicode 35 | 36 | 37 | Application 38 | false 39 | v143 40 | true 41 | Unicode 42 | 43 | 44 | Application 45 | true 46 | v143 47 | Unicode 48 | 49 | 50 | Application 51 | false 52 | v143 53 | true 54 | Unicode 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | false 76 | 77 | 78 | 79 | Level3 80 | true 81 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 82 | true 83 | 84 | 85 | Console 86 | true 87 | 88 | 89 | 90 | 91 | Level3 92 | true 93 | true 94 | true 95 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 96 | true 97 | 98 | 99 | Console 100 | true 101 | true 102 | true 103 | 104 | 105 | 106 | 107 | Level3 108 | true 109 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 110 | true 111 | Default 112 | stdc11 113 | MaxSpeed 114 | Speed 115 | true 116 | None 117 | Default 118 | 119 | 120 | Console 121 | true 122 | UseLinkTimeCodeGeneration 123 | 124 | 125 | 126 | 127 | Level3 128 | true 129 | true 130 | true 131 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 132 | true 133 | Speed 134 | MultiThreaded 135 | Default 136 | -march=native %(AdditionalOptions) 137 | Default 138 | 139 | 140 | Console 141 | true 142 | true 143 | true 144 | true 145 | $(CoreLibraryDependencies);Ws2_32.lib;Crypt32.lib;%(AdditionalDependencies) 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | -------------------------------------------------------------------------------- /Mnemonic_C++.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Исходные файлы 20 | 21 | 22 | Исходные файлы 23 | 24 | 25 | Исходные файлы 26 | 27 | 28 | Исходные файлы 29 | 30 | 31 | Исходные файлы 32 | 33 | 34 | Исходные файлы 35 | 36 | 37 | Исходные файлы 38 | 39 | 40 | Исходные файлы 41 | 42 | 43 | Исходные файлы 44 | 45 | 46 | Исходные файлы 47 | 48 | 49 | Исходные файлы 50 | 51 | 52 | 53 | 54 | Файлы заголовков 55 | 56 | 57 | Файлы заголовков 58 | 59 | 60 | Файлы заголовков 61 | 62 | 63 | Файлы заголовков 64 | 65 | 66 | Файлы заголовков 67 | 68 | 69 | Файлы заголовков 70 | 71 | 72 | Файлы заголовков 73 | 74 | 75 | Файлы заголовков 76 | 77 | 78 | -------------------------------------------------------------------------------- /Mnemonic_C++.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /Mnemonic_C++.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Mnemonic_C++.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Mnemonic_C++.xcodeproj/project.xcworkspace/xcuserdata/xopmc.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XopMC/Mnemonic_CPP/4127df062974bbb7d6ca1b15bf7d5e59d4d282e4/Mnemonic_C++.xcodeproj/project.xcworkspace/xcuserdata/xopmc.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /Mnemonic_C++.xcodeproj/xcshareddata/xcschemes/Mnemonic_C++.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 9 | 10 | 16 | 22 | 23 | 24 | 25 | 26 | 32 | 33 | 44 | 46 | 52 | 53 | 54 | 55 | 61 | 63 | 69 | 70 | 71 | 72 | 74 | 75 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /Mnemonic_C++.xcodeproj/xcuserdata/xopmc.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | Mnemonic_C++.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | CCD9F7E02BFBF5920011BF89 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Mnemonic_CPP 2 | Tool for Working with Mnemonics THIS TOOL IS INTENDED SOLELY FOR TESTING THE SECURITY OF YOUR OWN MNEMONICS AND/OR IDENTIFYING OTHER VULNERABILITIES TO ENSURE SECURE ACCESS TO CRYPTOCURRENCIES. THE PRODUCT IS PROVIDED "AS IS". 3 | # Donation: 4 | ETH: 0xDE85c1Ef7874A1D94578f11332e8fa9A6a0eE853 5 | BTC: bc1q063pks7ex93eka56zyumvutdt6zs9dj959pe9p 6 | LTC: ltc1qysumht4lxafwvmcu4ruxzuztc2xmj8tz986fmm 7 | TRX: TTZ3oL16BVNzU46MSJvaoKYAhvtwdTUcnz 8 | TON: UQC7eqLN_NlVz82YzsjzAo4iOzKjH3t095-CMtqTJ5aoqo0l 9 | DOT: 1jen89F5v6TbdQsRaKxsCqhNp9qAdeHeZyEUWjgrM8mW6hs 10 | ADA: addr1qx7qrlcy37xe7j58hjxmyhyqfgu0ppeqxzs43dayjjcgde973lzxgtgqzxdvfq3rswmngapc4sp528dpzfg7huam8v9san7h6z 11 | DASH: Xms41jaD967XMf2FAfEwGUxYKKhYQuok9T 12 | SOLANA: BvDQDEgq3kbNT7VQFQRQPjc4Ta5k7d5s7GdcgoKnq3KG 13 | 14 | # ENG 15 | ## 26.05.2024 - version 1.0.0 16 | ✅ Implemented mnemonic functionality in C++ 17 | ✅ Most operations are custom-written (except for hmac and pbkdf2, as the OpenSSL library showed better performance, so it was retained) 18 | ✅ Added support for Bloom filters (same type as used by brainflayer) 19 | ✅ Integrated with external generators and files containing mnemonics or entropy 20 | ✅ Fully implemented SLIP-0010 (for secp256k1 and ed25519 curves) - https://slips.readthedocs.io/en/latest/slip-0010/ 21 | ✅ Support for the ed25519 curve and Solana cryptocurrency in particular 22 | ✅ Support for invalid mnemonics and custom derivation paths 23 | ✅ Capability to generate mnemonics using a custom 2048-word dictionary 24 | ✅ Ability to save found hashes directly as cryptocurrency addresses 25 | ✅ Built-in fast and cryptographically secure entropy generator, fetching bytes from the processor (verified through testing various generators for quality and speed of generated values) 26 | ✅ Code adapted for 3 systems: Linux, Windows, OSX (MacOS) - added projects for Visual Studio, Xcode, Makefile (for Linux) 27 | 28 | ## Launch Argument Description: 29 | `-h` -- Displays help 30 | `-b file.blf` -- Bloom filter, can specify multiple files using `-b file.blf -b file2.blf ... -b file99.blf` 31 | `-d file.txt` -- Load derivation paths from file 32 | `-deep number` -- Derivation depth (optional if the derivation file contains full paths) 33 | `-c mode` -- Select hash search modes, multiple can be specified, e.g., `-c cuse` or `-c eS` 34 | u - uncompressed address 35 | c - compressed address 36 | s - segwit address 37 | e - ethereum address 38 | x - x coordinate (20-byte public key) 39 | S - Solana address 40 | `-custom file.txt` -- Specify your own 2048-word dictionary (one word per line, does not work with the `-lang` parameter) 41 | `-in` -- Use an external generator or file with mnemonics or entropy 42 | ________________________________________________________________________________ 43 | (These parameters work only with `-in`) 44 | `-f file.txt` -- Read from file 45 | `-entropy` -- Indicates that the input stream is entropy (works with `-lang` and `-custom`) 46 | `-n` -- Additionally adds the step value to the incoming entropy the specified number of times 47 | `-step` -- Step for `-n`, can be negative, default is 1 48 | For example, if we specify `-in -f ent.txt -entropy -n 10 -step 16`, and the file ent.txt contains this entropy - `00000000`, the program will check all these entropies: 49 | `00000000`, `00000010`, `00000020`, `00000030`, `00000040`, `00000050`, `00000060`, `00000070`, `00000080`, `00000090`, `00000100` 50 | ________________________________________________________________________________ 51 | 52 | `-lang language` (EN, CT, CS, KO, JA, IT, FR, SP) | Languages for mnemonics - 53 | English, ChineseTraditional, ChineseSimplified, Korean, Japanese, Italian, French, Spanish 54 | `-t number` -- Number of threads 55 | `-o file.txt` -- Save found results to the specified file 56 | `-save` -- Save found hashes as addresses 57 | `-w number of words` -- 3, 6, 9, 12, 15, 18, 21, 24 ... 48 - Number of words for mnemonic generator (default is 12) 58 | # Download builds 59 | - https://github.com/XopMC/Mnemonic_CPP/releases/tag/v.1.0.0 60 | # Building from Source 61 | Download builds - https://github.com/XopMC/Mnemonic_CPP/releases/tag/v.1.0.0 62 | The release on GitHub already includes builds for 3 systems, but if you need to build it yourself, here are the steps: 63 | ## Windows Build 64 | The files already contain a Visual Studio project - you just need to install the OpenSSL library for a successful build (this can be done using VCPKG) 65 | ## OSX (MacOS) Build 66 | The files already include a ready-to-use Xcode project, but the OpenSSL library is required. 67 | To install it, I've added a script `install_openssl_macos.sh` - running it will install homebrew and OpenSSL 68 | ## Linux Build 69 | The files already include a Makefile, which can be run with the command `make` 70 | Library installation is required, which can be done with `sudo apt install gcc g++ make openssl libssl-dev` 71 | 72 | # Examples of Running in Different Modes 73 | 1) The program requires a derivation file to run, it will not start without it. 74 | No hard-coded derivations, only custom ones. 75 | The file must contain full derivations starting with m/ 76 | Example: 77 | ![image](https://github.com/XopMC/Mnemonic_CPP/assets/89750173/6ddc74ed-5e09-4749-ad66-794b5c0b9bfb) 78 | 79 | 2) Bloom filters containing hashes for search are required. 80 | To create them, in the GitHub Release menu for each system, I've included these programs: 81 | `base58-bech32_to_hash160` -- Program for converting different types of addresses into a 20-byte hash, tested on BTC, BCH, Tron, ETH, LTC addresses - other currencies need testing 82 | `Solana_to_hex` -- Converts Solana addresses into a 20-byte public key 83 | `hex_to_bloom` -- Creates Bloom filters from the specified file with hashes. The program itself will split the file into the necessary number of Bloom filters, controlled by the `-capacity` parameter - I recommend not setting more than 38000000, which is the number of hashes in one Bloom filter 84 | ![image](https://github.com/XopMC/Mnemonic_CPP/assets/89750173/44dc06d9-25f8-4085-bfec-fe50d46c5bca) 85 | 86 | 3) Example of generating 12 random words: 87 | `MnemonicC.exe -c cus -d der.txt -b btc.blf -b btc_2.blf -w 12 -t 8` 88 | where `-c cus` -- search for Compressed, Uncompressed, and Segwit hashes 89 | `-d der.txt` -- derivation file 90 | `-b btc.blf -b btc_2.blf` -- Bloom filters 91 | `-w 12` -- number of words to generate 92 | `-t 8` -- use 8 processor threads 93 | 94 | ![image](https://github.com/XopMC/Mnemonic_CPP/assets/89750173/f1e27eb5-e5ec-4f1d-b868-61c4395d0e40) 95 | 96 | 4) Example of running with an external mnemonic generator: 97 | `Generator.exe | MnemonicC.exe -c cus -d der.txt -b btc.blf -b btc_2.blf -t 8 -in` 98 | where `-in` -- indicates working with an external generator 99 | 100 | ![image](https://github.com/XopMC/Mnemonic_CPP/assets/89750173/27a2292d-c813-41a0-83ef-9ff0df05f134) 101 | 102 | 5) Example of running from a file, with found results displayed 103 | `MnemonicC.exe -c cus -d der.txt -b btc.blf -b btc_2.blf -t 8 -in -f file.txt` 104 | where `-f file.txt` -- file with mnemonics 105 | Adding the `-save` parameter will save hashes as addresses 106 | 107 | ![image](https://github.com/XopMC/Mnemonic_CPP/assets/89750173/9481c73c-48db-4326-959d-9552122a72d2) 108 | 109 | For Ethereum and Solana respectively 110 | 111 | ![image](https://github.com/XopMC/Mnemonic_CPP/assets/89750173/45d5e30e-97c7-4e18-a93c-37a88e6f92c2) 112 | 113 | 6) Entropy mode 114 | `MnemonicC.exe -c cusexS -d der.txt -b bloom.blf -in -f test.txt -entropy -n 5 -step 1` 115 | ![image](https://github.com/XopMC/Mnemonic_CPP/assets/89750173/89c4cb2f-ac5a-490b-86a2-ffa016ddc0f3) 116 | 117 | 7) Custom dictionary + entropy mode 118 | `MnemonicC.exe -c cusexS -d der.txt -b bloom.blf -in -f test.txt -entropy -n 5 -step 1 -custom rus.txt` 119 | 120 | ![image](https://github.com/XopMC/Mnemonic_CPP/assets/89750173/959f954f-6937-4ef6-9a82-3445263ec4d5) 121 | 122 | # For Lucky Owners of AMD Threadripper Processors 123 | The program can work with all cores and threads, it's important that the processor is unlocked in the BIOS, i.e., it can use more power than stock settings 124 | Example on Threadripper PRO 7995WX 125 | ![image](https://github.com/XopMC/Mnemonic_CPP/assets/89750173/f3bb9a04-93a7-47e3-ab2e-6d4eea6f30f5) 126 | ![image](https://github.com/XopMC/Mnemonic_CPP/assets/89750173/50adc5d6-00cc-493c-adb1-fe180d3d9052) 127 | # RUS 128 | ## 26.05.2024 - version 1.0.0 129 | ✅ Релизована работа с мнемоникой на языке C++ 130 | ✅ Практически всё операции самописные (за исключением hmac и pbkdf2, почему-то либа OpenSSL показала лучший результат нежели своя реализация, поэтому оставил эту либу) 131 | ✅ Реализована поддежрка блюмфильтов (того-же типа, что использует brainflayer) 132 | ✅ Работа с внешними генераторами и файлами с мнемониками или энтропиями 133 | ✅ Рабочая реализация SLIP-0010 (для кривых secp256k1 и ed25519) - https://slips.readthedocs.io/en/latest/slip-0010/ 134 | ✅ Поддержка кривой ed25519 и криптовалюты Solana в частности 135 | ✅ Поддержка невалидных мнемоник и кастомных путей деривации 136 | ✅ Возможность генерации мнемоники по кастомному словарю 2048 слов 137 | ✅ Возможность сохранения найденных хешей сразу в виде адресов криптовалют 138 | ✅ Встроенный в программу генератор энтропии, быстрый и криптостойкий, дергающий байты с процессора (сделаный методом проверки, я действительно брал разные генераторы и проверял на качество сгенерированных значений и скорость генерации) 139 | ✅ Код адаптирован сразу под 3 системы: Linux, Windows, OSX(MacOS) - добавлены проекты Visual Studio, Xcode, Makefile(для Linux) 140 | 141 | ## Описани аргументов запуска: 142 | `-h` -- Показывает справку 143 | `-b file.blf` -- Блюмфильтр, можно указывать несколько - `-b file.blf -b file2.blf ... -b file99.blf` 144 | `-d файл.txt` -- загрузка путей деривации из файла 145 | `-deep число` -- Глубина деривации (не обязательно использовать, если в файле с деривациями указаны полные пути) 146 | `-c режим` -- выбор режимов для поиска хэшей, можно указывать сразу несколько, например `-c cuse` или `-c eS` 147 | u - uncompressed address 148 | c - compressed address 149 | s - segwit address 150 | e - ethereum address 151 | x - x coordinate (20-байт публичного ключа) 152 | S - Solana address 153 | `-custom файл.txt` -- Указание своего словаря из 2048 слов (каждое слово с новой строки, не работает с параметром `-lang`) 154 | `-in` -- Использование внешнего генератора или файла с мнемониками или энтропией 155 | ________________________________________________________________________________ 156 | (Эти параметры работают только с `-in` ) 157 | `-f файл.txt` -- Чтение из файла 158 | `-entropy` -- Указывает что входной поток это энтропия (работает с `-lang` и с `-custom`) 159 | `-n` -- Дополнительно прибавляет шаг step к пришедшей энтропии указанное количество раз 160 | `-step` -- Шаг для `-n`, может быть отрицательным, по умолчанию - 1 161 | То есть, если мы укажем `-in -f ent.txt -entropy -n 10 -step 16`, и файл ent.txt будет содеражать такую энтропию - `00000000`, то программа проверит все эти энтропии: 162 | `00000000`, `00000010`, `00000020`, `00000030`, `00000040`, `00000050`, `00000060`, `00000070`, `00000080`, `00000090`, `00000100` 163 | ________________________________________________________________________________ 164 | 165 | `-lang язык` (EN, CT, CS, KO, JA, IT, FR, SP) | Языки для мнемоники - 166 | English, ChineseTraditional, ChineseSimplified, Korean , Japanese, Italian, French, Spanish 167 | `-t число` -- Количество потоков 168 | `-o файл.txt` -- Сохранение найденого в указанный файл 169 | `-save` -- Сохранение найденых хэшей в виде адресов 170 | `-w кол-во слов` -- 3, 6, 9, 12, 15, 18, 21, 24 ... 48 - Количество слов для генератора мнемоники (По стандарту 12) 171 | # Скачать готовые сборки 172 | - https://github.com/XopMC/Mnemonic_CPP/releases/tag/v.1.0.0 173 | # Сборка из исходников 174 | В Release на GitHub уже есть сборки для 3-х систем, однако если вам нужно собрать самостоятельно, то вот шаги действий для этого: 175 | ## Windows сборка 176 | В файлах уже находится проект для Visual Studio - вам нужно лишь установить библиотеку OpenSSL для успешной сборки (сделать это можно с помощью VCPKG) 177 | ## OSX(MacOS) сборка 178 | В файлах уже лежит готовый проект для Xcode, однако требуется библиотека OpenSSL 179 | Для её установки я добавил скрипт `install_openssl_macos.sh` - запустив который вы установите homebrew и OpenSSL 180 | ## Linux сборка 181 | В файлах уже лежит Makefile, который можно запустить командой `make` 182 | Требуется установка библиотек, можно установить так - `sudo apt install gcc g++ make openssl libssl-dev` 183 | 184 | # Примеры запуска для некоторых режимов 185 | 1) Программа обязательно требует файл с деривациями, без него не будет запуска 186 | Никаких зашитых в коде дериваций, только кастом 187 | В файле должны быть полные деривации, начиная с m/ 188 | Пример: 189 | ![image](https://github.com/XopMC/Mnemonic_CPP/assets/89750173/6ddc74ed-5e09-4749-ad66-794b5c0b9bfb) 190 | 191 | 2) Обязательно требуются блюмфильтры, содержащие хэши для поиска 192 | Для того, что-бы их сделать, в меню Release GitHub для каждой системы я собрал эти программы: 193 | `base58-bech32_to_hash160` -- Программа для преобразования разных типов адресов в 20-байт хэш, проверял на адресах BTC, BCH, Tron, ETH, LTC - другие валюты нужно тестировать 194 | `Solana_to_hex` -- Преобразует адреса соланы в 20-байт публичного ключа 195 | `hex_to_bloom` -- создает блюмфильтры из указанного файла с хэшами. Программа сама разделит файл на нужное кол-во блюмфильтров, управляется параметром `-capacity` - рекомендую не ставить более 38000000, это количество хэшей в одном блюме 196 | ![image](https://github.com/XopMC/Mnemonic_CPP/assets/89750173/44dc06d9-25f8-4085-bfec-fe50d46c5bca) 197 | 198 | 199 | 3) Пример запуска рандомной генерации 12 слов: 200 | `MnemonicC.exe -c cus -d der.txt -b btc.blf -b btc_2.blf -w 12 -t 8` 201 | где `-c cus` -- поиск Compressed, Uncompressed и Segwit хэшей 202 | `-d der.txt` -- файл с деривациями 203 | `-b btc.blf -b btc_2.blf` -- блюмфильтры 204 | `-w 12` -- количество слов для генерации 205 | `-t 8` -- Использование 8 потоков процессора 206 | 207 | ![image](https://github.com/XopMC/Mnemonic_CPP/assets/89750173/f1e27eb5-e5ec-4f1d-b868-61c4395d0e40) 208 | 209 | 4) Пример запуска со сторонним генератором мнемоник: 210 | `Generator.exe | MnemonicC.exe -c cus -d der.txt -b btc.blf -b btc_2.blf -t 8 -in` 211 | где `in` -- указание работы с внешним генератором 212 | 213 | ![image](https://github.com/XopMC/Mnemonic_CPP/assets/89750173/27a2292d-c813-41a0-83ef-9ff0df05f134) 214 | 215 | 5) Пример запуска из файла, с отображением найденного 216 | `MnemonicC.exe -c cus -d der.txt -b btc.blf -b btc_2.blf -t 8 -in -f file.txt` 217 | где `-f file.txt` -- файл с мнемониками 218 | А добавление параметра `save` будет сохранять хэши в виде адресов 219 | 220 | ![image](https://github.com/XopMC/Mnemonic_CPP/assets/89750173/9481c73c-48db-4326-959d-9552122a72d2) 221 | 222 | Для Эфира и Соланы соответственно 223 | 224 | ![image](https://github.com/XopMC/Mnemonic_CPP/assets/89750173/45d5e30e-97c7-4e18-a93c-37a88e6f92c2) 225 | 226 | 6) режим энтропии 227 | `MnemonicC.exe -c cusexS -d der.txt -b bloom.blf -in -f test.txt -entropy -n 5 -step 1` 228 | ![image](https://github.com/XopMC/Mnemonic_CPP/assets/89750173/89c4cb2f-ac5a-490b-86a2-ffa016ddc0f3) 229 | 230 | 7) свой словарь + режим энтропии 231 | `MnemonicC.exe -c cusexS -d der.txt -b bloom.blf -in -f test.txt -entropy -n 5 -step 1 -custom rus.txt` 232 | 233 | ![image](https://github.com/XopMC/Mnemonic_CPP/assets/89750173/959f954f-6937-4ef6-9a82-3445263ec4d5) 234 | 235 | # Для счастливых обладателей процессоров AMD Threadripper 236 | Программа умеет работать со всеми ядрами и потоками, важно что-бы сам процессор в БИОС был разблокирован, т.е. мог использовать больше мощности, чем в стоке 237 | Пример на Threadripper PRO 7995WX 238 | ![image](https://github.com/XopMC/Mnemonic_CPP/assets/89750173/f3bb9a04-93a7-47e3-ab2e-6d4eea6f30f5) 239 | ![image](https://github.com/XopMC/Mnemonic_CPP/assets/89750173/50adc5d6-00cc-493c-adb1-fe180d3d9052) 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | -------------------------------------------------------------------------------- /add_scalar.c: -------------------------------------------------------------------------------- 1 | #include "ed25519.h" 2 | #include "ge.h" 3 | #include "sc.h" 4 | #include "sha512.h" 5 | void ed25519_add_scalar(unsigned char *public_key, unsigned char *private_key, const unsigned char *scalar) { 6 | const unsigned char SC_1[32] = {1}; 7 | 8 | unsigned char n[32]; 9 | ge_p3 nB; 10 | ge_p1p1 A_p1p1; 11 | ge_p3 A; 12 | ge_p3 public_key_unpacked; 13 | ge_cached T; 14 | 15 | sha512_context hash; 16 | unsigned char hashbuf[64]; 17 | 18 | int i; 19 | 20 | 21 | for (i = 0; i < 31; ++i) { 22 | n[i] = scalar[i]; 23 | } 24 | n[31] = scalar[31] & 127; 25 | 26 | 27 | if (private_key) { 28 | sc_muladd(private_key, SC_1, n, private_key); 29 | 30 | sha512_init(&hash); 31 | sha512_update(&hash, private_key + 32, 32); 32 | sha512_update(&hash, scalar, 32); 33 | sha512_final(&hash, hashbuf); 34 | for (i = 0; i < 32; ++i) { 35 | private_key[32 + i] = hashbuf[i]; 36 | } 37 | } 38 | 39 | 40 | if (public_key) { 41 | 42 | /* using a "timing attack" you could find out wether or not we know the private 43 | key, but this information seems rather useless - if this is important pass 44 | public_key and private_key seperately in 2 function calls */ 45 | if (private_key) { 46 | ge_scalarmult_base(&A, private_key); 47 | } else { 48 | 49 | ge_frombytes_negate_vartime(&public_key_unpacked, public_key); 50 | fe_neg(public_key_unpacked.X, public_key_unpacked.X); 51 | fe_neg(public_key_unpacked.T, public_key_unpacked.T); 52 | ge_p3_to_cached(&T, &public_key_unpacked); 53 | 54 | 55 | ge_scalarmult_base(&nB, n); 56 | 57 | 58 | ge_add(&A_p1p1, &nB, &T); 59 | ge_p1p1_to_p3(&A, &A_p1p1); 60 | } 61 | 62 | 63 | ge_p3_tobytes(public_key, &A); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /ed25519.h: -------------------------------------------------------------------------------- 1 | #ifndef ED25519_H 2 | #define ED25519_H 3 | 4 | #include 5 | 6 | #if defined(_WIN32) 7 | #if defined(ED25519_BUILD_DLL) 8 | #define ED25519_DECLSPEC __declspec(dllexport) 9 | #elif defined(ED25519_DLL) 10 | #define ED25519_DECLSPEC __declspec(dllimport) 11 | #else 12 | #define ED25519_DECLSPEC 13 | #endif 14 | #else 15 | #define ED25519_DECLSPEC 16 | #endif 17 | 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | #ifndef ED25519_NO_SEED 24 | int ED25519_DECLSPEC ed25519_create_seed(unsigned char *seed); 25 | #endif 26 | 27 | void ED25519_DECLSPEC ed25519_create_keypair(unsigned char *public_key, unsigned char *private_key, const unsigned char *seed); 28 | void ED25519_DECLSPEC ed25519_sign(unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key, const unsigned char *private_key); 29 | int ED25519_DECLSPEC ed25519_verify(const unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key); 30 | void ED25519_DECLSPEC ed25519_add_scalar(unsigned char *public_key, unsigned char *private_key, const unsigned char *scalar); 31 | void ED25519_DECLSPEC ed25519_key_exchange(unsigned char *shared_secret, const unsigned char *public_key, const unsigned char *private_key); 32 | 33 | 34 | #ifdef __cplusplus 35 | } 36 | #endif 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /fe.c: -------------------------------------------------------------------------------- 1 | #include "fixedint.h" 2 | #include "fe.h" 3 | 4 | 5 | /* 6 | helper functions 7 | */ 8 | static uint64_t load_3(const unsigned char *in) { 9 | uint64_t result; 10 | 11 | result = (uint64_t) in[0]; 12 | result |= ((uint64_t) in[1]) << 8; 13 | result |= ((uint64_t) in[2]) << 16; 14 | 15 | return result; 16 | } 17 | 18 | static uint64_t load_4(const unsigned char *in) { 19 | uint64_t result; 20 | 21 | result = (uint64_t) in[0]; 22 | result |= ((uint64_t) in[1]) << 8; 23 | result |= ((uint64_t) in[2]) << 16; 24 | result |= ((uint64_t) in[3]) << 24; 25 | 26 | return result; 27 | } 28 | 29 | 30 | 31 | /* 32 | h = 0 33 | */ 34 | 35 | void fe_0(fe h) { 36 | h[0] = 0; 37 | h[1] = 0; 38 | h[2] = 0; 39 | h[3] = 0; 40 | h[4] = 0; 41 | h[5] = 0; 42 | h[6] = 0; 43 | h[7] = 0; 44 | h[8] = 0; 45 | h[9] = 0; 46 | } 47 | 48 | 49 | 50 | /* 51 | h = 1 52 | */ 53 | 54 | void fe_1(fe h) { 55 | h[0] = 1; 56 | h[1] = 0; 57 | h[2] = 0; 58 | h[3] = 0; 59 | h[4] = 0; 60 | h[5] = 0; 61 | h[6] = 0; 62 | h[7] = 0; 63 | h[8] = 0; 64 | h[9] = 0; 65 | } 66 | 67 | 68 | 69 | /* 70 | h = f + g 71 | Can overlap h with f or g. 72 | 73 | Preconditions: 74 | |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. 75 | |g| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. 76 | 77 | Postconditions: 78 | |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. 79 | */ 80 | 81 | void fe_add(fe h, const fe f, const fe g) { 82 | int32_t f0 = f[0]; 83 | int32_t f1 = f[1]; 84 | int32_t f2 = f[2]; 85 | int32_t f3 = f[3]; 86 | int32_t f4 = f[4]; 87 | int32_t f5 = f[5]; 88 | int32_t f6 = f[6]; 89 | int32_t f7 = f[7]; 90 | int32_t f8 = f[8]; 91 | int32_t f9 = f[9]; 92 | int32_t g0 = g[0]; 93 | int32_t g1 = g[1]; 94 | int32_t g2 = g[2]; 95 | int32_t g3 = g[3]; 96 | int32_t g4 = g[4]; 97 | int32_t g5 = g[5]; 98 | int32_t g6 = g[6]; 99 | int32_t g7 = g[7]; 100 | int32_t g8 = g[8]; 101 | int32_t g9 = g[9]; 102 | int32_t h0 = f0 + g0; 103 | int32_t h1 = f1 + g1; 104 | int32_t h2 = f2 + g2; 105 | int32_t h3 = f3 + g3; 106 | int32_t h4 = f4 + g4; 107 | int32_t h5 = f5 + g5; 108 | int32_t h6 = f6 + g6; 109 | int32_t h7 = f7 + g7; 110 | int32_t h8 = f8 + g8; 111 | int32_t h9 = f9 + g9; 112 | 113 | h[0] = h0; 114 | h[1] = h1; 115 | h[2] = h2; 116 | h[3] = h3; 117 | h[4] = h4; 118 | h[5] = h5; 119 | h[6] = h6; 120 | h[7] = h7; 121 | h[8] = h8; 122 | h[9] = h9; 123 | } 124 | 125 | 126 | 127 | /* 128 | Replace (f,g) with (g,g) if b == 1; 129 | replace (f,g) with (f,g) if b == 0. 130 | 131 | Preconditions: b in {0,1}. 132 | */ 133 | 134 | void fe_cmov(fe f, const fe g, unsigned int b) { 135 | int32_t f0 = f[0]; 136 | int32_t f1 = f[1]; 137 | int32_t f2 = f[2]; 138 | int32_t f3 = f[3]; 139 | int32_t f4 = f[4]; 140 | int32_t f5 = f[5]; 141 | int32_t f6 = f[6]; 142 | int32_t f7 = f[7]; 143 | int32_t f8 = f[8]; 144 | int32_t f9 = f[9]; 145 | int32_t g0 = g[0]; 146 | int32_t g1 = g[1]; 147 | int32_t g2 = g[2]; 148 | int32_t g3 = g[3]; 149 | int32_t g4 = g[4]; 150 | int32_t g5 = g[5]; 151 | int32_t g6 = g[6]; 152 | int32_t g7 = g[7]; 153 | int32_t g8 = g[8]; 154 | int32_t g9 = g[9]; 155 | int32_t x0 = f0 ^ g0; 156 | int32_t x1 = f1 ^ g1; 157 | int32_t x2 = f2 ^ g2; 158 | int32_t x3 = f3 ^ g3; 159 | int32_t x4 = f4 ^ g4; 160 | int32_t x5 = f5 ^ g5; 161 | int32_t x6 = f6 ^ g6; 162 | int32_t x7 = f7 ^ g7; 163 | int32_t x8 = f8 ^ g8; 164 | int32_t x9 = f9 ^ g9; 165 | 166 | b = (unsigned int) (- (int) b); 167 | x0 &= b; 168 | x1 &= b; 169 | x2 &= b; 170 | x3 &= b; 171 | x4 &= b; 172 | x5 &= b; 173 | x6 &= b; 174 | x7 &= b; 175 | x8 &= b; 176 | x9 &= b; 177 | 178 | f[0] = f0 ^ x0; 179 | f[1] = f1 ^ x1; 180 | f[2] = f2 ^ x2; 181 | f[3] = f3 ^ x3; 182 | f[4] = f4 ^ x4; 183 | f[5] = f5 ^ x5; 184 | f[6] = f6 ^ x6; 185 | f[7] = f7 ^ x7; 186 | f[8] = f8 ^ x8; 187 | f[9] = f9 ^ x9; 188 | } 189 | 190 | /* 191 | Replace (f,g) with (g,f) if b == 1; 192 | replace (f,g) with (f,g) if b == 0. 193 | 194 | Preconditions: b in {0,1}. 195 | */ 196 | 197 | void fe_cswap(fe f,fe g,unsigned int b) { 198 | int32_t f0 = f[0]; 199 | int32_t f1 = f[1]; 200 | int32_t f2 = f[2]; 201 | int32_t f3 = f[3]; 202 | int32_t f4 = f[4]; 203 | int32_t f5 = f[5]; 204 | int32_t f6 = f[6]; 205 | int32_t f7 = f[7]; 206 | int32_t f8 = f[8]; 207 | int32_t f9 = f[9]; 208 | int32_t g0 = g[0]; 209 | int32_t g1 = g[1]; 210 | int32_t g2 = g[2]; 211 | int32_t g3 = g[3]; 212 | int32_t g4 = g[4]; 213 | int32_t g5 = g[5]; 214 | int32_t g6 = g[6]; 215 | int32_t g7 = g[7]; 216 | int32_t g8 = g[8]; 217 | int32_t g9 = g[9]; 218 | int32_t x0 = f0 ^ g0; 219 | int32_t x1 = f1 ^ g1; 220 | int32_t x2 = f2 ^ g2; 221 | int32_t x3 = f3 ^ g3; 222 | int32_t x4 = f4 ^ g4; 223 | int32_t x5 = f5 ^ g5; 224 | int32_t x6 = f6 ^ g6; 225 | int32_t x7 = f7 ^ g7; 226 | int32_t x8 = f8 ^ g8; 227 | int32_t x9 = f9 ^ g9; 228 | b = (unsigned int) (- (int) b); 229 | x0 &= b; 230 | x1 &= b; 231 | x2 &= b; 232 | x3 &= b; 233 | x4 &= b; 234 | x5 &= b; 235 | x6 &= b; 236 | x7 &= b; 237 | x8 &= b; 238 | x9 &= b; 239 | f[0] = f0 ^ x0; 240 | f[1] = f1 ^ x1; 241 | f[2] = f2 ^ x2; 242 | f[3] = f3 ^ x3; 243 | f[4] = f4 ^ x4; 244 | f[5] = f5 ^ x5; 245 | f[6] = f6 ^ x6; 246 | f[7] = f7 ^ x7; 247 | f[8] = f8 ^ x8; 248 | f[9] = f9 ^ x9; 249 | g[0] = g0 ^ x0; 250 | g[1] = g1 ^ x1; 251 | g[2] = g2 ^ x2; 252 | g[3] = g3 ^ x3; 253 | g[4] = g4 ^ x4; 254 | g[5] = g5 ^ x5; 255 | g[6] = g6 ^ x6; 256 | g[7] = g7 ^ x7; 257 | g[8] = g8 ^ x8; 258 | g[9] = g9 ^ x9; 259 | } 260 | 261 | 262 | 263 | /* 264 | h = f 265 | */ 266 | 267 | void fe_copy(fe h, const fe f) { 268 | int32_t f0 = f[0]; 269 | int32_t f1 = f[1]; 270 | int32_t f2 = f[2]; 271 | int32_t f3 = f[3]; 272 | int32_t f4 = f[4]; 273 | int32_t f5 = f[5]; 274 | int32_t f6 = f[6]; 275 | int32_t f7 = f[7]; 276 | int32_t f8 = f[8]; 277 | int32_t f9 = f[9]; 278 | 279 | h[0] = f0; 280 | h[1] = f1; 281 | h[2] = f2; 282 | h[3] = f3; 283 | h[4] = f4; 284 | h[5] = f5; 285 | h[6] = f6; 286 | h[7] = f7; 287 | h[8] = f8; 288 | h[9] = f9; 289 | } 290 | 291 | 292 | 293 | /* 294 | Ignores top bit of h. 295 | */ 296 | 297 | void fe_frombytes(fe h, const unsigned char *s) { 298 | int64_t h0 = load_4(s); 299 | int64_t h1 = load_3(s + 4) << 6; 300 | int64_t h2 = load_3(s + 7) << 5; 301 | int64_t h3 = load_3(s + 10) << 3; 302 | int64_t h4 = load_3(s + 13) << 2; 303 | int64_t h5 = load_4(s + 16); 304 | int64_t h6 = load_3(s + 20) << 7; 305 | int64_t h7 = load_3(s + 23) << 5; 306 | int64_t h8 = load_3(s + 26) << 4; 307 | int64_t h9 = (load_3(s + 29) & 8388607) << 2; 308 | int64_t carry0; 309 | int64_t carry1; 310 | int64_t carry2; 311 | int64_t carry3; 312 | int64_t carry4; 313 | int64_t carry5; 314 | int64_t carry6; 315 | int64_t carry7; 316 | int64_t carry8; 317 | int64_t carry9; 318 | 319 | carry9 = (h9 + (int64_t) (1 << 24)) >> 25; 320 | h0 += carry9 * 19; 321 | h9 -= carry9 << 25; 322 | carry1 = (h1 + (int64_t) (1 << 24)) >> 25; 323 | h2 += carry1; 324 | h1 -= carry1 << 25; 325 | carry3 = (h3 + (int64_t) (1 << 24)) >> 25; 326 | h4 += carry3; 327 | h3 -= carry3 << 25; 328 | carry5 = (h5 + (int64_t) (1 << 24)) >> 25; 329 | h6 += carry5; 330 | h5 -= carry5 << 25; 331 | carry7 = (h7 + (int64_t) (1 << 24)) >> 25; 332 | h8 += carry7; 333 | h7 -= carry7 << 25; 334 | carry0 = (h0 + (int64_t) (1 << 25)) >> 26; 335 | h1 += carry0; 336 | h0 -= carry0 << 26; 337 | carry2 = (h2 + (int64_t) (1 << 25)) >> 26; 338 | h3 += carry2; 339 | h2 -= carry2 << 26; 340 | carry4 = (h4 + (int64_t) (1 << 25)) >> 26; 341 | h5 += carry4; 342 | h4 -= carry4 << 26; 343 | carry6 = (h6 + (int64_t) (1 << 25)) >> 26; 344 | h7 += carry6; 345 | h6 -= carry6 << 26; 346 | carry8 = (h8 + (int64_t) (1 << 25)) >> 26; 347 | h9 += carry8; 348 | h8 -= carry8 << 26; 349 | 350 | h[0] = (int32_t) h0; 351 | h[1] = (int32_t) h1; 352 | h[2] = (int32_t) h2; 353 | h[3] = (int32_t) h3; 354 | h[4] = (int32_t) h4; 355 | h[5] = (int32_t) h5; 356 | h[6] = (int32_t) h6; 357 | h[7] = (int32_t) h7; 358 | h[8] = (int32_t) h8; 359 | h[9] = (int32_t) h9; 360 | } 361 | 362 | 363 | 364 | void fe_invert(fe out, const fe z) { 365 | fe t0; 366 | fe t1; 367 | fe t2; 368 | fe t3; 369 | int i; 370 | 371 | fe_sq(t0, z); 372 | 373 | for (i = 1; i < 1; ++i) { 374 | fe_sq(t0, t0); 375 | } 376 | 377 | fe_sq(t1, t0); 378 | 379 | for (i = 1; i < 2; ++i) { 380 | fe_sq(t1, t1); 381 | } 382 | 383 | fe_mul(t1, z, t1); 384 | fe_mul(t0, t0, t1); 385 | fe_sq(t2, t0); 386 | 387 | for (i = 1; i < 1; ++i) { 388 | fe_sq(t2, t2); 389 | } 390 | 391 | fe_mul(t1, t1, t2); 392 | fe_sq(t2, t1); 393 | 394 | for (i = 1; i < 5; ++i) { 395 | fe_sq(t2, t2); 396 | } 397 | 398 | fe_mul(t1, t2, t1); 399 | fe_sq(t2, t1); 400 | 401 | for (i = 1; i < 10; ++i) { 402 | fe_sq(t2, t2); 403 | } 404 | 405 | fe_mul(t2, t2, t1); 406 | fe_sq(t3, t2); 407 | 408 | for (i = 1; i < 20; ++i) { 409 | fe_sq(t3, t3); 410 | } 411 | 412 | fe_mul(t2, t3, t2); 413 | fe_sq(t2, t2); 414 | 415 | for (i = 1; i < 10; ++i) { 416 | fe_sq(t2, t2); 417 | } 418 | 419 | fe_mul(t1, t2, t1); 420 | fe_sq(t2, t1); 421 | 422 | for (i = 1; i < 50; ++i) { 423 | fe_sq(t2, t2); 424 | } 425 | 426 | fe_mul(t2, t2, t1); 427 | fe_sq(t3, t2); 428 | 429 | for (i = 1; i < 100; ++i) { 430 | fe_sq(t3, t3); 431 | } 432 | 433 | fe_mul(t2, t3, t2); 434 | fe_sq(t2, t2); 435 | 436 | for (i = 1; i < 50; ++i) { 437 | fe_sq(t2, t2); 438 | } 439 | 440 | fe_mul(t1, t2, t1); 441 | fe_sq(t1, t1); 442 | 443 | for (i = 1; i < 5; ++i) { 444 | fe_sq(t1, t1); 445 | } 446 | 447 | fe_mul(out, t1, t0); 448 | } 449 | 450 | 451 | 452 | /* 453 | return 1 if f is in {1,3,5,...,q-2} 454 | return 0 if f is in {0,2,4,...,q-1} 455 | 456 | Preconditions: 457 | |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. 458 | */ 459 | 460 | int fe_isnegative(const fe f) { 461 | unsigned char s[32]; 462 | 463 | fe_tobytes(s, f); 464 | 465 | return s[0] & 1; 466 | } 467 | 468 | 469 | 470 | /* 471 | return 1 if f == 0 472 | return 0 if f != 0 473 | 474 | Preconditions: 475 | |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. 476 | */ 477 | 478 | int fe_isnonzero(const fe f) { 479 | unsigned char s[32]; 480 | unsigned char r; 481 | 482 | fe_tobytes(s, f); 483 | 484 | r = s[0]; 485 | #define F(i) r |= s[i] 486 | F(1); 487 | F(2); 488 | F(3); 489 | F(4); 490 | F(5); 491 | F(6); 492 | F(7); 493 | F(8); 494 | F(9); 495 | F(10); 496 | F(11); 497 | F(12); 498 | F(13); 499 | F(14); 500 | F(15); 501 | F(16); 502 | F(17); 503 | F(18); 504 | F(19); 505 | F(20); 506 | F(21); 507 | F(22); 508 | F(23); 509 | F(24); 510 | F(25); 511 | F(26); 512 | F(27); 513 | F(28); 514 | F(29); 515 | F(30); 516 | F(31); 517 | #undef F 518 | 519 | return r != 0; 520 | } 521 | 522 | 523 | 524 | /* 525 | h = f * g 526 | Can overlap h with f or g. 527 | 528 | Preconditions: 529 | |f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc. 530 | |g| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc. 531 | 532 | Postconditions: 533 | |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc. 534 | */ 535 | 536 | /* 537 | Notes on implementation strategy: 538 | 539 | Using schoolbook multiplication. 540 | Karatsuba would save a little in some cost models. 541 | 542 | Most multiplications by 2 and 19 are 32-bit precomputations; 543 | cheaper than 64-bit postcomputations. 544 | 545 | There is one remaining multiplication by 19 in the carry chain; 546 | one *19 precomputation can be merged into this, 547 | but the resulting data flow is considerably less clean. 548 | 549 | There are 12 carries below. 550 | 10 of them are 2-way parallelizable and vectorizable. 551 | Can get away with 11 carries, but then data flow is much deeper. 552 | 553 | With tighter constraints on inputs can squeeze carries into int32. 554 | */ 555 | 556 | void fe_mul(fe h, const fe f, const fe g) { 557 | int32_t f0 = f[0]; 558 | int32_t f1 = f[1]; 559 | int32_t f2 = f[2]; 560 | int32_t f3 = f[3]; 561 | int32_t f4 = f[4]; 562 | int32_t f5 = f[5]; 563 | int32_t f6 = f[6]; 564 | int32_t f7 = f[7]; 565 | int32_t f8 = f[8]; 566 | int32_t f9 = f[9]; 567 | int32_t g0 = g[0]; 568 | int32_t g1 = g[1]; 569 | int32_t g2 = g[2]; 570 | int32_t g3 = g[3]; 571 | int32_t g4 = g[4]; 572 | int32_t g5 = g[5]; 573 | int32_t g6 = g[6]; 574 | int32_t g7 = g[7]; 575 | int32_t g8 = g[8]; 576 | int32_t g9 = g[9]; 577 | int32_t g1_19 = 19 * g1; 578 | int32_t g2_19 = 19 * g2; 579 | int32_t g3_19 = 19 * g3; 580 | int32_t g4_19 = 19 * g4; 581 | int32_t g5_19 = 19 * g5; 582 | int32_t g6_19 = 19 * g6; 583 | int32_t g7_19 = 19 * g7; 584 | int32_t g8_19 = 19 * g8; 585 | int32_t g9_19 = 19 * g9; 586 | int32_t f1_2 = 2 * f1; 587 | int32_t f3_2 = 2 * f3; 588 | int32_t f5_2 = 2 * f5; 589 | int32_t f7_2 = 2 * f7; 590 | int32_t f9_2 = 2 * f9; 591 | int64_t f0g0 = f0 * (int64_t) g0; 592 | int64_t f0g1 = f0 * (int64_t) g1; 593 | int64_t f0g2 = f0 * (int64_t) g2; 594 | int64_t f0g3 = f0 * (int64_t) g3; 595 | int64_t f0g4 = f0 * (int64_t) g4; 596 | int64_t f0g5 = f0 * (int64_t) g5; 597 | int64_t f0g6 = f0 * (int64_t) g6; 598 | int64_t f0g7 = f0 * (int64_t) g7; 599 | int64_t f0g8 = f0 * (int64_t) g8; 600 | int64_t f0g9 = f0 * (int64_t) g9; 601 | int64_t f1g0 = f1 * (int64_t) g0; 602 | int64_t f1g1_2 = f1_2 * (int64_t) g1; 603 | int64_t f1g2 = f1 * (int64_t) g2; 604 | int64_t f1g3_2 = f1_2 * (int64_t) g3; 605 | int64_t f1g4 = f1 * (int64_t) g4; 606 | int64_t f1g5_2 = f1_2 * (int64_t) g5; 607 | int64_t f1g6 = f1 * (int64_t) g6; 608 | int64_t f1g7_2 = f1_2 * (int64_t) g7; 609 | int64_t f1g8 = f1 * (int64_t) g8; 610 | int64_t f1g9_38 = f1_2 * (int64_t) g9_19; 611 | int64_t f2g0 = f2 * (int64_t) g0; 612 | int64_t f2g1 = f2 * (int64_t) g1; 613 | int64_t f2g2 = f2 * (int64_t) g2; 614 | int64_t f2g3 = f2 * (int64_t) g3; 615 | int64_t f2g4 = f2 * (int64_t) g4; 616 | int64_t f2g5 = f2 * (int64_t) g5; 617 | int64_t f2g6 = f2 * (int64_t) g6; 618 | int64_t f2g7 = f2 * (int64_t) g7; 619 | int64_t f2g8_19 = f2 * (int64_t) g8_19; 620 | int64_t f2g9_19 = f2 * (int64_t) g9_19; 621 | int64_t f3g0 = f3 * (int64_t) g0; 622 | int64_t f3g1_2 = f3_2 * (int64_t) g1; 623 | int64_t f3g2 = f3 * (int64_t) g2; 624 | int64_t f3g3_2 = f3_2 * (int64_t) g3; 625 | int64_t f3g4 = f3 * (int64_t) g4; 626 | int64_t f3g5_2 = f3_2 * (int64_t) g5; 627 | int64_t f3g6 = f3 * (int64_t) g6; 628 | int64_t f3g7_38 = f3_2 * (int64_t) g7_19; 629 | int64_t f3g8_19 = f3 * (int64_t) g8_19; 630 | int64_t f3g9_38 = f3_2 * (int64_t) g9_19; 631 | int64_t f4g0 = f4 * (int64_t) g0; 632 | int64_t f4g1 = f4 * (int64_t) g1; 633 | int64_t f4g2 = f4 * (int64_t) g2; 634 | int64_t f4g3 = f4 * (int64_t) g3; 635 | int64_t f4g4 = f4 * (int64_t) g4; 636 | int64_t f4g5 = f4 * (int64_t) g5; 637 | int64_t f4g6_19 = f4 * (int64_t) g6_19; 638 | int64_t f4g7_19 = f4 * (int64_t) g7_19; 639 | int64_t f4g8_19 = f4 * (int64_t) g8_19; 640 | int64_t f4g9_19 = f4 * (int64_t) g9_19; 641 | int64_t f5g0 = f5 * (int64_t) g0; 642 | int64_t f5g1_2 = f5_2 * (int64_t) g1; 643 | int64_t f5g2 = f5 * (int64_t) g2; 644 | int64_t f5g3_2 = f5_2 * (int64_t) g3; 645 | int64_t f5g4 = f5 * (int64_t) g4; 646 | int64_t f5g5_38 = f5_2 * (int64_t) g5_19; 647 | int64_t f5g6_19 = f5 * (int64_t) g6_19; 648 | int64_t f5g7_38 = f5_2 * (int64_t) g7_19; 649 | int64_t f5g8_19 = f5 * (int64_t) g8_19; 650 | int64_t f5g9_38 = f5_2 * (int64_t) g9_19; 651 | int64_t f6g0 = f6 * (int64_t) g0; 652 | int64_t f6g1 = f6 * (int64_t) g1; 653 | int64_t f6g2 = f6 * (int64_t) g2; 654 | int64_t f6g3 = f6 * (int64_t) g3; 655 | int64_t f6g4_19 = f6 * (int64_t) g4_19; 656 | int64_t f6g5_19 = f6 * (int64_t) g5_19; 657 | int64_t f6g6_19 = f6 * (int64_t) g6_19; 658 | int64_t f6g7_19 = f6 * (int64_t) g7_19; 659 | int64_t f6g8_19 = f6 * (int64_t) g8_19; 660 | int64_t f6g9_19 = f6 * (int64_t) g9_19; 661 | int64_t f7g0 = f7 * (int64_t) g0; 662 | int64_t f7g1_2 = f7_2 * (int64_t) g1; 663 | int64_t f7g2 = f7 * (int64_t) g2; 664 | int64_t f7g3_38 = f7_2 * (int64_t) g3_19; 665 | int64_t f7g4_19 = f7 * (int64_t) g4_19; 666 | int64_t f7g5_38 = f7_2 * (int64_t) g5_19; 667 | int64_t f7g6_19 = f7 * (int64_t) g6_19; 668 | int64_t f7g7_38 = f7_2 * (int64_t) g7_19; 669 | int64_t f7g8_19 = f7 * (int64_t) g8_19; 670 | int64_t f7g9_38 = f7_2 * (int64_t) g9_19; 671 | int64_t f8g0 = f8 * (int64_t) g0; 672 | int64_t f8g1 = f8 * (int64_t) g1; 673 | int64_t f8g2_19 = f8 * (int64_t) g2_19; 674 | int64_t f8g3_19 = f8 * (int64_t) g3_19; 675 | int64_t f8g4_19 = f8 * (int64_t) g4_19; 676 | int64_t f8g5_19 = f8 * (int64_t) g5_19; 677 | int64_t f8g6_19 = f8 * (int64_t) g6_19; 678 | int64_t f8g7_19 = f8 * (int64_t) g7_19; 679 | int64_t f8g8_19 = f8 * (int64_t) g8_19; 680 | int64_t f8g9_19 = f8 * (int64_t) g9_19; 681 | int64_t f9g0 = f9 * (int64_t) g0; 682 | int64_t f9g1_38 = f9_2 * (int64_t) g1_19; 683 | int64_t f9g2_19 = f9 * (int64_t) g2_19; 684 | int64_t f9g3_38 = f9_2 * (int64_t) g3_19; 685 | int64_t f9g4_19 = f9 * (int64_t) g4_19; 686 | int64_t f9g5_38 = f9_2 * (int64_t) g5_19; 687 | int64_t f9g6_19 = f9 * (int64_t) g6_19; 688 | int64_t f9g7_38 = f9_2 * (int64_t) g7_19; 689 | int64_t f9g8_19 = f9 * (int64_t) g8_19; 690 | int64_t f9g9_38 = f9_2 * (int64_t) g9_19; 691 | int64_t h0 = f0g0 + f1g9_38 + f2g8_19 + f3g7_38 + f4g6_19 + f5g5_38 + f6g4_19 + f7g3_38 + f8g2_19 + f9g1_38; 692 | int64_t h1 = f0g1 + f1g0 + f2g9_19 + f3g8_19 + f4g7_19 + f5g6_19 + f6g5_19 + f7g4_19 + f8g3_19 + f9g2_19; 693 | int64_t h2 = f0g2 + f1g1_2 + f2g0 + f3g9_38 + f4g8_19 + f5g7_38 + f6g6_19 + f7g5_38 + f8g4_19 + f9g3_38; 694 | int64_t h3 = f0g3 + f1g2 + f2g1 + f3g0 + f4g9_19 + f5g8_19 + f6g7_19 + f7g6_19 + f8g5_19 + f9g4_19; 695 | int64_t h4 = f0g4 + f1g3_2 + f2g2 + f3g1_2 + f4g0 + f5g9_38 + f6g8_19 + f7g7_38 + f8g6_19 + f9g5_38; 696 | int64_t h5 = f0g5 + f1g4 + f2g3 + f3g2 + f4g1 + f5g0 + f6g9_19 + f7g8_19 + f8g7_19 + f9g6_19; 697 | int64_t h6 = f0g6 + f1g5_2 + f2g4 + f3g3_2 + f4g2 + f5g1_2 + f6g0 + f7g9_38 + f8g8_19 + f9g7_38; 698 | int64_t h7 = f0g7 + f1g6 + f2g5 + f3g4 + f4g3 + f5g2 + f6g1 + f7g0 + f8g9_19 + f9g8_19; 699 | int64_t h8 = f0g8 + f1g7_2 + f2g6 + f3g5_2 + f4g4 + f5g3_2 + f6g2 + f7g1_2 + f8g0 + f9g9_38; 700 | int64_t h9 = f0g9 + f1g8 + f2g7 + f3g6 + f4g5 + f5g4 + f6g3 + f7g2 + f8g1 + f9g0 ; 701 | int64_t carry0; 702 | int64_t carry1; 703 | int64_t carry2; 704 | int64_t carry3; 705 | int64_t carry4; 706 | int64_t carry5; 707 | int64_t carry6; 708 | int64_t carry7; 709 | int64_t carry8; 710 | int64_t carry9; 711 | 712 | carry0 = (h0 + (int64_t) (1 << 25)) >> 26; 713 | h1 += carry0; 714 | h0 -= carry0 << 26; 715 | carry4 = (h4 + (int64_t) (1 << 25)) >> 26; 716 | h5 += carry4; 717 | h4 -= carry4 << 26; 718 | 719 | carry1 = (h1 + (int64_t) (1 << 24)) >> 25; 720 | h2 += carry1; 721 | h1 -= carry1 << 25; 722 | carry5 = (h5 + (int64_t) (1 << 24)) >> 25; 723 | h6 += carry5; 724 | h5 -= carry5 << 25; 725 | 726 | carry2 = (h2 + (int64_t) (1 << 25)) >> 26; 727 | h3 += carry2; 728 | h2 -= carry2 << 26; 729 | carry6 = (h6 + (int64_t) (1 << 25)) >> 26; 730 | h7 += carry6; 731 | h6 -= carry6 << 26; 732 | 733 | carry3 = (h3 + (int64_t) (1 << 24)) >> 25; 734 | h4 += carry3; 735 | h3 -= carry3 << 25; 736 | carry7 = (h7 + (int64_t) (1 << 24)) >> 25; 737 | h8 += carry7; 738 | h7 -= carry7 << 25; 739 | 740 | carry4 = (h4 + (int64_t) (1 << 25)) >> 26; 741 | h5 += carry4; 742 | h4 -= carry4 << 26; 743 | carry8 = (h8 + (int64_t) (1 << 25)) >> 26; 744 | h9 += carry8; 745 | h8 -= carry8 << 26; 746 | 747 | carry9 = (h9 + (int64_t) (1 << 24)) >> 25; 748 | h0 += carry9 * 19; 749 | h9 -= carry9 << 25; 750 | 751 | carry0 = (h0 + (int64_t) (1 << 25)) >> 26; 752 | h1 += carry0; 753 | h0 -= carry0 << 26; 754 | 755 | h[0] = (int32_t) h0; 756 | h[1] = (int32_t) h1; 757 | h[2] = (int32_t) h2; 758 | h[3] = (int32_t) h3; 759 | h[4] = (int32_t) h4; 760 | h[5] = (int32_t) h5; 761 | h[6] = (int32_t) h6; 762 | h[7] = (int32_t) h7; 763 | h[8] = (int32_t) h8; 764 | h[9] = (int32_t) h9; 765 | } 766 | 767 | 768 | /* 769 | h = f * 121666 770 | Can overlap h with f. 771 | 772 | Preconditions: 773 | |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. 774 | 775 | Postconditions: 776 | |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. 777 | */ 778 | 779 | void fe_mul121666(fe h, fe f) { 780 | int32_t f0 = f[0]; 781 | int32_t f1 = f[1]; 782 | int32_t f2 = f[2]; 783 | int32_t f3 = f[3]; 784 | int32_t f4 = f[4]; 785 | int32_t f5 = f[5]; 786 | int32_t f6 = f[6]; 787 | int32_t f7 = f[7]; 788 | int32_t f8 = f[8]; 789 | int32_t f9 = f[9]; 790 | int64_t h0 = f0 * (int64_t) 121666; 791 | int64_t h1 = f1 * (int64_t) 121666; 792 | int64_t h2 = f2 * (int64_t) 121666; 793 | int64_t h3 = f3 * (int64_t) 121666; 794 | int64_t h4 = f4 * (int64_t) 121666; 795 | int64_t h5 = f5 * (int64_t) 121666; 796 | int64_t h6 = f6 * (int64_t) 121666; 797 | int64_t h7 = f7 * (int64_t) 121666; 798 | int64_t h8 = f8 * (int64_t) 121666; 799 | int64_t h9 = f9 * (int64_t) 121666; 800 | int64_t carry0; 801 | int64_t carry1; 802 | int64_t carry2; 803 | int64_t carry3; 804 | int64_t carry4; 805 | int64_t carry5; 806 | int64_t carry6; 807 | int64_t carry7; 808 | int64_t carry8; 809 | int64_t carry9; 810 | 811 | carry9 = (h9 + (int64_t) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25; 812 | carry1 = (h1 + (int64_t) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25; 813 | carry3 = (h3 + (int64_t) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25; 814 | carry5 = (h5 + (int64_t) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25; 815 | carry7 = (h7 + (int64_t) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25; 816 | 817 | carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; 818 | carry2 = (h2 + (int64_t) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26; 819 | carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; 820 | carry6 = (h6 + (int64_t) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26; 821 | carry8 = (h8 + (int64_t) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26; 822 | 823 | h[0] = (int32_t) h0; 824 | h[1] = (int32_t) h1; 825 | h[2] = (int32_t) h2; 826 | h[3] = (int32_t) h3; 827 | h[4] = (int32_t) h4; 828 | h[5] = (int32_t) h5; 829 | h[6] = (int32_t) h6; 830 | h[7] = (int32_t) h7; 831 | h[8] = (int32_t) h8; 832 | h[9] = (int32_t) h9; 833 | } 834 | 835 | 836 | /* 837 | h = -f 838 | 839 | Preconditions: 840 | |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. 841 | 842 | Postconditions: 843 | |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. 844 | */ 845 | 846 | void fe_neg(fe h, const fe f) { 847 | int32_t f0 = f[0]; 848 | int32_t f1 = f[1]; 849 | int32_t f2 = f[2]; 850 | int32_t f3 = f[3]; 851 | int32_t f4 = f[4]; 852 | int32_t f5 = f[5]; 853 | int32_t f6 = f[6]; 854 | int32_t f7 = f[7]; 855 | int32_t f8 = f[8]; 856 | int32_t f9 = f[9]; 857 | int32_t h0 = -f0; 858 | int32_t h1 = -f1; 859 | int32_t h2 = -f2; 860 | int32_t h3 = -f3; 861 | int32_t h4 = -f4; 862 | int32_t h5 = -f5; 863 | int32_t h6 = -f6; 864 | int32_t h7 = -f7; 865 | int32_t h8 = -f8; 866 | int32_t h9 = -f9; 867 | 868 | h[0] = h0; 869 | h[1] = h1; 870 | h[2] = h2; 871 | h[3] = h3; 872 | h[4] = h4; 873 | h[5] = h5; 874 | h[6] = h6; 875 | h[7] = h7; 876 | h[8] = h8; 877 | h[9] = h9; 878 | } 879 | 880 | 881 | void fe_pow22523(fe out, const fe z) { 882 | fe t0; 883 | fe t1; 884 | fe t2; 885 | int i; 886 | fe_sq(t0, z); 887 | 888 | for (i = 1; i < 1; ++i) { 889 | fe_sq(t0, t0); 890 | } 891 | 892 | fe_sq(t1, t0); 893 | 894 | for (i = 1; i < 2; ++i) { 895 | fe_sq(t1, t1); 896 | } 897 | 898 | fe_mul(t1, z, t1); 899 | fe_mul(t0, t0, t1); 900 | fe_sq(t0, t0); 901 | 902 | for (i = 1; i < 1; ++i) { 903 | fe_sq(t0, t0); 904 | } 905 | 906 | fe_mul(t0, t1, t0); 907 | fe_sq(t1, t0); 908 | 909 | for (i = 1; i < 5; ++i) { 910 | fe_sq(t1, t1); 911 | } 912 | 913 | fe_mul(t0, t1, t0); 914 | fe_sq(t1, t0); 915 | 916 | for (i = 1; i < 10; ++i) { 917 | fe_sq(t1, t1); 918 | } 919 | 920 | fe_mul(t1, t1, t0); 921 | fe_sq(t2, t1); 922 | 923 | for (i = 1; i < 20; ++i) { 924 | fe_sq(t2, t2); 925 | } 926 | 927 | fe_mul(t1, t2, t1); 928 | fe_sq(t1, t1); 929 | 930 | for (i = 1; i < 10; ++i) { 931 | fe_sq(t1, t1); 932 | } 933 | 934 | fe_mul(t0, t1, t0); 935 | fe_sq(t1, t0); 936 | 937 | for (i = 1; i < 50; ++i) { 938 | fe_sq(t1, t1); 939 | } 940 | 941 | fe_mul(t1, t1, t0); 942 | fe_sq(t2, t1); 943 | 944 | for (i = 1; i < 100; ++i) { 945 | fe_sq(t2, t2); 946 | } 947 | 948 | fe_mul(t1, t2, t1); 949 | fe_sq(t1, t1); 950 | 951 | for (i = 1; i < 50; ++i) { 952 | fe_sq(t1, t1); 953 | } 954 | 955 | fe_mul(t0, t1, t0); 956 | fe_sq(t0, t0); 957 | 958 | for (i = 1; i < 2; ++i) { 959 | fe_sq(t0, t0); 960 | } 961 | 962 | fe_mul(out, t0, z); 963 | return; 964 | } 965 | 966 | 967 | /* 968 | h = f * f 969 | Can overlap h with f. 970 | 971 | Preconditions: 972 | |f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc. 973 | 974 | Postconditions: 975 | |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc. 976 | */ 977 | 978 | /* 979 | See fe_mul.c for discussion of implementation strategy. 980 | */ 981 | 982 | void fe_sq(fe h, const fe f) { 983 | int32_t f0 = f[0]; 984 | int32_t f1 = f[1]; 985 | int32_t f2 = f[2]; 986 | int32_t f3 = f[3]; 987 | int32_t f4 = f[4]; 988 | int32_t f5 = f[5]; 989 | int32_t f6 = f[6]; 990 | int32_t f7 = f[7]; 991 | int32_t f8 = f[8]; 992 | int32_t f9 = f[9]; 993 | int32_t f0_2 = 2 * f0; 994 | int32_t f1_2 = 2 * f1; 995 | int32_t f2_2 = 2 * f2; 996 | int32_t f3_2 = 2 * f3; 997 | int32_t f4_2 = 2 * f4; 998 | int32_t f5_2 = 2 * f5; 999 | int32_t f6_2 = 2 * f6; 1000 | int32_t f7_2 = 2 * f7; 1001 | int32_t f5_38 = 38 * f5; 1002 | int32_t f6_19 = 19 * f6; 1003 | int32_t f7_38 = 38 * f7; 1004 | int32_t f8_19 = 19 * f8; 1005 | int32_t f9_38 = 38 * f9; 1006 | int64_t f0f0 = f0 * (int64_t) f0; 1007 | int64_t f0f1_2 = f0_2 * (int64_t) f1; 1008 | int64_t f0f2_2 = f0_2 * (int64_t) f2; 1009 | int64_t f0f3_2 = f0_2 * (int64_t) f3; 1010 | int64_t f0f4_2 = f0_2 * (int64_t) f4; 1011 | int64_t f0f5_2 = f0_2 * (int64_t) f5; 1012 | int64_t f0f6_2 = f0_2 * (int64_t) f6; 1013 | int64_t f0f7_2 = f0_2 * (int64_t) f7; 1014 | int64_t f0f8_2 = f0_2 * (int64_t) f8; 1015 | int64_t f0f9_2 = f0_2 * (int64_t) f9; 1016 | int64_t f1f1_2 = f1_2 * (int64_t) f1; 1017 | int64_t f1f2_2 = f1_2 * (int64_t) f2; 1018 | int64_t f1f3_4 = f1_2 * (int64_t) f3_2; 1019 | int64_t f1f4_2 = f1_2 * (int64_t) f4; 1020 | int64_t f1f5_4 = f1_2 * (int64_t) f5_2; 1021 | int64_t f1f6_2 = f1_2 * (int64_t) f6; 1022 | int64_t f1f7_4 = f1_2 * (int64_t) f7_2; 1023 | int64_t f1f8_2 = f1_2 * (int64_t) f8; 1024 | int64_t f1f9_76 = f1_2 * (int64_t) f9_38; 1025 | int64_t f2f2 = f2 * (int64_t) f2; 1026 | int64_t f2f3_2 = f2_2 * (int64_t) f3; 1027 | int64_t f2f4_2 = f2_2 * (int64_t) f4; 1028 | int64_t f2f5_2 = f2_2 * (int64_t) f5; 1029 | int64_t f2f6_2 = f2_2 * (int64_t) f6; 1030 | int64_t f2f7_2 = f2_2 * (int64_t) f7; 1031 | int64_t f2f8_38 = f2_2 * (int64_t) f8_19; 1032 | int64_t f2f9_38 = f2 * (int64_t) f9_38; 1033 | int64_t f3f3_2 = f3_2 * (int64_t) f3; 1034 | int64_t f3f4_2 = f3_2 * (int64_t) f4; 1035 | int64_t f3f5_4 = f3_2 * (int64_t) f5_2; 1036 | int64_t f3f6_2 = f3_2 * (int64_t) f6; 1037 | int64_t f3f7_76 = f3_2 * (int64_t) f7_38; 1038 | int64_t f3f8_38 = f3_2 * (int64_t) f8_19; 1039 | int64_t f3f9_76 = f3_2 * (int64_t) f9_38; 1040 | int64_t f4f4 = f4 * (int64_t) f4; 1041 | int64_t f4f5_2 = f4_2 * (int64_t) f5; 1042 | int64_t f4f6_38 = f4_2 * (int64_t) f6_19; 1043 | int64_t f4f7_38 = f4 * (int64_t) f7_38; 1044 | int64_t f4f8_38 = f4_2 * (int64_t) f8_19; 1045 | int64_t f4f9_38 = f4 * (int64_t) f9_38; 1046 | int64_t f5f5_38 = f5 * (int64_t) f5_38; 1047 | int64_t f5f6_38 = f5_2 * (int64_t) f6_19; 1048 | int64_t f5f7_76 = f5_2 * (int64_t) f7_38; 1049 | int64_t f5f8_38 = f5_2 * (int64_t) f8_19; 1050 | int64_t f5f9_76 = f5_2 * (int64_t) f9_38; 1051 | int64_t f6f6_19 = f6 * (int64_t) f6_19; 1052 | int64_t f6f7_38 = f6 * (int64_t) f7_38; 1053 | int64_t f6f8_38 = f6_2 * (int64_t) f8_19; 1054 | int64_t f6f9_38 = f6 * (int64_t) f9_38; 1055 | int64_t f7f7_38 = f7 * (int64_t) f7_38; 1056 | int64_t f7f8_38 = f7_2 * (int64_t) f8_19; 1057 | int64_t f7f9_76 = f7_2 * (int64_t) f9_38; 1058 | int64_t f8f8_19 = f8 * (int64_t) f8_19; 1059 | int64_t f8f9_38 = f8 * (int64_t) f9_38; 1060 | int64_t f9f9_38 = f9 * (int64_t) f9_38; 1061 | int64_t h0 = f0f0 + f1f9_76 + f2f8_38 + f3f7_76 + f4f6_38 + f5f5_38; 1062 | int64_t h1 = f0f1_2 + f2f9_38 + f3f8_38 + f4f7_38 + f5f6_38; 1063 | int64_t h2 = f0f2_2 + f1f1_2 + f3f9_76 + f4f8_38 + f5f7_76 + f6f6_19; 1064 | int64_t h3 = f0f3_2 + f1f2_2 + f4f9_38 + f5f8_38 + f6f7_38; 1065 | int64_t h4 = f0f4_2 + f1f3_4 + f2f2 + f5f9_76 + f6f8_38 + f7f7_38; 1066 | int64_t h5 = f0f5_2 + f1f4_2 + f2f3_2 + f6f9_38 + f7f8_38; 1067 | int64_t h6 = f0f6_2 + f1f5_4 + f2f4_2 + f3f3_2 + f7f9_76 + f8f8_19; 1068 | int64_t h7 = f0f7_2 + f1f6_2 + f2f5_2 + f3f4_2 + f8f9_38; 1069 | int64_t h8 = f0f8_2 + f1f7_4 + f2f6_2 + f3f5_4 + f4f4 + f9f9_38; 1070 | int64_t h9 = f0f9_2 + f1f8_2 + f2f7_2 + f3f6_2 + f4f5_2; 1071 | int64_t carry0; 1072 | int64_t carry1; 1073 | int64_t carry2; 1074 | int64_t carry3; 1075 | int64_t carry4; 1076 | int64_t carry5; 1077 | int64_t carry6; 1078 | int64_t carry7; 1079 | int64_t carry8; 1080 | int64_t carry9; 1081 | carry0 = (h0 + (int64_t) (1 << 25)) >> 26; 1082 | h1 += carry0; 1083 | h0 -= carry0 << 26; 1084 | carry4 = (h4 + (int64_t) (1 << 25)) >> 26; 1085 | h5 += carry4; 1086 | h4 -= carry4 << 26; 1087 | carry1 = (h1 + (int64_t) (1 << 24)) >> 25; 1088 | h2 += carry1; 1089 | h1 -= carry1 << 25; 1090 | carry5 = (h5 + (int64_t) (1 << 24)) >> 25; 1091 | h6 += carry5; 1092 | h5 -= carry5 << 25; 1093 | carry2 = (h2 + (int64_t) (1 << 25)) >> 26; 1094 | h3 += carry2; 1095 | h2 -= carry2 << 26; 1096 | carry6 = (h6 + (int64_t) (1 << 25)) >> 26; 1097 | h7 += carry6; 1098 | h6 -= carry6 << 26; 1099 | carry3 = (h3 + (int64_t) (1 << 24)) >> 25; 1100 | h4 += carry3; 1101 | h3 -= carry3 << 25; 1102 | carry7 = (h7 + (int64_t) (1 << 24)) >> 25; 1103 | h8 += carry7; 1104 | h7 -= carry7 << 25; 1105 | carry4 = (h4 + (int64_t) (1 << 25)) >> 26; 1106 | h5 += carry4; 1107 | h4 -= carry4 << 26; 1108 | carry8 = (h8 + (int64_t) (1 << 25)) >> 26; 1109 | h9 += carry8; 1110 | h8 -= carry8 << 26; 1111 | carry9 = (h9 + (int64_t) (1 << 24)) >> 25; 1112 | h0 += carry9 * 19; 1113 | h9 -= carry9 << 25; 1114 | carry0 = (h0 + (int64_t) (1 << 25)) >> 26; 1115 | h1 += carry0; 1116 | h0 -= carry0 << 26; 1117 | h[0] = (int32_t) h0; 1118 | h[1] = (int32_t) h1; 1119 | h[2] = (int32_t) h2; 1120 | h[3] = (int32_t) h3; 1121 | h[4] = (int32_t) h4; 1122 | h[5] = (int32_t) h5; 1123 | h[6] = (int32_t) h6; 1124 | h[7] = (int32_t) h7; 1125 | h[8] = (int32_t) h8; 1126 | h[9] = (int32_t) h9; 1127 | } 1128 | 1129 | 1130 | /* 1131 | h = 2 * f * f 1132 | Can overlap h with f. 1133 | 1134 | Preconditions: 1135 | |f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc. 1136 | 1137 | Postconditions: 1138 | |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc. 1139 | */ 1140 | 1141 | /* 1142 | See fe_mul.c for discussion of implementation strategy. 1143 | */ 1144 | 1145 | void fe_sq2(fe h, const fe f) { 1146 | int32_t f0 = f[0]; 1147 | int32_t f1 = f[1]; 1148 | int32_t f2 = f[2]; 1149 | int32_t f3 = f[3]; 1150 | int32_t f4 = f[4]; 1151 | int32_t f5 = f[5]; 1152 | int32_t f6 = f[6]; 1153 | int32_t f7 = f[7]; 1154 | int32_t f8 = f[8]; 1155 | int32_t f9 = f[9]; 1156 | int32_t f0_2 = 2 * f0; 1157 | int32_t f1_2 = 2 * f1; 1158 | int32_t f2_2 = 2 * f2; 1159 | int32_t f3_2 = 2 * f3; 1160 | int32_t f4_2 = 2 * f4; 1161 | int32_t f5_2 = 2 * f5; 1162 | int32_t f6_2 = 2 * f6; 1163 | int32_t f7_2 = 2 * f7; 1164 | int32_t f5_38 = 38 * f5; 1165 | int32_t f6_19 = 19 * f6; 1166 | int32_t f7_38 = 38 * f7; 1167 | int32_t f8_19 = 19 * f8; 1168 | int32_t f9_38 = 38 * f9; 1169 | int64_t f0f0 = f0 * (int64_t) f0; 1170 | int64_t f0f1_2 = f0_2 * (int64_t) f1; 1171 | int64_t f0f2_2 = f0_2 * (int64_t) f2; 1172 | int64_t f0f3_2 = f0_2 * (int64_t) f3; 1173 | int64_t f0f4_2 = f0_2 * (int64_t) f4; 1174 | int64_t f0f5_2 = f0_2 * (int64_t) f5; 1175 | int64_t f0f6_2 = f0_2 * (int64_t) f6; 1176 | int64_t f0f7_2 = f0_2 * (int64_t) f7; 1177 | int64_t f0f8_2 = f0_2 * (int64_t) f8; 1178 | int64_t f0f9_2 = f0_2 * (int64_t) f9; 1179 | int64_t f1f1_2 = f1_2 * (int64_t) f1; 1180 | int64_t f1f2_2 = f1_2 * (int64_t) f2; 1181 | int64_t f1f3_4 = f1_2 * (int64_t) f3_2; 1182 | int64_t f1f4_2 = f1_2 * (int64_t) f4; 1183 | int64_t f1f5_4 = f1_2 * (int64_t) f5_2; 1184 | int64_t f1f6_2 = f1_2 * (int64_t) f6; 1185 | int64_t f1f7_4 = f1_2 * (int64_t) f7_2; 1186 | int64_t f1f8_2 = f1_2 * (int64_t) f8; 1187 | int64_t f1f9_76 = f1_2 * (int64_t) f9_38; 1188 | int64_t f2f2 = f2 * (int64_t) f2; 1189 | int64_t f2f3_2 = f2_2 * (int64_t) f3; 1190 | int64_t f2f4_2 = f2_2 * (int64_t) f4; 1191 | int64_t f2f5_2 = f2_2 * (int64_t) f5; 1192 | int64_t f2f6_2 = f2_2 * (int64_t) f6; 1193 | int64_t f2f7_2 = f2_2 * (int64_t) f7; 1194 | int64_t f2f8_38 = f2_2 * (int64_t) f8_19; 1195 | int64_t f2f9_38 = f2 * (int64_t) f9_38; 1196 | int64_t f3f3_2 = f3_2 * (int64_t) f3; 1197 | int64_t f3f4_2 = f3_2 * (int64_t) f4; 1198 | int64_t f3f5_4 = f3_2 * (int64_t) f5_2; 1199 | int64_t f3f6_2 = f3_2 * (int64_t) f6; 1200 | int64_t f3f7_76 = f3_2 * (int64_t) f7_38; 1201 | int64_t f3f8_38 = f3_2 * (int64_t) f8_19; 1202 | int64_t f3f9_76 = f3_2 * (int64_t) f9_38; 1203 | int64_t f4f4 = f4 * (int64_t) f4; 1204 | int64_t f4f5_2 = f4_2 * (int64_t) f5; 1205 | int64_t f4f6_38 = f4_2 * (int64_t) f6_19; 1206 | int64_t f4f7_38 = f4 * (int64_t) f7_38; 1207 | int64_t f4f8_38 = f4_2 * (int64_t) f8_19; 1208 | int64_t f4f9_38 = f4 * (int64_t) f9_38; 1209 | int64_t f5f5_38 = f5 * (int64_t) f5_38; 1210 | int64_t f5f6_38 = f5_2 * (int64_t) f6_19; 1211 | int64_t f5f7_76 = f5_2 * (int64_t) f7_38; 1212 | int64_t f5f8_38 = f5_2 * (int64_t) f8_19; 1213 | int64_t f5f9_76 = f5_2 * (int64_t) f9_38; 1214 | int64_t f6f6_19 = f6 * (int64_t) f6_19; 1215 | int64_t f6f7_38 = f6 * (int64_t) f7_38; 1216 | int64_t f6f8_38 = f6_2 * (int64_t) f8_19; 1217 | int64_t f6f9_38 = f6 * (int64_t) f9_38; 1218 | int64_t f7f7_38 = f7 * (int64_t) f7_38; 1219 | int64_t f7f8_38 = f7_2 * (int64_t) f8_19; 1220 | int64_t f7f9_76 = f7_2 * (int64_t) f9_38; 1221 | int64_t f8f8_19 = f8 * (int64_t) f8_19; 1222 | int64_t f8f9_38 = f8 * (int64_t) f9_38; 1223 | int64_t f9f9_38 = f9 * (int64_t) f9_38; 1224 | int64_t h0 = f0f0 + f1f9_76 + f2f8_38 + f3f7_76 + f4f6_38 + f5f5_38; 1225 | int64_t h1 = f0f1_2 + f2f9_38 + f3f8_38 + f4f7_38 + f5f6_38; 1226 | int64_t h2 = f0f2_2 + f1f1_2 + f3f9_76 + f4f8_38 + f5f7_76 + f6f6_19; 1227 | int64_t h3 = f0f3_2 + f1f2_2 + f4f9_38 + f5f8_38 + f6f7_38; 1228 | int64_t h4 = f0f4_2 + f1f3_4 + f2f2 + f5f9_76 + f6f8_38 + f7f7_38; 1229 | int64_t h5 = f0f5_2 + f1f4_2 + f2f3_2 + f6f9_38 + f7f8_38; 1230 | int64_t h6 = f0f6_2 + f1f5_4 + f2f4_2 + f3f3_2 + f7f9_76 + f8f8_19; 1231 | int64_t h7 = f0f7_2 + f1f6_2 + f2f5_2 + f3f4_2 + f8f9_38; 1232 | int64_t h8 = f0f8_2 + f1f7_4 + f2f6_2 + f3f5_4 + f4f4 + f9f9_38; 1233 | int64_t h9 = f0f9_2 + f1f8_2 + f2f7_2 + f3f6_2 + f4f5_2; 1234 | int64_t carry0; 1235 | int64_t carry1; 1236 | int64_t carry2; 1237 | int64_t carry3; 1238 | int64_t carry4; 1239 | int64_t carry5; 1240 | int64_t carry6; 1241 | int64_t carry7; 1242 | int64_t carry8; 1243 | int64_t carry9; 1244 | h0 += h0; 1245 | h1 += h1; 1246 | h2 += h2; 1247 | h3 += h3; 1248 | h4 += h4; 1249 | h5 += h5; 1250 | h6 += h6; 1251 | h7 += h7; 1252 | h8 += h8; 1253 | h9 += h9; 1254 | carry0 = (h0 + (int64_t) (1 << 25)) >> 26; 1255 | h1 += carry0; 1256 | h0 -= carry0 << 26; 1257 | carry4 = (h4 + (int64_t) (1 << 25)) >> 26; 1258 | h5 += carry4; 1259 | h4 -= carry4 << 26; 1260 | carry1 = (h1 + (int64_t) (1 << 24)) >> 25; 1261 | h2 += carry1; 1262 | h1 -= carry1 << 25; 1263 | carry5 = (h5 + (int64_t) (1 << 24)) >> 25; 1264 | h6 += carry5; 1265 | h5 -= carry5 << 25; 1266 | carry2 = (h2 + (int64_t) (1 << 25)) >> 26; 1267 | h3 += carry2; 1268 | h2 -= carry2 << 26; 1269 | carry6 = (h6 + (int64_t) (1 << 25)) >> 26; 1270 | h7 += carry6; 1271 | h6 -= carry6 << 26; 1272 | carry3 = (h3 + (int64_t) (1 << 24)) >> 25; 1273 | h4 += carry3; 1274 | h3 -= carry3 << 25; 1275 | carry7 = (h7 + (int64_t) (1 << 24)) >> 25; 1276 | h8 += carry7; 1277 | h7 -= carry7 << 25; 1278 | carry4 = (h4 + (int64_t) (1 << 25)) >> 26; 1279 | h5 += carry4; 1280 | h4 -= carry4 << 26; 1281 | carry8 = (h8 + (int64_t) (1 << 25)) >> 26; 1282 | h9 += carry8; 1283 | h8 -= carry8 << 26; 1284 | carry9 = (h9 + (int64_t) (1 << 24)) >> 25; 1285 | h0 += carry9 * 19; 1286 | h9 -= carry9 << 25; 1287 | carry0 = (h0 + (int64_t) (1 << 25)) >> 26; 1288 | h1 += carry0; 1289 | h0 -= carry0 << 26; 1290 | h[0] = (int32_t) h0; 1291 | h[1] = (int32_t) h1; 1292 | h[2] = (int32_t) h2; 1293 | h[3] = (int32_t) h3; 1294 | h[4] = (int32_t) h4; 1295 | h[5] = (int32_t) h5; 1296 | h[6] = (int32_t) h6; 1297 | h[7] = (int32_t) h7; 1298 | h[8] = (int32_t) h8; 1299 | h[9] = (int32_t) h9; 1300 | } 1301 | 1302 | 1303 | /* 1304 | h = f - g 1305 | Can overlap h with f or g. 1306 | 1307 | Preconditions: 1308 | |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. 1309 | |g| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. 1310 | 1311 | Postconditions: 1312 | |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. 1313 | */ 1314 | 1315 | void fe_sub(fe h, const fe f, const fe g) { 1316 | int32_t f0 = f[0]; 1317 | int32_t f1 = f[1]; 1318 | int32_t f2 = f[2]; 1319 | int32_t f3 = f[3]; 1320 | int32_t f4 = f[4]; 1321 | int32_t f5 = f[5]; 1322 | int32_t f6 = f[6]; 1323 | int32_t f7 = f[7]; 1324 | int32_t f8 = f[8]; 1325 | int32_t f9 = f[9]; 1326 | int32_t g0 = g[0]; 1327 | int32_t g1 = g[1]; 1328 | int32_t g2 = g[2]; 1329 | int32_t g3 = g[3]; 1330 | int32_t g4 = g[4]; 1331 | int32_t g5 = g[5]; 1332 | int32_t g6 = g[6]; 1333 | int32_t g7 = g[7]; 1334 | int32_t g8 = g[8]; 1335 | int32_t g9 = g[9]; 1336 | int32_t h0 = f0 - g0; 1337 | int32_t h1 = f1 - g1; 1338 | int32_t h2 = f2 - g2; 1339 | int32_t h3 = f3 - g3; 1340 | int32_t h4 = f4 - g4; 1341 | int32_t h5 = f5 - g5; 1342 | int32_t h6 = f6 - g6; 1343 | int32_t h7 = f7 - g7; 1344 | int32_t h8 = f8 - g8; 1345 | int32_t h9 = f9 - g9; 1346 | 1347 | h[0] = h0; 1348 | h[1] = h1; 1349 | h[2] = h2; 1350 | h[3] = h3; 1351 | h[4] = h4; 1352 | h[5] = h5; 1353 | h[6] = h6; 1354 | h[7] = h7; 1355 | h[8] = h8; 1356 | h[9] = h9; 1357 | } 1358 | 1359 | 1360 | 1361 | /* 1362 | Preconditions: 1363 | |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. 1364 | 1365 | Write p=2^255-19; q=floor(h/p). 1366 | Basic claim: q = floor(2^(-255)(h + 19 2^(-25)h9 + 2^(-1))). 1367 | 1368 | Proof: 1369 | Have |h|<=p so |q|<=1 so |19^2 2^(-255) q|<1/4. 1370 | Also have |h-2^230 h9|<2^231 so |19 2^(-255)(h-2^230 h9)|<1/4. 1371 | 1372 | Write y=2^(-1)-19^2 2^(-255)q-19 2^(-255)(h-2^230 h9). 1373 | Then 0> 25; 1409 | q = (h0 + q) >> 26; 1410 | q = (h1 + q) >> 25; 1411 | q = (h2 + q) >> 26; 1412 | q = (h3 + q) >> 25; 1413 | q = (h4 + q) >> 26; 1414 | q = (h5 + q) >> 25; 1415 | q = (h6 + q) >> 26; 1416 | q = (h7 + q) >> 25; 1417 | q = (h8 + q) >> 26; 1418 | q = (h9 + q) >> 25; 1419 | 1420 | h0 += 19 * q; 1421 | 1422 | carry0 = h0 >> 26; 1423 | h1 += carry0; 1424 | h0 -= carry0 << 26; 1425 | carry1 = h1 >> 25; 1426 | h2 += carry1; 1427 | h1 -= carry1 << 25; 1428 | carry2 = h2 >> 26; 1429 | h3 += carry2; 1430 | h2 -= carry2 << 26; 1431 | carry3 = h3 >> 25; 1432 | h4 += carry3; 1433 | h3 -= carry3 << 25; 1434 | carry4 = h4 >> 26; 1435 | h5 += carry4; 1436 | h4 -= carry4 << 26; 1437 | carry5 = h5 >> 25; 1438 | h6 += carry5; 1439 | h5 -= carry5 << 25; 1440 | carry6 = h6 >> 26; 1441 | h7 += carry6; 1442 | h6 -= carry6 << 26; 1443 | carry7 = h7 >> 25; 1444 | h8 += carry7; 1445 | h7 -= carry7 << 25; 1446 | carry8 = h8 >> 26; 1447 | h9 += carry8; 1448 | h8 -= carry8 << 26; 1449 | carry9 = h9 >> 25; 1450 | h9 -= carry9 << 25; 1451 | 1452 | 1453 | /* 1454 | Goal: Output h0+...+2^255 h10-2^255 q, which is between 0 and 2^255-20. 1455 | Have h0+...+2^230 h9 between 0 and 2^255-1; 1456 | evidently 2^255 h10-2^255 q = 0. 1457 | Goal: Output h0+...+2^230 h9. 1458 | */ 1459 | s[0] = (unsigned char) (h0 >> 0); 1460 | s[1] = (unsigned char) (h0 >> 8); 1461 | s[2] = (unsigned char) (h0 >> 16); 1462 | s[3] = (unsigned char) ((h0 >> 24) | (h1 << 2)); 1463 | s[4] = (unsigned char) (h1 >> 6); 1464 | s[5] = (unsigned char) (h1 >> 14); 1465 | s[6] = (unsigned char) ((h1 >> 22) | (h2 << 3)); 1466 | s[7] = (unsigned char) (h2 >> 5); 1467 | s[8] = (unsigned char) (h2 >> 13); 1468 | s[9] = (unsigned char) ((h2 >> 21) | (h3 << 5)); 1469 | s[10] = (unsigned char) (h3 >> 3); 1470 | s[11] = (unsigned char) (h3 >> 11); 1471 | s[12] = (unsigned char) ((h3 >> 19) | (h4 << 6)); 1472 | s[13] = (unsigned char) (h4 >> 2); 1473 | s[14] = (unsigned char) (h4 >> 10); 1474 | s[15] = (unsigned char) (h4 >> 18); 1475 | s[16] = (unsigned char) (h5 >> 0); 1476 | s[17] = (unsigned char) (h5 >> 8); 1477 | s[18] = (unsigned char) (h5 >> 16); 1478 | s[19] = (unsigned char) ((h5 >> 24) | (h6 << 1)); 1479 | s[20] = (unsigned char) (h6 >> 7); 1480 | s[21] = (unsigned char) (h6 >> 15); 1481 | s[22] = (unsigned char) ((h6 >> 23) | (h7 << 3)); 1482 | s[23] = (unsigned char) (h7 >> 5); 1483 | s[24] = (unsigned char) (h7 >> 13); 1484 | s[25] = (unsigned char) ((h7 >> 21) | (h8 << 4)); 1485 | s[26] = (unsigned char) (h8 >> 4); 1486 | s[27] = (unsigned char) (h8 >> 12); 1487 | s[28] = (unsigned char) ((h8 >> 20) | (h9 << 6)); 1488 | s[29] = (unsigned char) (h9 >> 2); 1489 | s[30] = (unsigned char) (h9 >> 10); 1490 | s[31] = (unsigned char) (h9 >> 18); 1491 | } 1492 | -------------------------------------------------------------------------------- /fe.h: -------------------------------------------------------------------------------- 1 | #ifndef FE_H 2 | #define FE_H 3 | 4 | #include "fixedint.h" 5 | 6 | 7 | /* 8 | fe means field element. 9 | Here the field is \Z/(2^255-19). 10 | An element t, entries t[0]...t[9], represents the integer 11 | t[0]+2^26 t[1]+2^51 t[2]+2^77 t[3]+2^102 t[4]+...+2^230 t[9]. 12 | Bounds on each t[i] vary depending on context. 13 | */ 14 | 15 | 16 | typedef int32_t fe[10]; 17 | 18 | 19 | void fe_0(fe h); 20 | void fe_1(fe h); 21 | 22 | void fe_frombytes(fe h, const unsigned char *s); 23 | void fe_tobytes(unsigned char *s, const fe h); 24 | 25 | void fe_copy(fe h, const fe f); 26 | int fe_isnegative(const fe f); 27 | int fe_isnonzero(const fe f); 28 | void fe_cmov(fe f, const fe g, unsigned int b); 29 | void fe_cswap(fe f, fe g, unsigned int b); 30 | 31 | void fe_neg(fe h, const fe f); 32 | void fe_add(fe h, const fe f, const fe g); 33 | void fe_invert(fe out, const fe z); 34 | void fe_sq(fe h, const fe f); 35 | void fe_sq2(fe h, const fe f); 36 | void fe_mul(fe h, const fe f, const fe g); 37 | void fe_mul121666(fe h, fe f); 38 | void fe_pow22523(fe out, const fe z); 39 | void fe_sub(fe h, const fe f, const fe g); 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /fixedint.h: -------------------------------------------------------------------------------- 1 | /* 2 | Portable header to provide the 32 and 64 bits type. 3 | 4 | Not a compatible replacement for , do not blindly use it as such. 5 | */ 6 | 7 | #if ((defined(__STDC__) && __STDC__ && __STDC_VERSION__ >= 199901L) || (defined(__WATCOMC__) && (defined(_STDINT_H_INCLUDED) || __WATCOMC__ >= 1250)) || (defined(__GNUC__) && (defined(_STDINT_H) || defined(_STDINT_H_) || defined(__UINT_FAST64_TYPE__)) )) && !defined(FIXEDINT_H_INCLUDED) 8 | #include 9 | #define FIXEDINT_H_INCLUDED 10 | 11 | #if defined(__WATCOMC__) && __WATCOMC__ >= 1250 && !defined(UINT64_C) 12 | #include 13 | #define UINT64_C(x) (x + (UINT64_MAX - UINT64_MAX)) 14 | #endif 15 | #endif 16 | 17 | 18 | #ifndef FIXEDINT_H_INCLUDED 19 | #define FIXEDINT_H_INCLUDED 20 | 21 | #include 22 | 23 | 24 | #ifndef uint32_t 25 | #if (ULONG_MAX == 0xffffffffUL) 26 | typedef unsigned long uint32_t; 27 | #elif (UINT_MAX == 0xffffffffUL) 28 | typedef unsigned int uint32_t; 29 | #elif (USHRT_MAX == 0xffffffffUL) 30 | typedef unsigned short uint32_t; 31 | #endif 32 | #endif 33 | 34 | 35 | #ifndef int32_t 36 | #if (LONG_MAX == 0x7fffffffL) 37 | typedef signed long int32_t; 38 | #elif (INT_MAX == 0x7fffffffL) 39 | typedef signed int int32_t; 40 | #elif (SHRT_MAX == 0x7fffffffL) 41 | typedef signed short int32_t; 42 | #endif 43 | #endif 44 | 45 | 46 | 47 | #if (defined(__STDC__) && defined(__STDC_VERSION__) && __STDC__ && __STDC_VERSION__ >= 199901L) 48 | typedef long long int64_t; 49 | typedef unsigned long long uint64_t; 50 | 51 | #define UINT64_C(v) v ##ULL 52 | #define INT64_C(v) v ##LL 53 | #elif defined(__GNUC__) 54 | __extension__ typedef long long int64_t; 55 | __extension__ typedef unsigned long long uint64_t; 56 | 57 | #define UINT64_C(v) v ##ULL 58 | #define INT64_C(v) v ##LL 59 | #elif defined(__MWERKS__) || defined(__SUNPRO_C) || defined(__SUNPRO_CC) || defined(__APPLE_CC__) || defined(_LONG_LONG) || defined(_CRAYC) 60 | typedef long long int64_t; 61 | typedef unsigned long long uint64_t; 62 | 63 | #define UINT64_C(v) v ##ULL 64 | #define INT64_C(v) v ##LL 65 | #elif (defined(__WATCOMC__) && defined(__WATCOM_INT64__)) || (defined(_MSC_VER) && _INTEGRAL_MAX_BITS >= 64) || (defined(__BORLANDC__) && __BORLANDC__ > 0x460) || defined(__alpha) || defined(__DECC) 66 | typedef __int64 int64_t; 67 | typedef unsigned __int64 uint64_t; 68 | 69 | #define UINT64_C(v) v ##UI64 70 | #define INT64_C(v) v ##I64 71 | #endif 72 | #endif 73 | -------------------------------------------------------------------------------- /ge.c: -------------------------------------------------------------------------------- 1 | #include "ge.h" 2 | #include "precomp_data.h" 3 | 4 | 5 | /* 6 | r = p + q 7 | */ 8 | 9 | void ge_add(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q) { 10 | fe t0; 11 | fe_add(r->X, p->Y, p->X); 12 | fe_sub(r->Y, p->Y, p->X); 13 | fe_mul(r->Z, r->X, q->YplusX); 14 | fe_mul(r->Y, r->Y, q->YminusX); 15 | fe_mul(r->T, q->T2d, p->T); 16 | fe_mul(r->X, p->Z, q->Z); 17 | fe_add(t0, r->X, r->X); 18 | fe_sub(r->X, r->Z, r->Y); 19 | fe_add(r->Y, r->Z, r->Y); 20 | fe_add(r->Z, t0, r->T); 21 | fe_sub(r->T, t0, r->T); 22 | } 23 | 24 | 25 | static void slide(signed char *r, const unsigned char *a) { 26 | int i; 27 | int b; 28 | int k; 29 | 30 | for (i = 0; i < 256; ++i) { 31 | r[i] = 1 & (a[i >> 3] >> (i & 7)); 32 | } 33 | 34 | for (i = 0; i < 256; ++i) 35 | if (r[i]) { 36 | for (b = 1; b <= 6 && i + b < 256; ++b) { 37 | if (r[i + b]) { 38 | if (r[i] + (r[i + b] << b) <= 15) { 39 | r[i] += r[i + b] << b; 40 | r[i + b] = 0; 41 | } else if (r[i] - (r[i + b] << b) >= -15) { 42 | r[i] -= r[i + b] << b; 43 | 44 | for (k = i + b; k < 256; ++k) { 45 | if (!r[k]) { 46 | r[k] = 1; 47 | break; 48 | } 49 | 50 | r[k] = 0; 51 | } 52 | } else { 53 | break; 54 | } 55 | } 56 | } 57 | } 58 | } 59 | 60 | /* 61 | r = a * A + b * B 62 | where a = a[0]+256*a[1]+...+256^31 a[31]. 63 | and b = b[0]+256*b[1]+...+256^31 b[31]. 64 | B is the Ed25519 base point (x,4/5) with x positive. 65 | */ 66 | 67 | void ge_double_scalarmult_vartime(ge_p2 *r, const unsigned char *a, const ge_p3 *A, const unsigned char *b) { 68 | signed char aslide[256]; 69 | signed char bslide[256]; 70 | ge_cached Ai[8]; 71 | ge_p1p1 t; 72 | ge_p3 u; 73 | ge_p3 A2; 74 | int i; 75 | slide(aslide, a); 76 | slide(bslide, b); 77 | ge_p3_to_cached(&Ai[0], A); 78 | ge_p3_dbl(&t, A); 79 | ge_p1p1_to_p3(&A2, &t); 80 | ge_add(&t, &A2, &Ai[0]); 81 | ge_p1p1_to_p3(&u, &t); 82 | ge_p3_to_cached(&Ai[1], &u); 83 | ge_add(&t, &A2, &Ai[1]); 84 | ge_p1p1_to_p3(&u, &t); 85 | ge_p3_to_cached(&Ai[2], &u); 86 | ge_add(&t, &A2, &Ai[2]); 87 | ge_p1p1_to_p3(&u, &t); 88 | ge_p3_to_cached(&Ai[3], &u); 89 | ge_add(&t, &A2, &Ai[3]); 90 | ge_p1p1_to_p3(&u, &t); 91 | ge_p3_to_cached(&Ai[4], &u); 92 | ge_add(&t, &A2, &Ai[4]); 93 | ge_p1p1_to_p3(&u, &t); 94 | ge_p3_to_cached(&Ai[5], &u); 95 | ge_add(&t, &A2, &Ai[5]); 96 | ge_p1p1_to_p3(&u, &t); 97 | ge_p3_to_cached(&Ai[6], &u); 98 | ge_add(&t, &A2, &Ai[6]); 99 | ge_p1p1_to_p3(&u, &t); 100 | ge_p3_to_cached(&Ai[7], &u); 101 | ge_p2_0(r); 102 | 103 | for (i = 255; i >= 0; --i) { 104 | if (aslide[i] || bslide[i]) { 105 | break; 106 | } 107 | } 108 | 109 | for (; i >= 0; --i) { 110 | ge_p2_dbl(&t, r); 111 | 112 | if (aslide[i] > 0) { 113 | ge_p1p1_to_p3(&u, &t); 114 | ge_add(&t, &u, &Ai[aslide[i] / 2]); 115 | } else if (aslide[i] < 0) { 116 | ge_p1p1_to_p3(&u, &t); 117 | ge_sub(&t, &u, &Ai[(-aslide[i]) / 2]); 118 | } 119 | 120 | if (bslide[i] > 0) { 121 | ge_p1p1_to_p3(&u, &t); 122 | ge_madd(&t, &u, &Bi[bslide[i] / 2]); 123 | } else if (bslide[i] < 0) { 124 | ge_p1p1_to_p3(&u, &t); 125 | ge_msub(&t, &u, &Bi[(-bslide[i]) / 2]); 126 | } 127 | 128 | ge_p1p1_to_p2(r, &t); 129 | } 130 | } 131 | 132 | 133 | static const fe d = { 134 | -10913610, 13857413, -15372611, 6949391, 114729, -8787816, -6275908, -3247719, -18696448, -12055116 135 | }; 136 | 137 | static const fe sqrtm1 = { 138 | -32595792, -7943725, 9377950, 3500415, 12389472, -272473, -25146209, -2005654, 326686, 11406482 139 | }; 140 | 141 | int ge_frombytes_negate_vartime(ge_p3 *h, const unsigned char *s) { 142 | fe u; 143 | fe v; 144 | fe v3; 145 | fe vxx; 146 | fe check; 147 | fe_frombytes(h->Y, s); 148 | fe_1(h->Z); 149 | fe_sq(u, h->Y); 150 | fe_mul(v, u, d); 151 | fe_sub(u, u, h->Z); 152 | fe_add(v, v, h->Z); 153 | fe_sq(v3, v); 154 | fe_mul(v3, v3, v); 155 | fe_sq(h->X, v3); 156 | fe_mul(h->X, h->X, v); 157 | fe_mul(h->X, h->X, u); 158 | fe_pow22523(h->X, h->X); 159 | fe_mul(h->X, h->X, v3); 160 | fe_mul(h->X, h->X, u); 161 | fe_sq(vxx, h->X); 162 | fe_mul(vxx, vxx, v); 163 | fe_sub(check, vxx, u); 164 | 165 | if (fe_isnonzero(check)) { 166 | fe_add(check, vxx, u); 167 | 168 | if (fe_isnonzero(check)) { 169 | return -1; 170 | } 171 | 172 | fe_mul(h->X, h->X, sqrtm1); 173 | } 174 | 175 | if (fe_isnegative(h->X) == (s[31] >> 7)) { 176 | fe_neg(h->X, h->X); 177 | } 178 | 179 | fe_mul(h->T, h->X, h->Y); 180 | return 0; 181 | } 182 | 183 | 184 | /* 185 | r = p + q 186 | */ 187 | 188 | void ge_madd(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q) { 189 | fe t0; 190 | fe_add(r->X, p->Y, p->X); 191 | fe_sub(r->Y, p->Y, p->X); 192 | fe_mul(r->Z, r->X, q->yplusx); 193 | fe_mul(r->Y, r->Y, q->yminusx); 194 | fe_mul(r->T, q->xy2d, p->T); 195 | fe_add(t0, p->Z, p->Z); 196 | fe_sub(r->X, r->Z, r->Y); 197 | fe_add(r->Y, r->Z, r->Y); 198 | fe_add(r->Z, t0, r->T); 199 | fe_sub(r->T, t0, r->T); 200 | } 201 | 202 | 203 | /* 204 | r = p - q 205 | */ 206 | 207 | void ge_msub(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q) { 208 | fe t0; 209 | 210 | fe_add(r->X, p->Y, p->X); 211 | fe_sub(r->Y, p->Y, p->X); 212 | fe_mul(r->Z, r->X, q->yminusx); 213 | fe_mul(r->Y, r->Y, q->yplusx); 214 | fe_mul(r->T, q->xy2d, p->T); 215 | fe_add(t0, p->Z, p->Z); 216 | fe_sub(r->X, r->Z, r->Y); 217 | fe_add(r->Y, r->Z, r->Y); 218 | fe_sub(r->Z, t0, r->T); 219 | fe_add(r->T, t0, r->T); 220 | } 221 | 222 | 223 | /* 224 | r = p 225 | */ 226 | 227 | void ge_p1p1_to_p2(ge_p2 *r, const ge_p1p1 *p) { 228 | fe_mul(r->X, p->X, p->T); 229 | fe_mul(r->Y, p->Y, p->Z); 230 | fe_mul(r->Z, p->Z, p->T); 231 | } 232 | 233 | 234 | 235 | /* 236 | r = p 237 | */ 238 | 239 | void ge_p1p1_to_p3(ge_p3 *r, const ge_p1p1 *p) { 240 | fe_mul(r->X, p->X, p->T); 241 | fe_mul(r->Y, p->Y, p->Z); 242 | fe_mul(r->Z, p->Z, p->T); 243 | fe_mul(r->T, p->X, p->Y); 244 | } 245 | 246 | 247 | void ge_p2_0(ge_p2 *h) { 248 | fe_0(h->X); 249 | fe_1(h->Y); 250 | fe_1(h->Z); 251 | } 252 | 253 | 254 | 255 | /* 256 | r = 2 * p 257 | */ 258 | 259 | void ge_p2_dbl(ge_p1p1 *r, const ge_p2 *p) { 260 | fe t0; 261 | 262 | fe_sq(r->X, p->X); 263 | fe_sq(r->Z, p->Y); 264 | fe_sq2(r->T, p->Z); 265 | fe_add(r->Y, p->X, p->Y); 266 | fe_sq(t0, r->Y); 267 | fe_add(r->Y, r->Z, r->X); 268 | fe_sub(r->Z, r->Z, r->X); 269 | fe_sub(r->X, t0, r->Y); 270 | fe_sub(r->T, r->T, r->Z); 271 | } 272 | 273 | 274 | void ge_p3_0(ge_p3 *h) { 275 | fe_0(h->X); 276 | fe_1(h->Y); 277 | fe_1(h->Z); 278 | fe_0(h->T); 279 | } 280 | 281 | 282 | /* 283 | r = 2 * p 284 | */ 285 | 286 | void ge_p3_dbl(ge_p1p1 *r, const ge_p3 *p) { 287 | ge_p2 q; 288 | ge_p3_to_p2(&q, p); 289 | ge_p2_dbl(r, &q); 290 | } 291 | 292 | 293 | 294 | /* 295 | r = p 296 | */ 297 | 298 | static const fe d2 = { 299 | -21827239, -5839606, -30745221, 13898782, 229458, 15978800, -12551817, -6495438, 29715968, 9444199 300 | }; 301 | 302 | void ge_p3_to_cached(ge_cached *r, const ge_p3 *p) { 303 | fe_add(r->YplusX, p->Y, p->X); 304 | fe_sub(r->YminusX, p->Y, p->X); 305 | fe_copy(r->Z, p->Z); 306 | fe_mul(r->T2d, p->T, d2); 307 | } 308 | 309 | 310 | /* 311 | r = p 312 | */ 313 | 314 | void ge_p3_to_p2(ge_p2 *r, const ge_p3 *p) { 315 | fe_copy(r->X, p->X); 316 | fe_copy(r->Y, p->Y); 317 | fe_copy(r->Z, p->Z); 318 | } 319 | 320 | 321 | void ge_p3_tobytes(unsigned char *s, const ge_p3 *h) { 322 | fe recip; 323 | fe x; 324 | fe y; 325 | fe_invert(recip, h->Z); 326 | fe_mul(x, h->X, recip); 327 | fe_mul(y, h->Y, recip); 328 | fe_tobytes(s, y); 329 | s[31] ^= fe_isnegative(x) << 7; 330 | } 331 | 332 | 333 | static unsigned char equal(signed char b, signed char c) { 334 | unsigned char ub = b; 335 | unsigned char uc = c; 336 | unsigned char x = ub ^ uc; 337 | uint64_t y = x; 338 | y -= 1; 339 | y >>= 63; 340 | return (unsigned char) y; 341 | } 342 | 343 | static unsigned char negative(signed char b) { 344 | uint64_t x = b; 345 | x >>= 63; 346 | return (unsigned char) x; 347 | } 348 | 349 | static void cmov(ge_precomp *t, const ge_precomp *u, unsigned char b) { 350 | fe_cmov(t->yplusx, u->yplusx, b); 351 | fe_cmov(t->yminusx, u->yminusx, b); 352 | fe_cmov(t->xy2d, u->xy2d, b); 353 | } 354 | 355 | 356 | static void select(ge_precomp *t, int pos, signed char b) { 357 | ge_precomp minust; 358 | unsigned char bnegative = negative(b); 359 | unsigned char babs = b - (((-bnegative) & b) << 1); 360 | fe_1(t->yplusx); 361 | fe_1(t->yminusx); 362 | fe_0(t->xy2d); 363 | cmov(t, &base[pos][0], equal(babs, 1)); 364 | cmov(t, &base[pos][1], equal(babs, 2)); 365 | cmov(t, &base[pos][2], equal(babs, 3)); 366 | cmov(t, &base[pos][3], equal(babs, 4)); 367 | cmov(t, &base[pos][4], equal(babs, 5)); 368 | cmov(t, &base[pos][5], equal(babs, 6)); 369 | cmov(t, &base[pos][6], equal(babs, 7)); 370 | cmov(t, &base[pos][7], equal(babs, 8)); 371 | fe_copy(minust.yplusx, t->yminusx); 372 | fe_copy(minust.yminusx, t->yplusx); 373 | fe_neg(minust.xy2d, t->xy2d); 374 | cmov(t, &minust, bnegative); 375 | } 376 | 377 | /* 378 | h = a * B 379 | where a = a[0]+256*a[1]+...+256^31 a[31] 380 | B is the Ed25519 base point (x,4/5) with x positive. 381 | 382 | Preconditions: 383 | a[31] <= 127 384 | */ 385 | 386 | void ge_scalarmult_base(ge_p3 *h, const unsigned char *a) { 387 | signed char e[64]; 388 | signed char carry; 389 | ge_p1p1 r; 390 | ge_p2 s; 391 | ge_precomp t; 392 | int i; 393 | 394 | for (i = 0; i < 32; ++i) { 395 | e[2 * i + 0] = (a[i] >> 0) & 15; 396 | e[2 * i + 1] = (a[i] >> 4) & 15; 397 | } 398 | 399 | 400 | 401 | carry = 0; 402 | 403 | for (i = 0; i < 63; ++i) { 404 | e[i] += carry; 405 | carry = e[i] + 8; 406 | carry >>= 4; 407 | e[i] -= carry << 4; 408 | } 409 | 410 | e[63] += carry; 411 | 412 | ge_p3_0(h); 413 | 414 | for (i = 1; i < 64; i += 2) { 415 | select(&t, i / 2, e[i]); 416 | ge_madd(&r, h, &t); 417 | ge_p1p1_to_p3(h, &r); 418 | } 419 | 420 | ge_p3_dbl(&r, h); 421 | ge_p1p1_to_p2(&s, &r); 422 | ge_p2_dbl(&r, &s); 423 | ge_p1p1_to_p2(&s, &r); 424 | ge_p2_dbl(&r, &s); 425 | ge_p1p1_to_p2(&s, &r); 426 | ge_p2_dbl(&r, &s); 427 | ge_p1p1_to_p3(h, &r); 428 | 429 | for (i = 0; i < 64; i += 2) { 430 | select(&t, i / 2, e[i]); 431 | ge_madd(&r, h, &t); 432 | ge_p1p1_to_p3(h, &r); 433 | } 434 | } 435 | 436 | 437 | /* 438 | r = p - q 439 | */ 440 | 441 | void ge_sub(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q) { 442 | fe t0; 443 | 444 | fe_add(r->X, p->Y, p->X); 445 | fe_sub(r->Y, p->Y, p->X); 446 | fe_mul(r->Z, r->X, q->YminusX); 447 | fe_mul(r->Y, r->Y, q->YplusX); 448 | fe_mul(r->T, q->T2d, p->T); 449 | fe_mul(r->X, p->Z, q->Z); 450 | fe_add(t0, r->X, r->X); 451 | fe_sub(r->X, r->Z, r->Y); 452 | fe_add(r->Y, r->Z, r->Y); 453 | fe_sub(r->Z, t0, r->T); 454 | fe_add(r->T, t0, r->T); 455 | } 456 | 457 | 458 | void ge_tobytes(unsigned char *s, const ge_p2 *h) { 459 | fe recip; 460 | fe x; 461 | fe y; 462 | fe_invert(recip, h->Z); 463 | fe_mul(x, h->X, recip); 464 | fe_mul(y, h->Y, recip); 465 | fe_tobytes(s, y); 466 | s[31] ^= fe_isnegative(x) << 7; 467 | } 468 | -------------------------------------------------------------------------------- /ge.h: -------------------------------------------------------------------------------- 1 | #ifndef GE_H 2 | #define GE_H 3 | 4 | #include "fe.h" 5 | 6 | 7 | /* 8 | ge means group element. 9 | 10 | Here the group is the set of pairs (x,y) of field elements (see fe.h) 11 | satisfying -x^2 + y^2 = 1 + d x^2y^2 12 | where d = -121665/121666. 13 | 14 | Representations: 15 | ge_p2 (projective): (X:Y:Z) satisfying x=X/Z, y=Y/Z 16 | ge_p3 (extended): (X:Y:Z:T) satisfying x=X/Z, y=Y/Z, XY=ZT 17 | ge_p1p1 (completed): ((X:Z),(Y:T)) satisfying x=X/Z, y=Y/T 18 | ge_precomp (Duif): (y+x,y-x,2dxy) 19 | */ 20 | 21 | typedef struct { 22 | fe X; 23 | fe Y; 24 | fe Z; 25 | } ge_p2; 26 | 27 | typedef struct { 28 | fe X; 29 | fe Y; 30 | fe Z; 31 | fe T; 32 | } ge_p3; 33 | 34 | typedef struct { 35 | fe X; 36 | fe Y; 37 | fe Z; 38 | fe T; 39 | } ge_p1p1; 40 | 41 | typedef struct { 42 | fe yplusx; 43 | fe yminusx; 44 | fe xy2d; 45 | } ge_precomp; 46 | 47 | typedef struct { 48 | fe YplusX; 49 | fe YminusX; 50 | fe Z; 51 | fe T2d; 52 | } ge_cached; 53 | 54 | void ge_p3_tobytes(unsigned char *s, const ge_p3 *h); 55 | void ge_tobytes(unsigned char *s, const ge_p2 *h); 56 | int ge_frombytes_negate_vartime(ge_p3 *h, const unsigned char *s); 57 | 58 | void ge_add(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q); 59 | void ge_sub(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q); 60 | void ge_double_scalarmult_vartime(ge_p2 *r, const unsigned char *a, const ge_p3 *A, const unsigned char *b); 61 | void ge_madd(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q); 62 | void ge_msub(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q); 63 | void ge_scalarmult_base(ge_p3 *h, const unsigned char *a); 64 | 65 | void ge_p1p1_to_p2(ge_p2 *r, const ge_p1p1 *p); 66 | void ge_p1p1_to_p3(ge_p3 *r, const ge_p1p1 *p); 67 | void ge_p2_0(ge_p2 *h); 68 | void ge_p2_dbl(ge_p1p1 *r, const ge_p2 *p); 69 | void ge_p3_0(ge_p3 *h); 70 | void ge_p3_dbl(ge_p1p1 *r, const ge_p3 *p); 71 | void ge_p3_to_cached(ge_cached *r, const ge_p3 *p); 72 | void ge_p3_to_p2(ge_p2 *r, const ge_p3 *p); 73 | 74 | #endif 75 | -------------------------------------------------------------------------------- /install_openssl_macos.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | 4 | if ! command -v brew &>/dev/null 5 | then 6 | echo "Установка Homebrew..." 7 | 8 | /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" 9 | 10 | echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> /Users/$(whoami)/.zprofile 11 | eval "$(/opt/homebrew/bin/brew shellenv)" 12 | else 13 | echo "Homebrew already installed." 14 | fi 15 | 16 | echo "Update Homebrew..." 17 | brew update 18 | 19 | echo "Install OpenSSL..." 20 | brew install openssl@3 21 | 22 | echo "Install done." 23 | 24 | -------------------------------------------------------------------------------- /key_exchange.c: -------------------------------------------------------------------------------- 1 | #include "ed25519.h" 2 | #include "fe.h" 3 | 4 | void ed25519_key_exchange(unsigned char *shared_secret, const unsigned char *public_key, const unsigned char *private_key) { 5 | unsigned char e[32]; 6 | unsigned int i; 7 | 8 | fe x1; 9 | fe x2; 10 | fe z2; 11 | fe x3; 12 | fe z3; 13 | fe tmp0; 14 | fe tmp1; 15 | 16 | int pos; 17 | unsigned int swap; 18 | unsigned int b; 19 | 20 | 21 | for (i = 0; i < 32; ++i) { 22 | e[i] = private_key[i]; 23 | } 24 | 25 | e[0] &= 248; 26 | e[31] &= 63; 27 | e[31] |= 64; 28 | 29 | 30 | 31 | fe_frombytes(x1, public_key); 32 | fe_1(tmp1); 33 | fe_add(tmp0, x1, tmp1); 34 | fe_sub(tmp1, tmp1, x1); 35 | fe_invert(tmp1, tmp1); 36 | fe_mul(x1, tmp0, tmp1); 37 | 38 | fe_1(x2); 39 | fe_0(z2); 40 | fe_copy(x3, x1); 41 | fe_1(z3); 42 | 43 | swap = 0; 44 | for (pos = 254; pos >= 0; --pos) { 45 | b = e[pos / 8] >> (pos & 7); 46 | b &= 1; 47 | swap ^= b; 48 | fe_cswap(x2, x3, swap); 49 | fe_cswap(z2, z3, swap); 50 | swap = b; 51 | 52 | 53 | fe_sub(tmp0, x3, z3); 54 | fe_sub(tmp1, x2, z2); 55 | fe_add(x2, x2, z2); 56 | fe_add(z2, x3, z3); 57 | fe_mul(z3, tmp0, x2); 58 | fe_mul(z2, z2, tmp1); 59 | fe_sq(tmp0, tmp1); 60 | fe_sq(tmp1, x2); 61 | fe_add(x3, z3, z2); 62 | fe_sub(z2, z3, z2); 63 | fe_mul(x2, tmp1, tmp0); 64 | fe_sub(tmp1, tmp1, tmp0); 65 | fe_sq(z2, z2); 66 | fe_mul121666(z3, tmp1); 67 | fe_sq(x3, x3); 68 | fe_add(tmp0, tmp0, z3); 69 | fe_mul(z3, x1, z2); 70 | fe_mul(z2, tmp1, tmp0); 71 | } 72 | 73 | fe_cswap(x2, x3, swap); 74 | fe_cswap(z2, z3, swap); 75 | 76 | fe_invert(z2, z2); 77 | fe_mul(x2, x2, z2); 78 | fe_tobytes(shared_secret, x2); 79 | } 80 | -------------------------------------------------------------------------------- /keypair.c: -------------------------------------------------------------------------------- 1 | #include "ed25519.h" 2 | #include "sha512.h" 3 | #include "ge.h" 4 | 5 | 6 | void ed25519_create_keypair(unsigned char *public_key, unsigned char *private_key, const unsigned char *seed) { 7 | ge_p3 A; 8 | 9 | sha512(seed, 32, private_key); 10 | private_key[0] &= 248; 11 | private_key[31] &= 63; 12 | private_key[31] |= 64; 13 | 14 | ge_scalarmult_base(&A, private_key); 15 | ge_p3_tobytes(public_key, &A); 16 | } 17 | -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | 2 | CXX = g++ 3 | CC = gcc 4 | 5 | CXXFLAGS = -O3 -Wall -mrdrnd -I. 6 | CFLAGS = -O3 -Wall -mrdrnd -I. 7 | 8 | LDFLAGS = -lssl -lcrypto 9 | 10 | CPP_SOURCES = $(wildcard *.cpp) 11 | C_SOURCES = $(wildcard *.c) 12 | 13 | CPP_OBJECTS = $(CPP_SOURCES:.cpp=.o) 14 | C_OBJECTS = $(C_SOURCES:.c=.o) 15 | OBJECTS = $(CPP_OBJECTS) $(C_OBJECTS) 16 | 17 | TARGET = Mnemonic_C++ 18 | 19 | all: $(TARGET) 20 | 21 | $(TARGET): $(OBJECTS) 22 | $(CXX) $(OBJECTS) -o $@ $(LDFLAGS) 23 | 24 | %.o: %.cpp 25 | $(CXX) $(CXXFLAGS) -c $< -o $@ $(LDFLAGS) 26 | 27 | %.o: %.c 28 | $(CC) $(CFLAGS) -c $< -o $@ 29 | 30 | 31 | clean: 32 | rm -f $(OBJECTS) 33 | 34 | .PHONY: all clean 35 | -------------------------------------------------------------------------------- /sc.c: -------------------------------------------------------------------------------- 1 | #include "fixedint.h" 2 | #include "sc.h" 3 | 4 | static uint64_t load_3(const unsigned char *in) { 5 | uint64_t result; 6 | 7 | result = (uint64_t) in[0]; 8 | result |= ((uint64_t) in[1]) << 8; 9 | result |= ((uint64_t) in[2]) << 16; 10 | 11 | return result; 12 | } 13 | 14 | static uint64_t load_4(const unsigned char *in) { 15 | uint64_t result; 16 | 17 | result = (uint64_t) in[0]; 18 | result |= ((uint64_t) in[1]) << 8; 19 | result |= ((uint64_t) in[2]) << 16; 20 | result |= ((uint64_t) in[3]) << 24; 21 | 22 | return result; 23 | } 24 | 25 | /* 26 | Input: 27 | s[0]+256*s[1]+...+256^63*s[63] = s 28 | 29 | Output: 30 | s[0]+256*s[1]+...+256^31*s[31] = s mod l 31 | where l = 2^252 + 27742317777372353535851937790883648493. 32 | Overwrites s in place. 33 | */ 34 | 35 | void sc_reduce(unsigned char *s) { 36 | int64_t s0 = 2097151 & load_3(s); 37 | int64_t s1 = 2097151 & (load_4(s + 2) >> 5); 38 | int64_t s2 = 2097151 & (load_3(s + 5) >> 2); 39 | int64_t s3 = 2097151 & (load_4(s + 7) >> 7); 40 | int64_t s4 = 2097151 & (load_4(s + 10) >> 4); 41 | int64_t s5 = 2097151 & (load_3(s + 13) >> 1); 42 | int64_t s6 = 2097151 & (load_4(s + 15) >> 6); 43 | int64_t s7 = 2097151 & (load_3(s + 18) >> 3); 44 | int64_t s8 = 2097151 & load_3(s + 21); 45 | int64_t s9 = 2097151 & (load_4(s + 23) >> 5); 46 | int64_t s10 = 2097151 & (load_3(s + 26) >> 2); 47 | int64_t s11 = 2097151 & (load_4(s + 28) >> 7); 48 | int64_t s12 = 2097151 & (load_4(s + 31) >> 4); 49 | int64_t s13 = 2097151 & (load_3(s + 34) >> 1); 50 | int64_t s14 = 2097151 & (load_4(s + 36) >> 6); 51 | int64_t s15 = 2097151 & (load_3(s + 39) >> 3); 52 | int64_t s16 = 2097151 & load_3(s + 42); 53 | int64_t s17 = 2097151 & (load_4(s + 44) >> 5); 54 | int64_t s18 = 2097151 & (load_3(s + 47) >> 2); 55 | int64_t s19 = 2097151 & (load_4(s + 49) >> 7); 56 | int64_t s20 = 2097151 & (load_4(s + 52) >> 4); 57 | int64_t s21 = 2097151 & (load_3(s + 55) >> 1); 58 | int64_t s22 = 2097151 & (load_4(s + 57) >> 6); 59 | int64_t s23 = (load_4(s + 60) >> 3); 60 | int64_t carry0; 61 | int64_t carry1; 62 | int64_t carry2; 63 | int64_t carry3; 64 | int64_t carry4; 65 | int64_t carry5; 66 | int64_t carry6; 67 | int64_t carry7; 68 | int64_t carry8; 69 | int64_t carry9; 70 | int64_t carry10; 71 | int64_t carry11; 72 | int64_t carry12; 73 | int64_t carry13; 74 | int64_t carry14; 75 | int64_t carry15; 76 | int64_t carry16; 77 | 78 | s11 += s23 * 666643; 79 | s12 += s23 * 470296; 80 | s13 += s23 * 654183; 81 | s14 -= s23 * 997805; 82 | s15 += s23 * 136657; 83 | s16 -= s23 * 683901; 84 | s23 = 0; 85 | s10 += s22 * 666643; 86 | s11 += s22 * 470296; 87 | s12 += s22 * 654183; 88 | s13 -= s22 * 997805; 89 | s14 += s22 * 136657; 90 | s15 -= s22 * 683901; 91 | s22 = 0; 92 | s9 += s21 * 666643; 93 | s10 += s21 * 470296; 94 | s11 += s21 * 654183; 95 | s12 -= s21 * 997805; 96 | s13 += s21 * 136657; 97 | s14 -= s21 * 683901; 98 | s21 = 0; 99 | s8 += s20 * 666643; 100 | s9 += s20 * 470296; 101 | s10 += s20 * 654183; 102 | s11 -= s20 * 997805; 103 | s12 += s20 * 136657; 104 | s13 -= s20 * 683901; 105 | s20 = 0; 106 | s7 += s19 * 666643; 107 | s8 += s19 * 470296; 108 | s9 += s19 * 654183; 109 | s10 -= s19 * 997805; 110 | s11 += s19 * 136657; 111 | s12 -= s19 * 683901; 112 | s19 = 0; 113 | s6 += s18 * 666643; 114 | s7 += s18 * 470296; 115 | s8 += s18 * 654183; 116 | s9 -= s18 * 997805; 117 | s10 += s18 * 136657; 118 | s11 -= s18 * 683901; 119 | s18 = 0; 120 | carry6 = (s6 + (1 << 20)) >> 21; 121 | s7 += carry6; 122 | s6 -= carry6 << 21; 123 | carry8 = (s8 + (1 << 20)) >> 21; 124 | s9 += carry8; 125 | s8 -= carry8 << 21; 126 | carry10 = (s10 + (1 << 20)) >> 21; 127 | s11 += carry10; 128 | s10 -= carry10 << 21; 129 | carry12 = (s12 + (1 << 20)) >> 21; 130 | s13 += carry12; 131 | s12 -= carry12 << 21; 132 | carry14 = (s14 + (1 << 20)) >> 21; 133 | s15 += carry14; 134 | s14 -= carry14 << 21; 135 | carry16 = (s16 + (1 << 20)) >> 21; 136 | s17 += carry16; 137 | s16 -= carry16 << 21; 138 | carry7 = (s7 + (1 << 20)) >> 21; 139 | s8 += carry7; 140 | s7 -= carry7 << 21; 141 | carry9 = (s9 + (1 << 20)) >> 21; 142 | s10 += carry9; 143 | s9 -= carry9 << 21; 144 | carry11 = (s11 + (1 << 20)) >> 21; 145 | s12 += carry11; 146 | s11 -= carry11 << 21; 147 | carry13 = (s13 + (1 << 20)) >> 21; 148 | s14 += carry13; 149 | s13 -= carry13 << 21; 150 | carry15 = (s15 + (1 << 20)) >> 21; 151 | s16 += carry15; 152 | s15 -= carry15 << 21; 153 | s5 += s17 * 666643; 154 | s6 += s17 * 470296; 155 | s7 += s17 * 654183; 156 | s8 -= s17 * 997805; 157 | s9 += s17 * 136657; 158 | s10 -= s17 * 683901; 159 | s17 = 0; 160 | s4 += s16 * 666643; 161 | s5 += s16 * 470296; 162 | s6 += s16 * 654183; 163 | s7 -= s16 * 997805; 164 | s8 += s16 * 136657; 165 | s9 -= s16 * 683901; 166 | s16 = 0; 167 | s3 += s15 * 666643; 168 | s4 += s15 * 470296; 169 | s5 += s15 * 654183; 170 | s6 -= s15 * 997805; 171 | s7 += s15 * 136657; 172 | s8 -= s15 * 683901; 173 | s15 = 0; 174 | s2 += s14 * 666643; 175 | s3 += s14 * 470296; 176 | s4 += s14 * 654183; 177 | s5 -= s14 * 997805; 178 | s6 += s14 * 136657; 179 | s7 -= s14 * 683901; 180 | s14 = 0; 181 | s1 += s13 * 666643; 182 | s2 += s13 * 470296; 183 | s3 += s13 * 654183; 184 | s4 -= s13 * 997805; 185 | s5 += s13 * 136657; 186 | s6 -= s13 * 683901; 187 | s13 = 0; 188 | s0 += s12 * 666643; 189 | s1 += s12 * 470296; 190 | s2 += s12 * 654183; 191 | s3 -= s12 * 997805; 192 | s4 += s12 * 136657; 193 | s5 -= s12 * 683901; 194 | s12 = 0; 195 | carry0 = (s0 + (1 << 20)) >> 21; 196 | s1 += carry0; 197 | s0 -= carry0 << 21; 198 | carry2 = (s2 + (1 << 20)) >> 21; 199 | s3 += carry2; 200 | s2 -= carry2 << 21; 201 | carry4 = (s4 + (1 << 20)) >> 21; 202 | s5 += carry4; 203 | s4 -= carry4 << 21; 204 | carry6 = (s6 + (1 << 20)) >> 21; 205 | s7 += carry6; 206 | s6 -= carry6 << 21; 207 | carry8 = (s8 + (1 << 20)) >> 21; 208 | s9 += carry8; 209 | s8 -= carry8 << 21; 210 | carry10 = (s10 + (1 << 20)) >> 21; 211 | s11 += carry10; 212 | s10 -= carry10 << 21; 213 | carry1 = (s1 + (1 << 20)) >> 21; 214 | s2 += carry1; 215 | s1 -= carry1 << 21; 216 | carry3 = (s3 + (1 << 20)) >> 21; 217 | s4 += carry3; 218 | s3 -= carry3 << 21; 219 | carry5 = (s5 + (1 << 20)) >> 21; 220 | s6 += carry5; 221 | s5 -= carry5 << 21; 222 | carry7 = (s7 + (1 << 20)) >> 21; 223 | s8 += carry7; 224 | s7 -= carry7 << 21; 225 | carry9 = (s9 + (1 << 20)) >> 21; 226 | s10 += carry9; 227 | s9 -= carry9 << 21; 228 | carry11 = (s11 + (1 << 20)) >> 21; 229 | s12 += carry11; 230 | s11 -= carry11 << 21; 231 | s0 += s12 * 666643; 232 | s1 += s12 * 470296; 233 | s2 += s12 * 654183; 234 | s3 -= s12 * 997805; 235 | s4 += s12 * 136657; 236 | s5 -= s12 * 683901; 237 | s12 = 0; 238 | carry0 = s0 >> 21; 239 | s1 += carry0; 240 | s0 -= carry0 << 21; 241 | carry1 = s1 >> 21; 242 | s2 += carry1; 243 | s1 -= carry1 << 21; 244 | carry2 = s2 >> 21; 245 | s3 += carry2; 246 | s2 -= carry2 << 21; 247 | carry3 = s3 >> 21; 248 | s4 += carry3; 249 | s3 -= carry3 << 21; 250 | carry4 = s4 >> 21; 251 | s5 += carry4; 252 | s4 -= carry4 << 21; 253 | carry5 = s5 >> 21; 254 | s6 += carry5; 255 | s5 -= carry5 << 21; 256 | carry6 = s6 >> 21; 257 | s7 += carry6; 258 | s6 -= carry6 << 21; 259 | carry7 = s7 >> 21; 260 | s8 += carry7; 261 | s7 -= carry7 << 21; 262 | carry8 = s8 >> 21; 263 | s9 += carry8; 264 | s8 -= carry8 << 21; 265 | carry9 = s9 >> 21; 266 | s10 += carry9; 267 | s9 -= carry9 << 21; 268 | carry10 = s10 >> 21; 269 | s11 += carry10; 270 | s10 -= carry10 << 21; 271 | carry11 = s11 >> 21; 272 | s12 += carry11; 273 | s11 -= carry11 << 21; 274 | s0 += s12 * 666643; 275 | s1 += s12 * 470296; 276 | s2 += s12 * 654183; 277 | s3 -= s12 * 997805; 278 | s4 += s12 * 136657; 279 | s5 -= s12 * 683901; 280 | s12 = 0; 281 | carry0 = s0 >> 21; 282 | s1 += carry0; 283 | s0 -= carry0 << 21; 284 | carry1 = s1 >> 21; 285 | s2 += carry1; 286 | s1 -= carry1 << 21; 287 | carry2 = s2 >> 21; 288 | s3 += carry2; 289 | s2 -= carry2 << 21; 290 | carry3 = s3 >> 21; 291 | s4 += carry3; 292 | s3 -= carry3 << 21; 293 | carry4 = s4 >> 21; 294 | s5 += carry4; 295 | s4 -= carry4 << 21; 296 | carry5 = s5 >> 21; 297 | s6 += carry5; 298 | s5 -= carry5 << 21; 299 | carry6 = s6 >> 21; 300 | s7 += carry6; 301 | s6 -= carry6 << 21; 302 | carry7 = s7 >> 21; 303 | s8 += carry7; 304 | s7 -= carry7 << 21; 305 | carry8 = s8 >> 21; 306 | s9 += carry8; 307 | s8 -= carry8 << 21; 308 | carry9 = s9 >> 21; 309 | s10 += carry9; 310 | s9 -= carry9 << 21; 311 | carry10 = s10 >> 21; 312 | s11 += carry10; 313 | s10 -= carry10 << 21; 314 | 315 | s[0] = (unsigned char) (s0 >> 0); 316 | s[1] = (unsigned char) (s0 >> 8); 317 | s[2] = (unsigned char) ((s0 >> 16) | (s1 << 5)); 318 | s[3] = (unsigned char) (s1 >> 3); 319 | s[4] = (unsigned char) (s1 >> 11); 320 | s[5] = (unsigned char) ((s1 >> 19) | (s2 << 2)); 321 | s[6] = (unsigned char) (s2 >> 6); 322 | s[7] = (unsigned char) ((s2 >> 14) | (s3 << 7)); 323 | s[8] = (unsigned char) (s3 >> 1); 324 | s[9] = (unsigned char) (s3 >> 9); 325 | s[10] = (unsigned char) ((s3 >> 17) | (s4 << 4)); 326 | s[11] = (unsigned char) (s4 >> 4); 327 | s[12] = (unsigned char) (s4 >> 12); 328 | s[13] = (unsigned char) ((s4 >> 20) | (s5 << 1)); 329 | s[14] = (unsigned char) (s5 >> 7); 330 | s[15] = (unsigned char) ((s5 >> 15) | (s6 << 6)); 331 | s[16] = (unsigned char) (s6 >> 2); 332 | s[17] = (unsigned char) (s6 >> 10); 333 | s[18] = (unsigned char) ((s6 >> 18) | (s7 << 3)); 334 | s[19] = (unsigned char) (s7 >> 5); 335 | s[20] = (unsigned char) (s7 >> 13); 336 | s[21] = (unsigned char) (s8 >> 0); 337 | s[22] = (unsigned char) (s8 >> 8); 338 | s[23] = (unsigned char) ((s8 >> 16) | (s9 << 5)); 339 | s[24] = (unsigned char) (s9 >> 3); 340 | s[25] = (unsigned char) (s9 >> 11); 341 | s[26] = (unsigned char) ((s9 >> 19) | (s10 << 2)); 342 | s[27] = (unsigned char) (s10 >> 6); 343 | s[28] = (unsigned char) ((s10 >> 14) | (s11 << 7)); 344 | s[29] = (unsigned char) (s11 >> 1); 345 | s[30] = (unsigned char) (s11 >> 9); 346 | s[31] = (unsigned char) (s11 >> 17); 347 | } 348 | 349 | 350 | 351 | /* 352 | Input: 353 | a[0]+256*a[1]+...+256^31*a[31] = a 354 | b[0]+256*b[1]+...+256^31*b[31] = b 355 | c[0]+256*c[1]+...+256^31*c[31] = c 356 | 357 | Output: 358 | s[0]+256*s[1]+...+256^31*s[31] = (ab+c) mod l 359 | where l = 2^252 + 27742317777372353535851937790883648493. 360 | */ 361 | 362 | void sc_muladd(unsigned char *s, const unsigned char *a, const unsigned char *b, const unsigned char *c) { 363 | int64_t a0 = 2097151 & load_3(a); 364 | int64_t a1 = 2097151 & (load_4(a + 2) >> 5); 365 | int64_t a2 = 2097151 & (load_3(a + 5) >> 2); 366 | int64_t a3 = 2097151 & (load_4(a + 7) >> 7); 367 | int64_t a4 = 2097151 & (load_4(a + 10) >> 4); 368 | int64_t a5 = 2097151 & (load_3(a + 13) >> 1); 369 | int64_t a6 = 2097151 & (load_4(a + 15) >> 6); 370 | int64_t a7 = 2097151 & (load_3(a + 18) >> 3); 371 | int64_t a8 = 2097151 & load_3(a + 21); 372 | int64_t a9 = 2097151 & (load_4(a + 23) >> 5); 373 | int64_t a10 = 2097151 & (load_3(a + 26) >> 2); 374 | int64_t a11 = (load_4(a + 28) >> 7); 375 | int64_t b0 = 2097151 & load_3(b); 376 | int64_t b1 = 2097151 & (load_4(b + 2) >> 5); 377 | int64_t b2 = 2097151 & (load_3(b + 5) >> 2); 378 | int64_t b3 = 2097151 & (load_4(b + 7) >> 7); 379 | int64_t b4 = 2097151 & (load_4(b + 10) >> 4); 380 | int64_t b5 = 2097151 & (load_3(b + 13) >> 1); 381 | int64_t b6 = 2097151 & (load_4(b + 15) >> 6); 382 | int64_t b7 = 2097151 & (load_3(b + 18) >> 3); 383 | int64_t b8 = 2097151 & load_3(b + 21); 384 | int64_t b9 = 2097151 & (load_4(b + 23) >> 5); 385 | int64_t b10 = 2097151 & (load_3(b + 26) >> 2); 386 | int64_t b11 = (load_4(b + 28) >> 7); 387 | int64_t c0 = 2097151 & load_3(c); 388 | int64_t c1 = 2097151 & (load_4(c + 2) >> 5); 389 | int64_t c2 = 2097151 & (load_3(c + 5) >> 2); 390 | int64_t c3 = 2097151 & (load_4(c + 7) >> 7); 391 | int64_t c4 = 2097151 & (load_4(c + 10) >> 4); 392 | int64_t c5 = 2097151 & (load_3(c + 13) >> 1); 393 | int64_t c6 = 2097151 & (load_4(c + 15) >> 6); 394 | int64_t c7 = 2097151 & (load_3(c + 18) >> 3); 395 | int64_t c8 = 2097151 & load_3(c + 21); 396 | int64_t c9 = 2097151 & (load_4(c + 23) >> 5); 397 | int64_t c10 = 2097151 & (load_3(c + 26) >> 2); 398 | int64_t c11 = (load_4(c + 28) >> 7); 399 | int64_t s0; 400 | int64_t s1; 401 | int64_t s2; 402 | int64_t s3; 403 | int64_t s4; 404 | int64_t s5; 405 | int64_t s6; 406 | int64_t s7; 407 | int64_t s8; 408 | int64_t s9; 409 | int64_t s10; 410 | int64_t s11; 411 | int64_t s12; 412 | int64_t s13; 413 | int64_t s14; 414 | int64_t s15; 415 | int64_t s16; 416 | int64_t s17; 417 | int64_t s18; 418 | int64_t s19; 419 | int64_t s20; 420 | int64_t s21; 421 | int64_t s22; 422 | int64_t s23; 423 | int64_t carry0; 424 | int64_t carry1; 425 | int64_t carry2; 426 | int64_t carry3; 427 | int64_t carry4; 428 | int64_t carry5; 429 | int64_t carry6; 430 | int64_t carry7; 431 | int64_t carry8; 432 | int64_t carry9; 433 | int64_t carry10; 434 | int64_t carry11; 435 | int64_t carry12; 436 | int64_t carry13; 437 | int64_t carry14; 438 | int64_t carry15; 439 | int64_t carry16; 440 | int64_t carry17; 441 | int64_t carry18; 442 | int64_t carry19; 443 | int64_t carry20; 444 | int64_t carry21; 445 | int64_t carry22; 446 | 447 | s0 = c0 + a0 * b0; 448 | s1 = c1 + a0 * b1 + a1 * b0; 449 | s2 = c2 + a0 * b2 + a1 * b1 + a2 * b0; 450 | s3 = c3 + a0 * b3 + a1 * b2 + a2 * b1 + a3 * b0; 451 | s4 = c4 + a0 * b4 + a1 * b3 + a2 * b2 + a3 * b1 + a4 * b0; 452 | s5 = c5 + a0 * b5 + a1 * b4 + a2 * b3 + a3 * b2 + a4 * b1 + a5 * b0; 453 | s6 = c6 + a0 * b6 + a1 * b5 + a2 * b4 + a3 * b3 + a4 * b2 + a5 * b1 + a6 * b0; 454 | s7 = c7 + a0 * b7 + a1 * b6 + a2 * b5 + a3 * b4 + a4 * b3 + a5 * b2 + a6 * b1 + a7 * b0; 455 | s8 = c8 + a0 * b8 + a1 * b7 + a2 * b6 + a3 * b5 + a4 * b4 + a5 * b3 + a6 * b2 + a7 * b1 + a8 * b0; 456 | s9 = c9 + a0 * b9 + a1 * b8 + a2 * b7 + a3 * b6 + a4 * b5 + a5 * b4 + a6 * b3 + a7 * b2 + a8 * b1 + a9 * b0; 457 | s10 = c10 + a0 * b10 + a1 * b9 + a2 * b8 + a3 * b7 + a4 * b6 + a5 * b5 + a6 * b4 + a7 * b3 + a8 * b2 + a9 * b1 + a10 * b0; 458 | s11 = c11 + a0 * b11 + a1 * b10 + a2 * b9 + a3 * b8 + a4 * b7 + a5 * b6 + a6 * b5 + a7 * b4 + a8 * b3 + a9 * b2 + a10 * b1 + a11 * b0; 459 | s12 = a1 * b11 + a2 * b10 + a3 * b9 + a4 * b8 + a5 * b7 + a6 * b6 + a7 * b5 + a8 * b4 + a9 * b3 + a10 * b2 + a11 * b1; 460 | s13 = a2 * b11 + a3 * b10 + a4 * b9 + a5 * b8 + a6 * b7 + a7 * b6 + a8 * b5 + a9 * b4 + a10 * b3 + a11 * b2; 461 | s14 = a3 * b11 + a4 * b10 + a5 * b9 + a6 * b8 + a7 * b7 + a8 * b6 + a9 * b5 + a10 * b4 + a11 * b3; 462 | s15 = a4 * b11 + a5 * b10 + a6 * b9 + a7 * b8 + a8 * b7 + a9 * b6 + a10 * b5 + a11 * b4; 463 | s16 = a5 * b11 + a6 * b10 + a7 * b9 + a8 * b8 + a9 * b7 + a10 * b6 + a11 * b5; 464 | s17 = a6 * b11 + a7 * b10 + a8 * b9 + a9 * b8 + a10 * b7 + a11 * b6; 465 | s18 = a7 * b11 + a8 * b10 + a9 * b9 + a10 * b8 + a11 * b7; 466 | s19 = a8 * b11 + a9 * b10 + a10 * b9 + a11 * b8; 467 | s20 = a9 * b11 + a10 * b10 + a11 * b9; 468 | s21 = a10 * b11 + a11 * b10; 469 | s22 = a11 * b11; 470 | s23 = 0; 471 | carry0 = (s0 + (1 << 20)) >> 21; 472 | s1 += carry0; 473 | s0 -= carry0 << 21; 474 | carry2 = (s2 + (1 << 20)) >> 21; 475 | s3 += carry2; 476 | s2 -= carry2 << 21; 477 | carry4 = (s4 + (1 << 20)) >> 21; 478 | s5 += carry4; 479 | s4 -= carry4 << 21; 480 | carry6 = (s6 + (1 << 20)) >> 21; 481 | s7 += carry6; 482 | s6 -= carry6 << 21; 483 | carry8 = (s8 + (1 << 20)) >> 21; 484 | s9 += carry8; 485 | s8 -= carry8 << 21; 486 | carry10 = (s10 + (1 << 20)) >> 21; 487 | s11 += carry10; 488 | s10 -= carry10 << 21; 489 | carry12 = (s12 + (1 << 20)) >> 21; 490 | s13 += carry12; 491 | s12 -= carry12 << 21; 492 | carry14 = (s14 + (1 << 20)) >> 21; 493 | s15 += carry14; 494 | s14 -= carry14 << 21; 495 | carry16 = (s16 + (1 << 20)) >> 21; 496 | s17 += carry16; 497 | s16 -= carry16 << 21; 498 | carry18 = (s18 + (1 << 20)) >> 21; 499 | s19 += carry18; 500 | s18 -= carry18 << 21; 501 | carry20 = (s20 + (1 << 20)) >> 21; 502 | s21 += carry20; 503 | s20 -= carry20 << 21; 504 | carry22 = (s22 + (1 << 20)) >> 21; 505 | s23 += carry22; 506 | s22 -= carry22 << 21; 507 | carry1 = (s1 + (1 << 20)) >> 21; 508 | s2 += carry1; 509 | s1 -= carry1 << 21; 510 | carry3 = (s3 + (1 << 20)) >> 21; 511 | s4 += carry3; 512 | s3 -= carry3 << 21; 513 | carry5 = (s5 + (1 << 20)) >> 21; 514 | s6 += carry5; 515 | s5 -= carry5 << 21; 516 | carry7 = (s7 + (1 << 20)) >> 21; 517 | s8 += carry7; 518 | s7 -= carry7 << 21; 519 | carry9 = (s9 + (1 << 20)) >> 21; 520 | s10 += carry9; 521 | s9 -= carry9 << 21; 522 | carry11 = (s11 + (1 << 20)) >> 21; 523 | s12 += carry11; 524 | s11 -= carry11 << 21; 525 | carry13 = (s13 + (1 << 20)) >> 21; 526 | s14 += carry13; 527 | s13 -= carry13 << 21; 528 | carry15 = (s15 + (1 << 20)) >> 21; 529 | s16 += carry15; 530 | s15 -= carry15 << 21; 531 | carry17 = (s17 + (1 << 20)) >> 21; 532 | s18 += carry17; 533 | s17 -= carry17 << 21; 534 | carry19 = (s19 + (1 << 20)) >> 21; 535 | s20 += carry19; 536 | s19 -= carry19 << 21; 537 | carry21 = (s21 + (1 << 20)) >> 21; 538 | s22 += carry21; 539 | s21 -= carry21 << 21; 540 | s11 += s23 * 666643; 541 | s12 += s23 * 470296; 542 | s13 += s23 * 654183; 543 | s14 -= s23 * 997805; 544 | s15 += s23 * 136657; 545 | s16 -= s23 * 683901; 546 | s23 = 0; 547 | s10 += s22 * 666643; 548 | s11 += s22 * 470296; 549 | s12 += s22 * 654183; 550 | s13 -= s22 * 997805; 551 | s14 += s22 * 136657; 552 | s15 -= s22 * 683901; 553 | s22 = 0; 554 | s9 += s21 * 666643; 555 | s10 += s21 * 470296; 556 | s11 += s21 * 654183; 557 | s12 -= s21 * 997805; 558 | s13 += s21 * 136657; 559 | s14 -= s21 * 683901; 560 | s21 = 0; 561 | s8 += s20 * 666643; 562 | s9 += s20 * 470296; 563 | s10 += s20 * 654183; 564 | s11 -= s20 * 997805; 565 | s12 += s20 * 136657; 566 | s13 -= s20 * 683901; 567 | s20 = 0; 568 | s7 += s19 * 666643; 569 | s8 += s19 * 470296; 570 | s9 += s19 * 654183; 571 | s10 -= s19 * 997805; 572 | s11 += s19 * 136657; 573 | s12 -= s19 * 683901; 574 | s19 = 0; 575 | s6 += s18 * 666643; 576 | s7 += s18 * 470296; 577 | s8 += s18 * 654183; 578 | s9 -= s18 * 997805; 579 | s10 += s18 * 136657; 580 | s11 -= s18 * 683901; 581 | s18 = 0; 582 | carry6 = (s6 + (1 << 20)) >> 21; 583 | s7 += carry6; 584 | s6 -= carry6 << 21; 585 | carry8 = (s8 + (1 << 20)) >> 21; 586 | s9 += carry8; 587 | s8 -= carry8 << 21; 588 | carry10 = (s10 + (1 << 20)) >> 21; 589 | s11 += carry10; 590 | s10 -= carry10 << 21; 591 | carry12 = (s12 + (1 << 20)) >> 21; 592 | s13 += carry12; 593 | s12 -= carry12 << 21; 594 | carry14 = (s14 + (1 << 20)) >> 21; 595 | s15 += carry14; 596 | s14 -= carry14 << 21; 597 | carry16 = (s16 + (1 << 20)) >> 21; 598 | s17 += carry16; 599 | s16 -= carry16 << 21; 600 | carry7 = (s7 + (1 << 20)) >> 21; 601 | s8 += carry7; 602 | s7 -= carry7 << 21; 603 | carry9 = (s9 + (1 << 20)) >> 21; 604 | s10 += carry9; 605 | s9 -= carry9 << 21; 606 | carry11 = (s11 + (1 << 20)) >> 21; 607 | s12 += carry11; 608 | s11 -= carry11 << 21; 609 | carry13 = (s13 + (1 << 20)) >> 21; 610 | s14 += carry13; 611 | s13 -= carry13 << 21; 612 | carry15 = (s15 + (1 << 20)) >> 21; 613 | s16 += carry15; 614 | s15 -= carry15 << 21; 615 | s5 += s17 * 666643; 616 | s6 += s17 * 470296; 617 | s7 += s17 * 654183; 618 | s8 -= s17 * 997805; 619 | s9 += s17 * 136657; 620 | s10 -= s17 * 683901; 621 | s17 = 0; 622 | s4 += s16 * 666643; 623 | s5 += s16 * 470296; 624 | s6 += s16 * 654183; 625 | s7 -= s16 * 997805; 626 | s8 += s16 * 136657; 627 | s9 -= s16 * 683901; 628 | s16 = 0; 629 | s3 += s15 * 666643; 630 | s4 += s15 * 470296; 631 | s5 += s15 * 654183; 632 | s6 -= s15 * 997805; 633 | s7 += s15 * 136657; 634 | s8 -= s15 * 683901; 635 | s15 = 0; 636 | s2 += s14 * 666643; 637 | s3 += s14 * 470296; 638 | s4 += s14 * 654183; 639 | s5 -= s14 * 997805; 640 | s6 += s14 * 136657; 641 | s7 -= s14 * 683901; 642 | s14 = 0; 643 | s1 += s13 * 666643; 644 | s2 += s13 * 470296; 645 | s3 += s13 * 654183; 646 | s4 -= s13 * 997805; 647 | s5 += s13 * 136657; 648 | s6 -= s13 * 683901; 649 | s13 = 0; 650 | s0 += s12 * 666643; 651 | s1 += s12 * 470296; 652 | s2 += s12 * 654183; 653 | s3 -= s12 * 997805; 654 | s4 += s12 * 136657; 655 | s5 -= s12 * 683901; 656 | s12 = 0; 657 | carry0 = (s0 + (1 << 20)) >> 21; 658 | s1 += carry0; 659 | s0 -= carry0 << 21; 660 | carry2 = (s2 + (1 << 20)) >> 21; 661 | s3 += carry2; 662 | s2 -= carry2 << 21; 663 | carry4 = (s4 + (1 << 20)) >> 21; 664 | s5 += carry4; 665 | s4 -= carry4 << 21; 666 | carry6 = (s6 + (1 << 20)) >> 21; 667 | s7 += carry6; 668 | s6 -= carry6 << 21; 669 | carry8 = (s8 + (1 << 20)) >> 21; 670 | s9 += carry8; 671 | s8 -= carry8 << 21; 672 | carry10 = (s10 + (1 << 20)) >> 21; 673 | s11 += carry10; 674 | s10 -= carry10 << 21; 675 | carry1 = (s1 + (1 << 20)) >> 21; 676 | s2 += carry1; 677 | s1 -= carry1 << 21; 678 | carry3 = (s3 + (1 << 20)) >> 21; 679 | s4 += carry3; 680 | s3 -= carry3 << 21; 681 | carry5 = (s5 + (1 << 20)) >> 21; 682 | s6 += carry5; 683 | s5 -= carry5 << 21; 684 | carry7 = (s7 + (1 << 20)) >> 21; 685 | s8 += carry7; 686 | s7 -= carry7 << 21; 687 | carry9 = (s9 + (1 << 20)) >> 21; 688 | s10 += carry9; 689 | s9 -= carry9 << 21; 690 | carry11 = (s11 + (1 << 20)) >> 21; 691 | s12 += carry11; 692 | s11 -= carry11 << 21; 693 | s0 += s12 * 666643; 694 | s1 += s12 * 470296; 695 | s2 += s12 * 654183; 696 | s3 -= s12 * 997805; 697 | s4 += s12 * 136657; 698 | s5 -= s12 * 683901; 699 | s12 = 0; 700 | carry0 = s0 >> 21; 701 | s1 += carry0; 702 | s0 -= carry0 << 21; 703 | carry1 = s1 >> 21; 704 | s2 += carry1; 705 | s1 -= carry1 << 21; 706 | carry2 = s2 >> 21; 707 | s3 += carry2; 708 | s2 -= carry2 << 21; 709 | carry3 = s3 >> 21; 710 | s4 += carry3; 711 | s3 -= carry3 << 21; 712 | carry4 = s4 >> 21; 713 | s5 += carry4; 714 | s4 -= carry4 << 21; 715 | carry5 = s5 >> 21; 716 | s6 += carry5; 717 | s5 -= carry5 << 21; 718 | carry6 = s6 >> 21; 719 | s7 += carry6; 720 | s6 -= carry6 << 21; 721 | carry7 = s7 >> 21; 722 | s8 += carry7; 723 | s7 -= carry7 << 21; 724 | carry8 = s8 >> 21; 725 | s9 += carry8; 726 | s8 -= carry8 << 21; 727 | carry9 = s9 >> 21; 728 | s10 += carry9; 729 | s9 -= carry9 << 21; 730 | carry10 = s10 >> 21; 731 | s11 += carry10; 732 | s10 -= carry10 << 21; 733 | carry11 = s11 >> 21; 734 | s12 += carry11; 735 | s11 -= carry11 << 21; 736 | s0 += s12 * 666643; 737 | s1 += s12 * 470296; 738 | s2 += s12 * 654183; 739 | s3 -= s12 * 997805; 740 | s4 += s12 * 136657; 741 | s5 -= s12 * 683901; 742 | s12 = 0; 743 | carry0 = s0 >> 21; 744 | s1 += carry0; 745 | s0 -= carry0 << 21; 746 | carry1 = s1 >> 21; 747 | s2 += carry1; 748 | s1 -= carry1 << 21; 749 | carry2 = s2 >> 21; 750 | s3 += carry2; 751 | s2 -= carry2 << 21; 752 | carry3 = s3 >> 21; 753 | s4 += carry3; 754 | s3 -= carry3 << 21; 755 | carry4 = s4 >> 21; 756 | s5 += carry4; 757 | s4 -= carry4 << 21; 758 | carry5 = s5 >> 21; 759 | s6 += carry5; 760 | s5 -= carry5 << 21; 761 | carry6 = s6 >> 21; 762 | s7 += carry6; 763 | s6 -= carry6 << 21; 764 | carry7 = s7 >> 21; 765 | s8 += carry7; 766 | s7 -= carry7 << 21; 767 | carry8 = s8 >> 21; 768 | s9 += carry8; 769 | s8 -= carry8 << 21; 770 | carry9 = s9 >> 21; 771 | s10 += carry9; 772 | s9 -= carry9 << 21; 773 | carry10 = s10 >> 21; 774 | s11 += carry10; 775 | s10 -= carry10 << 21; 776 | 777 | s[0] = (unsigned char) (s0 >> 0); 778 | s[1] = (unsigned char) (s0 >> 8); 779 | s[2] = (unsigned char) ((s0 >> 16) | (s1 << 5)); 780 | s[3] = (unsigned char) (s1 >> 3); 781 | s[4] = (unsigned char) (s1 >> 11); 782 | s[5] = (unsigned char) ((s1 >> 19) | (s2 << 2)); 783 | s[6] = (unsigned char) (s2 >> 6); 784 | s[7] = (unsigned char) ((s2 >> 14) | (s3 << 7)); 785 | s[8] = (unsigned char) (s3 >> 1); 786 | s[9] = (unsigned char) (s3 >> 9); 787 | s[10] = (unsigned char) ((s3 >> 17) | (s4 << 4)); 788 | s[11] = (unsigned char) (s4 >> 4); 789 | s[12] = (unsigned char) (s4 >> 12); 790 | s[13] = (unsigned char) ((s4 >> 20) | (s5 << 1)); 791 | s[14] = (unsigned char) (s5 >> 7); 792 | s[15] = (unsigned char) ((s5 >> 15) | (s6 << 6)); 793 | s[16] = (unsigned char) (s6 >> 2); 794 | s[17] = (unsigned char) (s6 >> 10); 795 | s[18] = (unsigned char) ((s6 >> 18) | (s7 << 3)); 796 | s[19] = (unsigned char) (s7 >> 5); 797 | s[20] = (unsigned char) (s7 >> 13); 798 | s[21] = (unsigned char) (s8 >> 0); 799 | s[22] = (unsigned char) (s8 >> 8); 800 | s[23] = (unsigned char) ((s8 >> 16) | (s9 << 5)); 801 | s[24] = (unsigned char) (s9 >> 3); 802 | s[25] = (unsigned char) (s9 >> 11); 803 | s[26] = (unsigned char) ((s9 >> 19) | (s10 << 2)); 804 | s[27] = (unsigned char) (s10 >> 6); 805 | s[28] = (unsigned char) ((s10 >> 14) | (s11 << 7)); 806 | s[29] = (unsigned char) (s11 >> 1); 807 | s[30] = (unsigned char) (s11 >> 9); 808 | s[31] = (unsigned char) (s11 >> 17); 809 | } 810 | -------------------------------------------------------------------------------- /sc.h: -------------------------------------------------------------------------------- 1 | #ifndef SC_H 2 | #define SC_H 3 | 4 | /* 5 | The set of scalars is \Z/l 6 | where l = 2^252 + 27742317777372353535851937790883648493. 7 | */ 8 | 9 | void sc_reduce(unsigned char *s); 10 | void sc_muladd(unsigned char *s, const unsigned char *a, const unsigned char *b, const unsigned char *c); 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /seed.c: -------------------------------------------------------------------------------- 1 | #include "ed25519.h" 2 | 3 | #ifndef ED25519_NO_SEED 4 | 5 | #ifdef _WIN32 6 | #include 7 | #include 8 | #else 9 | #include 10 | #endif 11 | 12 | int ed25519_create_seed(unsigned char *seed) { 13 | #ifdef _WIN32 14 | HCRYPTPROV prov; 15 | 16 | if (!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { 17 | return 1; 18 | } 19 | 20 | if (!CryptGenRandom(prov, 32, seed)) { 21 | CryptReleaseContext(prov, 0); 22 | return 1; 23 | } 24 | 25 | CryptReleaseContext(prov, 0); 26 | #else 27 | FILE *f = fopen("/dev/urandom", "rb"); 28 | 29 | if (f == NULL) { 30 | return 1; 31 | } 32 | 33 | fread(seed, 1, 32, f); 34 | fclose(f); 35 | #endif 36 | 37 | return 0; 38 | } 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /sha512.c: -------------------------------------------------------------------------------- 1 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis 2 | * 3 | * LibTomCrypt is a library that provides various cryptographic 4 | * algorithms in a highly modular and flexible manner. 5 | * 6 | * The library is free for all purposes without any express 7 | * guarantee it works. 8 | * 9 | * Tom St Denis, tomstdenis@gmail.com, http: */ 10 | 11 | #include "fixedint.h" 12 | #include "sha512.h" 13 | 14 | 15 | static const uint64_t K[80] = { 16 | UINT64_C(0x428a2f98d728ae22), UINT64_C(0x7137449123ef65cd), 17 | UINT64_C(0xb5c0fbcfec4d3b2f), UINT64_C(0xe9b5dba58189dbbc), 18 | UINT64_C(0x3956c25bf348b538), UINT64_C(0x59f111f1b605d019), 19 | UINT64_C(0x923f82a4af194f9b), UINT64_C(0xab1c5ed5da6d8118), 20 | UINT64_C(0xd807aa98a3030242), UINT64_C(0x12835b0145706fbe), 21 | UINT64_C(0x243185be4ee4b28c), UINT64_C(0x550c7dc3d5ffb4e2), 22 | UINT64_C(0x72be5d74f27b896f), UINT64_C(0x80deb1fe3b1696b1), 23 | UINT64_C(0x9bdc06a725c71235), UINT64_C(0xc19bf174cf692694), 24 | UINT64_C(0xe49b69c19ef14ad2), UINT64_C(0xefbe4786384f25e3), 25 | UINT64_C(0x0fc19dc68b8cd5b5), UINT64_C(0x240ca1cc77ac9c65), 26 | UINT64_C(0x2de92c6f592b0275), UINT64_C(0x4a7484aa6ea6e483), 27 | UINT64_C(0x5cb0a9dcbd41fbd4), UINT64_C(0x76f988da831153b5), 28 | UINT64_C(0x983e5152ee66dfab), UINT64_C(0xa831c66d2db43210), 29 | UINT64_C(0xb00327c898fb213f), UINT64_C(0xbf597fc7beef0ee4), 30 | UINT64_C(0xc6e00bf33da88fc2), UINT64_C(0xd5a79147930aa725), 31 | UINT64_C(0x06ca6351e003826f), UINT64_C(0x142929670a0e6e70), 32 | UINT64_C(0x27b70a8546d22ffc), UINT64_C(0x2e1b21385c26c926), 33 | UINT64_C(0x4d2c6dfc5ac42aed), UINT64_C(0x53380d139d95b3df), 34 | UINT64_C(0x650a73548baf63de), UINT64_C(0x766a0abb3c77b2a8), 35 | UINT64_C(0x81c2c92e47edaee6), UINT64_C(0x92722c851482353b), 36 | UINT64_C(0xa2bfe8a14cf10364), UINT64_C(0xa81a664bbc423001), 37 | UINT64_C(0xc24b8b70d0f89791), UINT64_C(0xc76c51a30654be30), 38 | UINT64_C(0xd192e819d6ef5218), UINT64_C(0xd69906245565a910), 39 | UINT64_C(0xf40e35855771202a), UINT64_C(0x106aa07032bbd1b8), 40 | UINT64_C(0x19a4c116b8d2d0c8), UINT64_C(0x1e376c085141ab53), 41 | UINT64_C(0x2748774cdf8eeb99), UINT64_C(0x34b0bcb5e19b48a8), 42 | UINT64_C(0x391c0cb3c5c95a63), UINT64_C(0x4ed8aa4ae3418acb), 43 | UINT64_C(0x5b9cca4f7763e373), UINT64_C(0x682e6ff3d6b2b8a3), 44 | UINT64_C(0x748f82ee5defb2fc), UINT64_C(0x78a5636f43172f60), 45 | UINT64_C(0x84c87814a1f0ab72), UINT64_C(0x8cc702081a6439ec), 46 | UINT64_C(0x90befffa23631e28), UINT64_C(0xa4506cebde82bde9), 47 | UINT64_C(0xbef9a3f7b2c67915), UINT64_C(0xc67178f2e372532b), 48 | UINT64_C(0xca273eceea26619c), UINT64_C(0xd186b8c721c0c207), 49 | UINT64_C(0xeada7dd6cde0eb1e), UINT64_C(0xf57d4f7fee6ed178), 50 | UINT64_C(0x06f067aa72176fba), UINT64_C(0x0a637dc5a2c898a6), 51 | UINT64_C(0x113f9804bef90dae), UINT64_C(0x1b710b35131c471b), 52 | UINT64_C(0x28db77f523047d84), UINT64_C(0x32caab7b40c72493), 53 | UINT64_C(0x3c9ebe0a15c9bebc), UINT64_C(0x431d67c49c100d4c), 54 | UINT64_C(0x4cc5d4becb3e42b6), UINT64_C(0x597f299cfc657e2a), 55 | UINT64_C(0x5fcb6fab3ad6faec), UINT64_C(0x6c44198c4a475817) 56 | }; 57 | 58 | 59 | 60 | #define ROR64c(x, y) \ 61 | ( ((((x)&UINT64_C(0xFFFFFFFFFFFFFFFF))>>((uint64_t)(y)&UINT64_C(63))) | \ 62 | ((x)<<((uint64_t)(64-((y)&UINT64_C(63)))))) & UINT64_C(0xFFFFFFFFFFFFFFFF)) 63 | 64 | #define STORE64H(x, y) \ 65 | { (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \ 66 | (y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \ 67 | (y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \ 68 | (y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); } 69 | 70 | #define LOAD64H(x, y) \ 71 | { x = (((uint64_t)((y)[0] & 255))<<56)|(((uint64_t)((y)[1] & 255))<<48) | \ 72 | (((uint64_t)((y)[2] & 255))<<40)|(((uint64_t)((y)[3] & 255))<<32) | \ 73 | (((uint64_t)((y)[4] & 255))<<24)|(((uint64_t)((y)[5] & 255))<<16) | \ 74 | (((uint64_t)((y)[6] & 255))<<8)|(((uint64_t)((y)[7] & 255))); } 75 | 76 | 77 | #define Ch(x,y,z) (z ^ (x & (y ^ z))) 78 | #define Maj(x,y,z) (((x | y) & z) | (x & y)) 79 | #define S(x, n) ROR64c(x, n) 80 | #define R(x, n) (((x) &UINT64_C(0xFFFFFFFFFFFFFFFF))>>((uint64_t)n)) 81 | #define Sigma0(x) (S(x, 28) ^ S(x, 34) ^ S(x, 39)) 82 | #define Sigma1(x) (S(x, 14) ^ S(x, 18) ^ S(x, 41)) 83 | #define Gamma0(x) (S(x, 1) ^ S(x, 8) ^ R(x, 7)) 84 | #define Gamma1(x) (S(x, 19) ^ S(x, 61) ^ R(x, 6)) 85 | #ifndef MIN 86 | #define MIN(x, y) ( ((x)<(y))?(x):(y) ) 87 | #endif 88 | 89 | 90 | static int sha512_compress(sha512_context *md, unsigned char *buf) 91 | { 92 | uint64_t S[8], W[80], t0, t1; 93 | int i; 94 | 95 | 96 | for (i = 0; i < 8; i++) { 97 | S[i] = md->state[i]; 98 | } 99 | 100 | 101 | for (i = 0; i < 16; i++) { 102 | LOAD64H(W[i], buf + (8*i)); 103 | } 104 | 105 | 106 | for (i = 16; i < 80; i++) { 107 | W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16]; 108 | } 109 | 110 | 111 | #define RND(a,b,c,d,e,f,g,h,i) \ 112 | t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \ 113 | t1 = Sigma0(a) + Maj(a, b, c);\ 114 | d += t0; \ 115 | h = t0 + t1; 116 | 117 | for (i = 0; i < 80; i += 8) { 118 | RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i+0); 119 | RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],i+1); 120 | RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],i+2); 121 | RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],i+3); 122 | RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],i+4); 123 | RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],i+5); 124 | RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],i+6); 125 | RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],i+7); 126 | } 127 | 128 | #undef RND 129 | 130 | 131 | 132 | 133 | for (i = 0; i < 8; i++) { 134 | md->state[i] = md->state[i] + S[i]; 135 | } 136 | 137 | return 0; 138 | } 139 | 140 | 141 | /** 142 | Initialize the hash state 143 | @param md The hash state you wish to initialize 144 | @return 0 if successful 145 | */ 146 | int sha512_init(sha512_context * md) { 147 | if (md == NULL) return 1; 148 | 149 | md->curlen = 0; 150 | md->length = 0; 151 | md->state[0] = UINT64_C(0x6a09e667f3bcc908); 152 | md->state[1] = UINT64_C(0xbb67ae8584caa73b); 153 | md->state[2] = UINT64_C(0x3c6ef372fe94f82b); 154 | md->state[3] = UINT64_C(0xa54ff53a5f1d36f1); 155 | md->state[4] = UINT64_C(0x510e527fade682d1); 156 | md->state[5] = UINT64_C(0x9b05688c2b3e6c1f); 157 | md->state[6] = UINT64_C(0x1f83d9abfb41bd6b); 158 | md->state[7] = UINT64_C(0x5be0cd19137e2179); 159 | 160 | return 0; 161 | } 162 | 163 | /** 164 | Process a block of memory though the hash 165 | @param md The hash state 166 | @param in The data to hash 167 | @param inlen The length of the data (octets) 168 | @return 0 if successful 169 | */ 170 | int sha512_update (sha512_context * md, const unsigned char *in, size_t inlen) 171 | { 172 | size_t n; 173 | size_t i; 174 | int err; 175 | if (md == NULL) return 1; 176 | if (in == NULL) return 1; 177 | if (md->curlen > sizeof(md->buf)) { 178 | return 1; 179 | } 180 | while (inlen > 0) { 181 | if (md->curlen == 0 && inlen >= 128) { 182 | if ((err = sha512_compress (md, (unsigned char *)in)) != 0) { 183 | return err; 184 | } 185 | md->length += 128 * 8; 186 | in += 128; 187 | inlen -= 128; 188 | } else { 189 | n = MIN(inlen, (128 - md->curlen)); 190 | 191 | for (i = 0; i < n; i++) { 192 | md->buf[i + md->curlen] = in[i]; 193 | } 194 | 195 | 196 | md->curlen += n; 197 | in += n; 198 | inlen -= n; 199 | if (md->curlen == 128) { 200 | if ((err = sha512_compress (md, md->buf)) != 0) { 201 | return err; 202 | } 203 | md->length += 8*128; 204 | md->curlen = 0; 205 | } 206 | } 207 | } 208 | return 0; 209 | } 210 | 211 | /** 212 | Terminate the hash to get the digest 213 | @param md The hash state 214 | @param out [out] The destination of the hash (64 bytes) 215 | @return 0 if successful 216 | */ 217 | int sha512_final(sha512_context * md, unsigned char *out) 218 | { 219 | int i; 220 | 221 | if (md == NULL) return 1; 222 | if (out == NULL) return 1; 223 | 224 | if (md->curlen >= sizeof(md->buf)) { 225 | return 1; 226 | } 227 | 228 | 229 | md->length += md->curlen * UINT64_C(8); 230 | 231 | 232 | md->buf[md->curlen++] = (unsigned char)0x80; 233 | 234 | /* if the length is currently above 112 bytes we append zeros 235 | * then compress. Then we can fall back to padding zeros and length 236 | * encoding like normal. 237 | */ 238 | if (md->curlen > 112) { 239 | while (md->curlen < 128) { 240 | md->buf[md->curlen++] = (unsigned char)0; 241 | } 242 | sha512_compress(md, md->buf); 243 | md->curlen = 0; 244 | } 245 | 246 | /* pad upto 120 bytes of zeroes 247 | * note: that from 112 to 120 is the 64 MSB of the length. We assume that you won't hash 248 | * > 2^64 bits of data... :-) 249 | */ 250 | while (md->curlen < 120) { 251 | md->buf[md->curlen++] = (unsigned char)0; 252 | } 253 | 254 | 255 | STORE64H(md->length, md->buf+120); 256 | sha512_compress(md, md->buf); 257 | 258 | 259 | for (i = 0; i < 8; i++) { 260 | STORE64H(md->state[i], out+(8*i)); 261 | } 262 | 263 | return 0; 264 | } 265 | 266 | int sha512(const unsigned char *message, size_t message_len, unsigned char *out) 267 | { 268 | sha512_context ctx; 269 | int ret; 270 | if ((ret = sha512_init(&ctx))) return ret; 271 | if ((ret = sha512_update(&ctx, message, message_len))) return ret; 272 | if ((ret = sha512_final(&ctx, out))) return ret; 273 | return 0; 274 | } 275 | -------------------------------------------------------------------------------- /sha512.h: -------------------------------------------------------------------------------- 1 | #ifndef SHA512_H 2 | #define SHA512_H 3 | 4 | #include 5 | 6 | #include "fixedint.h" 7 | 8 | 9 | typedef struct sha512_context_ { 10 | uint64_t length, state[8]; 11 | size_t curlen; 12 | unsigned char buf[128]; 13 | } sha512_context; 14 | 15 | 16 | int sha512_init(sha512_context * md); 17 | int sha512_final(sha512_context * md, unsigned char *out); 18 | int sha512_update(sha512_context * md, const unsigned char *in, size_t inlen); 19 | int sha512(const unsigned char *message, size_t message_len, unsigned char *out); 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /sign.c: -------------------------------------------------------------------------------- 1 | #include "ed25519.h" 2 | #include "sha512.h" 3 | #include "ge.h" 4 | #include "sc.h" 5 | 6 | 7 | void ed25519_sign(unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key, const unsigned char *private_key) { 8 | sha512_context hash; 9 | unsigned char hram[64]; 10 | unsigned char r[64]; 11 | ge_p3 R; 12 | 13 | 14 | sha512_init(&hash); 15 | sha512_update(&hash, private_key + 32, 32); 16 | sha512_update(&hash, message, message_len); 17 | sha512_final(&hash, r); 18 | 19 | sc_reduce(r); 20 | ge_scalarmult_base(&R, r); 21 | ge_p3_tobytes(signature, &R); 22 | 23 | sha512_init(&hash); 24 | sha512_update(&hash, signature, 32); 25 | sha512_update(&hash, public_key, 32); 26 | sha512_update(&hash, message, message_len); 27 | sha512_final(&hash, hram); 28 | 29 | sc_reduce(hram); 30 | sc_muladd(signature + 32, hram, private_key, r); 31 | } 32 | -------------------------------------------------------------------------------- /verify.c: -------------------------------------------------------------------------------- 1 | #include "ed25519.h" 2 | #include "sha512.h" 3 | #include "ge.h" 4 | #include "sc.h" 5 | 6 | static int consttime_equal(const unsigned char *x, const unsigned char *y) { 7 | unsigned char r = 0; 8 | 9 | r = x[0] ^ y[0]; 10 | #define F(i) r |= x[i] ^ y[i] 11 | F(1); 12 | F(2); 13 | F(3); 14 | F(4); 15 | F(5); 16 | F(6); 17 | F(7); 18 | F(8); 19 | F(9); 20 | F(10); 21 | F(11); 22 | F(12); 23 | F(13); 24 | F(14); 25 | F(15); 26 | F(16); 27 | F(17); 28 | F(18); 29 | F(19); 30 | F(20); 31 | F(21); 32 | F(22); 33 | F(23); 34 | F(24); 35 | F(25); 36 | F(26); 37 | F(27); 38 | F(28); 39 | F(29); 40 | F(30); 41 | F(31); 42 | #undef F 43 | 44 | return !r; 45 | } 46 | 47 | int ed25519_verify(const unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key) { 48 | unsigned char h[64]; 49 | unsigned char checker[32]; 50 | sha512_context hash; 51 | ge_p3 A; 52 | ge_p2 R; 53 | 54 | if (signature[63] & 224) { 55 | return 0; 56 | } 57 | 58 | if (ge_frombytes_negate_vartime(&A, public_key) != 0) { 59 | return 0; 60 | } 61 | 62 | sha512_init(&hash); 63 | sha512_update(&hash, signature, 32); 64 | sha512_update(&hash, public_key, 32); 65 | sha512_update(&hash, message, message_len); 66 | sha512_final(&hash, h); 67 | 68 | sc_reduce(h); 69 | ge_double_scalarmult_vartime(&R, h, &A, signature + 32); 70 | ge_tobytes(checker, &R); 71 | 72 | if (!consttime_equal(checker, signature)) { 73 | return 0; 74 | } 75 | 76 | return 1; 77 | } 78 | --------------------------------------------------------------------------------