├── 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 | 
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 | 
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 | 
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 | 
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 | 
108 |
109 | For Ethereum and Solana respectively
110 |
111 | 
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 | 
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 | 
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 | 
126 | 
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 | 
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 | 
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 | 
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 | 
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 | 
221 |
222 | Для Эфира и Соланы соответственно
223 |
224 | 
225 |
226 | 6) режим энтропии
227 | `MnemonicC.exe -c cusexS -d der.txt -b bloom.blf -in -f test.txt -entropy -n 5 -step 1`
228 | 
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 | 
234 |
235 | # Для счастливых обладателей процессоров AMD Threadripper
236 | Программа умеет работать со всеми ядрами и потоками, важно что-бы сам процессор в БИОС был разблокирован, т.е. мог использовать больше мощности, чем в стоке
237 | Пример на Threadripper PRO 7995WX
238 | 
239 | 
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 |
--------------------------------------------------------------------------------