├── .github └── workflows │ └── build-test.yml ├── .gitignore ├── .gitmodules ├── CMakeLists.txt ├── LICENSE ├── README.md ├── build_and_test.sh ├── include ├── Monocypher.hh ├── monocypher.h └── monocypher │ ├── base.hh │ ├── encryption.hh │ ├── ext │ ├── blake3.hh │ ├── ed25519.hh │ ├── sha256.hh │ ├── sha512.hh │ └── xsalsa20.hh │ ├── hash.hh │ ├── key_derivation.hh │ ├── key_exchange.hh │ └── signatures.hh ├── src ├── Monocypher+blake3.cc ├── Monocypher+sha256.cc ├── Monocypher+xsalsa20.cc ├── Monocypher-ed25519.cc └── Monocypher.cc ├── tests ├── CaseListReporter.hh ├── MonocypherCppTests.cc ├── Test_Blake3.cc ├── hexString.hh └── tests_main.cc └── vendor ├── B-Con ├── sha256.c └── sha256.h ├── catch2 └── catch.hpp └── tweetnacl ├── tweetnacl.c └── tweetnacl.h /.github/workflows/build-test.yml: -------------------------------------------------------------------------------- 1 | name: Build+Test 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | build: 11 | name: Build and test 12 | 13 | strategy: 14 | matrix: 15 | os: [ubuntu-latest, macOS-latest, windows-latest] 16 | runs-on: ${{ matrix.os }} 17 | 18 | steps: 19 | - name: checkout 20 | uses: actions/checkout@v2 21 | - name: checkout submodules 22 | run: git submodule update --init --recursive 23 | - name: build and test 24 | run: ./build_and_test.sh 25 | shell: bash 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build_cmake 2 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "vendor/monocypher"] 2 | path = vendor/monocypher 3 | url = https://github.com/snej/Monocypher.git 4 | [submodule "vendor/BLAKE3"] 5 | path = vendor/BLAKE3 6 | url = https://github.com/BLAKE3-team/BLAKE3.git 7 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | 3 | project(MonocypherCpp 4 | VERSION 1.2 5 | DESCRIPTION "C++ bindings for Monocypher crypto library, and more" 6 | LANGUAGES C CXX 7 | ) 8 | 9 | option(MONOCYPHER_ENABLE_BLAKE3 "Adds the Blake3 digest algorithm" ON) 10 | 11 | if (MONOCYPHER_ENABLE_BLAKE3) 12 | add_subdirectory(vendor/BLAKE3/c) 13 | endif() 14 | 15 | set(CMAKE_CXX_STANDARD 17) 16 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 17 | set(CMAKE_C_STANDARD 11) 18 | set(CMAKE_C_STANDARD_REQUIRED ON) 19 | 20 | if (MSVC) 21 | add_compile_options(/W4) # TODO: Add /WX 22 | else() 23 | add_compile_options(-Wall -Wpedantic -Werror) 24 | endif() 25 | 26 | include_directories( 27 | "include/" 28 | ) 29 | 30 | 31 | #### MAIN LIBRARY 32 | 33 | 34 | add_library( MonocypherCpp STATIC 35 | src/Monocypher.cc 36 | src/Monocypher-ed25519.cc 37 | src/Monocypher+sha256.cc 38 | src/Monocypher+xsalsa20.cc 39 | ) 40 | 41 | if (NOT MSVC) 42 | set_source_files_properties( 43 | src/Monocypher+xsalsa20.cc PROPERTIES COMPILE_OPTIONS "-Wno-sign-compare" 44 | ) 45 | endif() 46 | 47 | if (MONOCYPHER_ENABLE_BLAKE3) 48 | target_sources( MonocypherCpp PRIVATE 49 | src/Monocypher+blake3.cc 50 | ) 51 | target_include_directories( MonocypherCpp PRIVATE 52 | vendor/BLAKE3/c/ 53 | ) 54 | target_link_libraries( MonocypherCpp INTERFACE 55 | blake3 56 | ) 57 | endif() 58 | 59 | 60 | #### TESTS 61 | 62 | 63 | add_executable( MonocypherCppTests 64 | tests/MonocypherCppTests.cc 65 | tests/tests_main.cc 66 | ) 67 | 68 | if (MONOCYPHER_ENABLE_BLAKE3) 69 | target_sources( MonocypherCppTests PRIVATE 70 | tests/Test_Blake3.cc 71 | ) 72 | endif() 73 | 74 | target_include_directories( MonocypherCppTests PRIVATE 75 | "vendor/catch2/" 76 | ) 77 | 78 | target_link_libraries( MonocypherCppTests PRIVATE 79 | MonocypherCpp 80 | ) 81 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | (This is a standard 2-clause BSD licence.) 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | 1. Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the 13 | distribution. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Build+Test](https://github.com/snej/monocypher-cpp/workflows/Build+Test/badge.svg) 2 | 3 | # Monocypher C++ API 4 | 5 | This is an idiomatic C++ API for [Monocypher](https://monocypher.org). Monocypher is: 6 | 7 | > an easy to use, easy to deploy, auditable crypto library written in portable C. 8 | > It approaches the size of TweetNaCl and the speed of Libsodium. 9 | 10 | This API here is: 11 | 12 | **Unofficial:** It's not part of Monocypher, but for convenience includes it as a Git submodule. 13 | 14 | **C++:** Requires C++17 or later. 15 | 16 | **Idiomatic:** Cryptographic entities are C++ classes, mostly subclasses of `std::array`. Arrays can be easily concatenated or sliced. Options like key sizes and algorithms are template parameters. Operations are methods. 17 | 18 | **Namespaced:** All symbols are in the C++ namespace `monocypher`. Nothing is defined at global scope, not even the Monocypher C API. This prevents symbol collisions in binaries that also use libSodium or OpenSSL, all of which use the same C `crypto_` prefix as regular Monocypher. 19 | 20 | **Safe:** 21 | 22 | * All keys, hashes, nonces and seeds are distinct types. For example, you can't accidentally pass a Diffie-Hellman public key (`monocypher::key_exchange::public_key`) to a function expecting an Ed25519 public key (`monocypher::public_key`). 23 | * Values are C++ `std::array` objects, which are value types, so you can't accidentally pass invalid pointers, pass a pointer to data of the wrong size, or return a dangling pointer to a local array. 24 | * Private keys and other sensitive data are automaticaly zeroed out when destructed, to avoid leaving secrets in memory. 25 | * The `==` and `!=` operators use constant-time comparisons instead of regular `memcmp`, to avoid timing attacks. 26 | * Concatenating data in memory (to encrypt or digest it) is easy and safe thanks to the `|` operator, unlike the typical series of fragile `memcpy` operations used in C, where it's too easy to get offsets or array sizes wrong. 27 | 28 | ## Features 29 | 30 | | Functionality | Algorithm(s) | 31 | | --------------------------- | ---------------------------------------- | 32 | | Cryptographic digests | Blake2b, SHA-512, *Blake3\**, *SHA-256\**| 33 | | Password-to-key derivation | Argon2i | 34 | | Diffie-Hellman key exchange | Curve25519 (raw or with HChaCha20) | 35 | | Authenticated encryption | XChaCha20 *or XSalsa20\**, with Poly1305 | 36 | | Digital signatures | Ed25519 (with Blake2b or SHA-512) | 37 | 38 | \* denotes optional algorithms not implemented in Monocypher itself. XSalsa20 is from [tweetnacl](https://tweetnacl.cr.yp.to), SHA-256 is from Brad Conte’s [crypto-algorithms](https://github.com/B-Con/crypto-algorithms) (both public-domain), and Blake3 is from the [reference C implementation](https://github.com/BLAKE3-team/BLAKE3/blob/master/c) (Apache2 or CC). 39 | 40 | ## Using it 41 | 42 | You should be OK on recent versions of Linux, Windows, and Apple platforms, using up-to-date versions of Clang, GCC or MSVC, and CMake 3.16 or later. That's what the CI tests cover. 43 | 44 | 1. If you haven't already, get the Monocypher submodule by running `git submodule update --init`. 45 | 2. Run the script `build_and_test.sh`. This uses CMake to build the library and some unit tests, and runs the tests. 46 | 47 | If your project uses CMake to build, all you hve to do is update your `CMakeLists.txt`, adding the line `add_subdirectory(monocypher-cpp)` and adding `MonocypherCpp` to your target's `target_link_libraries`. 48 | 49 | If you don't use CMake: 50 | 1. Add the `include` directory to your compiler's include path. 51 | 2. Add `src/Monocypher.cc` to your project's source file list. 52 | 3. `#include "Monocypher.hh"` in source files where you want to use Monocypher. 53 | 4. If you need to use Ed25519 signatures or SHA-512 digests, also compile `src/Monocypher-ed25519.cc` and `#include "Monocypher-ed25519.hh"`. Ditto for SHA-256, XSalsa20, which have their own headers and source files. 54 | 5. Blake3 is somewhat harder to build because you also need to build the code in `vendor/BLAKE3/c`, which has some specializations for different CPU types. 55 | 56 | After building, read the [Monocypher documentation](https://monocypher.org/manual/) to learn how to use the API! The correspondence between the functions documented there, and the classes/methods here, should be clear. You can also consult `tests/MonocypherCppTests.cc` as a source of examples. 57 | 58 | > ⚠️ You do _not_ need to compile or include the Monocypher C files in `vendor/monocypher/`. The C++ source files compile and include them for you indirectly, wrapping their symbols in a C++ namespace. 59 | 60 | ## Change Log 61 | 62 | ### 28 May 2024 -- Added Blake3 63 | 64 | ### 24 Oct 2023 -- Monocypher 4.0.2 65 | 66 | ### 10 April 2023 -- Monocypher 4.0.1 67 | 68 | Upgraded the Monocypher library from 3.1.3 to 4.0.1. There were a lot of API changes in the C API, but most of them don't affect the C++ API. I've even added (trivial) wrappers for some functionality that was removed. 69 | 70 | The change you _will_ notice is to the signature API. Monocypher used to keep the Ed25519 secret and public keys separate. But in 4.0 Loup decided to include the public key in the secret key, as libSodium does. This is because signing and verification use both keys, and there was a danger that application code might accidentally pass a mismatched pair, producing garbage results. The C API now only takes the secret key, which is actually both keys in one. 71 | 72 | I already had a `key_pair` struct that combined the two keys, so that stays the same. The breaking change is that **`signing_key` is now renamed `key_pair::seed`**, and you can't use it directly to sign and verify anymore; only the `key_pair` does that. Wherever you were signing and verifying with the `signing_key`, alone, you'll now need to construct a `key_pair` from it and then call the `key_pair`. Also consider changing your code to use `key_pair` instead of `seed`; it's only 32 bytes larger and you'll save time on every signature or verification. 73 | 74 | PS: When reading the Monocypher C API docs, keep in mind that what they call the "secret key" corresponds to the `key_pair` struct in the C++ API. 75 | 76 | ## To-Do 77 | 78 | * iostream adapters for incremental operations. 79 | * A clean way to get a `byte_array` pointing to crypto data at some address. Currently you can just do e.g. `((public_key*)keyPtr)->check(...)`. 80 | 81 | ## Caveats 82 | 83 | * Monocypher doesn't supply its own random-number generator API. I've provided `byte_array::randomize()`, which tries to call `arc4_randombuf` where available. The fallback is `std::random_device`, which usually wraps the platform's RNG. But if your platform has no secure RNG (probably only true on embedded systems...) then `random_device` will happily provide low-entry pseudorandom output, which could lead to security problems. In that case you'll need to find your own source of randomness and modify the `randomize()` method to call it instead. 84 | * The tests in this repository are far from exhaustive. Since Monocypher itself does the hard work, and is well-tested, my tests mostly just ensure that the C++ wrappers themselves are usable and seem to provide sane output. 85 | -------------------------------------------------------------------------------- /build_and_test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -e 2 | 3 | if [ ! -d vendor/monocypher/src ] 4 | then 5 | echo "vendor/monocypher is missing! (Try running 'git submodule update --init')" 6 | exit 1 7 | fi 8 | 9 | echo "Building..." 10 | 11 | mkdir -p build_cmake 12 | cd build_cmake 13 | cmake .. 14 | cmake --build . 15 | 16 | echo "Running tests..." 17 | 18 | if [ -e Debug/MonocypherCppTests.exe ] 19 | then 20 | Debug/MonocypherCppTests.exe -r list 21 | else 22 | ./MonocypherCppTests -r list 23 | fi 24 | -------------------------------------------------------------------------------- /include/Monocypher.hh: -------------------------------------------------------------------------------- 1 | // 2 | // Monocypher.hh 3 | // 4 | // Monocypher-Cpp: Unofficial idiomatic C++17 wrapper for Monocypher 5 | // 6 | // 7 | // Copyright (c) 2020 Jens Alfke. All rights reserved. 8 | // 9 | // --- Standard 2-clause BSD licence follows --- 10 | // Redistribution and use in source and binary forms, with or without 11 | // modification, are permitted provided that the following conditions are 12 | // met: 13 | // 14 | // 1. Redistributions of source code must retain the above copyright 15 | // notice, this list of conditions and the following disclaimer. 16 | // 17 | // 2. Redistributions in binary form must reproduce the above copyright 18 | // notice, this list of conditions and the following disclaimer in the 19 | // documentation and/or other materials provided with the 20 | // distribution. 21 | // 22 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 25 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 26 | // HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 27 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 28 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 32 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 | 34 | #pragma once 35 | 36 | // This is an "umbrella header" for all the core Monocypher headers. 37 | // Look in monocypher/ext/ for additional headers. 38 | 39 | #include "monocypher/base.hh" 40 | #include "monocypher/hash.hh" 41 | #include "monocypher/key_derivation.hh" 42 | #include "monocypher/key_exchange.hh" 43 | #include "monocypher/encryption.hh" 44 | #include "monocypher/signatures.hh" 45 | -------------------------------------------------------------------------------- /include/monocypher.h: -------------------------------------------------------------------------------- 1 | // 2 | // monocypher.h 3 | // 4 | // Monocypher-Cpp: Unofficial idiomatic C++17 wrapper for Monocypher 5 | // 6 | // 7 | // This is just a shim so that you can include the regular Monocypher C header 8 | // without having to also add vendor/monocypher/src to the include-path too. 9 | 10 | #ifndef MONOCYPHER_H 11 | #include "../vendor/monocypher/src/monocypher.h" 12 | #endif 13 | -------------------------------------------------------------------------------- /include/monocypher/base.hh: -------------------------------------------------------------------------------- 1 | // 2 | // monocypher/base.hh 3 | // 4 | // Monocypher-Cpp: Unofficial idiomatic C++17 wrapper for Monocypher 5 | // 6 | // 7 | // Copyright (c) 2022 Jens Alfke. All rights reserved. 8 | // 9 | // --- Standard 2-clause BSD licence follows --- 10 | // Redistribution and use in source and binary forms, with or without 11 | // modification, are permitted provided that the following conditions are 12 | // met: 13 | // 14 | // 1. Redistributions of source code must retain the above copyright 15 | // notice, this list of conditions and the following disclaimer. 16 | // 17 | // 2. Redistributions in binary form must reproduce the above copyright 18 | // notice, this list of conditions and the following disclaimer in the 19 | // documentation and/or other materials provided with the 20 | // distribution. 21 | // 22 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 25 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 26 | // HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 27 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 28 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 32 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 | 34 | #pragma once 35 | #define MONOCYPHER_CPP_NAMESPACE monocypher::c 36 | #include "../../vendor/monocypher/src/monocypher.h" 37 | 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | 45 | namespace monocypher { 46 | 47 | //======== Utilities: 48 | 49 | static inline const uint8_t* u8(const void *p) {return static_cast(p);} 50 | static inline uint8_t* u8(void *p) {return static_cast(p);} 51 | 52 | 53 | /// Fills the array with cryptographically-secure random bytes. 54 | /// \warning On platforms where `arc4random` is unavailable, this uses `std::random_device`. 55 | /// The C++ standard says "random_device may be implemented in terms of an implementation- 56 | /// defined pseudo-random number engine if a non-deterministic source (e.g. a hardware 57 | /// device) is not available to the implementation." In that situation you should try to use 58 | /// some other source of randomization. 59 | void randomize(void *dst, size_t size); 60 | 61 | /// Securely fills memory with zeroes. 62 | /// Unlike a regular `memset` this cannot be optimized away by the compiler. 63 | static inline void wipe(void *dst, size_t size) {c::crypto_wipe(dst, size);} 64 | 65 | /// Constant-time memory comparison, used to avoid timing attacks. 66 | /// @note This returns `bool`, not `int` like `memcmp` or `crypto_verify`! 67 | bool constant_time_compare(const void *a, const void *b, size_t size); 68 | 69 | 70 | /// General-purpose byte array. Used for hashes, nonces, MACs, etc. 71 | template 72 | class byte_array: public std::array { 73 | public: 74 | static constexpr size_t byte_count = Size; 75 | 76 | explicit byte_array() = default; 77 | explicit byte_array(uint8_t b) {::memset(this->data(), b, Size);} 78 | explicit byte_array(const std::array &a) :std::array(a) { } 79 | explicit byte_array(const void *bytes, size_t size) {fillWith(bytes, size);} 80 | 81 | /// Fills the array with cryptographically-secure random bytes. 82 | /// \warning See the above warning on the standalone `randomize` function. 83 | void randomize() {monocypher::randomize(this->data(), Size);} 84 | 85 | /// Securely fills the array with zeroes. Unlike a regular `memset` this cannot be optimized 86 | /// away even if the array is about to be destructed. 87 | void wipe() {c::crypto_wipe(this->data(), Size);} 88 | 89 | /// Idiomatic synonym for `wipe`. 90 | void clear() {this->wipe();} 91 | 92 | void fill(uint8_t b) { // "overridden" to use `wipe` first 93 | this->wipe(); 94 | if (b != 0) std::array::fill(b); // (wipe already fills with 0) 95 | } 96 | 97 | void fillWith(const void *bytes, size_t size) { 98 | assert(size == sizeof(*this)); 99 | ::memcpy(this->data(), bytes, sizeof(*this)); 100 | } 101 | 102 | void fillWithString(const char *str) { 103 | clear(); 104 | ::memcpy(this->data(), str, std::min(strlen(str), Size)); 105 | } 106 | 107 | /// Returns a subrange of this array, as a mutable reference. 108 | template 109 | byte_array& range() { 110 | static_assert(Pos + Len <= Size); 111 | return reinterpret_cast&>((*this)[Pos]); 112 | } 113 | 114 | /// Returns a subrange of this array, as a reference. 115 | template 116 | byte_array const& range() const { 117 | static_assert(Pos + Len <= Size); 118 | return reinterpret_cast const&>((*this)[Pos]); 119 | } 120 | 121 | /// The `|` operator concatenates two arrays. It's mathematical! 122 | template 123 | byte_array operator| (byte_array const& other) const { 124 | byte_array result; 125 | result.template range<0,Size>() = *this; 126 | result.template range() = other; 127 | return result; 128 | } 129 | 130 | /// Treats the array as a little-endian base-256 integer, and adds 1 to it. 131 | void increment() { 132 | for (size_t i = 0; i < Size; ++i) { 133 | if (++(*this)[i] != 0) 134 | break; 135 | } 136 | } 137 | 138 | explicit operator uint8_t*() {return this->data();} 139 | explicit operator const uint8_t*() const {return this->data();} 140 | }; 141 | 142 | 143 | /// Byte-array of secret data. Its destructor securely erases the contents. 144 | /// Used for private keys and shared secrets. 145 | template 146 | class secret_byte_array: public byte_array { 147 | public: 148 | explicit secret_byte_array() = default; 149 | explicit secret_byte_array(uint8_t b) :byte_array(b) { } 150 | explicit secret_byte_array(const std::array &a) :byte_array(a) { } 151 | explicit secret_byte_array(const void *p, size_t s) :byte_array(p, s) { } 152 | ~secret_byte_array() {this->wipe();} 153 | 154 | template 155 | secret_byte_array operator| (byte_array const& other) const { 156 | secret_byte_array result; 157 | result.template range<0,Size>() = *this; 158 | result.template range() = other; 159 | return result; 160 | } 161 | }; 162 | 163 | 164 | 165 | // byte_arrays use constant-time comparison. 166 | template 167 | static inline bool operator== (const byte_array &a, const byte_array &b) { 168 | static_assert(Size % 16 == 0); 169 | return constant_time_compare(a.data(), b.data(), Size); 170 | } 171 | 172 | template 173 | static inline bool operator!= (const byte_array &a, const byte_array &b) { 174 | return !(a == b); 175 | } 176 | 177 | // specialized comparisons for common sizes 178 | template<> inline bool operator== (const byte_array<16> &a, const byte_array<16> &b) { 179 | return 0 == c::crypto_verify16(a.data(), b.data()); 180 | } 181 | template<> inline bool operator== (const byte_array<24> &a, const byte_array<24> &b) { 182 | return 0 == c::crypto_verify16(a.data(), b.data()) && 0 == c::crypto_verify16(&a[8], &b[8]); 183 | } 184 | template<> inline bool operator== (const byte_array<32> &a, const byte_array<32> &b) { 185 | return 0 == c::crypto_verify32(a.data(), b.data()); 186 | } 187 | template<> inline bool operator== (const byte_array<64> &a, const byte_array<64> &b) { 188 | return 0 == c::crypto_verify64(a.data(), b.data()); 189 | } 190 | 191 | 192 | /// Variable-length data input to a function. Implicit conversion from string and array. 193 | struct input_bytes { 194 | uint8_t const* data; 195 | size_t size; 196 | 197 | input_bytes(const void *d, size_t s) :data(u8(d)), size(s) { } 198 | input_bytes(std::string_view str) :input_bytes(str.data(), str.size()) { } 199 | input_bytes(std::string const& str) :input_bytes(str.data(), str.size()) { } 200 | 201 | template 202 | input_bytes(byte_array const& a) :data(a.data()), size(a.size()) { } 203 | 204 | void consume(size_t n) {assert(n <= size); data += n; size -= n;} 205 | }; 206 | 207 | 208 | /// Variable-length mutable data to be returned from a function. 209 | struct output_bytes { 210 | void* data; 211 | size_t size; 212 | 213 | output_bytes() :data(nullptr), size(0) { } 214 | output_bytes(void *d, size_t s) :data(d), size(s) { } 215 | 216 | template 217 | output_bytes(byte_array &a) :data(a.data()), size(a.size()) { } 218 | 219 | output_bytes shrunk_to(size_t s) const {assert(s <= size); return {data, s};} 220 | 221 | explicit operator bool() const {return data != nullptr;} 222 | }; 223 | 224 | } 225 | -------------------------------------------------------------------------------- /include/monocypher/encryption.hh: -------------------------------------------------------------------------------- 1 | // 2 | // monocypher/encryption.hh 3 | // 4 | // Monocypher-Cpp: Unofficial idiomatic C++17 wrapper for Monocypher 5 | // 6 | // 7 | // Copyright (c) 2022 Jens Alfke. All rights reserved. 8 | // 9 | // --- Standard 2-clause BSD licence follows --- 10 | // Redistribution and use in source and binary forms, with or without 11 | // modification, are permitted provided that the following conditions are 12 | // met: 13 | // 14 | // 1. Redistributions of source code must retain the above copyright 15 | // notice, this list of conditions and the following disclaimer. 16 | // 17 | // 2. Redistributions in binary form must reproduce the above copyright 18 | // notice, this list of conditions and the following disclaimer in the 19 | // documentation and/or other materials provided with the 20 | // distribution. 21 | // 22 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 25 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 26 | // HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 27 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 28 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 32 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 | 34 | #pragma once 35 | #include "base.hh" 36 | 37 | namespace monocypher { 38 | using namespace MONOCYPHER_CPP_NAMESPACE; 39 | 40 | struct XChaCha20_Poly1305; 41 | 42 | // Namespace for symmetric session-key-based encryption. 43 | namespace session { 44 | 45 | /// A one-time-use value to be sent along with an encrypted message. 46 | /// @warning A nonce value should never be used more than once with any one session key! 47 | struct nonce : public byte_array<24> { 48 | /// Constructs a randomized nonce. 49 | nonce() {randomize();} 50 | 51 | /// Constructs a nonce containing the number `n` in little-endian encoding. 52 | /// @note Only 64 bits are set; the last 128 bits of the nonce are set to 0. 53 | explicit nonce(uint64_t n) { 54 | for (size_t i = 0; i < 24; ++i, n >>= 8) 55 | (*this)[i] = uint8_t(n & 0xFF); 56 | } 57 | 58 | explicit nonce(const std::array &a) :byte_array<24>(a) { } 59 | 60 | nonce& operator= (uint64_t n) {*this = nonce(n); return *this;} 61 | 62 | /// Convenience function to increment a nonce (interpreted as 192-bit little-endian.) 63 | nonce& operator++ () { 64 | increment(); 65 | return *this; 66 | } 67 | }; 68 | 69 | 70 | /// A Message Authentication Code, to be sent along with an encrypted message. 71 | /// (Like a signature, but can only be verified by someone who knows the session key.) 72 | struct mac : public byte_array<16> { }; 73 | 74 | 75 | namespace { // internal stuff 76 | constexpr size_t boxedSize(size_t plaintextSize) { 77 | return plaintextSize + sizeof(mac); 78 | } 79 | 80 | constexpr size_t unboxedSize(size_t ciphertextSize) { 81 | return std::max(ciphertextSize, sizeof(mac)) - sizeof(mac); 82 | } 83 | 84 | // callback signature is `mac cb(uint8_t *out)` 85 | template 86 | output_bytes _box(output_bytes output_buffer, size_t msg_size, Callback cb) { 87 | output_buffer = output_buffer.shrunk_to(boxedSize(msg_size)); 88 | auto mac_p = (mac*)output_buffer.data; 89 | *mac_p = cb(mac_p + 1); 90 | return output_buffer; 91 | } 92 | 93 | // callback signature is `bool cb(mac const&, input_buffer, uint8_t* out)` 94 | template 95 | [[nodiscard]] 96 | output_bytes _unbox(output_bytes output_buffer, input_bytes boxed_cipher_text, Callback cb) { 97 | if (boxed_cipher_text.size < sizeof(mac)) 98 | return {}; 99 | output_buffer = output_buffer.shrunk_to(unboxedSize(boxed_cipher_text.size)); 100 | auto mac_p = (const mac*)boxed_cipher_text.data; 101 | if (!cb(*mac_p, input_bytes{mac_p + 1, output_buffer.size}, output_buffer.data)) 102 | return {}; 103 | return output_buffer; 104 | } 105 | } 106 | 107 | 108 | /// A session key for _symmetric_ encryption/decryption -- both sides must use the same key. 109 | /// Consider using the shared secret produced by `key_exchange` as the key. 110 | template 111 | struct encryption_key : public secret_byte_array<32> { 112 | encryption_key() {randomize();} 113 | explicit encryption_key(const std::array &a) :secret_byte_array<32>(a) { } 114 | encryption_key(const void *data, size_t size) :secret_byte_array<32>(data, size) { } 115 | explicit encryption_key(input_bytes k3y) :encryption_key(k3y.data, k3y.size) { } 116 | 117 | /// Encrypts `plain_text`, writing the result to `cipher_text` and producing a `mac`. 118 | /// The MAC _must_ be sent along with the ciphertext. 119 | /// 120 | /// The nonce used must be known to the recipient; you can send it too, or you can use 121 | /// a protocol that ensures both parties start with the same nonce and keep them in 122 | /// sync, e.g. by incrementing. 123 | /// Just remember that you must **never reuse a nonce** with the same key! 124 | /// @param nonce One-time value that must never have been used with this key before. 125 | /// @param plain_text The input data to be encrypted. 126 | /// @param text_size The length in bytes of the input data. 127 | /// @param cipher_text Where to write the encrypted output; will be the same size as 128 | /// the input. It's OK to pass the same address as `plain_text`. 129 | /// @return The Message Authentication Code. Must be sent along with the ciphertext. 130 | [[nodiscard]] 131 | mac lock(const nonce &nonce, 132 | const void *plain_text, size_t text_size, 133 | void *cipher_text) const { 134 | return lock(nonce, {plain_text, text_size}, input_bytes{nullptr, 0}, cipher_text); 135 | } 136 | 137 | [[nodiscard]] 138 | mac lock(const nonce &nonce, 139 | input_bytes plain_text, 140 | void *cipher_text) const { 141 | return lock(nonce, plain_text, input_bytes{nullptr, 0}, cipher_text); 142 | } 143 | 144 | /// Enhanced version of `lock` that includes additional data, also known as 145 | /// "authenticated data", in calculating the MAC. 146 | [[nodiscard]] 147 | mac lock(const nonce &nonce, 148 | input_bytes plain_text, 149 | input_bytes additional_data, 150 | void *cipher_text) const { 151 | fixOverlap(plain_text, cipher_text); 152 | mac out_mac; 153 | Algorithm::lock(u8(cipher_text), 154 | out_mac.data(), 155 | this->data(), 156 | nonce.data(), 157 | additional_data.data, additional_data.size, 158 | plain_text.data, plain_text.size); 159 | return out_mac; 160 | } 161 | 162 | /// Authenticates `cipher_text` using the `mac`, then decrypts it, writing the result to 163 | /// `plain_text` (which may be the same address.) 164 | /// @param nonce The same nonce value used by the `lock` call. 165 | /// @param mac The Message Authentication Code produced by the `lock` call. 166 | /// @param cipher_text The input encrypted data. 167 | /// @param text_size The length in bytes of the input data. 168 | /// @param plain_text Where to write the decrypted output; will be the same size as the 169 | /// input. It's OK to pass the same address as `cipher_text`. 170 | /// @return True on success, false if the data has been altered or corrupted. 171 | [[nodiscard]] 172 | bool unlock(const nonce &nonce, 173 | const mac &mac, 174 | const void *cipher_text, size_t text_size, 175 | void *plain_text) const 176 | { 177 | return unlock(nonce, mac, {cipher_text, text_size}, plain_text); 178 | } 179 | 180 | [[nodiscard]] 181 | bool unlock(const nonce &nonce, 182 | mac in_mac, 183 | input_bytes cipher_text, 184 | void *plain_text) const 185 | { 186 | return unlock(nonce, in_mac, cipher_text, input_bytes{nullptr, 0}, plain_text); 187 | } 188 | 189 | /// Enhanced version of `unlock` that takes additional data, also known as 190 | /// "authenticated data", used when verifying the MAC. If this data doesn't match 191 | /// that given when encrypting, the MAC will not match and decryption will fail. 192 | [[nodiscard]] 193 | bool unlock(const nonce &nonce, 194 | mac in_mac, 195 | input_bytes cipher_text, 196 | input_bytes additional_data, 197 | void *plain_text) const 198 | { 199 | fixOverlap(cipher_text, plain_text); 200 | return 0 == Algorithm::unlock(u8(plain_text), 201 | in_mac.data(), 202 | this->data(), 203 | nonce.data(), 204 | additional_data.data, additional_data.size, 205 | cipher_text.data, cipher_text.size); 206 | } 207 | 208 | 209 | //-------- Higher-level "box" convenience API 210 | 211 | 212 | /// Encrypts `plain_text`, writing the MAC and ciphertext to `output_buffer`. 213 | /// Returns `output_buffer` resized to the actual output size, which is 214 | /// `sizeof(mac) + plain_text.size`. 215 | /// \note The output data is compatible with that of libSodium's `crypto_box_easy`. 216 | output_bytes box(const nonce &nonce, 217 | input_bytes plain_text, 218 | output_bytes output_buffer) const 219 | { 220 | return _box(output_buffer, plain_text.size, 221 | [&](void *out) {return lock(nonce, plain_text, out);}); 222 | } 223 | 224 | /// A version of `box` that returns the output as a `byte_array`. 225 | /// The array **must** be the exact size of the output. 226 | template 227 | byte_array box(const nonce &nonce, 228 | input_bytes plain_text) const 229 | { 230 | assert(OutputSize == boxedSize(plain_text.size)); 231 | byte_array result; 232 | box(nonce, plain_text, result); 233 | return result; 234 | } 235 | 236 | /// Decrypts a MAC-and-ciphertext produced by `box`, into `output_buffer`. 237 | /// Returns `output_buffer` resized to the actual output size, which is 238 | /// `boxed_cipher_text.size - sizeof(mac)`, or {NULL,0} if the ciphertext is invalid. 239 | /// \note This function is compatible with libSodium's `crypto_unbox_easy`. 240 | [[nodiscard]] 241 | output_bytes unbox(const nonce &nonce, 242 | input_bytes boxed_cipher_text, 243 | output_bytes output_buffer) const 244 | { 245 | return _unbox(output_buffer, boxed_cipher_text, 246 | [&](mac const& m, input_bytes cipher, void* plain) { 247 | return unlock(nonce, m, cipher, plain); 248 | }); 249 | } 250 | 251 | /// A version of `unbox` that returns the output as a `byte_array`. 252 | template 253 | bool unbox(const nonce &nonce, 254 | input_bytes boxed_cipher_text, 255 | byte_array &output) const 256 | { 257 | output_bytes out = unbox(nonce, boxed_cipher_text, {output.data(), output.size()}); 258 | return out.size == output.size(); 259 | } 260 | 261 | private: 262 | // `crypto_lock` only allows input and output buffers to overlap if they're identical. 263 | // If the src and dst ranges overlap but are not identical, copy src to dst and set 264 | // src.data to dst. 265 | static void fixOverlap(input_bytes &src, void *dst) { 266 | if ((src.data > dst && src.data < (uint8_t*)dst + src.size) 267 | || (src.data < dst && src.data + src.size > dst)) { 268 | ::memmove(dst, src.data, src.size); 269 | src.data = (const uint8_t*)dst; 270 | } 271 | } 272 | }; 273 | 274 | using key = encryption_key; 275 | 276 | 277 | /// Lets you send a stream as a series of symmetrically-encrypted "chunks", 278 | /// which can be decrypted by an `encrypted_reader` initialized with the same key & nonce. 279 | /// 280 | /// The encryption key is changed between each chunk, providing a symmetric ratchet 281 | /// that prevents an attacker from reordering messages unnoticed. 282 | /// 283 | /// Truncation however is not detected. You must detect the last chunk manually. 284 | /// Possible methods include: 285 | /// - Putting an end-of-data marker in the plaintext of the final chunk 286 | /// - Putting a length value in the first chunk 287 | /// - Add 'additional data' to the final chunk; the reader won't be able to decrypt it 288 | /// without additional data, but will with it, signalling that this is the last. 289 | template 290 | struct encrypted_writer { 291 | /// Constructs an encrypted_writer from a symmetric key and a nonce. 292 | encrypted_writer(encryption_key const& key, nonce const& n) { 293 | Algorithm::init_stream(&_context, key.data(), n.data()); 294 | } 295 | 296 | ~encrypted_writer() {c::crypto_wipe(&_context, sizeof(_context));} 297 | 298 | /// Encrypts a chunk, producing ciphertext of the same size and a MAC. 299 | /// (It's OK to to encrypt in place.) 300 | mac write(input_bytes plain_text, 301 | void *out_ciphertext) { 302 | return write(plain_text, {nullptr, 0}, out_ciphertext); 303 | } 304 | 305 | /// Encrypts a chunk, producing ciphertext of the same size and a MAC. 306 | /// The `additional_data` is not sent, but it affects the MAC such that the reader 307 | /// must present the same data when decrypting. 308 | mac write(input_bytes plain_text, 309 | input_bytes additional_data, 310 | void *out_ciphertext) { 311 | mac m; 312 | Algorithm::write_stream(&_context, (uint8_t*)out_ciphertext, m.data(), 313 | additional_data.data, additional_data.size, 314 | plain_text.data, plain_text.size); 315 | return m; 316 | } 317 | 318 | /// Encrypts `plain_text`, writing the MAC and ciphertext to `output_buffer`. 319 | /// Returns `output_buffer` resized to the actual output size, which is 320 | /// `sizeof(mac) + plain_text.size`. 321 | output_bytes box(input_bytes plain_text, 322 | output_bytes output_buffer) { 323 | return _box(output_buffer, plain_text.size, 324 | [&](void *out) {return write(plain_text, out);}); 325 | } 326 | 327 | /// A version of `box` that takes `additional_data`. 328 | output_bytes box(input_bytes plain_text, 329 | input_bytes additional_data, 330 | output_bytes output_buffer) { 331 | return _box(output_buffer, plain_text.size, 332 | [&](void *out) {return write(plain_text, additional_data, out);}); 333 | } 334 | 335 | private: 336 | typename Algorithm::stream_context _context; 337 | }; 338 | 339 | 340 | /// Decrypts a series of symmetrically-encrypted "chunks" generated by `encrypted_writer`. 341 | /// The chunks must be decrypted in the same order in which they were written. 342 | template 343 | struct encrypted_reader { 344 | /// Constructs an encrypted_reader from a symmetric key and a nonce, which must be 345 | /// the same ones used by the sender. 346 | encrypted_reader(encryption_key const& key, nonce const& n) { 347 | Algorithm::init_stream(&_context, key.data(), n.data()); 348 | } 349 | 350 | ~encrypted_reader() {c::crypto_wipe(&_context, sizeof(_context));} 351 | 352 | /// Decrypts a chunk given its ciphertext and MAC. 353 | /// (It's OK to to decrypt in place.) 354 | /// @return True on success, false if authentication fails. 355 | [[nodiscard]] 356 | bool read(mac mac, 357 | input_bytes ciphertext, 358 | void *out_plaintext) { 359 | return read(mac, ciphertext, {nullptr, 0}, out_plaintext); 360 | } 361 | 362 | /// Decrypts a chunk given its ciphertext, MAC, 363 | /// and additional data that must match that given by the writer. 364 | /// @return True on success, false if authentication fails. 365 | [[nodiscard]] 366 | bool read(mac mac, 367 | input_bytes ciphertext, 368 | input_bytes additional_data, 369 | void *out_plaintext) { 370 | return Algorithm::read_stream(&_context, (uint8_t*)out_plaintext, mac.data(), 371 | additional_data.data, additional_data.size, 372 | ciphertext.data, ciphertext.size) == 0; 373 | } 374 | 375 | /// Decrypts a MAC-and-ciphertext produced by `encrypted_writer::box`, 376 | /// writing the plaintext to `output_buffer`. 377 | /// Returns `output_buffer` resized to the actual plaintext size, which is 378 | /// `boxed_ciphertext.size - sizeof(mac)`. 379 | /// If the ciphertext is invalid, returns `{nullptr, 0}`. 380 | [[nodiscard]] 381 | output_bytes unbox(input_bytes boxed_ciphertext, 382 | output_bytes output_buffer) { 383 | return _unbox(output_buffer, boxed_ciphertext, 384 | [&](mac const& m, input_bytes cipher, void* plain) { 385 | return read(m, cipher, plain); 386 | }); 387 | } 388 | 389 | /// A version of `unbox` that takes `additional_data`. 390 | [[nodiscard]] 391 | output_bytes unbox(input_bytes boxed_ciphertext, 392 | input_bytes additional_data, 393 | output_bytes output_buffer) { 394 | return _unbox(output_buffer, boxed_ciphertext, 395 | [&](mac const& m, input_bytes cipher, void* plain) { 396 | return read(m, cipher, additional_data, plain); 397 | }); 398 | } 399 | 400 | private: 401 | typename Algorithm::stream_context _context; 402 | }; 403 | 404 | } // end 'session' 405 | 406 | 407 | /// Default algorithm for `session::encryption_key` -- 408 | /// XChaCha20 encryption and Poly1305 authentication. 409 | /// @note This is not compatible with libSodium or NaCl, which use the XSalsa20 cipher. 410 | /// But see `XSalsa20_Poly1305`, in `Monocypher+xsalsa20.hh`. 411 | struct XChaCha20_Poly1305 { 412 | static constexpr const char* name = "XChaCha20+Poly1305"; 413 | 414 | static constexpr auto lock = c::crypto_aead_lock; 415 | static constexpr auto unlock = c::crypto_aead_unlock; 416 | 417 | static constexpr auto init_stream = c::crypto_aead_init_x; 418 | static constexpr auto write_stream = c::crypto_aead_write; 419 | static constexpr auto read_stream = c::crypto_aead_read; 420 | using stream_context = c::crypto_aead_ctx; 421 | }; 422 | 423 | } 424 | -------------------------------------------------------------------------------- /include/monocypher/ext/blake3.hh: -------------------------------------------------------------------------------- 1 | // 2 | // monocypher/ext/blake3.hh 3 | // 4 | // Monocypher-Cpp: Unofficial idiomatic C++17 wrapper for Monocypher 5 | // 6 | // 7 | // Copyright (c) 2024 Jens Alfke. All rights reserved. 8 | // 9 | // --- Standard 2-clause BSD licence follows --- 10 | // Redistribution and use in source and binary forms, with or without 11 | // modification, are permitted provided that the following conditions are 12 | // met: 13 | // 14 | // 1. Redistributions of source code must retain the above copyright 15 | // notice, this list of conditions and the following disclaimer. 16 | // 17 | // 2. Redistributions in binary form must reproduce the above copyright 18 | // notice, this list of conditions and the following disclaimer in the 19 | // documentation and/or other materials provided with the 20 | // distribution. 21 | // 22 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 25 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 26 | // HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 27 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 28 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 32 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 | 34 | #pragma once 35 | #include "../hash.hh" 36 | #include 37 | 38 | namespace monocypher::ext { 39 | 40 | struct Blake3Base { 41 | static constexpr const char* name = "BLAKE3"; 42 | using context = byte_array<1912>; 43 | static void init_fn (context *ctx); 44 | static void update_fn(context *ctx, const uint8_t *message, size_t message_size); 45 | protected: 46 | static void final_fn(context *ctx, uint8_t *hash, size_t hash_size); 47 | static void create_fn(uint8_t *hash, size_t hash_size, const uint8_t *msg, size_t msg_size); 48 | static void init_mac_fn(context *ctx, const uint8_t *key, size_t key_size); 49 | static void create_mac_fn(uint8_t *hash, size_t hash_size, 50 | const uint8_t *key, size_t key_size, 51 | const uint8_t *message, size_t message_size); 52 | }; 53 | 54 | /// The BLAKE3 digest algorithm, for use as the template parameter to `hash`. 55 | /// 56 | /// @note This functionality is NOT part of Monocypher itself. 57 | /// It uses the C reference implementation, 58 | template 59 | struct Blake3 : public Blake3Base { 60 | static constexpr size_t hash_size = Size; 61 | 62 | static void final_fn (context *ctx, uint8_t hash[Size]) { 63 | Blake3Base::final_fn(ctx, hash, hash_size); 64 | } 65 | static void create_fn(uint8_t hash[Size], const uint8_t *message, size_t message_size) { 66 | Blake3Base::create_fn(hash, hash_size, message, message_size); 67 | } 68 | 69 | /// Note: BLAKE3's HMAC algorithm requires the key to be exactly 32 bytes. 70 | struct mac { 71 | using context = Blake3::context; 72 | 73 | static void create_fn(uint8_t *hash, const uint8_t *key, size_t key_size, 74 | const uint8_t *message, size_t message_size) 75 | { 76 | Blake3Base::create_mac_fn(hash, hash_size, key, key_size, message, message_size); 77 | } 78 | static void init_fn(context *ctx, const uint8_t *key, size_t key_size) { 79 | Blake3Base::init_mac_fn(ctx, key, key_size); 80 | } 81 | static constexpr auto update_fn = Blake3::update_fn; 82 | static constexpr auto final_fn = Blake3::final_fn; 83 | }; 84 | }; 85 | 86 | /// Blake3 hash class with default 256-bit (32-byte) hash size.. 87 | using blake3 = hash>; 88 | } 89 | -------------------------------------------------------------------------------- /include/monocypher/ext/ed25519.hh: -------------------------------------------------------------------------------- 1 | // 2 | // monocypher/ext/ed25519.hh 3 | // 4 | // Monocypher-Cpp: Unofficial idiomatic C++17 wrapper for Monocypher 5 | // 6 | // 7 | // Copyright (c) 2022 Jens Alfke. All rights reserved. 8 | // 9 | // --- Standard 2-clause BSD licence follows --- 10 | // Redistribution and use in source and binary forms, with or without 11 | // modification, are permitted provided that the following conditions are 12 | // met: 13 | // 14 | // 1. Redistributions of source code must retain the above copyright 15 | // notice, this list of conditions and the following disclaimer. 16 | // 17 | // 2. Redistributions in binary form must reproduce the above copyright 18 | // notice, this list of conditions and the following disclaimer in the 19 | // documentation and/or other materials provided with the 20 | // distribution. 21 | // 22 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 25 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 26 | // HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 27 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 28 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 32 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 | 34 | #pragma once 35 | #include "../hash.hh" 36 | #include "../signatures.hh" 37 | #include "../../../vendor/monocypher/src/optional/monocypher-ed25519.h" 38 | 39 | namespace monocypher { 40 | 41 | // This functionality is an extension that comes with Monocypher. 42 | // It's not considered part of the core API, but is provided for compatibility. 43 | 44 | /// EdDSA with Curve25519 and SHA-512. 45 | /// \note This algorithm is more widely used than `EdDSA`, but slower and brings in more code. 46 | /// (Use as `` parameter to `signature`, `public_key`, `key_pair`.) 47 | struct Ed25519 { 48 | static constexpr const char* name = "Ed25519"; 49 | static constexpr auto generate_fn = c::crypto_ed25519_key_pair; 50 | static constexpr auto check_fn = c::crypto_ed25519_check; 51 | static constexpr auto sign_fn = c::crypto_ed25519_sign; 52 | static constexpr auto public_to_kx_fn = c::crypto_eddsa_to_x25519; // yup, it's the same 53 | 54 | static void private_to_kx_fn(uint8_t x25519[32], const uint8_t eddsa[32]) { 55 | // Adapted from Monocypher 3's crypto_from_ed25519_private() 56 | secret_byte_array<64> a; 57 | c::crypto_sha512(a.data(), eddsa, 32); 58 | ::memcpy(x25519, a.data(), 32); 59 | } 60 | 61 | // Convenient type aliases for those who don't like angle brackets 62 | using signature = monocypher::signature; 63 | using public_key = monocypher::public_key; 64 | using key_pair = monocypher::key_pair; 65 | }; 66 | 67 | } 68 | -------------------------------------------------------------------------------- /include/monocypher/ext/sha256.hh: -------------------------------------------------------------------------------- 1 | // 2 | // monocypher/ext/sha256.hh 3 | // 4 | // Monocypher-Cpp: Unofficial idiomatic C++17 wrapper for Monocypher 5 | // 6 | // 7 | // Copyright (c) 2022 Jens Alfke. All rights reserved. 8 | // 9 | // --- Standard 2-clause BSD licence follows --- 10 | // Redistribution and use in source and binary forms, with or without 11 | // modification, are permitted provided that the following conditions are 12 | // met: 13 | // 14 | // 1. Redistributions of source code must retain the above copyright 15 | // notice, this list of conditions and the following disclaimer. 16 | // 17 | // 2. Redistributions in binary form must reproduce the above copyright 18 | // notice, this list of conditions and the following disclaimer in the 19 | // documentation and/or other materials provided with the 20 | // distribution. 21 | // 22 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 25 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 26 | // HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 27 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 28 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 32 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 | 34 | #pragma once 35 | #include "../hash.hh" 36 | 37 | namespace monocypher::ext { 38 | 39 | /// SHA-256 algorithm, for use as the template parameter to `hash`. 40 | /// 41 | /// @note This functionality is NOT part of Monocypher itself. It's provided for compatibility. 42 | /// The implementation is Brad Conte, from . 43 | struct SHA256 { 44 | static constexpr const char* name = "SHA-256"; 45 | static constexpr size_t hash_size = 256 / 8; 46 | 47 | using context = std::array; 48 | 49 | static void init_fn (context *ctx); 50 | static void update_fn(context *ctx, const uint8_t *message, size_t message_size); 51 | static void final_fn (context *ctx, uint8_t hash[32]); 52 | static void create_fn(uint8_t hash[32], const uint8_t *message, size_t message_size); 53 | // (no MAC support, sorry) 54 | }; 55 | 56 | using sha256 = hash; 57 | } 58 | -------------------------------------------------------------------------------- /include/monocypher/ext/sha512.hh: -------------------------------------------------------------------------------- 1 | // 2 | // monocypher/ext/sha512.hh 3 | // 4 | // Monocypher-Cpp: Unofficial idiomatic C++17 wrapper for Monocypher 5 | // 6 | // 7 | // Copyright (c) 2022 Jens Alfke. All rights reserved. 8 | // 9 | // --- Standard 2-clause BSD licence follows --- 10 | // Redistribution and use in source and binary forms, with or without 11 | // modification, are permitted provided that the following conditions are 12 | // met: 13 | // 14 | // 1. Redistributions of source code must retain the above copyright 15 | // notice, this list of conditions and the following disclaimer. 16 | // 17 | // 2. Redistributions in binary form must reproduce the above copyright 18 | // notice, this list of conditions and the following disclaimer in the 19 | // documentation and/or other materials provided with the 20 | // distribution. 21 | // 22 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 25 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 26 | // HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 27 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 28 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 32 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 | 34 | #pragma once 35 | #include "../hash.hh" 36 | #include "../../../vendor/monocypher/src/optional/monocypher-ed25519.h" 37 | 38 | namespace monocypher { 39 | 40 | // This functionality is an extension that comes with Monocypher. 41 | // It's not considered part of the core API, but is provided for compatibility. 42 | 43 | /// SHA-512 algorithm, for use as the template parameter to `hash`. 44 | struct SHA512 { 45 | static constexpr const char* name = "SHA-512"; 46 | static constexpr size_t hash_size = 512 / 8; 47 | 48 | using context = c::crypto_sha512_ctx; 49 | static constexpr auto create_fn = c::crypto_sha512; 50 | static constexpr auto init_fn = c::crypto_sha512_init; 51 | static constexpr auto update_fn = c::crypto_sha512_update; 52 | static constexpr auto final_fn = c::crypto_sha512_final; 53 | 54 | struct mac { 55 | using context = c::crypto_sha512_hmac_ctx; 56 | static constexpr auto create_fn = c::crypto_sha512_hmac; 57 | static constexpr auto init_fn = c::crypto_sha512_hmac_init; 58 | static constexpr auto update_fn = c::crypto_sha512_hmac_update; 59 | static constexpr auto final_fn = c::crypto_sha512_hmac_final; 60 | }; 61 | }; 62 | 63 | using sha512 = hash; 64 | } 65 | -------------------------------------------------------------------------------- /include/monocypher/ext/xsalsa20.hh: -------------------------------------------------------------------------------- 1 | // 2 | // monocypher/ext/.hh 3 | // 4 | // Monocypher-Cpp: Unofficial idiomatic C++17 wrapper for Monocypher 5 | // 6 | // 7 | // Copyright (c) 2022 Jens Alfke. All rights reserved. 8 | // 9 | // --- Standard 2-clause BSD licence follows --- 10 | // Redistribution and use in source and binary forms, with or without 11 | // modification, are permitted provided that the following conditions are 12 | // met: 13 | // 14 | // 1. Redistributions of source code must retain the above copyright 15 | // notice, this list of conditions and the following disclaimer. 16 | // 17 | // 2. Redistributions in binary form must reproduce the above copyright 18 | // notice, this list of conditions and the following disclaimer in the 19 | // documentation and/or other materials provided with the 20 | // distribution. 21 | // 22 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 25 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 26 | // HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 27 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 28 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 32 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 | 34 | #pragma once 35 | #include "../encryption.hh" 36 | 37 | namespace monocypher::ext { 38 | 39 | /// Alternative algorithm for `session::encryption_key` -- 40 | /// XSalsa20 encryption (instead of XChaCha20) and Poly1305 authentication. 41 | /// This is compatible with libSodium and NaCl. 42 | /// 43 | /// @warning This implementation does not support "additional data". calling `encryption_key`'s 44 | /// `lock` and `unlock` methods with `additional_data` parameters will cause an assertion 45 | /// failure (in debug builds) or ignore the additional data (in release builds.) 46 | /// @warning This implementation doesn't support streaming encryption. You'll get compile 47 | /// errors if you try to use this algorithm with `encrypted_writer` or `encrypted_reader`. 48 | /// 49 | /// @note This functionality is NOT part of Monocypher itself. It's provided for compatibility. 50 | /// The implementation is from tweetnacl, by Daniel J. Bernstein et al. 51 | /// 52 | struct XSalsa20_Poly1305 { 53 | static constexpr const char* name = "XSalsa20+Poly1305"; 54 | 55 | static void lock(uint8_t *cipher_text, 56 | uint8_t mac[16], 57 | const uint8_t key[32], 58 | const uint8_t nonce[24], 59 | const uint8_t *ad, size_t ad_size, 60 | const uint8_t *plain_text, size_t text_size); 61 | 62 | static int unlock(uint8_t *plain_text, 63 | const uint8_t mac[16], 64 | const uint8_t key[32], 65 | const uint8_t nonce[24], 66 | const uint8_t *ad, size_t ad_size, 67 | const uint8_t *cipher_text, size_t text_size); 68 | }; 69 | 70 | } 71 | -------------------------------------------------------------------------------- /include/monocypher/hash.hh: -------------------------------------------------------------------------------- 1 | // 2 | // monocypher/hash.hh 3 | // 4 | // Monocypher-Cpp: Unofficial idiomatic C++17 wrapper for Monocypher 5 | // 6 | // 7 | // Copyright (c) 2022 Jens Alfke. All rights reserved. 8 | // 9 | // --- Standard 2-clause BSD licence follows --- 10 | // Redistribution and use in source and binary forms, with or without 11 | // modification, are permitted provided that the following conditions are 12 | // met: 13 | // 14 | // 1. Redistributions of source code must retain the above copyright 15 | // notice, this list of conditions and the following disclaimer. 16 | // 17 | // 2. Redistributions in binary form must reproduce the above copyright 18 | // notice, this list of conditions and the following disclaimer in the 19 | // documentation and/or other materials provided with the 20 | // distribution. 21 | // 22 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 25 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 26 | // HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 27 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 28 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 32 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 | 34 | #pragma once 35 | #include "base.hh" 36 | 37 | namespace monocypher { 38 | using namespace MONOCYPHER_CPP_NAMESPACE; 39 | 40 | /// Cryptographic hash class, templated by algorithm and size. 41 | /// The `Size` is in bytes and must be between 1 and 64. 42 | /// 43 | /// Monocypher provides algorithms `Blake2b` (below) and `SHA512` (in ext/sha512.hh). 44 | /// Extra algorithms SHA256 (ext/sha256.hh) and Blake3 (ext/blake3.hh) are implemented by 45 | /// other codebases, not Monocypher. 46 | template 47 | class hash : public byte_array { 48 | public: 49 | static constexpr size_t Size = HashAlgorithm::hash_size; 50 | 51 | hash() :byte_array(0) { } 52 | explicit hash(const std::array &a) :byte_array(a) { } 53 | hash(const void *data, size_t size) :byte_array(data, size) { } 54 | 55 | /// Returns the hash of a message. 56 | static hash create(const void *message, size_t message_size) noexcept { 57 | hash result; 58 | HashAlgorithm::create_fn(result.data(), u8(message), message_size); 59 | return result; 60 | } 61 | 62 | /// Returns the hash of a message. 63 | static hash create(input_bytes message) noexcept { 64 | return create(message.data, message.size); 65 | } 66 | 67 | /// Returns the hash of a message and a secret key, for use as a MAC. 68 | /// @warning Some algorithms only work with specific key sizes. 69 | template 70 | static hash createMAC(const void *message, size_t message_size, 71 | const byte_array &key) noexcept { 72 | hash result; 73 | HashAlgorithm::mac::create_fn(result.data(), 74 | key.data(), key.size(), 75 | u8(message), message_size); 76 | return result; 77 | } 78 | 79 | template 80 | static hash createMAC(input_bytes message, 81 | const byte_array &key) noexcept { 82 | return createMAC(message.data, message.size, key); 83 | } 84 | 85 | 86 | template 87 | class _builder { 88 | public: 89 | /// Hashes more data. 90 | _builder& update(const void *message, size_t message_size) { 91 | BuilderAlg::update_fn(&_ctx, u8(message), message_size); 92 | return *this; 93 | } 94 | 95 | /// Hashes more data. 96 | _builder& update(input_bytes message) { 97 | return update(message.data, message.size); 98 | } 99 | 100 | /// Returns the final hash of all the data. 101 | [[nodiscard]] 102 | hash final() { 103 | hash result; 104 | BuilderAlg::final_fn(&_ctx, result.data()); 105 | return result; 106 | } 107 | 108 | protected: 109 | typename BuilderAlg::context _ctx; 110 | }; 111 | 112 | /// Incrementally constructs a hash. 113 | class builder : public _builder { 114 | public: 115 | /// Constructs a hash builder. 116 | /// Call `update` one or more times to hash data, then `final` to get the hash. 117 | builder() { 118 | HashAlgorithm::init_fn(&this->_ctx); 119 | } 120 | }; 121 | 122 | /// Incrementally constructs a MAC. 123 | class mac_builder : public _builder { 124 | public: 125 | /// Constructs a hash builder with a secret key, for creating MACs. 126 | /// Call `update` one or more times to hash data, then `final` to get the hash. 127 | /// @warning Some algorithms only work with specific key sizes. 128 | template 129 | mac_builder(const byte_array &key) { 130 | HashAlgorithm::mac::init_fn(&this->_ctx, key.data(), key.size()); 131 | } 132 | }; 133 | }; 134 | 135 | 136 | /// Blake2b algorithm; use as `` in the `hash` template. 137 | template 138 | struct Blake2b { 139 | static constexpr const char* name = "Blake2b"; 140 | static constexpr size_t hash_size = Size; 141 | 142 | using context = c::crypto_blake2b_ctx; 143 | 144 | static void create_fn(uint8_t *hash, const uint8_t *message, size_t message_size) { 145 | c::crypto_blake2b(hash, hash_size, message, message_size); 146 | } 147 | static void init_fn(context *ctx) { 148 | c::crypto_blake2b_init(ctx, hash_size); 149 | } 150 | static constexpr auto update_fn = c::crypto_blake2b_update; 151 | static constexpr auto final_fn = c::crypto_blake2b_final; 152 | 153 | struct mac { 154 | using context = c::crypto_blake2b_ctx; 155 | 156 | static void create_fn(uint8_t *hash, const uint8_t *key, size_t key_size, 157 | const uint8_t *message, size_t message_size) 158 | { 159 | c::crypto_blake2b_keyed(hash, hash_size, key, key_size, message, message_size); 160 | } 161 | static void init_fn(context *ctx, const uint8_t *key, size_t key_size) { 162 | c::crypto_blake2b_keyed_init(ctx, hash_size, key, key_size); 163 | } 164 | static constexpr auto update_fn = c::crypto_blake2b_update; 165 | static constexpr auto final_fn = c::crypto_blake2b_final; 166 | }; 167 | }; 168 | 169 | 170 | /// Blake2b-64 hash class. 171 | using blake2b64 = hash>; 172 | 173 | /// Blake2b-32 hash class. 174 | using blake2b32 = hash>; 175 | 176 | } 177 | -------------------------------------------------------------------------------- /include/monocypher/key_derivation.hh: -------------------------------------------------------------------------------- 1 | // 2 | // monocypher/key_derivation.hh 3 | // 4 | // Monocypher-Cpp: Unofficial idiomatic C++17 wrapper for Monocypher 5 | // 6 | // 7 | // Copyright (c) 2022 Jens Alfke. All rights reserved. 8 | // 9 | // --- Standard 2-clause BSD licence follows --- 10 | // Redistribution and use in source and binary forms, with or without 11 | // modification, are permitted provided that the following conditions are 12 | // met: 13 | // 14 | // 1. Redistributions of source code must retain the above copyright 15 | // notice, this list of conditions and the following disclaimer. 16 | // 17 | // 2. Redistributions in binary form must reproduce the above copyright 18 | // notice, this list of conditions and the following disclaimer in the 19 | // documentation and/or other materials provided with the 20 | // distribution. 21 | // 22 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 25 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 26 | // HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 27 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 28 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 32 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 | 34 | #pragma once 35 | #include "base.hh" 36 | #include // for std::make_unique 37 | #include // for std::pair 38 | 39 | namespace monocypher { 40 | using namespace MONOCYPHER_CPP_NAMESPACE; 41 | 42 | enum ArgonAlgorithm { 43 | Argon2d, 44 | Argon2i, 45 | Argon2id, 46 | }; 47 | 48 | /// Argon2 is a password key derivation scheme: given an arbitrary password string, 49 | /// it produces a 32- or 64-bit value derived from it, for use as a cryptographic key. 50 | /// It is deliberately slow and memory-intensive, to deter brute-force attacks. 51 | /// 52 | /// The template parameters adjust performance, but must be fixed ahead of time before any 53 | /// passwords are hashed, since changing them changes the derived keys. 54 | /// 55 | /// - `Algorithm` selects the variant of Argon2, defaulting to Argon2i. 56 | /// - `Size` is the size of the hash in bytes, and should be either 32 or 64. 57 | /// - `NBlocks` is the "number of blocks for the work area. Must be at least 8. 58 | /// A value of 100000 (one hundred megabytes) is a good starting point. 59 | /// If the computation takes too long, reduce this number. 60 | /// If it is too fast, increase it. 61 | /// If it is still too fast with all available memory, increase nb_passes." 62 | /// - `NIterations` is the "number of passes. Must be at least 1. 63 | /// A value of 3 is strongly recommended when using Argon2i; 64 | /// any value lower than 3 enables significantly more efficient attacks." 65 | template 69 | struct argon2 { 70 | /// An Argon2 hash generated from a password. 71 | struct hash : public secret_byte_array { 72 | hash() :secret_byte_array(0) { } 73 | explicit hash(const std::array &a) :secret_byte_array(a) { } 74 | hash(const void *data, size_t size) :secret_byte_array(data, size) { } 75 | }; 76 | 77 | /// The per-password "salt" input used to deter multi-password attacks. 78 | struct salt : public secret_byte_array<16> { 79 | salt() :secret_byte_array<16>(0) { } 80 | explicit salt(const std::array &a) :secret_byte_array<16>(a) { } 81 | salt(const void *data, size_t size) :secret_byte_array<16>(data, size) { } 82 | salt(const char *str) {fillWithString(str);} 83 | }; 84 | 85 | /// Generates an Argon2 hash from a password and a given salt value. 86 | /// \note This function is _deliberately_ slow. It's intended to take at least 0.5sec. 87 | /// \warning This _deliberately_ allocates a lot of memory while running: 100MB with the default 88 | /// `NBlocks`. Throws `std::bad_alloc` on allocation failure, unless you've disabled 89 | /// exceptions, in which case it aborts. 90 | static hash create(const void *password, size_t password_size, const salt &s4lt) { 91 | assert(password_size <= UINT32_MAX); 92 | hash result; 93 | auto work_area = std::make_unique(NBlocks * 1024); 94 | if (!work_area) 95 | abort(); // exceptions must be disabled, but we cannot continue. 96 | c::crypto_argon2_config config = { 97 | Algorithm, // algorithm; Argon2d, Argon2i, Argon2id 98 | NBlocks, // nb_blocks; memory hardness, >= 8 * nb_lanes 99 | NIterations,// nb_passes; CPU hardness, >= 1 (>= 3 recommended for Argon2i) 100 | 1, // nb_lanes; parallelism level (single threaded anyway) 101 | }; 102 | c::crypto_argon2_inputs inputs = { 103 | (const uint8_t*)password, 104 | s4lt.data(), 105 | uint32_t(password_size), 106 | sizeof(s4lt), 107 | }; 108 | c::crypto_argon2_extras extras = {}; 109 | c::crypto_argon2(result.data(), Size, work_area.get(), config, inputs, extras); 110 | return result; 111 | } 112 | 113 | static hash create(input_bytes password, const salt &s4lt) { 114 | return create(password.data, password.size, s4lt); 115 | } 116 | 117 | /// Generates an Argon2 hash from the input password and a randomly-generated salt value, 118 | /// and returns both. 119 | /// \note This function is _deliberately_ slow. It's intended to take at least 0.5sec. 120 | /// \warning This _deliberately_ allocates a lot of memory while running: 100MB with the default 121 | /// `NBlocks`. Throws `std::bad_alloc` on allocation failure, unless you've disabled 122 | /// exceptions, in which case it aborts. 123 | static std::pair create(const void *password, size_t password_size) { 124 | salt s4lt; 125 | s4lt.randomize(); 126 | return {create(password, password_size, s4lt), s4lt}; 127 | } 128 | 129 | static std::pair create(input_bytes password) { 130 | return create(password.data, password.size); 131 | } 132 | }; 133 | 134 | 135 | template 136 | using argon2i = argon2; 137 | 138 | } 139 | -------------------------------------------------------------------------------- /include/monocypher/key_exchange.hh: -------------------------------------------------------------------------------- 1 | // 2 | // monocypher/key_exchange.hh 3 | // 4 | // Monocypher-Cpp: Unofficial idiomatic C++17 wrapper for Monocypher 5 | // 6 | // 7 | // Copyright (c) 2022 Jens Alfke. All rights reserved. 8 | // 9 | // --- Standard 2-clause BSD licence follows --- 10 | // Redistribution and use in source and binary forms, with or without 11 | // modification, are permitted provided that the following conditions are 12 | // met: 13 | // 14 | // 1. Redistributions of source code must retain the above copyright 15 | // notice, this list of conditions and the following disclaimer. 16 | // 17 | // 2. Redistributions in binary form must reproduce the above copyright 18 | // notice, this list of conditions and the following disclaimer in the 19 | // documentation and/or other materials provided with the 20 | // distribution. 21 | // 22 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 25 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 26 | // HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 27 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 28 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 32 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 | 34 | #pragma once 35 | #include "base.hh" 36 | 37 | namespace monocypher { 38 | using namespace MONOCYPHER_CPP_NAMESPACE; 39 | 40 | template struct public_key; 41 | template struct key_pair; 42 | 43 | 44 | /// Raw Curve25519 key exchange algorithm for `key_exchange`; use only if you know what 45 | /// you're doing! 46 | /// @warning Shared secrets are not quite random. Hash them to derive an actual shared key; 47 | /// X25519_HChaCha20 does this. 48 | struct X25519_Raw { 49 | static constexpr const char* name = "X25519"; 50 | static constexpr auto get_public_key_fn = c::crypto_x25519_public_key; 51 | static constexpr auto key_exchange_fn = c::crypto_x25519; 52 | }; 53 | 54 | /// Curve25519 key exchange, with the output shared key run through the HChaCha20 hash function 55 | /// to improve its randomness. 56 | struct X25519_HChaCha20 { 57 | static constexpr const char* name = "X25519+HChaCha20"; 58 | static constexpr auto get_public_key_fn = c::crypto_x25519_public_key; 59 | 60 | static void key_exchange_fn (uint8_t shared_key[32], 61 | const uint8_t your_secret_key [32], 62 | const uint8_t their_public_key[32]) 63 | { 64 | c::crypto_x25519(shared_key, your_secret_key, their_public_key); 65 | byte_array<16> zero {0}; 66 | c::crypto_chacha20_h(shared_key, shared_key, zero.data()); 67 | } 68 | }; 69 | 70 | 71 | /// Performs a Diffie-Hellman key exchange with another party, combining your secret key with 72 | /// the other's public key to create a shared secret known to both of you. 73 | template 74 | class key_exchange { 75 | public: 76 | /// A secret key for key exchange. 77 | struct secret_key : public secret_byte_array<32> { }; 78 | 79 | /// A public key generated from the secret key, to be exchanged with the peer. 80 | struct public_key : public byte_array<32> { 81 | public_key() :byte_array<32>(0) { } 82 | explicit public_key(const std::array &a) :byte_array<32>(a) { } 83 | public_key(const void *data, size_t size) :byte_array<32>(data, size) { } 84 | 85 | /// Creates a key-exchange (Curve25519) public key from a signing (Ed25519) public key. 86 | template explicit public_key(const monocypher::public_key&); 87 | }; 88 | 89 | /// A secret value derived from two parties' keys, which will be the same for both. 90 | struct shared_secret : public secret_byte_array<32> { }; 91 | 92 | 93 | /// Initializes a key exchange, generating a random secret key. 94 | key_exchange() { 95 | _secret_key.randomize(); 96 | } 97 | 98 | /// Initializes a key exchange, using an existing secret key. 99 | explicit key_exchange(const secret_key &key) 100 | :_secret_key(key) { } 101 | 102 | /// Initializes a Curve25519 key-exchange context from an Ed25519 signing key-pair. 103 | template explicit key_exchange(const key_pair&); 104 | 105 | /// Returns the public key to send to the other party. 106 | public_key get_public_key() const { 107 | public_key pubkey; 108 | Algorithm::get_public_key_fn(pubkey.data(), _secret_key.data()); 109 | return pubkey; 110 | } 111 | 112 | /// Returns the secret key, in case you want to reuse it later. 113 | secret_key get_secret_key() const { 114 | return _secret_key; 115 | } 116 | 117 | /// Given the other party's public key, computes the shared secret. 118 | shared_secret get_shared_secret(const public_key &their_public_key) const { 119 | shared_secret shared; 120 | Algorithm::key_exchange_fn(shared.data(), _secret_key.data(), their_public_key.data()); 121 | return shared; 122 | } 123 | 124 | private: 125 | secret_key _secret_key; 126 | }; 127 | 128 | 129 | // Overloaded `*` for Curve25519 scalar multiplication: 130 | static inline key_exchange::shared_secret 131 | operator* (key_exchange const& k, key_exchange::public_key const& pk) { 132 | return k.get_shared_secret(pk); 133 | } 134 | 135 | } 136 | -------------------------------------------------------------------------------- /include/monocypher/signatures.hh: -------------------------------------------------------------------------------- 1 | // 2 | // monocypher/signatures.hh 3 | // 4 | // Monocypher-Cpp: Unofficial idiomatic C++17 wrapper for Monocypher 5 | // 6 | // 7 | // Copyright (c) 2022 Jens Alfke. All rights reserved. 8 | // 9 | // --- Standard 2-clause BSD licence follows --- 10 | // Redistribution and use in source and binary forms, with or without 11 | // modification, are permitted provided that the following conditions are 12 | // met: 13 | // 14 | // 1. Redistributions of source code must retain the above copyright 15 | // notice, this list of conditions and the following disclaimer. 16 | // 17 | // 2. Redistributions in binary form must reproduce the above copyright 18 | // notice, this list of conditions and the following disclaimer in the 19 | // documentation and/or other materials provided with the 20 | // distribution. 21 | // 22 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 25 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 26 | // HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 27 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 28 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 32 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 | 34 | #pragma once 35 | #include "base.hh" 36 | #include "key_exchange.hh" 37 | 38 | namespace monocypher { 39 | using namespace MONOCYPHER_CPP_NAMESPACE; 40 | 41 | struct EdDSA; 42 | 43 | 44 | /// A digital signature. (For use or .) 45 | template 46 | struct signature : public byte_array<64> { 47 | signature() :byte_array<64>(0) { } 48 | explicit signature(const std::array &a) :byte_array<64>(a) { } 49 | signature(const void *data, size_t size) :byte_array<64>(data, size) { } 50 | }; 51 | 52 | 53 | /// A public key for verifying signatures. (For use or .) 54 | template 55 | struct public_key : public byte_array<32> { 56 | public_key() :byte_array<32>(0) { } 57 | explicit public_key(const std::array &a) :byte_array<32>(a) { } 58 | public_key(const void *data, size_t size) :byte_array<32>(data, size) { } 59 | explicit public_key(input_bytes k) :public_key(k.data, k.size) { } 60 | 61 | /// Verifies a signature. 62 | [[nodiscard]] 63 | bool check(const signature &sig, const void *msg, size_t msg_size) const { 64 | return 0 == Algorithm::check_fn(sig.data(), this->data(), u8(msg), msg_size); 65 | } 66 | 67 | [[nodiscard]] 68 | bool check(const signature &sig, input_bytes msg) const { 69 | return check(sig, msg.data, msg.size); 70 | } 71 | 72 | /// Converts a public signature-verification key to a Curve25519 public key, 73 | /// for key exchange or encryption. 74 | /// @warning "It is generally considered poor form to reuse the same key for different 75 | /// purposes. While this conversion is technically safe, avoid these functions 76 | /// nonetheless unless you are particularly resource-constrained or have some other 77 | /// kind of hard requirement. It is otherwise an unnecessary risk factor." 78 | template 79 | typename key_exchange::public_key for_key_exchange() const { 80 | typename key_exchange::public_key pk; 81 | Algorithm::public_to_kx_fn(pk.data(), this->data()); 82 | return pk; 83 | } 84 | }; 85 | 86 | 87 | /// A key-pair for generating signatures. (For use or .) 88 | template 89 | struct key_pair : public secret_byte_array<64> { 90 | using public_key = monocypher::public_key; 91 | using signature = monocypher::signature; 92 | 93 | /// Creates a new key-pair at random. 94 | static key_pair generate() { 95 | secret_byte_array<32> initialSeed; 96 | initialSeed.randomize(); 97 | public_key pub; // ignored 98 | key_pair keyPair; 99 | Algorithm::generate_fn(keyPair.data(), pub.data(), initialSeed.data()); 100 | return keyPair; 101 | } 102 | 103 | explicit key_pair(const std::array &a) :secret_byte_array<64>(a) { } 104 | key_pair(const void *data, size_t size) :secret_byte_array<64>(data, size) { } 105 | explicit key_pair(input_bytes k) :secret_byte_array<64>(k.data, k.size) { } 106 | 107 | /// Returns the public key. 108 | const public_key& get_public_key() const { 109 | // "Now the private key is 64 bytes, and is the concatenation of the seed and the public 110 | // key just like Libsodium." --Loup Vaillant, commit da7b5407 111 | return reinterpret_cast(range<32,32>()); 112 | } 113 | 114 | /// Signs a message. 115 | [[nodiscard]] 116 | signature sign(const void *message, size_t message_size) const { 117 | signature sig; 118 | Algorithm::sign_fn(sig.data(), data(), u8(message), message_size); 119 | return sig; 120 | } 121 | 122 | /// Signs a message. 123 | [[nodiscard]] 124 | signature sign(input_bytes message) const { 125 | return sign(message.data, message.size); 126 | } 127 | 128 | /// Verifies a signature. 129 | [[nodiscard]] 130 | bool check(const signature &sig, const void *msg, size_t msg_size) const { 131 | return get_public_key().check(sig, msg, msg_size); 132 | } 133 | 134 | [[nodiscard]] 135 | bool check(const signature &sig, input_bytes msg) const { 136 | return check(sig, msg.data, msg.size); 137 | } 138 | 139 | /// The random data that a key_pair is derived from; also known as the secret key. 140 | struct seed : public secret_byte_array<32> { 141 | explicit seed(const std::array &a) :secret_byte_array<32>(a) { } 142 | seed(const void *data, size_t size) :secret_byte_array<32>(data, size) { } 143 | 144 | /// Computes and returns the matching public key. 145 | inline public_key get_public_key() const{ 146 | return key_pair(*this).get_public_key(); 147 | } 148 | 149 | /// Signs a message. 150 | /// @note This has to first recompute the public key, which makes it a bit slower. 151 | [[nodiscard]] 152 | inline signature sign(const void *message, size_t message_size) const{ 153 | return key_pair(*this).sign(message, message_size); 154 | } 155 | 156 | /// Signs a message. 157 | /// @note This has to first recompute the public key, which makes it a bit slower. 158 | [[nodiscard]] 159 | signature sign(input_bytes message) const { 160 | return sign(message.data, message.size); 161 | } 162 | 163 | /// Creates a key_exchange context using the equivalent Curve25519 secret key. 164 | template 165 | key_exchange as_key_exchange() const { 166 | typename monocypher::key_exchange::secret_key secretKey; 167 | Algorithm::private_to_kx_fn(secretKey.data(), this->data()); 168 | return monocypher::key_exchange(secretKey); 169 | } 170 | 171 | }; 172 | 173 | explicit key_pair(const seed &sk) { 174 | // "Users who can't afford the overhead of storing 32 additional bytes for 175 | // the secret key (say they need to burn the key into expensive fuses), 176 | // they can always only store the first 32 bytes, and re-derive the entire 177 | // key pair when they need it." --Loup Vaillant, commit da7b5407 178 | seed s33d = sk; 179 | public_key pub; // ignored 180 | Algorithm::generate_fn(data(), pub.data(), s33d.data()); 181 | assert(get_seed() == sk); 182 | } 183 | 184 | /// Returns the 32-byte seed, or secret key. The key_pair can be recreated from this. 185 | const seed& get_seed() const { 186 | return reinterpret_cast(range<0,32>()); 187 | } 188 | 189 | /// Initializes a key exchange, using an existing signing key-pair. 190 | /// Internally this converts the EdDSA or Ed25519 signing key to its Curve25519 equivalent. 191 | /// @warning "It is generally considered poor form to reuse the same key for different 192 | /// purposes. While this conversion is technically safe, avoid these functions 193 | /// nonetheless unless you are particularly resource-constrained or have some other 194 | /// kind of hard requirement. It is otherwise an unnecessary risk factor." 195 | template 196 | key_exchange as_key_exchange() const { 197 | return get_seed().template as_key_exchange(); 198 | } 199 | 200 | private: 201 | key_pair() = default; 202 | }; 203 | 204 | 205 | // compatibility alias for clients that used to use the `signing_key` class. 206 | template 207 | using signing_key = typename key_pair::seed; 208 | 209 | 210 | 211 | /// EdDSA with Curve25519 and Blake2b. 212 | /// (Use as `` parameter to `signature`, `public_key`, `key_pair`.) 213 | /// \note This is not the same as the commonly-used Ed25519, which uses SHA-512. 214 | /// An `Ed25519` struct is declared in `Monocypher-ed25519.hh`. 215 | struct EdDSA { 216 | static constexpr const char* name = "EdDSA"; 217 | static constexpr auto generate_fn = c::crypto_eddsa_key_pair; 218 | static constexpr auto check_fn = c::crypto_eddsa_check; 219 | static constexpr auto sign_fn = c::crypto_eddsa_sign; 220 | static constexpr auto public_to_kx_fn = c::crypto_eddsa_to_x25519; 221 | 222 | static void private_to_kx_fn(uint8_t x25519[32], const uint8_t eddsa[32]) { 223 | // Adapted from Monocypher 3's crypto_from_eddsa_private() 224 | secret_byte_array<64> a; 225 | c::crypto_blake2b(a.data(), 64, eddsa, 32); 226 | ::memcpy(x25519, a.data(), 32); 227 | } 228 | 229 | // Convenient type aliases for those who don't like angle brackets 230 | using signature = monocypher::signature; 231 | using public_key = monocypher::public_key; 232 | using key_pair = monocypher::key_pair; 233 | }; 234 | 235 | 236 | template 237 | template 238 | key_exchange::public_key::public_key(const monocypher::public_key &pk) { 239 | *this = pk.template for_key_exchange(); 240 | } 241 | 242 | template 243 | template 244 | key_exchange::key_exchange(const key_pair& keypair) { 245 | *this = keypair.template as_key_exchange(); 246 | } 247 | 248 | } 249 | -------------------------------------------------------------------------------- /src/Monocypher+blake3.cc: -------------------------------------------------------------------------------- 1 | // 2 | // monocypher/Monocypher+blake3.cc 3 | // 4 | // Monocypher-Cpp: Unofficial idiomatic C++17 wrapper for Monocypher 5 | // 6 | // 7 | // Copyright (c) 2024 Jens Alfke. All rights reserved. 8 | // 9 | // --- Standard 2-clause BSD licence follows --- 10 | // Redistribution and use in source and binary forms, with or without 11 | // modification, are permitted provided that the following conditions are 12 | // met: 13 | // 14 | // 1. Redistributions of source code must retain the above copyright 15 | // notice, this list of conditions and the following disclaimer. 16 | // 17 | // 2. Redistributions in binary form must reproduce the above copyright 18 | // notice, this list of conditions and the following disclaimer in the 19 | // documentation and/or other materials provided with the 20 | // distribution. 21 | // 22 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 25 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 26 | // HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 27 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 28 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 32 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 | 34 | #include "monocypher/ext/blake3.hh" 35 | #include "blake3.h" 36 | #include 37 | 38 | namespace monocypher::ext { 39 | using namespace std; 40 | 41 | // Verify that the size of `context` matches the actual hasher's size: 42 | static_assert(sizeof(Blake3Base::context) == sizeof(blake3_hasher)); 43 | 44 | static blake3_hasher* hasher(Blake3Base::context *ctx) { 45 | return reinterpret_cast(ctx); 46 | } 47 | 48 | void Blake3Base::init_fn(context *ctx) { 49 | blake3_hasher_init(hasher(ctx)); 50 | } 51 | 52 | void Blake3Base::update_fn(context *ctx, const uint8_t *message, size_t message_size) { 53 | blake3_hasher_update(hasher(ctx), message, message_size); 54 | } 55 | 56 | void Blake3Base::final_fn(context *ctx, uint8_t* hash, size_t hash_size) { 57 | blake3_hasher_finalize(hasher(ctx), hash, hash_size); 58 | } 59 | 60 | void Blake3Base::create_fn(uint8_t* hash, size_t hash_size, const uint8_t *message, size_t message_size) { 61 | blake3_hasher ctx; 62 | blake3_hasher_init(&ctx); 63 | blake3_hasher_update(&ctx, message, message_size); 64 | blake3_hasher_finalize(&ctx, hash, hash_size); 65 | } 66 | 67 | void Blake3Base::init_mac_fn(context *ctx, const uint8_t *key, size_t key_size) { 68 | if (key_size != 32) 69 | throw std::invalid_argument("Blake3 MAC requires a 32-byte key"); 70 | blake3_hasher_init_keyed(hasher(ctx), key); 71 | } 72 | 73 | void Blake3Base::create_mac_fn(uint8_t *hash, size_t hash_size, 74 | const uint8_t *key, size_t key_size, 75 | const uint8_t *message, size_t message_size) { 76 | if (key_size != 32) 77 | throw std::invalid_argument("Blake3 MAC requires a 32-byte key"); 78 | blake3_hasher ctx; 79 | blake3_hasher_init_keyed(&ctx, key); 80 | blake3_hasher_update(&ctx, message, message_size); 81 | blake3_hasher_finalize(&ctx, hash, hash_size); 82 | } 83 | 84 | } 85 | -------------------------------------------------------------------------------- /src/Monocypher+sha256.cc: -------------------------------------------------------------------------------- 1 | // 2 | // Monocypher+sha256.cc 3 | // 4 | // Copyright © 2022 Jens Alfke. All rights reserved. 5 | // 6 | // --- Standard 2-clause BSD licence follows --- 7 | // Redistribution and use in source and binary forms, with or without 8 | // modification, are permitted provided that the following conditions are 9 | // met: 10 | // 11 | // 1. Redistributions of source code must retain the above copyright 12 | // notice, this list of conditions and the following disclaimer. 13 | // 14 | // 2. Redistributions in binary form must reproduce the above copyright 15 | // notice, this list of conditions and the following disclaimer in the 16 | // documentation and/or other materials provided with the 17 | // distribution. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | #include "monocypher/ext/sha256.hh" 32 | 33 | // Wrap 3rd party sha256.c in a namespace to avoid messing with global namespace: 34 | namespace monocypher::b_con { 35 | #include "../vendor/B-Con/sha256.c" 36 | } 37 | 38 | namespace monocypher::ext { 39 | using namespace monocypher::b_con; 40 | 41 | // Make sure my `context` type can serve as a `SHA256_CTX` for the implementation: 42 | static_assert(sizeof(SHA256::context) == sizeof(SHA256_CTX)); 43 | static_assert(alignof(SHA256::context) == alignof(SHA256_CTX)); 44 | 45 | void SHA256::create_fn(uint8_t hash[32], const uint8_t *message, size_t message_size) { 46 | context ctx; 47 | init_fn(&ctx); 48 | update_fn(&ctx, message, message_size); 49 | final_fn(&ctx, hash); 50 | } 51 | 52 | void SHA256::init_fn(context *ctx) { 53 | sha256_init((SHA256_CTX*)ctx); 54 | } 55 | 56 | void SHA256::update_fn(context *ctx, const uint8_t *message, size_t message_size) { 57 | sha256_update((SHA256_CTX*)ctx, message, message_size); 58 | } 59 | 60 | void SHA256::final_fn(context *ctx, uint8_t hash[32]) { 61 | sha256_final((SHA256_CTX*)ctx, hash); 62 | } 63 | 64 | 65 | } 66 | -------------------------------------------------------------------------------- /src/Monocypher+xsalsa20.cc: -------------------------------------------------------------------------------- 1 | // 2 | // Monocypher+xsalsa20.cc 3 | // 4 | // Copyright © 2022 Jens Alfke. All rights reserved. 5 | // 6 | // --- Standard 2-clause BSD licence follows --- 7 | // Redistribution and use in source and binary forms, with or without 8 | // modification, are permitted provided that the following conditions are 9 | // met: 10 | // 11 | // 1. Redistributions of source code must retain the above copyright 12 | // notice, this list of conditions and the following disclaimer. 13 | // 14 | // 2. Redistributions in binary form must reproduce the above copyright 15 | // notice, this list of conditions and the following disclaimer in the 16 | // documentation and/or other materials provided with the 17 | // distribution. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | #include "monocypher/ext/xsalsa20.hh" 32 | #include 33 | #include 34 | 35 | // Wrap 3rd party tweetnacl.c in a namespace to avoid messing with global namespace: 36 | namespace monocypher::tweetnacl { 37 | #include "../vendor/tweetnacl/tweetnacl.c" 38 | 39 | // tweetnacl leaves this undefined. The code below doesn't require it, but in a debug build 40 | // without dead-stripping, we get link errors without it. 41 | void randombytes(uint8_t *bytes, unsigned long long size) { 42 | monocypher::randomize(bytes, size_t(size)); 43 | } 44 | } 45 | 46 | 47 | namespace monocypher::ext { 48 | using namespace monocypher::tweetnacl; 49 | 50 | // NaCL's `secretbox` C API is batshit crazy: https://nacl.cr.yp.to/secretbox.html 🤯 51 | // It requires 32 zero bytes before the plaintext, 52 | // and writes 16 zero bytes before the mac-and-ciphertext. 53 | // The size parameter needs to include those 32 bytes. 54 | // Unboxing is the reverse. 55 | // WTF. 56 | 57 | void XSalsa20_Poly1305::lock(uint8_t *out, 58 | uint8_t mac[16], 59 | const uint8_t key[32], 60 | const uint8_t nonce[24], 61 | const uint8_t *ad, size_t ad_size, 62 | const uint8_t *plaintext, size_t size) 63 | { 64 | assert(ad_size == 0); // XSalsa20_Poly1305 does not support additional authenticated data 65 | //TODO: Find a way to do this without having to allocate temporary buffers. 66 | auto inBuffer = std::make_unique(32 + size); 67 | memset(&inBuffer[ 0], 0, 32); 68 | memcpy(&inBuffer[32], plaintext, size); 69 | 70 | auto outBuffer = std::make_unique(32 + size); 71 | 72 | crypto_secretbox_xsalsa20poly1305_tweet(outBuffer.get(), 73 | inBuffer.get(), 74 | size + 32, 75 | nonce, key); 76 | 77 | memcpy(mac, &outBuffer[16], 16); 78 | memcpy(out, &outBuffer[32], size); 79 | 80 | // Self-test: 81 | // assert(0 == unlock(&inBuffer[0], key, nonce, mac, out, size) 82 | // && 0 == memcmp(plaintext, &inBuffer[0], size)); 83 | crypto_wipe(&inBuffer[32], size); 84 | } 85 | 86 | int XSalsa20_Poly1305::unlock(uint8_t *out, 87 | const uint8_t mac[16], 88 | const uint8_t key[32], 89 | const uint8_t nonce[24], 90 | const uint8_t *ad, size_t ad_size, 91 | const uint8_t *ciphertext, size_t size) 92 | { 93 | assert(ad_size == 0); // XSalsa20_Poly1305 does not support additional authenticated data 94 | //TODO: Find a way to do this without having to allocate temporary buffers. 95 | auto inBuffer = std::make_unique(32 + size); 96 | memset(&inBuffer[0], 0, 16); 97 | memcpy(&inBuffer[16], mac, 16); 98 | memcpy(&inBuffer[32], ciphertext, size); 99 | 100 | auto outBuffer = std::make_unique(32 + size); 101 | 102 | if (0 != crypto_secretbox_xsalsa20poly1305_tweet_open(outBuffer.get(), 103 | inBuffer.get(), size + 32, 104 | nonce, key)) 105 | return -1; 106 | memcpy(out, &outBuffer[32], size); 107 | crypto_wipe(&outBuffer[32], size); 108 | return 0; 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /src/Monocypher-ed25519.cc: -------------------------------------------------------------------------------- 1 | // 2 | // Monocypher-ed25519.cc 3 | // 4 | // Monocypher-Cpp: Unofficial idiomatic C++17 wrapper for Monocypher 5 | // 6 | // 7 | // Copyright (c) 2022 Jens Alfke. All rights reserved. 8 | // 9 | // --- Standard 2-clause BSD licence follows --- 10 | // Redistribution and use in source and binary forms, with or without 11 | // modification, are permitted provided that the following conditions are 12 | // met: 13 | // 14 | // 1. Redistributions of source code must retain the above copyright 15 | // notice, this list of conditions and the following disclaimer. 16 | // 17 | // 2. Redistributions in binary form must reproduce the above copyright 18 | // notice, this list of conditions and the following disclaimer in the 19 | // documentation and/or other materials provided with the 20 | // distribution. 21 | // 22 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 25 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 26 | // HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 27 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 28 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 32 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 | 34 | #include "monocypher/ext/ed25519.hh" 35 | 36 | // Bring in the monocypher implementation, still wrapped in a C++namespace: 37 | #include "../vendor/monocypher/src/optional/monocypher-ed25519.c" 38 | -------------------------------------------------------------------------------- /src/Monocypher.cc: -------------------------------------------------------------------------------- 1 | // 2 | // Monocypher.cc 3 | // 4 | // Monocypher-Cpp: Unofficial idiomatic C++17 wrapper for Monocypher 5 | // 6 | // 7 | // Copyright (c) 2022 Jens Alfke. All rights reserved. 8 | // 9 | // --- Standard 2-clause BSD licence follows --- 10 | // Redistribution and use in source and binary forms, with or without 11 | // modification, are permitted provided that the following conditions are 12 | // met: 13 | // 14 | // 1. Redistributions of source code must retain the above copyright 15 | // notice, this list of conditions and the following disclaimer. 16 | // 17 | // 2. Redistributions in binary form must reproduce the above copyright 18 | // notice, this list of conditions and the following disclaimer in the 19 | // documentation and/or other materials provided with the 20 | // distribution. 21 | // 22 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 25 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 26 | // HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 27 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 28 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 32 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 | 34 | #include "Monocypher.hh" 35 | 36 | // Bring in the monocypher implementation, still wrapped in a C++namespace: 37 | #include "../vendor/monocypher/src/monocypher.c" 38 | 39 | 40 | // On Apple platforms, `arc4random_buf()` is declared in . 41 | // On Linux, it _may_ be in if the BSD compatibility lib is present. 42 | // If it isn't available, we fall back to using C++ `std::random_device` (but see warning below.) 43 | #ifdef __APPLE__ 44 | # define MONOCYPHER_HAS_ARC4RANDOM 45 | #elif defined __has_include 46 | # if __has_include () 47 | # include 48 | # define MONOCYPHER_HAS_ARC4RANDOM 49 | # elif __has_include () 50 | # include 51 | # define MONOCYPHER_HAS_ARC4RANDOM 52 | # endif 53 | #endif 54 | 55 | #ifndef MONOCYPHER_HAS_ARC4RANDOM 56 | #include 57 | #endif 58 | 59 | 60 | namespace monocypher { 61 | 62 | void randomize(void *dst, size_t size) { 63 | #ifdef MONOCYPHER_HAS_ARC4RANDOM 64 | # undef MONOCYPHER_HAS_ARC4RANDOM 65 | ::arc4random_buf(dst, size); 66 | #else 67 | assert(size % sizeof(unsigned) == 0); // TODO: Handle odd sizes 68 | std::random_device rng; 69 | auto start = (uint8_t*)dst, end = start + size; 70 | for (uint8_t *i = start; i != end; i += sizeof(unsigned)) { 71 | unsigned r = rng(); 72 | memcpy(i, &r, sizeof(unsigned)); 73 | } 74 | #endif 75 | } 76 | 77 | 78 | bool constant_time_compare(const void *xa, const void *xb, size_t size) { 79 | auto a = (const uint8_t*)xa, b = (const uint8_t*)xb; 80 | size_t i = 0; 81 | while (i + 64 <= size) { 82 | if (0 != crypto_verify64(a+i, b+i)) 83 | return false; 84 | i += 64; 85 | } 86 | while (i + 32 <= size) { 87 | if (0 != crypto_verify32(a+i, b+i)) 88 | return false; 89 | i += 32; 90 | } 91 | while (i + 16 <= size) { 92 | if (0 != crypto_verify16(a+i, b+i)) 93 | return false; 94 | i += 16; 95 | } 96 | if (i < size) { 97 | if (size >= 16) { 98 | // Handle any remaining bytes by comparing the _last_ 16 bytes: 99 | return 0 == crypto_verify16(a + size - 16, b + size - 16); 100 | } else { 101 | // Kludge to handle size less than 16: 102 | uint8_t buf1[16] = {}, buf2[16] = {}; 103 | memcpy(buf1, a, size); 104 | memcpy(buf2, b, size); 105 | return 0 == crypto_verify16(buf1, buf2); 106 | } 107 | } 108 | return true; 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /tests/CaseListReporter.hh: -------------------------------------------------------------------------------- 1 | // 2 | // CaseListReporter.hh 3 | // 4 | // Created by Jens Alfke on 8/26/16. 5 | // Copyright (c) 2016 Couchbase. All rights reserved. 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #include "catch.hpp" 21 | #include 22 | #include 23 | #include 24 | 25 | #ifdef CASE_LIST_STOPWATCH 26 | #include "Stopwatch.hh" 27 | #endif 28 | 29 | #ifdef CASE_LIST_BACKTRACE 30 | #include "Backtrace.hh" 31 | #endif 32 | 33 | 34 | /** Custom reporter that logs a line for every test file and every test case being run. 35 | Use CLI args "-r list" to use it. */ 36 | struct CaseListReporter : public Catch::ConsoleReporter { 37 | CaseListReporter( Catch::ReporterConfig const& _config ) 38 | : Catch::ConsoleReporter( _config ) 39 | { 40 | _start = time(nullptr); 41 | stream << "STARTING TESTS AT " << ctime(&_start); 42 | stream.flush(); 43 | } 44 | 45 | virtual ~CaseListReporter() override { 46 | auto now = time(nullptr); 47 | stream << "ENDED TESTS IN " << (now - _start) << "sec, AT " << ctime(&now); 48 | stream.flush(); 49 | } 50 | 51 | static std::string getDescription() { 52 | return "Logs a line for every test case"; 53 | } 54 | 55 | virtual void testCaseStarting( Catch::TestCaseInfo const& _testInfo ) override { 56 | std::string file = _testInfo.lineInfo.file; 57 | if (file != _curFile) { 58 | _curFile = file; 59 | auto slash = file.rfind('/'); 60 | stream << "## " << file.substr(slash+1) << ":\n"; 61 | } 62 | stream << "\t>>> " << _testInfo.name << "\n"; 63 | _firstSection = true; 64 | _sectionNesting = 0; 65 | stream.flush(); 66 | ConsoleReporter::testCaseStarting(_testInfo); 67 | #ifdef CASE_LIST_STOPWATCH 68 | _stopwatch.reset(); 69 | #endif 70 | } 71 | #ifdef CASE_LIST_STOPWATCH 72 | virtual void testCaseEnded( Catch::TestCaseStats const& _testCaseStats ) override { 73 | stream << "\t [" << _stopwatch.elapsed() << " sec]\n"; 74 | stream.flush(); 75 | ConsoleReporter::testCaseEnded(_testCaseStats); 76 | } 77 | #endif 78 | 79 | virtual void sectionStarting( Catch::SectionInfo const& _sectionInfo ) override { 80 | if (_firstSection) 81 | _firstSection = false; 82 | else { 83 | for (unsigned i = 0; i < _sectionNesting; ++i) 84 | stream << "\t"; 85 | stream << "\t--- " << _sectionInfo.name << "\n"; 86 | stream.flush(); 87 | } 88 | ++_sectionNesting; 89 | ConsoleReporter::sectionStarting(_sectionInfo); 90 | } 91 | 92 | void sectionEnded( Catch::SectionStats const& sectionStats ) override { 93 | --_sectionNesting; 94 | ConsoleReporter::sectionEnded(sectionStats); 95 | } 96 | 97 | #ifdef CASE_LIST_BACKTRACE 98 | virtual bool assertionEnded( Catch::AssertionStats const& stats ) override { 99 | if (stats.assertionResult.getResultType() == Catch::ResultWas::FatalErrorCondition) { 100 | std::cerr << "\n\n********** CRASH: " 101 | << stats.assertionResult.getMessage() 102 | << " **********"; 103 | fleece::Backtrace bt(5); 104 | bt.writeTo(std::cerr); 105 | std::cerr << "\n********** CRASH **********\n"; 106 | } 107 | return Catch::ConsoleReporter::assertionEnded(stats); 108 | } 109 | #endif 110 | 111 | std::string _curFile; 112 | bool _firstSection; 113 | unsigned _sectionNesting; 114 | time_t _start; 115 | #ifdef CASE_LIST_STOPWATCH 116 | fleece::Stopwatch _stopwatch; 117 | #endif 118 | }; 119 | 120 | CATCH_REGISTER_REPORTER("list", CaseListReporter ) 121 | -------------------------------------------------------------------------------- /tests/MonocypherCppTests.cc: -------------------------------------------------------------------------------- 1 | // 2 | // tests.cc 3 | // Monocypher-Cpp 4 | // 5 | // Created by Jens Alfke on 9/24/20. 6 | // 7 | 8 | #include "hexString.hh" 9 | #include "Monocypher.hh" 10 | #include "monocypher/ext/ed25519.hh" 11 | #include "monocypher/ext/sha256.hh" 12 | #include "monocypher/ext/sha512.hh" 13 | #include "monocypher/ext/xsalsa20.hh" 14 | #include 15 | #include // for `tie` 16 | 17 | #include "catch.hpp" 18 | 19 | 20 | // These are some incomplete tests of the Monocypher.hh C++ API. 21 | 22 | using namespace std; 23 | using namespace monocypher; 24 | 25 | 26 | TEST_CASE("Randomize", "[Crypto") { 27 | // _Really_ testing a RNG is difficult and involves statistics. At this level all I want to 28 | // verify is that randomize() is touching every byte of the array. 29 | 30 | monocypher::session::key key; 31 | // First wipe the key and verify it's zeroed: 32 | key.wipe(); 33 | cout << "Before: " << hexString(key) << "\n"; 34 | for (size_t i = 0; i < sizeof(key); ++i) 35 | CHECK(key[i] == 0); 36 | 37 | // Randomize 'key', then check that all bytes have changed (from 00.) 38 | // Obviously this can fail even with a real RNG, so try multiple times. 39 | // (Chance of one failure is 12%; ten in a row is less than one in a billion.) 40 | bool changed = false; 41 | for (int attempt = 0; attempt < 10; ++attempt) { 42 | key.randomize(); 43 | cout << "After: " << hexString(key) << "\n"; 44 | changed = true; 45 | for (size_t i = 0; i < sizeof(key); ++i) { 46 | if (key[i] == 0) { 47 | cout << " nope, byte[" << i << "] is still 00...\n"; 48 | changed = false; 49 | break; 50 | } 51 | } 52 | if (changed) 53 | break; 54 | } 55 | CHECK(changed); 56 | } 57 | 58 | 59 | template 60 | static void test_blake2b() { 61 | using blake2b = monocypher::hash>; 62 | constexpr const char* kExpected = 63 | (Size == 32) ? "256C83B2 97114D20 1B30179F 3F0EF0CA CE978362 2DA59743 26B43617 8AEEF610" 64 | : "021CED87 99296CEC A557832A B941A50B 4A11F834 78CF141F 51F933F6 53AB9FBC " 65 | "C05A037C DDBED06E 309BF334 942C4E58 CDF1A46E 237911CC D7FCF978 7CBC7FD0"; 66 | 67 | blake2b h1 = blake2b::create("hello world"sv); 68 | string str1 = hexString(h1); 69 | cout << str1 << "\n"; 70 | CHECK(str1 == kExpected); 71 | 72 | typename blake2b::builder b; 73 | b.update("hello"sv).update(" "sv).update("world"sv); 74 | blake2b h2 = b.final(); 75 | 76 | string str2 = hexString(h2); 77 | cout << str2 << "\n"; 78 | CHECK(str2 == str1); 79 | CHECK(h2 == h1); 80 | 81 | // HMAC: 82 | constexpr const char* kExpectedMAC = 83 | (Size == 32) ? "E3EEFDF5 A34BD04B 40813366 D1609E50 43E7326B 3058DB9C 3C0C9AB0 253311C2" 84 | : "03323A49 AFDF08AA 4D4AEA87 E610BCB1 FEC593AE E11C9CC0 1C2B2474 9FF5A0C4 " 85 | "3D050C23 F8E325FB 8A8185AC 0B82C7E8 078E0D00 2907FF62 65D735AB 8F1A9CE2"; 86 | 87 | secret_byte_array<32> key; 88 | key.wipe(); 89 | key[7] = 123; 90 | blake2b mac = blake2b::createMAC("hello world"sv, key); 91 | cout << "HMAC = " << hexString(mac) << endl; 92 | CHECK(hexString(mac) == kExpectedMAC); 93 | 94 | typename blake2b::mac_builder hm(key); 95 | hm.update("hello"sv).update(" "sv).update("world"sv); 96 | blake2b mac2 = hm.final(); 97 | cout << "HMAC = " << hexString(mac2) << endl; 98 | CHECK(mac2 == mac); 99 | } 100 | 101 | TEST_CASE("Blake2b-32", "[Crypto") {test_blake2b<32>();} 102 | TEST_CASE("Blake2b-64", "[Crypto") {test_blake2b<64>();} 103 | 104 | 105 | TEST_CASE("SHA-256") { 106 | auto h1 = ext::sha256::create("hello world", 11); 107 | string str1 = hexString(h1); 108 | cout << str1 << "\n"; 109 | CHECK(str1 == "B94D27B9 934D3E08 A52E52D7 DA7DABFA C484EFE3 7A5380EE 9088F7AC E2EFCDE9"); 110 | 111 | ext::sha256::builder b; 112 | b.update("hello"sv).update(" "sv).update("world"sv); 113 | ext::sha256 h2 = b.final(); 114 | 115 | string str2 = hexString(h2); 116 | cout << str2 << "\n"; 117 | CHECK(str2 == str1); 118 | CHECK(h2 == h1); 119 | 120 | // (No HMAC support in SHA-256 yet) 121 | } 122 | 123 | 124 | TEST_CASE("SHA-512", "[Crypto") { 125 | auto h1 = sha512::create("hello world", 11); 126 | string str1 = hexString(h1); 127 | cout << str1 << "\n"; 128 | CHECK(str1 == "309ECC48 9C12D6EB 4CC40F50 C902F2B4 D0ED77EE 511A7C7A 9BCD3CA8 6D4CD86F " 129 | "989DD35B C5FF4996 70DA3425 5B45B0CF D830E81F 605DCF7D C5542E93 AE9CD76F"); 130 | 131 | sha512::builder b; 132 | b.update("hello"sv).update(" "sv).update("world"sv); 133 | sha512 h2 = b.final(); 134 | 135 | string str2 = hexString(h2); 136 | cout << str2 << "\n"; 137 | CHECK(str2 == str1); 138 | CHECK(h2 == h1); 139 | 140 | // HMAC: 141 | secret_byte_array<64> key; 142 | key.wipe(); 143 | key[7] = 123; 144 | sha512 mac = sha512::createMAC("hello world"sv, key); 145 | cout << "HMAC = " << hexString(mac) << endl; 146 | CHECK(hexString(mac) == "2FEDCA75 30B41289 556CFC3B E1D7014E E8468430 0B5B0FF2 845AE074 " 147 | "424C2DC6 538A3BB7 B2B33174 13CDA55D 0FD0D54C 29651E7C 2168E82D F72B5C89 9447BD7A"); 148 | 149 | sha512::mac_builder hm(key); 150 | hm.update("hello"sv).update(" "sv).update("world"sv); 151 | sha512 mac2 = hm.final(); 152 | cout << "HMAC = " << hexString(mac2) << endl; 153 | CHECK(mac2 == mac); 154 | } 155 | 156 | 157 | TEST_CASE("Argon2i", "[Crypto") { 158 | using FastArgon = argon2; 159 | // Note: I deliberately made NBlocks unrealistically small, to avoid slowing down tests. 160 | 161 | static const char *password = "password69"; 162 | FastArgon::hash h1; 163 | FastArgon::salt salt; 164 | tie(h1, salt) = FastArgon::create(password, strlen(password)); 165 | string str1 = hexString(h1); 166 | cout << "Argon2i hash = " << str1 << "\n"; 167 | cout << "Salt = " << hexString(salt) << "\n"; 168 | 169 | auto h2 = FastArgon::create(password, strlen(password), salt); 170 | string str2 = hexString(h2); 171 | cout << "Rebuilt hash = " << str2 << "\n"; 172 | CHECK(h1 == h2); 173 | CHECK(str1 == str2); 174 | 175 | // Try a known non-random salt: 176 | FastArgon::salt mySalt; 177 | strcpy((char*)mySalt.data(), "Morton's"); 178 | cout << "Fixed salt = " << hexString(mySalt) << "\n"; 179 | auto h3 = FastArgon::create(password, strlen(password), mySalt); 180 | string str3 = hexString(h3); 181 | cout << "Pre-salted hash = " << str3 << "\n"; 182 | CHECK(str3 == "35388F22 9FF73B11 D9E04E59 853547CC CA11A05E 3A67670F B5CA02AD BB52062D " 183 | "53CD02A5 DE5611B1 2D10B5E4 DBF28A48 A389F791 4F05F532 728DF45D 4283470F"); 184 | } 185 | 186 | 187 | TEST_CASE("key exchange", "[Crypto") { 188 | key_exchange kx1, kx2; 189 | 190 | auto pk1 = kx1.get_public_key(); 191 | auto pk2 = kx2.get_public_key(); 192 | cout << "public key 1 = " << hexString(pk1) << "\n"; 193 | cout << "public key 2 = " << hexString(pk2) << "\n"; 194 | 195 | auto secret1 = kx1.get_shared_secret(pk2); 196 | auto secret2 = kx2.get_shared_secret(pk1); 197 | cout << "shared secret 1 = " << hexString(secret1) << "\n"; 198 | cout << "shared secret 2 = " << hexString(secret2) << "\n"; 199 | CHECK(secret1 == secret2); 200 | } 201 | 202 | 203 | TEST_CASE("key_exchange_raw", "[Crypto") { 204 | key_exchange kx1, kx2; 205 | 206 | auto pk1 = kx1.get_public_key(); 207 | auto pk2 = kx2.get_public_key(); 208 | cout << "public key 1 = " << hexString(pk1) << "\n"; 209 | cout << "public key 2 = " << hexString(pk2) << "\n"; 210 | 211 | auto secret1 = kx1.get_shared_secret(pk2); 212 | auto secret2 = kx2.get_shared_secret(pk1); 213 | cout << "shared secret 1 = " << hexString(secret1) << "\n"; 214 | cout << "shared secret 2 = " << hexString(secret2) << "\n"; 215 | CHECK(secret1 == secret2); 216 | } 217 | 218 | 219 | template 220 | static void test_encryption() { 221 | const string message = "ATTACK AT DAWN"; 222 | 223 | monocypher::session::encryption_key key; // random key 224 | monocypher::session::nonce nonce; // random nonce 225 | 226 | { 227 | // lock/unlock: 228 | char ciphertext[14]; 229 | CHECK(sizeof(ciphertext) == message.size()); 230 | monocypher::session::mac mac = key.lock(nonce, message.c_str(), message.size(), ciphertext); 231 | cout << "locked: " << hexString<14>(ciphertext) << "\n"; 232 | cout << "nonce: " << hexString(nonce) << "\n"; 233 | cout << "MAC: " << hexString(mac) << "\n"; 234 | 235 | char plaintext[14]; 236 | CHECK(key.unlock(nonce, mac, ciphertext, sizeof(ciphertext), plaintext)); 237 | string plaintextStr(plaintext, sizeof(plaintext)); 238 | cout << "unlocked: '" << plaintextStr << "'\n"; 239 | CHECK(plaintextStr == message); 240 | } 241 | { 242 | // box/unbox: 243 | char boxbuf[100]; 244 | output_bytes outbuf{boxbuf, sizeof(boxbuf)}; 245 | output_bytes box = key.box(nonce, 246 | input_bytes{message.c_str(), message.size()}, 247 | outbuf); 248 | CHECK(box.data == outbuf.data); 249 | CHECK(box.size == 14 + sizeof(monocypher::session::mac)); 250 | cout << "boxed: " << hexString(box.data, box.size) << "\n"; 251 | 252 | char plaintext[100]; 253 | output_bytes unbox = key.unbox(nonce, 254 | input_bytes{box.data, box.size}, 255 | output_bytes{plaintext, sizeof(plaintext)}); 256 | REQUIRE(unbox.size > 0); 257 | CHECK(unbox.size == 14); 258 | CHECK(unbox.data == plaintext); 259 | string plaintextStr((char*)unbox.data, unbox.size); 260 | cout << "unlocked: '" << plaintextStr << "'\n"; 261 | CHECK(plaintextStr == message); 262 | } 263 | } 264 | 265 | TEST_CASE("XChaCha20-Poly1305 Encryption", "[Crypto") {test_encryption();} 266 | TEST_CASE("XSalsa20-Poly1305 Encryption", "[Crypto") {test_encryption();} 267 | 268 | TEST_CASE("Streaming Encryption") { 269 | monocypher::session::key key; // random key 270 | monocypher::session::nonce nonce; // random nonce 271 | 272 | string plain1 = "Let us go then, you and I,", 273 | plain2 = "When the evening is spread out against the sky", 274 | plain3 = "Like a patient etherized upon a table;"; 275 | char buffer[100]; 276 | output_bytes const outbuf{buffer, sizeof(buffer)}; 277 | string chunk1, chunk2, chunk3; 278 | { 279 | // write: 280 | monocypher::session::encrypted_writer writer(key, nonce); 281 | output_bytes out = writer.box(input_bytes(plain1), outbuf); 282 | chunk1 = string((char*)out.data, out.size); 283 | out = writer.box(input_bytes(plain2), outbuf); 284 | chunk2 = string((char*)out.data, out.size); 285 | out = writer.box(input_bytes(plain3), outbuf); 286 | chunk3 = string((char*)out.data, out.size); 287 | } 288 | { 289 | // read: 290 | monocypher::session::encrypted_reader reader(key, nonce); 291 | output_bytes out = reader.unbox(chunk1, outbuf); 292 | string decrypt1((char*)out.data, out.size); 293 | CHECK(decrypt1 == plain1); 294 | out = reader.unbox(chunk2, outbuf); 295 | string decrypt2((char*)out.data, out.size); 296 | CHECK(decrypt2 == plain2); 297 | out = reader.unbox(chunk3, outbuf); 298 | string decrypt3((char*)out.data, out.size); 299 | CHECK(decrypt3 == plain3); 300 | 301 | // out of order: 302 | out = reader.unbox(chunk2, outbuf); 303 | CHECK(out.size == 0); 304 | CHECK(out.data == nullptr); 305 | } 306 | } 307 | 308 | 309 | TEST_CASE("Nonces", "[Crypto") { 310 | // Test integer nonce: 311 | monocypher::session::nonce nonce(0x12345678FF); 312 | auto nonceStr = hexString(nonce); 313 | cout << "Integer Nonce = " << nonceStr << "\n"; 314 | CHECK(nonceStr == "FF785634 12000000 00000000 00000000 00000000 00000000"); 315 | 316 | // Increment it: 317 | ++nonce; 318 | nonceStr = hexString(nonce); 319 | cout << "Incr'd Nonce = " << nonceStr << "\n"; 320 | CHECK(nonceStr == "00795634 12000000 00000000 00000000 00000000 00000000"); 321 | } 322 | 323 | 324 | template 325 | static void test_signatures() { 326 | static const char *message = "THIS IS FINE. I'M OKAY WITH THE EVENTS THAT ARE UNFOLDING" 327 | " CURRENTLY. THAT'S OKAY, THINGS ARE GOING TO BE OKAY."; 328 | auto keyPair = key_pair::generate(); 329 | cout << "key pair: " << hexString(keyPair) << "\n"; 330 | auto pubKey = keyPair.get_public_key(); 331 | cout << "public key: " << hexString(pubKey) << "\n"; 332 | auto signature = keyPair.sign(message, strlen(message)); 333 | cout << "signature: " << hexString(signature) << "\n"; 334 | 335 | CHECK(pubKey.check(signature, message, strlen(message))); 336 | cout << "✔︎ signature is valid.\n"; 337 | 338 | signature[0] += 1; 339 | CHECK(!pubKey.check(signature, message, strlen(message))); 340 | cout << "✔︎ modified signature is not valid.\n"; 341 | } 342 | 343 | TEST_CASE("EdDSA Signatures", "[Crypto") {test_signatures();} 344 | TEST_CASE("Ed25519 Signatures", "[Crypto") {test_signatures();} 345 | 346 | 347 | template 348 | static void test_signatures_to_kx() { 349 | auto keyPair1 = key_pair::generate(); 350 | auto keyPair2 = key_pair::generate(); 351 | 352 | // Convert the signing key-pairs to key-exchange key-pairs: 353 | key_exchange kx1 = keyPair1.template as_key_exchange(); 354 | key_exchange kx2 = keyPair2.template as_key_exchange(); 355 | 356 | // Check that we can derive KX public keys from signing public keys: 357 | auto pk1 = kx1.get_public_key(); 358 | auto pk2 = kx2.get_public_key(); 359 | 360 | CHECK(pk1 == keyPair1.get_public_key().template for_key_exchange()); 361 | CHECK(pk2 == keyPair2.get_public_key().template for_key_exchange()); 362 | cout << "✔︎ KX public keys derived from signing public keys are correct.\n"; 363 | 364 | // Generate the shared secrets: 365 | auto secret1 = kx1.get_shared_secret(pk2); 366 | auto secret2 = kx2.get_shared_secret(pk1); 367 | cout << "shared secret 1 = " << hexString(secret1) << "\n"; 368 | cout << "shared secret 2 = " << hexString(secret2) << "\n"; 369 | CHECK(secret1 == secret2); 370 | cout << "✔︎ shared secrets match.\n"; 371 | } 372 | 373 | TEST_CASE("EdDSA Signature-to-KeyExchange", "[Crypto") {test_signatures_to_kx();} 374 | TEST_CASE("Ed25519 Signature-to-KeyExchange", "[Crypto") {test_signatures_to_kx();} 375 | -------------------------------------------------------------------------------- /tests/Test_Blake3.cc: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Jens Alfke on 5/28/24. 3 | // 4 | 5 | #include "hexString.hh" 6 | #include "Monocypher.hh" 7 | #include "monocypher/ext/blake3.hh" 8 | #include 9 | #include // for `tie` 10 | 11 | #include "catch.hpp" 12 | 13 | using namespace std; 14 | using namespace monocypher; 15 | 16 | // Digest and HMAC of empty string taken from the official test vectors, 17 | // https://github.com/BLAKE3-team/BLAKE3/blob/master/test_vectors/test_vectors.json 18 | 19 | TEST_CASE("Blake3") { 20 | auto h1 = ext::blake3::create(""sv); 21 | string str1 = hexString(h1); 22 | cout << str1 << "\n"; 23 | CHECK(str1 == "AF1349B9 F5F9A1A6 A0404DEA 36DCC949 9BCB25C9 ADC112B7 CC9A93CA E41F3262"); 24 | 25 | h1 = ext::blake3::create("hello world"sv); 26 | str1 = hexString(h1); 27 | cout << str1 << "\n"; 28 | CHECK(str1 == "D74981EF A70A0C88 0B8D8C19 85D075DB CBF679B9 9A5F9914 E5AAF96B 831A9E24"); 29 | 30 | ext::blake3::builder b; 31 | b.update("hello"sv).update(" "sv).update("world"sv); 32 | ext::blake3 h2 = b.final(); 33 | 34 | string str2 = hexString(h2); 35 | cout << str2 << "\n"; 36 | CHECK(str2 == str1); 37 | CHECK(h2 == h1); 38 | 39 | // (No HMAC support in Blake3 yet) 40 | } 41 | 42 | TEST_CASE("Blake3 HMAC") { 43 | secret_byte_array<32> key("whats the Elvish word for friend", 32); 44 | 45 | auto mac = ext::blake3::createMAC(""sv, key); 46 | string macStr = hexString(mac); 47 | cout << "HMAC = " << macStr << endl; 48 | CHECK(macStr == "92B2B756 04ED3C76 1F9D6F62 392C8A92 27AD0EA3 F09573E7 83F1498A 4ED60D26"); 49 | 50 | mac = ext::blake3::createMAC("hello world"sv, key); 51 | macStr = hexString(mac); 52 | cout << "HMAC = " << macStr << endl; 53 | CHECK(macStr == "546A11CF 08472EE6 8FB83C3F 28AB2DC2 1EF620A6 F03A64B4 29E4BAC4 E454D2B2"); 54 | 55 | typename ext::blake3::mac_builder hm(key); 56 | hm.update("hello"sv).update(" "sv).update("world"sv); 57 | ext::blake3 mac2 = hm.final(); 58 | cout << "HMAC = " << hexString(mac2) << endl; 59 | CHECK(mac2 == mac); 60 | 61 | } 62 | -------------------------------------------------------------------------------- /tests/hexString.hh: -------------------------------------------------------------------------------- 1 | // hexString.hh 2 | // 3 | // Copyright © 2022 Jens Alfke. All rights reserved. 4 | // 5 | // Licensed under the MIT License: 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in 15 | // all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | // THE SOFTWARE. 24 | 25 | #pragma once 26 | #include 27 | #include 28 | #include 29 | 30 | 31 | static inline std::string hexString(const void *buf, size_t size, bool spaces =true) { 32 | std::string hex; 33 | hex.resize(size * 2 + size / 4); 34 | char *dst = hex.data(), *end = &hex.back() + 1; 35 | for (size_t i = 0; i < size; i++) { 36 | if (spaces && i > 0 && (i % 4) == 0) 37 | *dst++ = ' '; 38 | dst += snprintf(dst, end - dst, "%02X", ((const uint8_t*)buf)[i]); 39 | } 40 | hex.resize(dst - hex.data()); 41 | return hex; 42 | } 43 | 44 | 45 | template 46 | static std::string hexString(const void *buf) { 47 | return hexString(buf, Size); 48 | } 49 | 50 | 51 | template 52 | static std::string hexString(const std::array &a) { 53 | return hexString(a.data()); 54 | } 55 | 56 | 57 | -------------------------------------------------------------------------------- /tests/tests_main.cc: -------------------------------------------------------------------------------- 1 | // 2 | // tests_main.cc 3 | // Monocypher-Cpp 4 | // 5 | // Created by Jens Alfke on 9/24/20. 6 | // 7 | 8 | #define CATCH_CONFIG_MAIN 9 | 10 | #include "catch.hpp" 11 | 12 | #include "CaseListReporter.hh" 13 | -------------------------------------------------------------------------------- /vendor/B-Con/sha256.c: -------------------------------------------------------------------------------- 1 | // 2 | // sha256.c 3 | // Monocypher-cpp 4 | // 5 | // Imported by Jens Alfke on 2/9/22. 6 | // Source: 7 | // Changes: 8 | // - Declare `sha256_transform` as `static` 9 | // License: 10 | // From the README.md: 11 | // >This code is released into the public domain free of any restrictions. The author requests 12 | // >acknowledgement if the code is used, but does not require it. This code is provided free of 13 | // >any liability and without any quality claims by the author. 14 | 15 | /********************************************************************* 16 | * Filename: sha256.c 17 | * Author: Brad Conte (brad AT bradconte.com) 18 | * Copyright: 19 | * Disclaimer: This code is presented "as is" without any guarantees. 20 | * Details: Implementation of the SHA-256 hashing algorithm. 21 | SHA-256 is one of the three algorithms in the SHA2 22 | specification. The others, SHA-384 and SHA-512, are not 23 | offered in this implementation. 24 | Algorithm specification can be found here: 25 | * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2withchangenotice.pdf 26 | This implementation uses little endian byte order. 27 | *********************************************************************/ 28 | 29 | /*************************** HEADER FILES ***************************/ 30 | #include 31 | #include 32 | #include "sha256.h" 33 | 34 | /****************************** MACROS ******************************/ 35 | #define ROTLEFT(a,b) (((a) << (b)) | ((a) >> (32-(b)))) 36 | #define ROTRIGHT(a,b) (((a) >> (b)) | ((a) << (32-(b)))) 37 | 38 | #define CH(x,y,z) (((x) & (y)) ^ (~(x) & (z))) 39 | #define MAJ(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) 40 | #define EP0(x) (ROTRIGHT(x,2) ^ ROTRIGHT(x,13) ^ ROTRIGHT(x,22)) 41 | #define EP1(x) (ROTRIGHT(x,6) ^ ROTRIGHT(x,11) ^ ROTRIGHT(x,25)) 42 | #define SIG0(x) (ROTRIGHT(x,7) ^ ROTRIGHT(x,18) ^ ((x) >> 3)) 43 | #define SIG1(x) (ROTRIGHT(x,17) ^ ROTRIGHT(x,19) ^ ((x) >> 10)) 44 | 45 | /**************************** VARIABLES *****************************/ 46 | static const WORD k[64] = { 47 | 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5, 48 | 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174, 49 | 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da, 50 | 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967, 51 | 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85, 52 | 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,0xd6990624,0xf40e3585,0x106aa070, 53 | 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3, 54 | 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 55 | }; 56 | 57 | /*********************** FUNCTION DEFINITIONS ***********************/ 58 | static void sha256_transform(SHA256_CTX *ctx, const BYTE data[]) 59 | { 60 | WORD a, b, c, d, e, f, g, h, i, j, t1, t2, m[64]; 61 | 62 | for (i = 0, j = 0; i < 16; ++i, j += 4) 63 | m[i] = (data[j] << 24) | (data[j + 1] << 16) | (data[j + 2] << 8) | (data[j + 3]); 64 | for ( ; i < 64; ++i) 65 | m[i] = SIG1(m[i - 2]) + m[i - 7] + SIG0(m[i - 15]) + m[i - 16]; 66 | 67 | a = ctx->state[0]; 68 | b = ctx->state[1]; 69 | c = ctx->state[2]; 70 | d = ctx->state[3]; 71 | e = ctx->state[4]; 72 | f = ctx->state[5]; 73 | g = ctx->state[6]; 74 | h = ctx->state[7]; 75 | 76 | for (i = 0; i < 64; ++i) { 77 | t1 = h + EP1(e) + CH(e,f,g) + k[i] + m[i]; 78 | t2 = EP0(a) + MAJ(a,b,c); 79 | h = g; 80 | g = f; 81 | f = e; 82 | e = d + t1; 83 | d = c; 84 | c = b; 85 | b = a; 86 | a = t1 + t2; 87 | } 88 | 89 | ctx->state[0] += a; 90 | ctx->state[1] += b; 91 | ctx->state[2] += c; 92 | ctx->state[3] += d; 93 | ctx->state[4] += e; 94 | ctx->state[5] += f; 95 | ctx->state[6] += g; 96 | ctx->state[7] += h; 97 | } 98 | 99 | void sha256_init(SHA256_CTX *ctx) 100 | { 101 | ctx->datalen = 0; 102 | ctx->bitlen = 0; 103 | ctx->state[0] = 0x6a09e667; 104 | ctx->state[1] = 0xbb67ae85; 105 | ctx->state[2] = 0x3c6ef372; 106 | ctx->state[3] = 0xa54ff53a; 107 | ctx->state[4] = 0x510e527f; 108 | ctx->state[5] = 0x9b05688c; 109 | ctx->state[6] = 0x1f83d9ab; 110 | ctx->state[7] = 0x5be0cd19; 111 | } 112 | 113 | void sha256_update(SHA256_CTX *ctx, const BYTE data[], size_t len) 114 | { 115 | WORD i; 116 | 117 | for (i = 0; i < len; ++i) { 118 | ctx->data[ctx->datalen] = data[i]; 119 | ctx->datalen++; 120 | if (ctx->datalen == 64) { 121 | sha256_transform(ctx, ctx->data); 122 | ctx->bitlen += 512; 123 | ctx->datalen = 0; 124 | } 125 | } 126 | } 127 | 128 | void sha256_final(SHA256_CTX *ctx, BYTE hash[]) 129 | { 130 | WORD i; 131 | 132 | i = ctx->datalen; 133 | 134 | // Pad whatever data is left in the buffer. 135 | if (ctx->datalen < 56) { 136 | ctx->data[i++] = 0x80; 137 | while (i < 56) 138 | ctx->data[i++] = 0x00; 139 | } 140 | else { 141 | ctx->data[i++] = 0x80; 142 | while (i < 64) 143 | ctx->data[i++] = 0x00; 144 | sha256_transform(ctx, ctx->data); 145 | memset(ctx->data, 0, 56); 146 | } 147 | 148 | // Append to the padding the total message's length in bits and transform. 149 | ctx->bitlen += ctx->datalen * 8; 150 | ctx->data[63] = BYTE(ctx->bitlen); 151 | ctx->data[62] = BYTE(ctx->bitlen >> 8); 152 | ctx->data[61] = BYTE(ctx->bitlen >> 16); 153 | ctx->data[60] = BYTE(ctx->bitlen >> 24); 154 | ctx->data[59] = BYTE(ctx->bitlen >> 32); 155 | ctx->data[58] = BYTE(ctx->bitlen >> 40); 156 | ctx->data[57] = BYTE(ctx->bitlen >> 48); 157 | ctx->data[56] = BYTE(ctx->bitlen >> 56); 158 | sha256_transform(ctx, ctx->data); 159 | 160 | // Since this implementation uses little endian byte ordering and SHA uses big endian, 161 | // reverse all the bytes when copying the final state to the output hash. 162 | for (i = 0; i < 4; ++i) { 163 | hash[i] = (ctx->state[0] >> (24 - i * 8)) & 0x000000ff; 164 | hash[i + 4] = (ctx->state[1] >> (24 - i * 8)) & 0x000000ff; 165 | hash[i + 8] = (ctx->state[2] >> (24 - i * 8)) & 0x000000ff; 166 | hash[i + 12] = (ctx->state[3] >> (24 - i * 8)) & 0x000000ff; 167 | hash[i + 16] = (ctx->state[4] >> (24 - i * 8)) & 0x000000ff; 168 | hash[i + 20] = (ctx->state[5] >> (24 - i * 8)) & 0x000000ff; 169 | hash[i + 24] = (ctx->state[6] >> (24 - i * 8)) & 0x000000ff; 170 | hash[i + 28] = (ctx->state[7] >> (24 - i * 8)) & 0x000000ff; 171 | } 172 | } 173 | -------------------------------------------------------------------------------- /vendor/B-Con/sha256.h: -------------------------------------------------------------------------------- 1 | // 2 | // sha256.h 3 | // Monocypher-cpp 4 | // 5 | // Imported by Jens Alfke on 2/9/22. 6 | // Source: 7 | // Changes: 8 | // - include 9 | // - Changed BYTE type from `unsigned char` to `uint8_t` 10 | // - Changed WORD type from `unsigned int` to `uint32_t` 11 | // 12 | 13 | /********************************************************************* 14 | * Filename: sha256.h 15 | * Author: Brad Conte (brad AT bradconte.com) 16 | * Copyright: 17 | * Disclaimer: This code is presented "as is" without any guarantees. 18 | * Details: Defines the API for the corresponding SHA1 implementation. 19 | *********************************************************************/ 20 | 21 | #ifndef SHA256_H 22 | #define SHA256_H 23 | 24 | /*************************** HEADER FILES ***************************/ 25 | #include 26 | #include 27 | 28 | /****************************** MACROS ******************************/ 29 | #define SHA256_BLOCK_SIZE 32 // SHA256 outputs a 32 byte digest 30 | 31 | /**************************** DATA TYPES ****************************/ 32 | typedef uint8_t BYTE; // 8-bit byte 33 | typedef uint32_t WORD; // 32-bit word, change to "long" for 16-bit machines 34 | 35 | typedef struct { 36 | BYTE data[64]; 37 | WORD datalen; 38 | unsigned long long bitlen; 39 | WORD state[8]; 40 | } SHA256_CTX; 41 | 42 | /*********************** FUNCTION DECLARATIONS **********************/ 43 | void sha256_init(SHA256_CTX *ctx); 44 | void sha256_update(SHA256_CTX *ctx, const BYTE data[], size_t len); 45 | void sha256_final(SHA256_CTX *ctx, BYTE hash[]); 46 | 47 | #endif // SHA256_H 48 | -------------------------------------------------------------------------------- /vendor/tweetnacl/tweetnacl.c: -------------------------------------------------------------------------------- 1 | // 2 | // tweetnacl.c 3 | // Monocypher-cpp 4 | // 5 | // Imported by Jens Alfke on 2/8/22. 6 | // Source: 7 | // Changes: 8 | // - Added a few `(int)` casts to fix compiler warnings about implicit conversions. 9 | // License: 10 | // From the home page: "TweetNaCl is a self-contained public-domain C library" 11 | 12 | #include "tweetnacl.h" 13 | #define FOR(i,n) for (i = 0;i < n;++i) 14 | #define sv static void 15 | 16 | typedef unsigned char u8; 17 | typedef unsigned long u32; 18 | typedef unsigned long long u64; 19 | typedef long long i64; 20 | typedef i64 gf[16]; 21 | extern void randombytes(u8 *,u64); 22 | 23 | static const u8 24 | _0[16] = {0}, 25 | _9[32] = {9}; 26 | static const gf 27 | gf0 = {0}, 28 | gf1 = {1}, 29 | _121665 = {0xDB41,1}, 30 | D = {0x78a3, 0x1359, 0x4dca, 0x75eb, 0xd8ab, 0x4141, 0x0a4d, 0x0070, 0xe898, 0x7779, 0x4079, 0x8cc7, 0xfe73, 0x2b6f, 0x6cee, 0x5203}, 31 | D2 = {0xf159, 0x26b2, 0x9b94, 0xebd6, 0xb156, 0x8283, 0x149a, 0x00e0, 0xd130, 0xeef3, 0x80f2, 0x198e, 0xfce7, 0x56df, 0xd9dc, 0x2406}, 32 | X = {0xd51a, 0x8f25, 0x2d60, 0xc956, 0xa7b2, 0x9525, 0xc760, 0x692c, 0xdc5c, 0xfdd6, 0xe231, 0xc0a4, 0x53fe, 0xcd6e, 0x36d3, 0x2169}, 33 | Y = {0x6658, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666}, 34 | I = {0xa0b0, 0x4a0e, 0x1b27, 0xc4ee, 0xe478, 0xad2f, 0x1806, 0x2f43, 0xd7a7, 0x3dfb, 0x0099, 0x2b4d, 0xdf0b, 0x4fc1, 0x2480, 0x2b83}; 35 | 36 | static u32 L32(u32 x,int c) { return (x << c) | ((x&0xffffffff) >> (32 - c)); } 37 | 38 | static u32 ld32(const u8 *x) 39 | { 40 | u32 u = x[3]; 41 | u = (u<<8)|x[2]; 42 | u = (u<<8)|x[1]; 43 | return (u<<8)|x[0]; 44 | } 45 | 46 | static u64 dl64(const u8 *x) 47 | { 48 | u64 i,u=0; 49 | FOR(i,8) u=(u<<8)|x[i]; 50 | return u; 51 | } 52 | 53 | sv st32(u8 *x,u32 u) 54 | { 55 | int i; 56 | FOR(i,4) { x[i] = u; u >>= 8; } 57 | } 58 | 59 | sv ts64(u8 *x,u64 u) 60 | { 61 | int i; 62 | for (i = 7;i >= 0;--i) { x[i] = u; u >>= 8; } 63 | } 64 | 65 | static int vn(const u8 *x,const u8 *y,int n) 66 | { 67 | u32 i,d = 0; 68 | FOR(i,n) d |= x[i]^y[i]; 69 | return (1 & ((d - 1) >> 8)) - 1; 70 | } 71 | 72 | int crypto_verify_16(const u8 *x,const u8 *y) 73 | { 74 | return vn(x,y,16); 75 | } 76 | 77 | int crypto_verify_32(const u8 *x,const u8 *y) 78 | { 79 | return vn(x,y,32); 80 | } 81 | 82 | sv core(u8 *out,const u8 *in,const u8 *k,const u8 *c,int h) 83 | { 84 | u32 w[16],x[16],y[16],t[4]; 85 | int i,j,m; 86 | 87 | FOR(i,4) { 88 | x[5*i] = ld32(c+4*i); 89 | x[1+i] = ld32(k+4*i); 90 | x[6+i] = ld32(in+4*i); 91 | x[11+i] = ld32(k+16+4*i); 92 | } 93 | 94 | FOR(i,16) y[i] = x[i]; 95 | 96 | FOR(i,20) { 97 | FOR(j,4) { 98 | FOR(m,4) t[m] = x[(5*j+4*m)%16]; 99 | t[1] ^= L32(t[0]+t[3], 7); 100 | t[2] ^= L32(t[1]+t[0], 9); 101 | t[3] ^= L32(t[2]+t[1],13); 102 | t[0] ^= L32(t[3]+t[2],18); 103 | FOR(m,4) w[4*j+(j+m)%4] = t[m]; 104 | } 105 | FOR(m,16) x[m] = w[m]; 106 | } 107 | 108 | if (h) { 109 | FOR(i,16) x[i] += y[i]; 110 | FOR(i,4) { 111 | x[5*i] -= ld32(c+4*i); 112 | x[6+i] -= ld32(in+4*i); 113 | } 114 | FOR(i,4) { 115 | st32(out+4*i,x[5*i]); 116 | st32(out+16+4*i,x[6+i]); 117 | } 118 | } else 119 | FOR(i,16) st32(out + 4 * i,x[i] + y[i]); 120 | } 121 | 122 | int crypto_core_salsa20(u8 *out,const u8 *in,const u8 *k,const u8 *c) 123 | { 124 | core(out,in,k,c,0); 125 | return 0; 126 | } 127 | 128 | int crypto_core_hsalsa20(u8 *out,const u8 *in,const u8 *k,const u8 *c) 129 | { 130 | core(out,in,k,c,1); 131 | return 0; 132 | } 133 | 134 | static const u8 sigma[17] = "expand 32-byte k"; // compiler makes us count the trailing 0 in size 135 | 136 | int crypto_stream_salsa20_xor(u8 *c,const u8 *m,u64 b,const u8 *n,const u8 *k) 137 | { 138 | u8 z[16],x[64]; 139 | u32 u,i; 140 | if (!b) return 0; 141 | FOR(i,16) z[i] = 0; 142 | FOR(i,8) z[i] = n[i]; 143 | while (b >= 64) { 144 | crypto_core_salsa20(x,z,k,sigma); 145 | FOR(i,64) c[i] = (m?m[i]:0) ^ x[i]; 146 | u = 1; 147 | for (i = 8;i < 16;++i) { 148 | u += (u32) z[i]; 149 | z[i] = u; 150 | u >>= 8; 151 | } 152 | b -= 64; 153 | c += 64; 154 | if (m) m += 64; 155 | } 156 | if (b) { 157 | crypto_core_salsa20(x,z,k,sigma); 158 | FOR(i,b) c[i] = (m?m[i]:0) ^ x[i]; 159 | } 160 | return 0; 161 | } 162 | 163 | int crypto_stream_salsa20(u8 *c,u64 d,const u8 *n,const u8 *k) 164 | { 165 | return crypto_stream_salsa20_xor(c,0,d,n,k); 166 | } 167 | 168 | int crypto_stream(u8 *c,u64 d,const u8 *n,const u8 *k) 169 | { 170 | u8 s[32]; 171 | crypto_core_hsalsa20(s,n,k,sigma); 172 | return crypto_stream_salsa20(c,d,n+16,s); 173 | } 174 | 175 | int crypto_stream_xor(u8 *c,const u8 *m,u64 d,const u8 *n,const u8 *k) 176 | { 177 | u8 s[32]; 178 | crypto_core_hsalsa20(s,n,k,sigma); 179 | return crypto_stream_salsa20_xor(c,m,d,n+16,s); 180 | } 181 | 182 | sv add1305(u32 *h,const u32 *c) 183 | { 184 | u32 j,u = 0; 185 | FOR(j,17) { 186 | u += h[j] + c[j]; 187 | h[j] = u & 255; 188 | u >>= 8; 189 | } 190 | } 191 | 192 | static const u32 minusp[17] = { 193 | 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252 194 | } ; 195 | 196 | int crypto_onetimeauth(u8 *out,const u8 *m,u64 n,const u8 *k) 197 | { 198 | u32 s,i,j,u,x[17],r[17],h[17],c[17],g[17]; 199 | 200 | FOR(j,17) r[j]=h[j]=0; 201 | FOR(j,16) r[j]=k[j]; 202 | r[3]&=15; 203 | r[4]&=252; 204 | r[7]&=15; 205 | r[8]&=252; 206 | r[11]&=15; 207 | r[12]&=252; 208 | r[15]&=15; 209 | 210 | while (n > 0) { 211 | FOR(j,17) c[j] = 0; 212 | for (j = 0;(j < 16) && (j < n);++j) c[j] = m[j]; 213 | c[j] = 1; 214 | m += j; n -= j; 215 | add1305(h,c); 216 | FOR(i,17) { 217 | x[i] = 0; 218 | FOR(j,17) x[i] += h[j] * ((j <= i) ? r[i - j] : 320 * r[i + 17 - j]); 219 | } 220 | FOR(i,17) h[i] = x[i]; 221 | u = 0; 222 | FOR(j,16) { 223 | u += h[j]; 224 | h[j] = u & 255; 225 | u >>= 8; 226 | } 227 | u += h[16]; h[16] = u & 3; 228 | u = 5 * (u >> 2); 229 | FOR(j,16) { 230 | u += h[j]; 231 | h[j] = u & 255; 232 | u >>= 8; 233 | } 234 | u += h[16]; h[16] = u; 235 | } 236 | 237 | FOR(j,17) g[j] = h[j]; 238 | add1305(h,minusp); 239 | s = -(h[16] >> 7); 240 | FOR(j,17) h[j] ^= s & (g[j] ^ h[j]); 241 | 242 | FOR(j,16) c[j] = k[j + 16]; 243 | c[16] = 0; 244 | add1305(h,c); 245 | FOR(j,16) out[j] = h[j]; 246 | return 0; 247 | } 248 | 249 | int crypto_onetimeauth_verify(const u8 *h,const u8 *m,u64 n,const u8 *k) 250 | { 251 | u8 x[16]; 252 | crypto_onetimeauth(x,m,n,k); 253 | return crypto_verify_16(h,x); 254 | } 255 | 256 | int crypto_secretbox(u8 *c,const u8 *m,u64 d,const u8 *n,const u8 *k) 257 | { 258 | int i; 259 | if (d < 32) return -1; 260 | crypto_stream_xor(c,m,d,n,k); 261 | crypto_onetimeauth(c + 16,c + 32,d - 32,c); 262 | FOR(i,16) c[i] = 0; 263 | return 0; 264 | } 265 | 266 | int crypto_secretbox_open(u8 *m,const u8 *c,u64 d,const u8 *n,const u8 *k) 267 | { 268 | int i; 269 | u8 x[32]; 270 | if (d < 32) return -1; 271 | crypto_stream(x,32,n,k); 272 | if (crypto_onetimeauth_verify(c + 16,c + 32,d - 32,x) != 0) return -1; 273 | crypto_stream_xor(m,c,d,n,k); 274 | FOR(i,32) m[i] = 0; 275 | return 0; 276 | } 277 | 278 | sv set25519(gf r, const gf a) 279 | { 280 | int i; 281 | FOR(i,16) r[i]=a[i]; 282 | } 283 | 284 | sv car25519(gf o) 285 | { 286 | int i; 287 | i64 c; 288 | FOR(i,16) { 289 | o[i]+=(1LL<<16); 290 | c=o[i]>>16; 291 | o[(i+1)*(i<15)]+=c-1+37*(c-1)*(i==15); 292 | o[i]-=c<<16; 293 | } 294 | } 295 | 296 | sv sel25519(gf p,gf q,int b) 297 | { 298 | i64 t,i,c=~(b-1); 299 | FOR(i,16) { 300 | t= c&(p[i]^q[i]); 301 | p[i]^=t; 302 | q[i]^=t; 303 | } 304 | } 305 | 306 | sv pack25519(u8 *o,const gf n) 307 | { 308 | int i,j,b; 309 | gf m,t; 310 | FOR(i,16) t[i]=n[i]; 311 | car25519(t); 312 | car25519(t); 313 | car25519(t); 314 | FOR(j,2) { 315 | m[0]=t[0]-0xffed; 316 | for(i=1;i<15;i++) { 317 | m[i]=t[i]-0xffff-((m[i-1]>>16)&1); 318 | m[i-1]&=0xffff; 319 | } 320 | m[15]=t[15]-0x7fff-((m[14]>>16)&1); 321 | b=(m[15]>>16)&1; 322 | m[14]&=0xffff; 323 | sel25519(t,m,1-b); 324 | } 325 | FOR(i,16) { 326 | o[2*i]=t[i]&0xff; 327 | o[2*i+1]=t[i]>>8; 328 | } 329 | } 330 | 331 | static int neq25519(const gf a, const gf b) 332 | { 333 | u8 c[32],d[32]; 334 | pack25519(c,a); 335 | pack25519(d,b); 336 | return crypto_verify_32(c,d); 337 | } 338 | 339 | static u8 par25519(const gf a) 340 | { 341 | u8 d[32]; 342 | pack25519(d,a); 343 | return d[0]&1; 344 | } 345 | 346 | sv unpack25519(gf o, const u8 *n) 347 | { 348 | int i; 349 | FOR(i,16) o[i]=n[2*i]+((i64)n[2*i+1]<<8); 350 | o[15]&=0x7fff; 351 | } 352 | 353 | sv A(gf o,const gf a,const gf b) 354 | { 355 | int i; 356 | FOR(i,16) o[i]=a[i]+b[i]; 357 | } 358 | 359 | sv Z(gf o,const gf a,const gf b) 360 | { 361 | int i; 362 | FOR(i,16) o[i]=a[i]-b[i]; 363 | } 364 | 365 | sv M(gf o,const gf a,const gf b) 366 | { 367 | i64 i,j,t[31]; 368 | FOR(i,31) t[i]=0; 369 | FOR(i,16) FOR(j,16) t[i+j]+=a[i]*b[j]; 370 | FOR(i,15) t[i]+=38*t[i+16]; 371 | FOR(i,16) o[i]=t[i]; 372 | car25519(o); 373 | car25519(o); 374 | } 375 | 376 | sv S(gf o,const gf a) 377 | { 378 | M(o,a,a); 379 | } 380 | 381 | sv inv25519(gf o,const gf i) 382 | { 383 | gf c; 384 | int a; 385 | FOR(a,16) c[a]=i[a]; 386 | for(a=253;a>=0;a--) { 387 | S(c,c); 388 | if(a!=2&&a!=4) M(c,c,i); 389 | } 390 | FOR(a,16) o[a]=c[a]; 391 | } 392 | 393 | sv pow2523(gf o,const gf i) 394 | { 395 | gf c; 396 | int a; 397 | FOR(a,16) c[a]=i[a]; 398 | for(a=250;a>=0;a--) { 399 | S(c,c); 400 | if(a!=1) M(c,c,i); 401 | } 402 | FOR(a,16) o[a]=c[a]; 403 | } 404 | 405 | int crypto_scalarmult(u8 *q,const u8 *n,const u8 *p) 406 | { 407 | u8 z[32]; 408 | i64 x[80],r,i; 409 | gf a,b,c,d,e,f; 410 | FOR(i,31) z[i]=n[i]; 411 | z[31]=(n[31]&127)|64; 412 | z[0]&=248; 413 | unpack25519(x,p); 414 | FOR(i,16) { 415 | b[i]=x[i]; 416 | d[i]=a[i]=c[i]=0; 417 | } 418 | a[0]=d[0]=1; 419 | for(i=254;i>=0;--i) { 420 | r=(z[i>>3]>>(i&7))&1; 421 | sel25519(a,b,(int)r); 422 | sel25519(c,d,(int)r); 423 | A(e,a,c); 424 | Z(a,a,c); 425 | A(c,b,d); 426 | Z(b,b,d); 427 | S(d,e); 428 | S(f,a); 429 | M(a,c,a); 430 | M(c,b,e); 431 | A(e,a,c); 432 | Z(a,a,c); 433 | S(b,a); 434 | Z(c,d,f); 435 | M(a,c,_121665); 436 | A(a,a,d); 437 | M(c,c,a); 438 | M(a,d,f); 439 | M(d,b,x); 440 | S(b,e); 441 | sel25519(a,b,(int)r); 442 | sel25519(c,d,(int)r); 443 | } 444 | FOR(i,16) { 445 | x[i+16]=a[i]; 446 | x[i+32]=c[i]; 447 | x[i+48]=b[i]; 448 | x[i+64]=d[i]; 449 | } 450 | inv25519(x+32,x+32); 451 | M(x+16,x+16,x+32); 452 | pack25519(q,x+16); 453 | return 0; 454 | } 455 | 456 | int crypto_scalarmult_base(u8 *q,const u8 *n) 457 | { 458 | return crypto_scalarmult(q,n,_9); 459 | } 460 | 461 | int crypto_box_keypair(u8 *y,u8 *x) 462 | { 463 | randombytes(x,32); 464 | return crypto_scalarmult_base(y,x); 465 | } 466 | 467 | int crypto_box_beforenm(u8 *k,const u8 *y,const u8 *x) 468 | { 469 | u8 s[32]; 470 | crypto_scalarmult(s,x,y); 471 | return crypto_core_hsalsa20(k,_0,s,sigma); 472 | } 473 | 474 | int crypto_box_afternm(u8 *c,const u8 *m,u64 d,const u8 *n,const u8 *k) 475 | { 476 | return crypto_secretbox(c,m,d,n,k); 477 | } 478 | 479 | int crypto_box_open_afternm(u8 *m,const u8 *c,u64 d,const u8 *n,const u8 *k) 480 | { 481 | return crypto_secretbox_open(m,c,d,n,k); 482 | } 483 | 484 | int crypto_box(u8 *c,const u8 *m,u64 d,const u8 *n,const u8 *y,const u8 *x) 485 | { 486 | u8 k[32]; 487 | crypto_box_beforenm(k,y,x); 488 | return crypto_box_afternm(c,m,d,n,k); 489 | } 490 | 491 | int crypto_box_open(u8 *m,const u8 *c,u64 d,const u8 *n,const u8 *y,const u8 *x) 492 | { 493 | u8 k[32]; 494 | crypto_box_beforenm(k,y,x); 495 | return crypto_box_open_afternm(m,c,d,n,k); 496 | } 497 | 498 | static u64 R(u64 x,int c) { return (x >> c) | (x << (64 - c)); } 499 | static u64 Ch(u64 x,u64 y,u64 z) { return (x & y) ^ (~x & z); } 500 | static u64 Maj(u64 x,u64 y,u64 z) { return (x & y) ^ (x & z) ^ (y & z); } 501 | static u64 Sigma0(u64 x) { return R(x,28) ^ R(x,34) ^ R(x,39); } 502 | static u64 Sigma1(u64 x) { return R(x,14) ^ R(x,18) ^ R(x,41); } 503 | static u64 sigma0(u64 x) { return R(x, 1) ^ R(x, 8) ^ (x >> 7); } 504 | static u64 sigma1(u64 x) { return R(x,19) ^ R(x,61) ^ (x >> 6); } 505 | 506 | static const u64 K[80] = 507 | { 508 | 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL, 509 | 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, 510 | 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, 511 | 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL, 512 | 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, 513 | 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, 514 | 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL, 515 | 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, 516 | 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, 517 | 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL, 518 | 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, 519 | 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, 520 | 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL, 521 | 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, 522 | 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, 523 | 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL, 524 | 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, 525 | 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, 526 | 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL, 527 | 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL 528 | }; 529 | 530 | int crypto_hashblocks(u8 *x,const u8 *m,u64 n) 531 | { 532 | u64 z[8],b[8],a[8],w[16],t; 533 | int i,j; 534 | 535 | FOR(i,8) z[i] = a[i] = dl64(x + 8 * i); 536 | 537 | while (n >= 128) { 538 | FOR(i,16) w[i] = dl64(m + 8 * i); 539 | 540 | FOR(i,80) { 541 | FOR(j,8) b[j] = a[j]; 542 | t = a[7] + Sigma1(a[4]) + Ch(a[4],a[5],a[6]) + K[i] + w[i%16]; 543 | b[7] = t + Sigma0(a[0]) + Maj(a[0],a[1],a[2]); 544 | b[3] += t; 545 | FOR(j,8) a[(j+1)%8] = b[j]; 546 | if (i%16 == 15) 547 | FOR(j,16) 548 | w[j] += w[(j+9)%16] + sigma0(w[(j+1)%16]) + sigma1(w[(j+14)%16]); 549 | } 550 | 551 | FOR(i,8) { a[i] += z[i]; z[i] = a[i]; } 552 | 553 | m += 128; 554 | n -= 128; 555 | } 556 | 557 | FOR(i,8) ts64(x+8*i,z[i]); 558 | 559 | return (int)n; 560 | } 561 | 562 | static const u8 iv[64] = { 563 | 0x6a,0x09,0xe6,0x67,0xf3,0xbc,0xc9,0x08, 564 | 0xbb,0x67,0xae,0x85,0x84,0xca,0xa7,0x3b, 565 | 0x3c,0x6e,0xf3,0x72,0xfe,0x94,0xf8,0x2b, 566 | 0xa5,0x4f,0xf5,0x3a,0x5f,0x1d,0x36,0xf1, 567 | 0x51,0x0e,0x52,0x7f,0xad,0xe6,0x82,0xd1, 568 | 0x9b,0x05,0x68,0x8c,0x2b,0x3e,0x6c,0x1f, 569 | 0x1f,0x83,0xd9,0xab,0xfb,0x41,0xbd,0x6b, 570 | 0x5b,0xe0,0xcd,0x19,0x13,0x7e,0x21,0x79 571 | } ; 572 | 573 | int crypto_hash(u8 *out,const u8 *m,u64 n) 574 | { 575 | u8 h[64],x[256]; 576 | u64 i,b = n; 577 | 578 | FOR(i,64) h[i] = iv[i]; 579 | 580 | crypto_hashblocks(h,m,n); 581 | m += n; 582 | n &= 127; 583 | m -= n; 584 | 585 | FOR(i,256) x[i] = 0; 586 | FOR(i,n) x[i] = m[i]; 587 | x[n] = 128; 588 | 589 | n = 256-128*(n<112); 590 | x[n-9] = b >> 61; 591 | ts64(x+n-8,b<<3); 592 | crypto_hashblocks(h,x,n); 593 | 594 | FOR(i,64) out[i] = h[i]; 595 | 596 | return 0; 597 | } 598 | 599 | sv add(gf p[4],gf q[4]) 600 | { 601 | gf a,b,c,d,t,e,f,g,h; 602 | 603 | Z(a, p[1], p[0]); 604 | Z(t, q[1], q[0]); 605 | M(a, a, t); 606 | A(b, p[0], p[1]); 607 | A(t, q[0], q[1]); 608 | M(b, b, t); 609 | M(c, p[3], q[3]); 610 | M(c, c, D2); 611 | M(d, p[2], q[2]); 612 | A(d, d, d); 613 | Z(e, b, a); 614 | Z(f, d, c); 615 | A(g, d, c); 616 | A(h, b, a); 617 | 618 | M(p[0], e, f); 619 | M(p[1], h, g); 620 | M(p[2], g, f); 621 | M(p[3], e, h); 622 | } 623 | 624 | sv cswap(gf p[4],gf q[4],u8 b) 625 | { 626 | int i; 627 | FOR(i,4) 628 | sel25519(p[i],q[i],b); 629 | } 630 | 631 | sv pack(u8 *r,gf p[4]) 632 | { 633 | gf tx, ty, zi; 634 | inv25519(zi, p[2]); 635 | M(tx, p[0], zi); 636 | M(ty, p[1], zi); 637 | pack25519(r, ty); 638 | r[31] ^= par25519(tx) << 7; 639 | } 640 | 641 | sv scalarmult(gf p[4],gf q[4],const u8 *s) 642 | { 643 | int i; 644 | set25519(p[0],gf0); 645 | set25519(p[1],gf1); 646 | set25519(p[2],gf1); 647 | set25519(p[3],gf0); 648 | for (i = 255;i >= 0;--i) { 649 | u8 b = (s[i/8]>>(i&7))&1; 650 | cswap(p,q,b); 651 | add(q,p); 652 | add(p,p); 653 | cswap(p,q,b); 654 | } 655 | } 656 | 657 | sv scalarbase(gf p[4],const u8 *s) 658 | { 659 | gf q[4]; 660 | set25519(q[0],X); 661 | set25519(q[1],Y); 662 | set25519(q[2],gf1); 663 | M(q[3],X,Y); 664 | scalarmult(p,q,s); 665 | } 666 | 667 | int crypto_sign_keypair(u8 *pk, u8 *sk) 668 | { 669 | u8 d[64]; 670 | gf p[4]; 671 | int i; 672 | 673 | randombytes(sk, 32); 674 | crypto_hash(d, sk, 32); 675 | d[0] &= 248; 676 | d[31] &= 127; 677 | d[31] |= 64; 678 | 679 | scalarbase(p,d); 680 | pack(pk,p); 681 | 682 | FOR(i,32) sk[32 + i] = pk[i]; 683 | return 0; 684 | } 685 | 686 | static const u64 L[32] = {0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10}; 687 | 688 | sv modL(u8 *r,i64 x[64]) 689 | { 690 | i64 carry,i,j; 691 | for (i = 63;i >= 32;--i) { 692 | carry = 0; 693 | for (j = i - 32;j < i - 12;++j) { 694 | x[j] += carry - 16 * x[i] * L[j - (i - 32)]; 695 | carry = (x[j] + 128) >> 8; 696 | x[j] -= carry << 8; 697 | } 698 | x[j] += carry; 699 | x[i] = 0; 700 | } 701 | carry = 0; 702 | FOR(j,32) { 703 | x[j] += carry - (x[31] >> 4) * L[j]; 704 | carry = x[j] >> 8; 705 | x[j] &= 255; 706 | } 707 | FOR(j,32) x[j] -= carry * L[j]; 708 | FOR(i,32) { 709 | x[i+1] += x[i] >> 8; 710 | r[i] = x[i] & 255; 711 | } 712 | } 713 | 714 | sv reduce(u8 *r) 715 | { 716 | i64 x[64],i; 717 | FOR(i,64) x[i] = (u64) r[i]; 718 | FOR(i,64) r[i] = 0; 719 | modL(r,x); 720 | } 721 | 722 | int crypto_sign(u8 *sm,u64 *smlen,const u8 *m,u64 n,const u8 *sk) 723 | { 724 | u8 d[64],h[64],r[64]; 725 | i64 i,j,x[64]; 726 | gf p[4]; 727 | 728 | crypto_hash(d, sk, 32); 729 | d[0] &= 248; 730 | d[31] &= 127; 731 | d[31] |= 64; 732 | 733 | *smlen = n+64; 734 | FOR(i,n) sm[64 + i] = m[i]; 735 | FOR(i,32) sm[32 + i] = d[32 + i]; 736 | 737 | crypto_hash(r, sm+32, n+32); 738 | reduce(r); 739 | scalarbase(p,r); 740 | pack(sm,p); 741 | 742 | FOR(i,32) sm[i+32] = sk[i+32]; 743 | crypto_hash(h,sm,n + 64); 744 | reduce(h); 745 | 746 | FOR(i,64) x[i] = 0; 747 | FOR(i,32) x[i] = (u64) r[i]; 748 | FOR(i,32) FOR(j,32) x[i+j] += h[i] * (u64) d[j]; 749 | modL(sm + 32,x); 750 | 751 | return 0; 752 | } 753 | 754 | static int unpackneg(gf r[4],const u8 p[32]) 755 | { 756 | gf t, chk, num, den, den2, den4, den6; 757 | set25519(r[2],gf1); 758 | unpack25519(r[1],p); 759 | S(num,r[1]); 760 | M(den,num,D); 761 | Z(num,num,r[2]); 762 | A(den,r[2],den); 763 | 764 | S(den2,den); 765 | S(den4,den2); 766 | M(den6,den4,den2); 767 | M(t,den6,num); 768 | M(t,t,den); 769 | 770 | pow2523(t,t); 771 | M(t,t,num); 772 | M(t,t,den); 773 | M(t,t,den); 774 | M(r[0],t,den); 775 | 776 | S(chk,r[0]); 777 | M(chk,chk,den); 778 | if (neq25519(chk, num)) M(r[0],r[0],I); 779 | 780 | S(chk,r[0]); 781 | M(chk,chk,den); 782 | if (neq25519(chk, num)) return -1; 783 | 784 | if (par25519(r[0]) == (p[31]>>7)) Z(r[0],gf0,r[0]); 785 | 786 | M(r[3],r[0],r[1]); 787 | return 0; 788 | } 789 | 790 | int crypto_sign_open(u8 *m,u64 *mlen,const u8 *sm,u64 n,const u8 *pk) 791 | { 792 | int i; 793 | u8 t[32],h[64]; 794 | gf p[4],q[4]; 795 | 796 | *mlen = -1; 797 | if (n < 64) return -1; 798 | 799 | if (unpackneg(q,pk)) return -1; 800 | 801 | FOR(i,n) m[i] = sm[i]; 802 | FOR(i,32) m[i+32] = pk[i]; 803 | crypto_hash(h,m,n); 804 | reduce(h); 805 | scalarmult(p,q,h); 806 | 807 | scalarbase(q,sm + 32); 808 | add(p,q); 809 | pack(t,p); 810 | 811 | n -= 64; 812 | if (crypto_verify_32(sm, t)) { 813 | FOR(i,n) m[i] = 0; 814 | return -1; 815 | } 816 | 817 | FOR(i,n) m[i] = sm[i + 64]; 818 | *mlen = n; 819 | return 0; 820 | } 821 | -------------------------------------------------------------------------------- /vendor/tweetnacl/tweetnacl.h: -------------------------------------------------------------------------------- 1 | // 2 | // tweetnacl.h 3 | // Monocypher-cpp 4 | // 5 | // Imported from: 6 | // by Jens Alfke on 2/8/22. 7 | // 8 | 9 | #ifndef TWEETNACL_H 10 | #define TWEETNACL_H 11 | 12 | #define crypto_auth_PRIMITIVE "hmacsha512256" 13 | #define crypto_auth crypto_auth_hmacsha512256 14 | #define crypto_auth_verify crypto_auth_hmacsha512256_verify 15 | #define crypto_auth_BYTES crypto_auth_hmacsha512256_BYTES 16 | #define crypto_auth_KEYBYTES crypto_auth_hmacsha512256_KEYBYTES 17 | #define crypto_auth_IMPLEMENTATION crypto_auth_hmacsha512256_IMPLEMENTATION 18 | #define crypto_auth_VERSION crypto_auth_hmacsha512256_VERSION 19 | #define crypto_auth_hmacsha512256_tweet_BYTES 32 20 | #define crypto_auth_hmacsha512256_tweet_KEYBYTES 32 21 | extern int crypto_auth_hmacsha512256_tweet(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *); 22 | extern int crypto_auth_hmacsha512256_tweet_verify(const unsigned char *,const unsigned char *,unsigned long long,const unsigned char *); 23 | #define crypto_auth_hmacsha512256_tweet_VERSION "-" 24 | #define crypto_auth_hmacsha512256 crypto_auth_hmacsha512256_tweet 25 | #define crypto_auth_hmacsha512256_verify crypto_auth_hmacsha512256_tweet_verify 26 | #define crypto_auth_hmacsha512256_BYTES crypto_auth_hmacsha512256_tweet_BYTES 27 | #define crypto_auth_hmacsha512256_KEYBYTES crypto_auth_hmacsha512256_tweet_KEYBYTES 28 | #define crypto_auth_hmacsha512256_VERSION crypto_auth_hmacsha512256_tweet_VERSION 29 | #define crypto_auth_hmacsha512256_IMPLEMENTATION "crypto_auth/hmacsha512256/tweet" 30 | #define crypto_box_PRIMITIVE "curve25519xsalsa20poly1305" 31 | #define crypto_box crypto_box_curve25519xsalsa20poly1305 32 | #define crypto_box_open crypto_box_curve25519xsalsa20poly1305_open 33 | #define crypto_box_keypair crypto_box_curve25519xsalsa20poly1305_keypair 34 | #define crypto_box_beforenm crypto_box_curve25519xsalsa20poly1305_beforenm 35 | #define crypto_box_afternm crypto_box_curve25519xsalsa20poly1305_afternm 36 | #define crypto_box_open_afternm crypto_box_curve25519xsalsa20poly1305_open_afternm 37 | #define crypto_box_PUBLICKEYBYTES crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES 38 | #define crypto_box_SECRETKEYBYTES crypto_box_curve25519xsalsa20poly1305_SECRETKEYBYTES 39 | #define crypto_box_BEFORENMBYTES crypto_box_curve25519xsalsa20poly1305_BEFORENMBYTES 40 | #define crypto_box_NONCEBYTES crypto_box_curve25519xsalsa20poly1305_NONCEBYTES 41 | #define crypto_box_ZEROBYTES crypto_box_curve25519xsalsa20poly1305_ZEROBYTES 42 | #define crypto_box_BOXZEROBYTES crypto_box_curve25519xsalsa20poly1305_BOXZEROBYTES 43 | #define crypto_box_IMPLEMENTATION crypto_box_curve25519xsalsa20poly1305_IMPLEMENTATION 44 | #define crypto_box_VERSION crypto_box_curve25519xsalsa20poly1305_VERSION 45 | #define crypto_box_curve25519xsalsa20poly1305_tweet_PUBLICKEYBYTES 32 46 | #define crypto_box_curve25519xsalsa20poly1305_tweet_SECRETKEYBYTES 32 47 | #define crypto_box_curve25519xsalsa20poly1305_tweet_BEFORENMBYTES 32 48 | #define crypto_box_curve25519xsalsa20poly1305_tweet_NONCEBYTES 24 49 | #define crypto_box_curve25519xsalsa20poly1305_tweet_ZEROBYTES 32 50 | #define crypto_box_curve25519xsalsa20poly1305_tweet_BOXZEROBYTES 16 51 | extern int crypto_box_curve25519xsalsa20poly1305_tweet(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *,const unsigned char *); 52 | extern int crypto_box_curve25519xsalsa20poly1305_tweet_open(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *,const unsigned char *); 53 | extern int crypto_box_curve25519xsalsa20poly1305_tweet_keypair(unsigned char *,unsigned char *); 54 | extern int crypto_box_curve25519xsalsa20poly1305_tweet_beforenm(unsigned char *,const unsigned char *,const unsigned char *); 55 | extern int crypto_box_curve25519xsalsa20poly1305_tweet_afternm(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); 56 | extern int crypto_box_curve25519xsalsa20poly1305_tweet_open_afternm(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); 57 | #define crypto_box_curve25519xsalsa20poly1305_tweet_VERSION "-" 58 | #define crypto_box_curve25519xsalsa20poly1305 crypto_box_curve25519xsalsa20poly1305_tweet 59 | #define crypto_box_curve25519xsalsa20poly1305_open crypto_box_curve25519xsalsa20poly1305_tweet_open 60 | #define crypto_box_curve25519xsalsa20poly1305_keypair crypto_box_curve25519xsalsa20poly1305_tweet_keypair 61 | #define crypto_box_curve25519xsalsa20poly1305_beforenm crypto_box_curve25519xsalsa20poly1305_tweet_beforenm 62 | #define crypto_box_curve25519xsalsa20poly1305_afternm crypto_box_curve25519xsalsa20poly1305_tweet_afternm 63 | #define crypto_box_curve25519xsalsa20poly1305_open_afternm crypto_box_curve25519xsalsa20poly1305_tweet_open_afternm 64 | #define crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES crypto_box_curve25519xsalsa20poly1305_tweet_PUBLICKEYBYTES 65 | #define crypto_box_curve25519xsalsa20poly1305_SECRETKEYBYTES crypto_box_curve25519xsalsa20poly1305_tweet_SECRETKEYBYTES 66 | #define crypto_box_curve25519xsalsa20poly1305_BEFORENMBYTES crypto_box_curve25519xsalsa20poly1305_tweet_BEFORENMBYTES 67 | #define crypto_box_curve25519xsalsa20poly1305_NONCEBYTES crypto_box_curve25519xsalsa20poly1305_tweet_NONCEBYTES 68 | #define crypto_box_curve25519xsalsa20poly1305_ZEROBYTES crypto_box_curve25519xsalsa20poly1305_tweet_ZEROBYTES 69 | #define crypto_box_curve25519xsalsa20poly1305_BOXZEROBYTES crypto_box_curve25519xsalsa20poly1305_tweet_BOXZEROBYTES 70 | #define crypto_box_curve25519xsalsa20poly1305_VERSION crypto_box_curve25519xsalsa20poly1305_tweet_VERSION 71 | #define crypto_box_curve25519xsalsa20poly1305_IMPLEMENTATION "crypto_box/curve25519xsalsa20poly1305/tweet" 72 | #define crypto_core_PRIMITIVE "salsa20" 73 | #define crypto_core crypto_core_salsa20 74 | #define crypto_core_OUTPUTBYTES crypto_core_salsa20_OUTPUTBYTES 75 | #define crypto_core_INPUTBYTES crypto_core_salsa20_INPUTBYTES 76 | #define crypto_core_KEYBYTES crypto_core_salsa20_KEYBYTES 77 | #define crypto_core_CONSTBYTES crypto_core_salsa20_CONSTBYTES 78 | #define crypto_core_IMPLEMENTATION crypto_core_salsa20_IMPLEMENTATION 79 | #define crypto_core_VERSION crypto_core_salsa20_VERSION 80 | #define crypto_core_salsa20_tweet_OUTPUTBYTES 64 81 | #define crypto_core_salsa20_tweet_INPUTBYTES 16 82 | #define crypto_core_salsa20_tweet_KEYBYTES 32 83 | #define crypto_core_salsa20_tweet_CONSTBYTES 16 84 | extern int crypto_core_salsa20_tweet(unsigned char *,const unsigned char *,const unsigned char *,const unsigned char *); 85 | #define crypto_core_salsa20_tweet_VERSION "-" 86 | #define crypto_core_salsa20 crypto_core_salsa20_tweet 87 | #define crypto_core_salsa20_OUTPUTBYTES crypto_core_salsa20_tweet_OUTPUTBYTES 88 | #define crypto_core_salsa20_INPUTBYTES crypto_core_salsa20_tweet_INPUTBYTES 89 | #define crypto_core_salsa20_KEYBYTES crypto_core_salsa20_tweet_KEYBYTES 90 | #define crypto_core_salsa20_CONSTBYTES crypto_core_salsa20_tweet_CONSTBYTES 91 | #define crypto_core_salsa20_VERSION crypto_core_salsa20_tweet_VERSION 92 | #define crypto_core_salsa20_IMPLEMENTATION "crypto_core/salsa20/tweet" 93 | #define crypto_core_hsalsa20_tweet_OUTPUTBYTES 32 94 | #define crypto_core_hsalsa20_tweet_INPUTBYTES 16 95 | #define crypto_core_hsalsa20_tweet_KEYBYTES 32 96 | #define crypto_core_hsalsa20_tweet_CONSTBYTES 16 97 | extern int crypto_core_hsalsa20_tweet(unsigned char *,const unsigned char *,const unsigned char *,const unsigned char *); 98 | #define crypto_core_hsalsa20_tweet_VERSION "-" 99 | #define crypto_core_hsalsa20 crypto_core_hsalsa20_tweet 100 | #define crypto_core_hsalsa20_OUTPUTBYTES crypto_core_hsalsa20_tweet_OUTPUTBYTES 101 | #define crypto_core_hsalsa20_INPUTBYTES crypto_core_hsalsa20_tweet_INPUTBYTES 102 | #define crypto_core_hsalsa20_KEYBYTES crypto_core_hsalsa20_tweet_KEYBYTES 103 | #define crypto_core_hsalsa20_CONSTBYTES crypto_core_hsalsa20_tweet_CONSTBYTES 104 | #define crypto_core_hsalsa20_VERSION crypto_core_hsalsa20_tweet_VERSION 105 | #define crypto_core_hsalsa20_IMPLEMENTATION "crypto_core/hsalsa20/tweet" 106 | #define crypto_hashblocks_PRIMITIVE "sha512" 107 | #define crypto_hashblocks crypto_hashblocks_sha512 108 | #define crypto_hashblocks_STATEBYTES crypto_hashblocks_sha512_STATEBYTES 109 | #define crypto_hashblocks_BLOCKBYTES crypto_hashblocks_sha512_BLOCKBYTES 110 | #define crypto_hashblocks_IMPLEMENTATION crypto_hashblocks_sha512_IMPLEMENTATION 111 | #define crypto_hashblocks_VERSION crypto_hashblocks_sha512_VERSION 112 | #define crypto_hashblocks_sha512_tweet_STATEBYTES 64 113 | #define crypto_hashblocks_sha512_tweet_BLOCKBYTES 128 114 | extern int crypto_hashblocks_sha512_tweet(unsigned char *,const unsigned char *,unsigned long long); 115 | #define crypto_hashblocks_sha512_tweet_VERSION "-" 116 | #define crypto_hashblocks_sha512 crypto_hashblocks_sha512_tweet 117 | #define crypto_hashblocks_sha512_STATEBYTES crypto_hashblocks_sha512_tweet_STATEBYTES 118 | #define crypto_hashblocks_sha512_BLOCKBYTES crypto_hashblocks_sha512_tweet_BLOCKBYTES 119 | #define crypto_hashblocks_sha512_VERSION crypto_hashblocks_sha512_tweet_VERSION 120 | #define crypto_hashblocks_sha512_IMPLEMENTATION "crypto_hashblocks/sha512/tweet" 121 | #define crypto_hashblocks_sha256_tweet_STATEBYTES 32 122 | #define crypto_hashblocks_sha256_tweet_BLOCKBYTES 64 123 | extern int crypto_hashblocks_sha256_tweet(unsigned char *,const unsigned char *,unsigned long long); 124 | #define crypto_hashblocks_sha256_tweet_VERSION "-" 125 | #define crypto_hashblocks_sha256 crypto_hashblocks_sha256_tweet 126 | #define crypto_hashblocks_sha256_STATEBYTES crypto_hashblocks_sha256_tweet_STATEBYTES 127 | #define crypto_hashblocks_sha256_BLOCKBYTES crypto_hashblocks_sha256_tweet_BLOCKBYTES 128 | #define crypto_hashblocks_sha256_VERSION crypto_hashblocks_sha256_tweet_VERSION 129 | #define crypto_hashblocks_sha256_IMPLEMENTATION "crypto_hashblocks/sha256/tweet" 130 | #define crypto_hash_PRIMITIVE "sha512" 131 | #define crypto_hash crypto_hash_sha512 132 | #define crypto_hash_BYTES crypto_hash_sha512_BYTES 133 | #define crypto_hash_IMPLEMENTATION crypto_hash_sha512_IMPLEMENTATION 134 | #define crypto_hash_VERSION crypto_hash_sha512_VERSION 135 | #define crypto_hash_sha512_tweet_BYTES 64 136 | extern int crypto_hash_sha512_tweet(unsigned char *,const unsigned char *,unsigned long long); 137 | #define crypto_hash_sha512_tweet_VERSION "-" 138 | #define crypto_hash_sha512 crypto_hash_sha512_tweet 139 | #define crypto_hash_sha512_BYTES crypto_hash_sha512_tweet_BYTES 140 | #define crypto_hash_sha512_VERSION crypto_hash_sha512_tweet_VERSION 141 | #define crypto_hash_sha512_IMPLEMENTATION "crypto_hash/sha512/tweet" 142 | #define crypto_hash_sha256_tweet_BYTES 32 143 | extern int crypto_hash_sha256_tweet(unsigned char *,const unsigned char *,unsigned long long); 144 | #define crypto_hash_sha256_tweet_VERSION "-" 145 | #define crypto_hash_sha256 crypto_hash_sha256_tweet 146 | #define crypto_hash_sha256_BYTES crypto_hash_sha256_tweet_BYTES 147 | #define crypto_hash_sha256_VERSION crypto_hash_sha256_tweet_VERSION 148 | #define crypto_hash_sha256_IMPLEMENTATION "crypto_hash/sha256/tweet" 149 | #define crypto_onetimeauth_PRIMITIVE "poly1305" 150 | #define crypto_onetimeauth crypto_onetimeauth_poly1305 151 | #define crypto_onetimeauth_verify crypto_onetimeauth_poly1305_verify 152 | #define crypto_onetimeauth_BYTES crypto_onetimeauth_poly1305_BYTES 153 | #define crypto_onetimeauth_KEYBYTES crypto_onetimeauth_poly1305_KEYBYTES 154 | #define crypto_onetimeauth_IMPLEMENTATION crypto_onetimeauth_poly1305_IMPLEMENTATION 155 | #define crypto_onetimeauth_VERSION crypto_onetimeauth_poly1305_VERSION 156 | #define crypto_onetimeauth_poly1305_tweet_BYTES 16 157 | #define crypto_onetimeauth_poly1305_tweet_KEYBYTES 32 158 | extern int crypto_onetimeauth_poly1305_tweet(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *); 159 | extern int crypto_onetimeauth_poly1305_tweet_verify(const unsigned char *,const unsigned char *,unsigned long long,const unsigned char *); 160 | #define crypto_onetimeauth_poly1305_tweet_VERSION "-" 161 | #define crypto_onetimeauth_poly1305 crypto_onetimeauth_poly1305_tweet 162 | #define crypto_onetimeauth_poly1305_verify crypto_onetimeauth_poly1305_tweet_verify 163 | #define crypto_onetimeauth_poly1305_BYTES crypto_onetimeauth_poly1305_tweet_BYTES 164 | #define crypto_onetimeauth_poly1305_KEYBYTES crypto_onetimeauth_poly1305_tweet_KEYBYTES 165 | #define crypto_onetimeauth_poly1305_VERSION crypto_onetimeauth_poly1305_tweet_VERSION 166 | #define crypto_onetimeauth_poly1305_IMPLEMENTATION "crypto_onetimeauth/poly1305/tweet" 167 | #define crypto_scalarmult_PRIMITIVE "curve25519" 168 | #define crypto_scalarmult crypto_scalarmult_curve25519 169 | #define crypto_scalarmult_base crypto_scalarmult_curve25519_base 170 | #define crypto_scalarmult_BYTES crypto_scalarmult_curve25519_BYTES 171 | #define crypto_scalarmult_SCALARBYTES crypto_scalarmult_curve25519_SCALARBYTES 172 | #define crypto_scalarmult_IMPLEMENTATION crypto_scalarmult_curve25519_IMPLEMENTATION 173 | #define crypto_scalarmult_VERSION crypto_scalarmult_curve25519_VERSION 174 | #define crypto_scalarmult_curve25519_tweet_BYTES 32 175 | #define crypto_scalarmult_curve25519_tweet_SCALARBYTES 32 176 | extern int crypto_scalarmult_curve25519_tweet(unsigned char *,const unsigned char *,const unsigned char *); 177 | extern int crypto_scalarmult_curve25519_tweet_base(unsigned char *,const unsigned char *); 178 | #define crypto_scalarmult_curve25519_tweet_VERSION "-" 179 | #define crypto_scalarmult_curve25519 crypto_scalarmult_curve25519_tweet 180 | #define crypto_scalarmult_curve25519_base crypto_scalarmult_curve25519_tweet_base 181 | #define crypto_scalarmult_curve25519_BYTES crypto_scalarmult_curve25519_tweet_BYTES 182 | #define crypto_scalarmult_curve25519_SCALARBYTES crypto_scalarmult_curve25519_tweet_SCALARBYTES 183 | #define crypto_scalarmult_curve25519_VERSION crypto_scalarmult_curve25519_tweet_VERSION 184 | #define crypto_scalarmult_curve25519_IMPLEMENTATION "crypto_scalarmult/curve25519/tweet" 185 | #define crypto_secretbox_PRIMITIVE "xsalsa20poly1305" 186 | #define crypto_secretbox crypto_secretbox_xsalsa20poly1305 187 | #define crypto_secretbox_open crypto_secretbox_xsalsa20poly1305_open 188 | #define crypto_secretbox_KEYBYTES crypto_secretbox_xsalsa20poly1305_KEYBYTES 189 | #define crypto_secretbox_NONCEBYTES crypto_secretbox_xsalsa20poly1305_NONCEBYTES 190 | #define crypto_secretbox_ZEROBYTES crypto_secretbox_xsalsa20poly1305_ZEROBYTES 191 | #define crypto_secretbox_BOXZEROBYTES crypto_secretbox_xsalsa20poly1305_BOXZEROBYTES 192 | #define crypto_secretbox_IMPLEMENTATION crypto_secretbox_xsalsa20poly1305_IMPLEMENTATION 193 | #define crypto_secretbox_VERSION crypto_secretbox_xsalsa20poly1305_VERSION 194 | #define crypto_secretbox_xsalsa20poly1305_tweet_KEYBYTES 32 195 | #define crypto_secretbox_xsalsa20poly1305_tweet_NONCEBYTES 24 196 | #define crypto_secretbox_xsalsa20poly1305_tweet_ZEROBYTES 32 197 | #define crypto_secretbox_xsalsa20poly1305_tweet_BOXZEROBYTES 16 198 | extern int crypto_secretbox_xsalsa20poly1305_tweet(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); 199 | extern int crypto_secretbox_xsalsa20poly1305_tweet_open(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); 200 | #define crypto_secretbox_xsalsa20poly1305_tweet_VERSION "-" 201 | #define crypto_secretbox_xsalsa20poly1305 crypto_secretbox_xsalsa20poly1305_tweet 202 | #define crypto_secretbox_xsalsa20poly1305_open crypto_secretbox_xsalsa20poly1305_tweet_open 203 | #define crypto_secretbox_xsalsa20poly1305_KEYBYTES crypto_secretbox_xsalsa20poly1305_tweet_KEYBYTES 204 | #define crypto_secretbox_xsalsa20poly1305_NONCEBYTES crypto_secretbox_xsalsa20poly1305_tweet_NONCEBYTES 205 | #define crypto_secretbox_xsalsa20poly1305_ZEROBYTES crypto_secretbox_xsalsa20poly1305_tweet_ZEROBYTES 206 | #define crypto_secretbox_xsalsa20poly1305_BOXZEROBYTES crypto_secretbox_xsalsa20poly1305_tweet_BOXZEROBYTES 207 | #define crypto_secretbox_xsalsa20poly1305_VERSION crypto_secretbox_xsalsa20poly1305_tweet_VERSION 208 | #define crypto_secretbox_xsalsa20poly1305_IMPLEMENTATION "crypto_secretbox/xsalsa20poly1305/tweet" 209 | #define crypto_sign_PRIMITIVE "ed25519" 210 | #define crypto_sign crypto_sign_ed25519 211 | #define crypto_sign_open crypto_sign_ed25519_open 212 | #define crypto_sign_keypair crypto_sign_ed25519_keypair 213 | #define crypto_sign_BYTES crypto_sign_ed25519_BYTES 214 | #define crypto_sign_PUBLICKEYBYTES crypto_sign_ed25519_PUBLICKEYBYTES 215 | #define crypto_sign_SECRETKEYBYTES crypto_sign_ed25519_SECRETKEYBYTES 216 | #define crypto_sign_IMPLEMENTATION crypto_sign_ed25519_IMPLEMENTATION 217 | #define crypto_sign_VERSION crypto_sign_ed25519_VERSION 218 | #define crypto_sign_ed25519_tweet_BYTES 64 219 | #define crypto_sign_ed25519_tweet_PUBLICKEYBYTES 32 220 | #define crypto_sign_ed25519_tweet_SECRETKEYBYTES 64 221 | extern int crypto_sign_ed25519_tweet(unsigned char *,unsigned long long *,const unsigned char *,unsigned long long,const unsigned char *); 222 | extern int crypto_sign_ed25519_tweet_open(unsigned char *,unsigned long long *,const unsigned char *,unsigned long long,const unsigned char *); 223 | extern int crypto_sign_ed25519_tweet_keypair(unsigned char *,unsigned char *); 224 | #define crypto_sign_ed25519_tweet_VERSION "-" 225 | #define crypto_sign_ed25519 crypto_sign_ed25519_tweet 226 | #define crypto_sign_ed25519_open crypto_sign_ed25519_tweet_open 227 | #define crypto_sign_ed25519_keypair crypto_sign_ed25519_tweet_keypair 228 | #define crypto_sign_ed25519_BYTES crypto_sign_ed25519_tweet_BYTES 229 | #define crypto_sign_ed25519_PUBLICKEYBYTES crypto_sign_ed25519_tweet_PUBLICKEYBYTES 230 | #define crypto_sign_ed25519_SECRETKEYBYTES crypto_sign_ed25519_tweet_SECRETKEYBYTES 231 | #define crypto_sign_ed25519_VERSION crypto_sign_ed25519_tweet_VERSION 232 | #define crypto_sign_ed25519_IMPLEMENTATION "crypto_sign/ed25519/tweet" 233 | #define crypto_stream_PRIMITIVE "xsalsa20" 234 | #define crypto_stream crypto_stream_xsalsa20 235 | #define crypto_stream_xor crypto_stream_xsalsa20_xor 236 | #define crypto_stream_KEYBYTES crypto_stream_xsalsa20_KEYBYTES 237 | #define crypto_stream_NONCEBYTES crypto_stream_xsalsa20_NONCEBYTES 238 | #define crypto_stream_IMPLEMENTATION crypto_stream_xsalsa20_IMPLEMENTATION 239 | #define crypto_stream_VERSION crypto_stream_xsalsa20_VERSION 240 | #define crypto_stream_xsalsa20_tweet_KEYBYTES 32 241 | #define crypto_stream_xsalsa20_tweet_NONCEBYTES 24 242 | extern int crypto_stream_xsalsa20_tweet(unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); 243 | extern int crypto_stream_xsalsa20_tweet_xor(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); 244 | #define crypto_stream_xsalsa20_tweet_VERSION "-" 245 | #define crypto_stream_xsalsa20 crypto_stream_xsalsa20_tweet 246 | #define crypto_stream_xsalsa20_xor crypto_stream_xsalsa20_tweet_xor 247 | #define crypto_stream_xsalsa20_KEYBYTES crypto_stream_xsalsa20_tweet_KEYBYTES 248 | #define crypto_stream_xsalsa20_NONCEBYTES crypto_stream_xsalsa20_tweet_NONCEBYTES 249 | #define crypto_stream_xsalsa20_VERSION crypto_stream_xsalsa20_tweet_VERSION 250 | #define crypto_stream_xsalsa20_IMPLEMENTATION "crypto_stream/xsalsa20/tweet" 251 | #define crypto_stream_salsa20_tweet_KEYBYTES 32 252 | #define crypto_stream_salsa20_tweet_NONCEBYTES 8 253 | extern int crypto_stream_salsa20_tweet(unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); 254 | extern int crypto_stream_salsa20_tweet_xor(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); 255 | #define crypto_stream_salsa20_tweet_VERSION "-" 256 | #define crypto_stream_salsa20 crypto_stream_salsa20_tweet 257 | #define crypto_stream_salsa20_xor crypto_stream_salsa20_tweet_xor 258 | #define crypto_stream_salsa20_KEYBYTES crypto_stream_salsa20_tweet_KEYBYTES 259 | #define crypto_stream_salsa20_NONCEBYTES crypto_stream_salsa20_tweet_NONCEBYTES 260 | #define crypto_stream_salsa20_VERSION crypto_stream_salsa20_tweet_VERSION 261 | #define crypto_stream_salsa20_IMPLEMENTATION "crypto_stream/salsa20/tweet" 262 | #define crypto_verify_PRIMITIVE "16" 263 | #define crypto_verify crypto_verify_16 264 | #define crypto_verify_BYTES crypto_verify_16_BYTES 265 | #define crypto_verify_IMPLEMENTATION crypto_verify_16_IMPLEMENTATION 266 | #define crypto_verify_VERSION crypto_verify_16_VERSION 267 | #define crypto_verify_16_tweet_BYTES 16 268 | extern int crypto_verify_16_tweet(const unsigned char *,const unsigned char *); 269 | #define crypto_verify_16_tweet_VERSION "-" 270 | #define crypto_verify_16 crypto_verify_16_tweet 271 | #define crypto_verify_16_BYTES crypto_verify_16_tweet_BYTES 272 | #define crypto_verify_16_VERSION crypto_verify_16_tweet_VERSION 273 | #define crypto_verify_16_IMPLEMENTATION "crypto_verify/16/tweet" 274 | #define crypto_verify_32_tweet_BYTES 32 275 | extern int crypto_verify_32_tweet(const unsigned char *,const unsigned char *); 276 | #define crypto_verify_32_tweet_VERSION "-" 277 | #define crypto_verify_32 crypto_verify_32_tweet 278 | #define crypto_verify_32_BYTES crypto_verify_32_tweet_BYTES 279 | #define crypto_verify_32_VERSION crypto_verify_32_tweet_VERSION 280 | #define crypto_verify_32_IMPLEMENTATION "crypto_verify/32/tweet" 281 | #endif 282 | --------------------------------------------------------------------------------