aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md9
-rw-r--r--lib/Hashing.Portable/src/Argon2/Argon2Context.cs44
-rw-r--r--lib/Hashing.Portable/src/Argon2/VnArgon2.cs58
-rw-r--r--lib/Hashing.Portable/src/HashAlg.cs72
-rw-r--r--lib/Hashing.Portable/src/HashEncodingMode.cs52
-rw-r--r--lib/Hashing.Portable/src/ManagedHash.cs369
-rw-r--r--lib/Hashing.Portable/src/ManagedHashAlgImpl.cs227
-rw-r--r--lib/Hashing.Portable/src/Native/MonoCypher/IHashStream.cs54
-rw-r--r--lib/Hashing.Portable/src/Native/MonoCypher/IHmacStream.cs46
-rw-r--r--lib/Hashing.Portable/src/Native/MonoCypher/MCBlake2Module.cs420
-rw-r--r--lib/Hashing.Portable/src/Native/MonoCypher/MCHashingStreamExtensions.cs292
-rw-r--r--lib/Hashing.Portable/src/Native/MonoCypher/MCPasswordModule.cs159
-rw-r--r--lib/Hashing.Portable/src/Native/MonoCypher/MonoCypherLibrary.cs169
-rw-r--r--lib/Hashing.Portable/tests/.runsettings8
-rw-r--r--lib/Hashing.Portable/tests/ManagedHashTests.cs95
-rw-r--r--lib/Hashing.Portable/tests/VNLib.Hashing.PortableTests.csproj27
-rw-r--r--lib/Net.Compression/readme.md2
-rw-r--r--lib/Net.Rest.Client/src/VNLib.Net.Rest.Client.csproj2
-rw-r--r--lib/Plugins.Essentials/src/Accounts/PasswordHashing.cs10
-rw-r--r--lib/Plugins.Essentials/src/Extensions/EssentialHttpEventExtensions.cs2
-rw-r--r--lib/Plugins.Essentials/src/Extensions/ICookieController.cs8
-rw-r--r--lib/Plugins.Essentials/src/Extensions/SingleCookieController.cs34
-rw-r--r--lib/Plugins.Runtime/src/LoaderExtensions.cs42
-rw-r--r--lib/Plugins.Runtime/src/RuntimePluginLoader.cs1
-rw-r--r--lib/Utils.Cryptography/argon2/Taskfile.yaml12
-rw-r--r--lib/Utils.Cryptography/monocypher/CMakeLists.txt105
-rw-r--r--lib/Utils.Cryptography/monocypher/LICENSE293
-rw-r--r--lib/Utils.Cryptography/monocypher/Taskfile.yaml105
-rw-r--r--lib/Utils.Cryptography/monocypher/argon2.c102
-rw-r--r--lib/Utils.Cryptography/monocypher/argon2.h135
-rw-r--r--lib/Utils.Cryptography/monocypher/blake2b.c90
-rw-r--r--lib/Utils.Cryptography/monocypher/blake2b.h43
-rw-r--r--lib/Utils.Cryptography/monocypher/build.readme.txt0
-rw-r--r--lib/Utils.Cryptography/monocypher/package.json10
-rw-r--r--lib/Utils.Cryptography/monocypher/readme.md17
-rw-r--r--lib/Utils.Cryptography/monocypher/util.h77
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/.editorconfig16
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/.gitignore29
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/AUTHORS.md63
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/CHANGELOG.md295
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/CMakeLists.txt82
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/LICENCE.md173
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/README.md196
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/change-prefix.sh70
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/dist.sh119
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/dist_ignore36
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/doc/crypto_aead_lock.3monocypher507
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/doc/crypto_argon2.3monocypher400
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/doc/crypto_blake2b.3monocypher544
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/doc/crypto_chacha20_djb.3monocypher447
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/doc/crypto_ed25519_sign.3monocypher189
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/doc/crypto_eddsa_sign.3monocypher522
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/doc/crypto_elligator_map.3monocypher316
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/doc/crypto_poly1305.3monocypher279
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/doc/crypto_sha512.3monocypher578
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/doc/crypto_verify16.3monocypher132
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/doc/crypto_wipe.3monocypher116
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/doc/crypto_x25519.3monocypher329
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/doc/doc_check.py138
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/doc/doc_extract_examples.sh78
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/doc/doc_gen.sh93
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/doc/intro.3monocypher335
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/doc/style.css292
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/makefile211
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/monocypher.pc11
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/src/monocypher.c2956
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/src/monocypher.h321
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/src/optional/monocypher-ed25519.c500
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/src/optional/monocypher-ed25519.h140
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/coverage.sh59
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/ctgrind.c330
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/c25519/.gitignore5
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/c25519/AUTHORS.md5
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/c25519/c25519.c124
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/c25519/c25519.h48
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/c25519/ed25519.c320
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/c25519/ed25519.h82
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/c25519/edsign.c168
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/c25519/edsign.h51
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/c25519/f25519.c324
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/c25519/f25519.h92
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/c25519/fprime.c215
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/c25519/fprime.h70
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/c25519/morph25519.c87
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/c25519/morph25519.h29
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/c25519/sha512.c228
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/c25519/sha512.h52
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/ed25519-donna/AUTHORS.md42
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/ed25519-donna/curve25519-donna-32bit.h579
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/ed25519-donna/curve25519-donna-helpers.h67
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/ed25519-donna/ed25519-donna-32bit-tables.h61
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/ed25519-donna/ed25519-donna-basepoint-table.h259
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/ed25519-donna/ed25519-donna-batchverify.h275
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/ed25519-donna/ed25519-donna-impl-base.h364
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/ed25519-donna/ed25519-donna-portable-identify.h103
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/ed25519-donna/ed25519-donna-portable.h135
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/ed25519-donna/ed25519-donna.h117
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/ed25519-donna/ed25519-hash-custom.h23
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/ed25519-donna/ed25519-hash.h219
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/ed25519-donna/ed25519-randombytes.h91
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/ed25519-donna/ed25519.c150
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/ed25519-donna/ed25519.h30
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/ed25519-donna/modm-donna-32bit.h469
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/LICENCE121
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/cleanup.c9
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/cleanup.h7
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/crypto_hash_sha512.c110
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/crypto_hash_sha512.h12
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/crypto_int64.h8
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/crypto_onetimeauth_poly1305.c154
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/crypto_onetimeauth_poly1305.h16
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/crypto_scalarmult_curve25519.c73
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/crypto_scalarmult_curve25519.h16
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/crypto_sign_ed25519.c121
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/crypto_sign_ed25519.h20
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/crypto_stream_chacha20.c145
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/crypto_stream_chacha20.h16
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/crypto_uint32.h8
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/crypto_uint64.h8
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/crypto_verify_32.c6
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/crypto_verify_32.h12
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/fe.c171
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/fe.h21
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/fe25519.c236
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/fe25519.h22
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/ge25519.c226
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/ge25519.h14
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/randombytes.c41
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/randombytes.h10
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/sc25519.c67
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/sc25519.h7
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/uint32_pack.c11
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/uint32_pack.h8
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/uint32_unpack.c13
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/uint32_unpack.h8
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/verify.c10
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/verify.h6
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/tweetnacl/AUTHORS.md20
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/tweetnacl/tweetnacl.c809
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/externals/tweetnacl/tweetnacl.h272
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/formal-analysis.sh66
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/frama-c.sh61
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/gen/aead_8439.c83
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/gen/aead_ietf.c83
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/gen/argon2.c99
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/gen/blake2b.c83
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/gen/chacha20.c82
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/gen/edDSA.c74
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/gen/edDSA_pk.c76
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/gen/ed_25519.c75
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/gen/ed_25519_pk.c77
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/gen/elligator-direct.py84
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/gen/elligator-inverse.py128
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/gen/elligator.py370
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/gen/elligator_scalarmult.py230
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/gen/hchacha20.c73
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/gen/ietf_chacha20.c77
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/gen/makefile150
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/gen/poly1305.c74
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/gen/sha512.c74
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/gen/sha512_hkdf.py109
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/gen/sha512_hmac.c79
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/gen/utils.c100
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/gen/utils.h78
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/gen/vector_to_header.c122
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/gen/vectors/argon276
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/gen/vectors/blake2b1028
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/gen/vectors/chacha2036
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/gen/vectors/ed_25519_check1981
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/gen/vectors/ed_25519ph11
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/gen/vectors/elligator_dir115
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/gen/vectors/elligator_inv22
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/gen/vectors/poly1305105
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/gen/vectors/sha512_hmac155
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/gen/vectors/x255193168
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/gen/x25519.c83
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/gen/x25519_pk.c79
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/gen/xchacha20.c82
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/speed/README.md31
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/speed/libhydrogen.pc12
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/speed/makefile208
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/speed/speed-c25519.c123
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/speed/speed-donna.c92
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/speed/speed-hydrogen.c129
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/speed/speed-sodium.c191
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/speed/speed-tinyssh.c159
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/speed/speed-tweetnacl.c169
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/speed/speed.c270
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/speed/speed.h105
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/test.c1252
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/test.sh69
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/tis-ci-gen-config.sh114
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/tis-ci-vectors.h532
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/tis-ci.c474
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/utils.c176
-rw-r--r--lib/Utils.Cryptography/monocypher/vendor/tests/utils.h107
-rw-r--r--lib/Utils.Cryptography/monocypher/vnlib_monocypher.c119
-rw-r--r--lib/Utils.Cryptography/monocypher/vnlib_monocypher.h24
-rw-r--r--lib/Utils.Cryptography/monocypher/vnlib_monocypher.vcxitems28
-rw-r--r--lib/Utils/README.md5
-rw-r--r--lib/Utils/src/Async/AsyncAccessSerializer.cs20
-rw-r--r--lib/Utils/src/VnEncoding.cs109
202 files changed, 35564 insertions, 313 deletions
diff --git a/README.md b/README.md
index 433fb48..8cdfd8e 100644
--- a/README.md
+++ b/README.md
@@ -23,6 +23,9 @@ Again, go to my website below, my email address is available, go ahead and send
[Builds for VNLib.Core](https://www.vaughnnugent.com/resources/software/modules/VNLib.Core) - Per-project build artifacts
[Links for Nuget Feeds](https://www.vaughnnugent.com/resources/software/modules) - Get my NuGet feed links
+### .NET Version Notice
+I prefer sticking with lts .NET versions and 8 just released, so I will likely be upgrading once its "stable" and I have the time to port and test everything. Core libraries will be first then downstream packages.
+
## Index/NameSpaces
**VNLib.**
- [Utils](lib/Utils/#) - A mutli-use library focused on reducing complexity for working with native resources, memory, asynchronous patterns and data-structures, object/resource pooling, critical resource handling, and common logging abstractions.
@@ -38,6 +41,7 @@ Again, go to my website below, my email address is available, go ahead and send
- [Utils.Memory](lib/Utils.Memory/#) - Utilty libraries for native memory management framework for VNLib, including an x64 CMake build of rpmalloc.
- [Net.Compression](lib/Net.Compression/#) - A cross platform native compression provider and IHttpCompressorManager configured for runtime dynamic loading for high performance native response data compression.
- [Net.Rest.Client](lib/Net.Rest.Client/#) - A library for defining REST api clients via a fluent api by defining sites and endpoints, OAuth2 authenticator for RestSharp, and a simple RestSharp client pool.
+- [Utils.Cryptography](lib/Utils.Cryptography/#) - Contains vendored copies of recommended/referenced libraries and wrapper libraries such as Argon2 and Monocypher.
## Builds & Source
Builds contain the individual components listed below packaged per-project, available for download on my website. Build packages will be tgz archives (except for nuget packages). You can obtain debug and release builds, along with per-project source code
@@ -49,8 +53,11 @@ NuGet feeds for release and debug packages are available on my website as the li
[Links for Nuget Feeds](https://www.vaughnnugent.com/resources/software/modules)
+## Branches
+There are currently two branches I use, master and develop. Develop is the my default building branch, all changes are merged into master when I am satisfied. An internal PR is opened, reviewed and merged into master, you will notice this merge often consists of multiple commits. The develop branch will ALWAYS be ahead of the master branch.
+
## Notes
-As with all of my VNlib projects, there are in a very early pre-release state. This is my first large-scale software engineering project and it its not in highest of priorities to be a good "software developer", sorry :smiley:. I care about the highest performance code I know how to make for my applications regardless of complexity. I use ALL of the packages/libraries in these projects in my own infrastructure and as issues appear I try to fix and test them before publishing the build packages on my website (see builds below). I understand that most of my projects are often re-inventing the wheel, I'm aware, I enjoy boilerplate because it's mine... This all subject to change without warning.
+As with all of my VNlib projects, there are in a very early pre-release state. This is my first large-scale software engineering project and its not in highest of priorities to be a good "software developer", sorry :smiley:. I care about the highest performance code I know how to make for my applications regardless of complexity. I use ALL of the packages/libraries in these projects in my own infrastructure and as issues appear I try to fix and test them before publishing the build packages on my website (see builds below). I understand that most of my projects are often re-inventing the wheel, I'm aware, I enjoy boilerplate because it's mine... This all subject to change without warning.
### How is the code for this repo maintained?
I use many internal tools to build and maintain these projects. I use [OneDev](https://code.onedev.io/) for my internal source control (as well as other git tools) and code updates are pushed to GitHub as part of a build process. I use [Task](https://taskfile.dev) in the build process to publish builds for all projects in this repository. Builds are publicly available on my website from the link below. I do *not* intend to expose my internal tools for security reasons. I prefer to keep my dependencies/processes internal, and will be relying on GitHub for as little as possible.
diff --git a/lib/Hashing.Portable/src/Argon2/Argon2Context.cs b/lib/Hashing.Portable/src/Argon2/Argon2Context.cs
index 4631654..37abfbd 100644
--- a/lib/Hashing.Portable/src/Argon2/Argon2Context.cs
+++ b/lib/Hashing.Portable/src/Argon2/Argon2Context.cs
@@ -27,38 +27,34 @@ using System.Runtime.InteropServices;
namespace VNLib.Hashing
{
-
- public static unsafe partial class VnArgon2
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
+ internal unsafe ref struct Argon2Context
{
- [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
- private ref struct Argon2Context
- {
- public void* outptr; /* output array */
- public UInt32 outlen; /* digest length */
+ public void* outptr; /* output array */
+ public UInt32 outlen; /* digest length */
- public void* pwd; /* password array */
- public UInt32 pwdlen; /* password length */
+ public void* pwd; /* password array */
+ public UInt32 pwdlen; /* password length */
- public void* salt; /* salt array */
- public UInt32 saltlen; /* salt length */
+ public void* salt; /* salt array */
+ public UInt32 saltlen; /* salt length */
- public void* secret; /* key array */
- public UInt32 secretlen; /* key length */
+ public void* secret; /* key array */
+ public UInt32 secretlen; /* key length */
- public void* ad; /* associated data array */
- public UInt32 adlen; /* associated data length */
+ public void* ad; /* associated data array */
+ public UInt32 adlen; /* associated data length */
- public UInt32 t_cost; /* number of passes */
- public UInt32 m_cost; /* amount of memory requested (KB) */
- public UInt32 lanes; /* number of lanes */
- public UInt32 threads; /* maximum number of threads */
+ public UInt32 t_cost; /* number of passes */
+ public UInt32 m_cost; /* amount of memory requested (KB) */
+ public UInt32 lanes; /* number of lanes */
+ public UInt32 threads; /* maximum number of threads */
- public Argon2Version version; /* version number */
+ public Argon2Version version; /* version number */
- public void* allocate_cbk; /* pointer to memory allocator */
- public void* free_cbk; /* pointer to memory deallocator */
+ public void* allocate_cbk; /* pointer to memory allocator */
+ public void* free_cbk; /* pointer to memory deallocator */
- public UInt32 flags; /* array of bool options */
- }
+ public UInt32 flags; /* array of bool options */
}
} \ No newline at end of file
diff --git a/lib/Hashing.Portable/src/Argon2/VnArgon2.cs b/lib/Hashing.Portable/src/Argon2/VnArgon2.cs
index 9b27194..9d98050 100644
--- a/lib/Hashing.Portable/src/Argon2/VnArgon2.cs
+++ b/lib/Hashing.Portable/src/Argon2/VnArgon2.cs
@@ -24,7 +24,6 @@
using System;
using System.Text;
-using System.Buffers;
using System.Threading;
using System.Diagnostics;
using System.Buffers.Text;
@@ -34,6 +33,7 @@ using System.Runtime.InteropServices;
using VNLib.Utils.Memory;
using VNLib.Utils.Native;
using VNLib.Utils.Extensions;
+using VNLib.Hashing.Native.MonoCypher;
namespace VNLib.Hashing
{
@@ -42,40 +42,46 @@ namespace VNLib.Hashing
/// Implements the Argon2 data hashing library in .NET for cross platform use.
/// </summary>
/// <remarks>Buffers are allocted on a private <see cref="IUnmangedHeap"/> instance.</remarks>
- public static unsafe partial class VnArgon2
+ public static unsafe class VnArgon2
{
public const uint ARGON2_DEFAULT_FLAGS = 0U;
public const uint HASH_SIZE = 128;
public const int MAX_SALT_SIZE = 100;
public const string ID_MODE = "argon2id";
public const string ARGON2_DEFUALT_LIB_NAME = "argon2";
- public const string ARGON2_LIB_ENVIRONMENT_VAR_NAME = "ARGON2_DLL_PATH";
+ public const string ARGON2_LIB_ENVIRONMENT_VAR_NAME = "VNLIB_ARGON2_DLL_PATH";
private static readonly Encoding LocEncoding = Encoding.Unicode;
private static readonly Lazy<IUnmangedHeap> _heap = new (static () => MemoryUtil.InitializeNewHeapForProcess(true), LazyThreadSafetyMode.PublicationOnly);
- private static readonly Lazy<SafeArgon2Library> _nativeLibrary = new(LoadSharedLibInternal, LazyThreadSafetyMode.PublicationOnly);
+ private static readonly Lazy<IArgon2Library> _nativeLibrary = new(LoadSharedLibInternal, LazyThreadSafetyMode.PublicationOnly);
//Private heap initialized to 10k size, and all allocated buffers will be zeroed when allocated
- private static IUnmangedHeap PwHeap => _heap.Value;
+ private static IUnmangedHeap PwHeap => _heap.Value;
- /*
- * The native library delegate method
- */
- [SafeMethodName("argon2id_ctx")]
- delegate int Argon2InvokeHash(IntPtr context);
-
- private static SafeArgon2Library LoadSharedLibInternal()
+ private static IArgon2Library LoadSharedLibInternal()
{
//Get the path to the argon2 library
string? argon2EnvPath = Environment.GetEnvironmentVariable(ARGON2_LIB_ENVIRONMENT_VAR_NAME);
- //Default to the default library name
- argon2EnvPath ??= ARGON2_DEFUALT_LIB_NAME;
- Trace.WriteLine("Attempting to load global native Argon2 library from: " + argon2EnvPath, "VnArgon2");
+ //If no native library is set, try to load the monocypher library
+ if (string.IsNullOrWhiteSpace(argon2EnvPath) && MonoCypherLibrary.CanLoadDefaultLibrary())
+ {
+ Trace.WriteLine("Using the native MonoCypher library for Argon2 password hashing", "VnArgon2");
- SafeLibraryHandle lib = SafeLibraryHandle.LoadLibrary(argon2EnvPath, DllImportSearchPath.SafeDirectories);
- return new SafeArgon2Library(lib);
+ //Load shared monocyphter argon2 library
+ return MonoCypherLibrary.Shared.Argon2CreateLibrary(_heap.Value);
+ }
+ else
+ {
+ //Default to the default library name
+ argon2EnvPath ??= ARGON2_DEFUALT_LIB_NAME;
+
+ Trace.WriteLine("Attempting to load global native Argon2 library from: " + argon2EnvPath, "VnArgon2");
+
+ SafeLibraryHandle lib = SafeLibraryHandle.LoadLibrary(argon2EnvPath, DllImportSearchPath.SafeDirectories);
+ return new SafeArgon2Library(lib);
+ }
}
@@ -130,7 +136,7 @@ namespace VNLib.Hashing
int passBytes = LocEncoding.GetByteCount(password);
//Alloc memory for salt
- using IMemoryHandle<byte> buffer = PwHeap.Alloc<byte>(saltbytes + passBytes);
+ using MemoryHandle<byte> buffer = PwHeap.Alloc<byte>(saltbytes + passBytes);
Span<byte> saltBuffer = buffer.AsSpan(0, saltbytes);
Span<byte> passBuffer = buffer.AsSpan(saltbytes, passBytes);
@@ -175,7 +181,7 @@ namespace VNLib.Hashing
int passBytes = LocEncoding.GetByteCount(password);
//Alloc memory for password
- using IMemoryHandle<byte> pwdHandle = PwHeap.Alloc<byte>(passBytes);
+ using MemoryHandle<byte> pwdHandle = PwHeap.Alloc<byte>(passBytes);
//Encode password, create a new span to make sure its proper size
_ = LocEncoding.GetBytes(password, pwdHandle.Span);
@@ -223,9 +229,6 @@ namespace VNLib.Hashing
//encode salt
salts = Convert.ToBase64String(salt);
- //Zero buffer
- MemoryUtil.InitializeBlock(ref hashHandle.GetReference(), hashHandle.GetIntLength());
-
//Encode salt in base64
return $"${ID_MODE}$v={(int)Argon2Version.Version13},m={costParams.MemoryCost},t={costParams.TimeCost},p={costParams.Parallelism},s={salts}${hash}";
}
@@ -330,7 +333,7 @@ namespace VNLib.Hashing
int rawPassLen = LocEncoding.GetByteCount(rawPass);
//Alloc buffer for decoded data
- using IMemoryHandle<byte> rawBufferHandle = PwHeap.Alloc<byte>(passBase64BufSize + saltBase64BufSize + rawPassLen);
+ using MemoryHandle<byte> rawBufferHandle = PwHeap.Alloc<byte>(passBase64BufSize + saltBase64BufSize + rawPassLen);
//Split buffers
Span<byte> saltBuf = rawBufferHandle.Span[..saltBase64BufSize];
@@ -393,10 +396,7 @@ namespace VNLib.Hashing
)
{
//Alloc data for hash output
- using IMemoryHandle<byte> outputHandle = PwHeap.Alloc<byte>(hashBytes.Length);
-
- //Pin to get the base pointer
- using MemoryHandle outputPtr = outputHandle.Pin(0);
+ using MemoryHandle<byte> outputHandle = PwHeap.Alloc<byte>(hashBytes.Length);
//Get pointers
fixed (byte* secretptr = secret, pwd = rawPass, slptr = salt)
@@ -425,7 +425,7 @@ namespace VNLib.Hashing
context->secret = secretptr;
context->secretlen = (uint)secret.Length;
//Output
- context->outptr = outputPtr.Pointer;
+ context->outptr = outputHandle.Base;
context->outlen = (uint)outputHandle.Length;
//Hash
Argon2_ErrorCodes argResult = (Argon2_ErrorCodes)lib.Argon2Hash((IntPtr)context);
@@ -441,7 +441,7 @@ namespace VNLib.Hashing
return result;
}
- private static void ThrowOnArgonErr(Argon2_ErrorCodes result)
+ internal static void ThrowOnArgonErr(Argon2_ErrorCodes result)
{
switch (result)
{
diff --git a/lib/Hashing.Portable/src/HashAlg.cs b/lib/Hashing.Portable/src/HashAlg.cs
new file mode 100644
index 0000000..030e7e6
--- /dev/null
+++ b/lib/Hashing.Portable/src/HashAlg.cs
@@ -0,0 +1,72 @@
+/*
+* Copyright (c) 2023 Vaughn Nugent
+*
+* Library: VNLib
+* Package: VNLib.Hashing.Portable
+* File: HashAlg.cs
+*
+* HashAlg.cs is part of VNLib.Hashing.Portable which is part of the larger
+* VNLib collection of libraries and utilities.
+*
+* VNLib.Hashing.Portable is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published
+* by the Free Software Foundation, either version 2 of the License,
+* or (at your option) any later version.
+*
+* VNLib.Hashing.Portable is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with VNLib.Hashing.Portable. If not, see http://www.gnu.org/licenses/.
+*/
+
+using VNLib.Hashing.Native.MonoCypher;
+
+namespace VNLib.Hashing
+{
+ /// <summary>
+ /// Defines a hashing algorithm to use when computing a hash.
+ /// </summary>
+ public enum HashAlg
+ {
+ /// <summary>
+ /// Unused type, will cause a computation method to raise an argument exception when used.
+ /// </summary>
+ None,
+ /// <summary>
+ /// Defines the SHA-512 hashing algorithm
+ /// </summary>
+ SHA512 = 64,
+ /// <summary>
+ /// Defines the SHA-384 hashing algorithm
+ /// </summary>
+ SHA384 = 48,
+ /// <summary>
+ /// Defines the SHA-256 hashing algorithm
+ /// </summary>
+ SHA256 = 32,
+ /// <summary>
+ /// Defines the SHA-1 hashing algorithm
+ /// WARNING: This hashing method is considered insecure and cannot be corrected.
+ /// </summary>
+ SHA1 = 20,
+ /// <summary>
+ /// Defines the MD5 hashing algorithm
+ /// WARNING: This hashing method is considered insecure and cannot be corrected.
+ /// </summary>
+ MD5 = 16,
+
+ /*
+ * The blake2 value is negative because the hash size is variable and the enum value
+ * and cannot be used to determine the hash buffer size.
+ */
+ /// <summary>
+ /// Defines the BLAKE2B hashing algorithm
+ /// NOTE: This hashing method may not be supported on all platforms, you should check for support before using it.
+ /// Inspect the value of <see cref="ManagedHash.SupportsBlake2b"/>
+ /// </summary>
+ BlAKE2B = -MCBlake2Module.MaxHashSize,
+ }
+}
diff --git a/lib/Hashing.Portable/src/HashEncodingMode.cs b/lib/Hashing.Portable/src/HashEncodingMode.cs
new file mode 100644
index 0000000..cc1aa8c
--- /dev/null
+++ b/lib/Hashing.Portable/src/HashEncodingMode.cs
@@ -0,0 +1,52 @@
+/*
+* Copyright (c) 2023 Vaughn Nugent
+*
+* Library: VNLib
+* Package: VNLib.Hashing.Portable
+* File: HashEncodingMode.cs
+*
+* HashEncodingMode.cs is part of VNLib.Hashing.Portable which is part of the larger
+* VNLib collection of libraries and utilities.
+*
+* VNLib.Hashing.Portable is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published
+* by the Free Software Foundation, either version 2 of the License,
+* or (at your option) any later version.
+*
+* VNLib.Hashing.Portable is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with VNLib.Hashing.Portable. If not, see http://www.gnu.org/licenses/.
+*/
+
+using System;
+
+namespace VNLib.Hashing
+{
+ /// <summary>
+ /// The binary hash encoding type
+ /// </summary>
+ [Flags]
+ public enum HashEncodingMode
+ {
+ /// <summary>
+ /// Specifies the Base64 character encoding
+ /// </summary>
+ Base64 = 64,
+ /// <summary>
+ /// Specifies the hexadecimal character encoding
+ /// </summary>
+ Hexadecimal = 16,
+ /// <summary>
+ /// Specifies the Base32 character encoding
+ /// </summary>
+ Base32 = 32,
+ /// <summary>
+ /// Specifies the base64 URL safe character encoding
+ /// </summary>
+ Base64Url = 128
+ }
+}
diff --git a/lib/Hashing.Portable/src/ManagedHash.cs b/lib/Hashing.Portable/src/ManagedHash.cs
index 43c2a7c..5933804 100644
--- a/lib/Hashing.Portable/src/ManagedHash.cs
+++ b/lib/Hashing.Portable/src/ManagedHash.cs
@@ -28,61 +28,11 @@ using System.Security.Cryptography;
using VNLib.Utils;
using VNLib.Utils.Memory;
+using VNLib.Hashing.Native.MonoCypher;
+using VNLib.Utils.Extensions;
namespace VNLib.Hashing
{
- /// <summary>
- /// Defines a hashing algorithm to use when computing a hash.
- /// </summary>
- public enum HashAlg
- {
- /// <summary>
- /// Unused type, will cause a computation method to raise an argument exception when used.
- /// </summary>
- None,
- /// <summary>
- /// Defines the SHA-512 hashing algorithm
- /// </summary>
- SHA512 = 64,
- /// <summary>
- /// Defines the SHA-384 hashing algorithm
- /// </summary>
- SHA384 = 48,
- /// <summary>
- /// Defines the SHA-256 hashing algorithm
- /// </summary>
- SHA256 = 32,
- /// <summary>
- /// Defines the SHA-1 hashing algorithm
- /// WARNING: This hashing method is considered insecure and cannot be corrected.
- /// </summary>
- SHA1 = 20,
- /// <summary>
- /// Defines the MD5 hashing algorithm
- /// WARNING: This hashing method is considered insecure and cannot be corrected.
- /// </summary>
- MD5 = 16
- }
-
- /// <summary>
- /// The binary hash encoding type
- /// </summary>
- [Flags]
- public enum HashEncodingMode
- {
- /// <summary>
- /// Specifies the Base64 character encoding
- /// </summary>
- Base64 = 64,
- /// <summary>
- /// Specifies the hexadecimal character encoding
- /// </summary>
- Hexadecimal = 16,
- /// <summary>
- /// Specifies the Base32 character encoding
- /// </summary>
- Base32 = 32
- }
/// <summary>
/// Provides simple methods for common managed hashing functions
@@ -119,6 +69,19 @@ namespace VNLib.Hashing
};
}
+ private static readonly Sha1 _sha1Alg;
+ private static readonly Sha256 _sha256Alg;
+ private static readonly Sha384 _sha384Alg;
+ private static readonly Sha512 _sha512Alg;
+ private static readonly Md5 _md5Alg;
+ private static readonly Blake2b _blake2bAlg;
+
+ /// <summary>
+ /// Gets a value that indicates whether the current runtime has the required libraries
+ /// available to support the Blake2b hashing algorithm
+ /// </summary>
+ public static bool SupportsBlake2b => MonoCypherLibrary.CanLoadDefaultLibrary();
+
/// <summary>
/// Uses the UTF8 character encoding to encode the string, then
/// attempts to compute the hash and store the results into the output buffer
@@ -130,16 +93,16 @@ namespace VNLib.Hashing
/// <exception cref="ArgumentException"></exception>
public static ERRNO ComputeHash(ReadOnlySpan<char> data, Span<byte> buffer, HashAlg type)
{
- int byteCount = CharEncoding.GetByteCount(data);
-
- //Alloc buffer
- using UnsafeMemoryHandle<byte> binbuf = MemoryUtil.UnsafeAlloc(byteCount, true);
-
- //Encode data
- byteCount = CharEncoding.GetBytes(data, binbuf.Span);
-
- //hash the buffer
- return ComputeHash(binbuf.Span[..byteCount], buffer, type);
+ return type switch
+ {
+ HashAlg.BlAKE2B => ComputeHashInternal(in _blake2bAlg, data, buffer),
+ HashAlg.SHA512 => ComputeHashInternal(in _sha512Alg, data, buffer),
+ HashAlg.SHA384 => ComputeHashInternal(in _sha384Alg, data, buffer),
+ HashAlg.SHA256 => ComputeHashInternal(in _sha256Alg, data, buffer),
+ HashAlg.SHA1 => ComputeHashInternal(in _sha1Alg, data, buffer),
+ HashAlg.MD5 => ComputeHashInternal(in _md5Alg, data, buffer),
+ _ => throw new ArgumentException("Invalid hash algorithm", nameof(type))
+ };
}
/// <summary>
@@ -152,13 +115,16 @@ namespace VNLib.Hashing
/// <exception cref="ArgumentException"></exception>
public static byte[] ComputeHash(ReadOnlySpan<char> data, HashAlg type)
{
- int byteCount = CharEncoding.GetByteCount(data);
- //Alloc buffer
- using UnsafeMemoryHandle<byte> binbuf = MemoryUtil.UnsafeAlloc(byteCount, true);
- //Encode data
- byteCount = CharEncoding.GetBytes(data, binbuf.Span);
- //hash the buffer
- return ComputeHash(binbuf.Span[..byteCount], type);
+ return type switch
+ {
+ HashAlg.BlAKE2B => ComputeHashInternal(in _blake2bAlg, data),
+ HashAlg.SHA512 => ComputeHashInternal(in _sha512Alg, data),
+ HashAlg.SHA384 => ComputeHashInternal(in _sha384Alg, data),
+ HashAlg.SHA256 => ComputeHashInternal(in _sha256Alg, data),
+ HashAlg.SHA1 => ComputeHashInternal(in _sha1Alg, data),
+ HashAlg.MD5 => ComputeHashInternal(in _md5Alg, data),
+ _ => throw new ArgumentException("Invalid hash algorithm", nameof(type))
+ };
}
/// <summary>
@@ -174,11 +140,12 @@ namespace VNLib.Hashing
//hash the buffer
return type switch
{
- HashAlg.SHA512 => SHA512.TryHashData(data, output, out int count) ? count : ERRNO.E_FAIL,
- HashAlg.SHA384 => SHA384.TryHashData(data, output, out int count) ? count : ERRNO.E_FAIL,
- HashAlg.SHA256 => SHA256.TryHashData(data, output, out int count) ? count : ERRNO.E_FAIL,
- HashAlg.SHA1 => SHA1.TryHashData(data, output, out int count) ? count : ERRNO.E_FAIL,
- HashAlg.MD5 => MD5.TryHashData(data, output, out int count) ? count : ERRNO.E_FAIL,
+ HashAlg.BlAKE2B => ComputeHashInternal(in _blake2bAlg, data, output),
+ HashAlg.SHA512 => ComputeHashInternal(in _sha512Alg, data, output),
+ HashAlg.SHA384 => ComputeHashInternal(in _sha384Alg, data, output),
+ HashAlg.SHA256 => ComputeHashInternal(in _sha256Alg, data, output),
+ HashAlg.SHA1 => ComputeHashInternal(in _sha1Alg, data, output),
+ HashAlg.MD5 => ComputeHashInternal(in _md5Alg, data, output),
_ => throw new ArgumentException("Hash algorithm is not supported"),
};
}
@@ -195,12 +162,13 @@ namespace VNLib.Hashing
//hash the buffer
return type switch
{
- HashAlg.SHA512 => SHA512.HashData(data),
- HashAlg.SHA384 => SHA384.HashData(data),
- HashAlg.SHA256 => SHA256.HashData(data),
- HashAlg.SHA1 => SHA1.HashData(data),
- HashAlg.MD5 => MD5.HashData(data),
- _ => throw new ArgumentException("Hash algorithm is not supported"),
+ HashAlg.BlAKE2B => ComputeHashInternal(in _blake2bAlg, data),
+ HashAlg.SHA512 => ComputeHashInternal(in _sha512Alg, data),
+ HashAlg.SHA384 => ComputeHashInternal(in _sha384Alg, data),
+ HashAlg.SHA256 => ComputeHashInternal(in _sha256Alg, data),
+ HashAlg.SHA1 => ComputeHashInternal(in _sha1Alg, data),
+ HashAlg.MD5 => ComputeHashInternal(in _md5Alg, data),
+ _ => throw new ArgumentException("Invalid hash algorithm", nameof(type))
};
}
@@ -216,21 +184,15 @@ namespace VNLib.Hashing
/// <exception cref="CryptographicException"></exception>
public static string ComputeHash(ReadOnlySpan<byte> data, HashAlg type, HashEncodingMode mode)
{
- //Alloc hash buffer
- Span<byte> hashBuffer = stackalloc byte[(int)type];
- //hash the buffer
- ERRNO count = ComputeHash(data, hashBuffer, type);
- if (!count)
- {
- throw new CryptographicException("Failed to compute the hash of the data");
- }
- //Convert to hex string
- return mode switch
+ return type switch
{
- HashEncodingMode.Hexadecimal => Convert.ToHexString(hashBuffer.Slice(0, count)),
- HashEncodingMode.Base64 => Convert.ToBase64String(hashBuffer.Slice(0, count)),
- HashEncodingMode.Base32 => VnEncoding.ToBase32String(hashBuffer.Slice(0, count)),
- _ => throw new ArgumentException("Encoding mode is not supported"),
+ HashAlg.BlAKE2B => ComputeHashInternal(in _blake2bAlg, data, mode),
+ HashAlg.SHA512 => ComputeHashInternal(in _sha512Alg, data, mode),
+ HashAlg.SHA384 => ComputeHashInternal(in _sha384Alg, data, mode),
+ HashAlg.SHA256 => ComputeHashInternal(in _sha256Alg, data, mode),
+ HashAlg.SHA1 => ComputeHashInternal(in _sha1Alg, data, mode),
+ HashAlg.MD5 => ComputeHashInternal(in _md5Alg, data, mode),
+ _ => throw new ArgumentException("Invalid hash algorithm", nameof(type))
};
}
@@ -247,30 +209,18 @@ namespace VNLib.Hashing
/// <exception cref="CryptographicException"></exception>
public static string ComputeHash(ReadOnlySpan<char> data, HashAlg type, HashEncodingMode mode)
{
- //Alloc hash buffer
- Span<byte> hashBuffer = stackalloc byte[(int)type];
- //hash the buffer
- ERRNO count = ComputeHash(data, hashBuffer, type);
- if (!count)
- {
- throw new CryptographicException("Failed to compute the hash of the data");
- }
- //Convert to hex string
- return mode switch
+ return type switch
{
- HashEncodingMode.Hexadecimal => Convert.ToHexString(hashBuffer.Slice(0, count)),
- HashEncodingMode.Base64 => Convert.ToBase64String(hashBuffer.Slice(0, count)),
- HashEncodingMode.Base32 => VnEncoding.ToBase32String(hashBuffer.Slice(0, count)),
- _ => throw new ArgumentException("Encoding mode is not supported"),
+ HashAlg.BlAKE2B => ComputeHashInternal(in _blake2bAlg, data, mode),
+ HashAlg.SHA512 => ComputeHashInternal(in _sha512Alg, data, mode),
+ HashAlg.SHA384 => ComputeHashInternal(in _sha384Alg, data, mode),
+ HashAlg.SHA256 => ComputeHashInternal(in _sha256Alg, data, mode),
+ HashAlg.SHA1 => ComputeHashInternal(in _sha1Alg, data, mode),
+ HashAlg.MD5 => ComputeHashInternal(in _md5Alg, data, mode),
+ _ => throw new ArgumentException("Invalid hash algorithm", nameof(type))
};
}
-
- public static string ComputeHexHash(ReadOnlySpan<byte> data, HashAlg type) => ComputeHash(data, type, HashEncodingMode.Hexadecimal);
- public static string ComputeBase64Hash(ReadOnlySpan<byte> data, HashAlg type) => ComputeHash(data, type, HashEncodingMode.Base64);
- public static string ComputeHexHash(ReadOnlySpan<char> data, HashAlg type) => ComputeHash(data, type, HashEncodingMode.Hexadecimal);
- public static string ComputeBase64Hash(ReadOnlySpan<char> data, HashAlg type) => ComputeHash(data, type, HashEncodingMode.Base64);
-
/// <summary>
/// Computes the HMAC of the specified character buffer using the specified key and
/// writes the resuts to the output buffer.
@@ -283,16 +233,16 @@ namespace VNLib.Hashing
/// <exception cref="ArgumentException"></exception>
public static ERRNO ComputeHmac(ReadOnlySpan<byte> key, ReadOnlySpan<char> data, Span<byte> output, HashAlg type)
{
- int byteCount = CharEncoding.GetByteCount(data);
-
- //Alloc buffer
- using UnsafeMemoryHandle<byte> binbuf = MemoryUtil.UnsafeAlloc(byteCount, true);
-
- //Encode data
- byteCount = CharEncoding.GetBytes(data, binbuf.Span);
-
- //hash the buffer
- return ComputeHmac(key, binbuf.Span[..byteCount], output, type);
+ return type switch
+ {
+ HashAlg.BlAKE2B => ComputeHashInternal(in _blake2bAlg, data, output, key),
+ HashAlg.SHA512 => ComputeHashInternal(in _sha512Alg, data, output, key),
+ HashAlg.SHA384 => ComputeHashInternal(in _sha384Alg, data, output, key),
+ HashAlg.SHA256 => ComputeHashInternal(in _sha256Alg, data, output, key),
+ HashAlg.SHA1 => ComputeHashInternal(in _sha1Alg, data, output, key),
+ HashAlg.MD5 => ComputeHashInternal(in _md5Alg, data, output, key),
+ _ => ERRNO.E_FAIL
+ };
}
/// <summary>
@@ -306,17 +256,18 @@ namespace VNLib.Hashing
/// <exception cref="ArgumentException"></exception>
public static byte[] ComputeHmac(ReadOnlySpan<byte> key, ReadOnlySpan<char> data, HashAlg type)
{
- int byteCount = CharEncoding.GetByteCount(data);
-
- //Alloc buffer
- using UnsafeMemoryHandle<byte> binbuf = MemoryUtil.UnsafeAlloc(byteCount, true);
-
- //Encode data
- byteCount = CharEncoding.GetBytes(data, binbuf.Span);
-
- //hash the buffer
- return ComputeHmac(key, binbuf.Span[..byteCount], type);
+ return type switch
+ {
+ HashAlg.BlAKE2B => ComputeHashInternal(in _blake2bAlg, data, key),
+ HashAlg.SHA512 => ComputeHashInternal(in _sha512Alg, data, key),
+ HashAlg.SHA384 => ComputeHashInternal(in _sha384Alg, data, key),
+ HashAlg.SHA256 => ComputeHashInternal(in _sha256Alg, data, key),
+ HashAlg.SHA1 => ComputeHashInternal(in _sha1Alg, data, key),
+ HashAlg.MD5 => ComputeHashInternal(in _md5Alg, data, key),
+ _ => throw new ArgumentException("Hash algorithm is not supported"),
+ };
}
+
/// <summary>
/// Computes the HMAC of the specified data buffer using the specified key and
/// writes the resuts to the output buffer.
@@ -332,11 +283,12 @@ namespace VNLib.Hashing
//hash the buffer
return type switch
{
- HashAlg.SHA512 => HMACSHA512.TryHashData(key, data, output, out int count) ? count : ERRNO.E_FAIL,
- HashAlg.SHA384 => HMACSHA384.TryHashData(key, data, output, out int count) ? count : ERRNO.E_FAIL,
- HashAlg.SHA256 => HMACSHA256.TryHashData(key, data, output, out int count) ? count : ERRNO.E_FAIL,
- HashAlg.SHA1 => HMACSHA1.TryHashData(key, data, output, out int count) ? count : ERRNO.E_FAIL,
- HashAlg.MD5 => HMACMD5.TryHashData(key, data, output, out int count) ? count : ERRNO.E_FAIL,
+ HashAlg.BlAKE2B => ComputeHashInternal(in _blake2bAlg, data, output, key),
+ HashAlg.SHA512 => ComputeHashInternal(in _sha512Alg, data, output, key),
+ HashAlg.SHA384 => ComputeHashInternal(in _sha384Alg, data, output, key),
+ HashAlg.SHA256 => ComputeHashInternal(in _sha256Alg, data, output, key),
+ HashAlg.SHA1 => ComputeHashInternal(in _sha1Alg, data, output, key),
+ HashAlg.MD5 => ComputeHashInternal(in _md5Alg, data, output, key),
_ => throw new ArgumentException("Hash algorithm is not supported"),
};
}
@@ -355,11 +307,12 @@ namespace VNLib.Hashing
//hash the buffer
return type switch
{
- HashAlg.SHA512 => HMACSHA512.HashData(key, data),
- HashAlg.SHA384 => HMACSHA384.HashData(key, data),
- HashAlg.SHA256 => HMACSHA256.HashData(key, data),
- HashAlg.SHA1 => HMACSHA1.HashData(key, data),
- HashAlg.MD5 => HMACMD5.HashData(key, data),
+ HashAlg.BlAKE2B => ComputeHashInternal(in _blake2bAlg, data, key),
+ HashAlg.SHA512 => ComputeHashInternal(in _sha512Alg, data, key),
+ HashAlg.SHA384 => ComputeHashInternal(in _sha384Alg, data, key),
+ HashAlg.SHA256 => ComputeHashInternal(in _sha256Alg, data, key),
+ HashAlg.SHA1 => ComputeHashInternal(in _sha1Alg, data, key),
+ HashAlg.MD5 => ComputeHashInternal(in _md5Alg, data, key),
_ => throw new ArgumentException("Hash algorithm is not supported"),
};
}
@@ -376,24 +329,15 @@ namespace VNLib.Hashing
/// <exception cref="ArgumentException"></exception>
public static string ComputeHmac(ReadOnlySpan<byte> key, ReadOnlySpan<byte> data, HashAlg type, HashEncodingMode mode)
{
- //Alloc hash buffer
- Span<byte> hashBuffer = stackalloc byte[(int)type];
-
- //hash the buffer
- ERRNO count = ComputeHmac(key, data, hashBuffer, type);
-
- if (!count)
- {
- throw new InternalBufferTooSmallException("Failed to compute the hash of the data");
- }
-
- //Convert to hex string
- return mode switch
+ return type switch
{
- HashEncodingMode.Hexadecimal => Convert.ToHexString(hashBuffer.Slice(0, count)),
- HashEncodingMode.Base64 => Convert.ToBase64String(hashBuffer.Slice(0, count)),
- HashEncodingMode.Base32 => VnEncoding.ToBase32String(hashBuffer.Slice(0, count)),
- _ => throw new ArgumentException("Encoding mode is not supported"),
+ HashAlg.BlAKE2B => ComputeHashInternal(in _blake2bAlg, data, mode, key),
+ HashAlg.SHA512 => ComputeHashInternal(in _sha512Alg, data, mode, key),
+ HashAlg.SHA384 => ComputeHashInternal(in _sha384Alg, data, mode, key),
+ HashAlg.SHA256 => ComputeHashInternal(in _sha256Alg, data, mode, key),
+ HashAlg.SHA1 => ComputeHashInternal(in _sha1Alg, data, mode, key),
+ HashAlg.MD5 => ComputeHashInternal(in _md5Alg, data, mode, key),
+ _ => throw new ArgumentException("Invalid hash algorithm", nameof(type))
};
}
@@ -409,25 +353,114 @@ namespace VNLib.Hashing
/// <exception cref="ArgumentException"></exception>
public static string ComputeHmac(ReadOnlySpan<byte> key, ReadOnlySpan<char> data, HashAlg type, HashEncodingMode mode)
{
- //Alloc hash buffer
- Span<byte> hashBuffer = stackalloc byte[(int)type];
+ return type switch
+ {
+ HashAlg.BlAKE2B => ComputeHashInternal(in _blake2bAlg, data, mode, key),
+ HashAlg.SHA512 => ComputeHashInternal(in _sha512Alg, data, mode, key),
+ HashAlg.SHA384 => ComputeHashInternal(in _sha384Alg, data, mode, key),
+ HashAlg.SHA256 => ComputeHashInternal(in _sha256Alg, data, mode, key),
+ HashAlg.SHA1 => ComputeHashInternal(in _sha1Alg, data, mode, key),
+ HashAlg.MD5 => ComputeHashInternal(in _md5Alg, data, mode, key),
+ _ => throw new ArgumentException("Invalid hash algorithm", nameof(type))
+ };
+ }
+
+ #region internal
+
+ private static byte[] ComputeHashInternal<T>(in T algorithm, ReadOnlySpan<char> data, ReadOnlySpan<byte> key = default) where T : IHashAlgorithm
+ {
+ int byteCount = CharEncoding.GetByteCount(data);
+ //Alloc buffer
+ using UnsafeMemoryHandle<byte> binbuf = MemoryUtil.UnsafeAlloc(byteCount, true);
+ //Encode data
+ byteCount = CharEncoding.GetBytes(data, binbuf.Span);
+ //hash the buffer
+ return ComputeHashInternal(in algorithm, binbuf.AsSpan(0, byteCount), key);
+ }
+
+ private static string ComputeHashInternal<T>(in T algorithm, ReadOnlySpan<char> data, HashEncodingMode mode, ReadOnlySpan<byte> key = default) where T : IHashAlgorithm
+ {
+ //Alloc stack buffer to store hash output
+ Span<byte> hashBuffer = stackalloc byte[algorithm.HashSize];
+ //hash the buffer
+ ERRNO count = ComputeHashInternal(in algorithm, data, hashBuffer, key);
+ if (!count)
+ {
+ throw new CryptographicException("Failed to compute the hash of the data");
+ }
+
+ //Convert to encoded string
+ return mode switch
+ {
+ HashEncodingMode.Hexadecimal => Convert.ToHexString(hashBuffer.Slice(0, count)),
+ HashEncodingMode.Base64 => Convert.ToBase64String(hashBuffer.Slice(0, count)),
+ HashEncodingMode.Base32 => VnEncoding.ToBase32String(hashBuffer.Slice(0, count)),
+ HashEncodingMode.Base64Url => VnEncoding.ToBase64UrlSafeString(hashBuffer.Slice(0, count), true),
+ _ => throw new ArgumentException("Encoding mode is not supported"),
+ };
+ }
+
+ private static string ComputeHashInternal<T>(in T algorithm, ReadOnlySpan<byte> data, HashEncodingMode mode, ReadOnlySpan<byte> key = default) where T : IHashAlgorithm
+ {
+ //Alloc stack buffer to store hash output
+ Span<byte> hashBuffer = stackalloc byte[algorithm.HashSize];
//hash the buffer
- ERRNO count = ComputeHmac(key, data, hashBuffer, type);
-
+ ERRNO count = ComputeHashInternal(in algorithm, data, hashBuffer, key);
if (!count)
{
- throw new InternalBufferTooSmallException("Failed to compute the hash of the data");
+ throw new CryptographicException("Failed to compute the hash of the data");
}
-
- //Convert to hex string
+
+ //Convert to encoded string
return mode switch
{
HashEncodingMode.Hexadecimal => Convert.ToHexString(hashBuffer.Slice(0, count)),
HashEncodingMode.Base64 => Convert.ToBase64String(hashBuffer.Slice(0, count)),
HashEncodingMode.Base32 => VnEncoding.ToBase32String(hashBuffer.Slice(0, count)),
+ HashEncodingMode.Base64Url => VnEncoding.ToBase64UrlSafeString(hashBuffer.Slice(0, count), true),
_ => throw new ArgumentException("Encoding mode is not supported"),
};
}
+
+ private static ERRNO ComputeHashInternal<T>(in T algorithm, ReadOnlySpan<char> data, Span<byte> output, ReadOnlySpan<byte> key = default) where T : IHashAlgorithm
+ {
+ int byteCount = CharEncoding.GetByteCount(data);
+ //Alloc buffer
+ using UnsafeMemoryHandle<byte> binbuf = MemoryUtil.UnsafeAlloc(byteCount, true);
+ //Encode data
+ byteCount = CharEncoding.GetBytes(data, binbuf.Span);
+ //hash the buffer or hmac if key is not empty
+ return ComputeHashInternal(in algorithm, binbuf.Span[..byteCount], output, key);
+ }
+
+
+ private static ERRNO ComputeHashInternal<T>(in T algorithm, ReadOnlySpan<byte> data, Span<byte> buffer, ReadOnlySpan<byte> key = default) where T : IHashAlgorithm
+ {
+ //hash the buffer or hmac if key is not empty
+ if (key.IsEmpty)
+ {
+ return algorithm.TryComputeHash(data, buffer, out int written) ? written : ERRNO.E_FAIL;
+ }
+ else
+ {
+ return algorithm.TryComputeHmac(key, data, buffer, out int written) ? written : ERRNO.E_FAIL;
+ }
+ }
+
+ private static byte[] ComputeHashInternal<T>(in T algorithm, ReadOnlySpan<byte> data, ReadOnlySpan<byte> key = default) where T : IHashAlgorithm
+ {
+ //hash the buffer or hmac if key is not empty
+ if (key.IsEmpty)
+ {
+ return algorithm.ComputeHash(data);
+ }
+ else
+ {
+ return algorithm.ComputeHmac(key, data);
+ }
+ }
+
+ #endregion
}
}
diff --git a/lib/Hashing.Portable/src/ManagedHashAlgImpl.cs b/lib/Hashing.Portable/src/ManagedHashAlgImpl.cs
new file mode 100644
index 0000000..7e2262e
--- /dev/null
+++ b/lib/Hashing.Portable/src/ManagedHashAlgImpl.cs
@@ -0,0 +1,227 @@
+/*
+* Copyright (c) 2023 Vaughn Nugent
+*
+* Library: VNLib
+* Package: VNLib.Hashing.Portable
+* File: ManagedHashAlgImpl.cs
+*
+* ManagedHashAlgImpl.cs is part of VNLib.Hashing.Portable which is part of the larger
+* VNLib collection of libraries and utilities.
+*
+* VNLib.Hashing.Portable is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published
+* by the Free Software Foundation, either version 2 of the License,
+* or (at your option) any later version.
+*
+* VNLib.Hashing.Portable is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with VNLib.Hashing.Portable. If not, see http://www.gnu.org/licenses/.
+*/
+
+using System;
+using System.Diagnostics;
+using System.Security.Cryptography;
+
+using VNLib.Utils;
+using VNLib.Hashing.Native.MonoCypher;
+
+namespace VNLib.Hashing
+{
+ public static partial class ManagedHash
+ {
+ private interface IHashAlgorithm
+ {
+ int HashSize { get; }
+
+ byte[] ComputeHash(ReadOnlySpan<byte> data);
+
+ bool TryComputeHash(ReadOnlySpan<byte> data, Span<byte> output, out int count);
+
+ byte[] ComputeHmac(ReadOnlySpan<byte> key, ReadOnlySpan<byte> data);
+
+ bool TryComputeHmac(ReadOnlySpan<byte> key, ReadOnlySpan<byte> data, Span<byte> output, out int count);
+ }
+
+ private readonly struct Sha1 : IHashAlgorithm
+ {
+ ///<inheritdoc/>
+ public readonly int HashSize => (int)HashAlg.SHA1;
+ ///<inheritdoc/>
+ public readonly byte[] ComputeHash(ReadOnlySpan<byte> data) => SHA1.HashData(data);
+ ///<inheritdoc/>
+ public readonly bool TryComputeHash(ReadOnlySpan<byte> data, Span<byte> output, out int count) => SHA1.TryHashData(data, output, out count);
+
+ ///<inheritdoc/>
+ public readonly byte[] ComputeHmac(ReadOnlySpan<byte> key, ReadOnlySpan<byte> data) => HMACSHA1.HashData(key, data);
+ ///<inheritdoc/>
+ public readonly bool TryComputeHmac(ReadOnlySpan<byte> key, ReadOnlySpan<byte> data, Span<byte> output, out int count) => HMACSHA1.TryHashData(key, data, output, out count);
+ }
+
+ private readonly struct Sha256 : IHashAlgorithm
+ {
+ ///<inheritdoc/>
+ public readonly int HashSize => (int)HashAlg.SHA256;
+
+ ///<inheritdoc/>
+ public readonly byte[] ComputeHash(ReadOnlySpan<byte> data) => SHA256.HashData(data);
+
+ ///<inheritdoc/>
+ public readonly bool TryComputeHash(ReadOnlySpan<byte> data, Span<byte> output, out int count) => SHA256.TryHashData(data, output, out count);
+
+ ///<inheritdoc/>
+ public readonly byte[] ComputeHmac(ReadOnlySpan<byte> key, ReadOnlySpan<byte> data) => HMACSHA256.HashData(key, data);
+
+ ///<inheritdoc/>
+ public readonly bool TryComputeHmac(ReadOnlySpan<byte> key, ReadOnlySpan<byte> data, Span<byte> output, out int count) => HMACSHA256.TryHashData(key, data, output, out count);
+ }
+
+ private readonly struct Sha384 : IHashAlgorithm
+ {
+ ///<inheritdoc/>
+ public readonly int HashSize => (int)HashAlg.SHA384;
+ ///<inheritdoc/>
+ public readonly byte[] ComputeHash(ReadOnlySpan<byte> data) => SHA384.HashData(data);
+ ///<inheritdoc/>
+ public readonly bool TryComputeHash(ReadOnlySpan<byte> data, Span<byte> output, out int count) => SHA384.TryHashData(data, output, out count);
+
+ ///<inheritdoc/>
+ public readonly byte[] ComputeHmac(ReadOnlySpan<byte> key, ReadOnlySpan<byte> data) => HMACSHA384.HashData(key, data);
+
+ ///<inheritdoc/>
+ public readonly bool TryComputeHmac(ReadOnlySpan<byte> key, ReadOnlySpan<byte> data, Span<byte> output, out int count) => HMACSHA384.TryHashData(key, data, output, out count);
+ }
+
+ private readonly struct Sha512 : IHashAlgorithm
+ {
+ ///<inheritdoc/>
+ public readonly int HashSize => (int)HashAlg.SHA512;
+ ///<inheritdoc/>
+ public readonly byte[] ComputeHash(ReadOnlySpan<byte> data) => SHA512.HashData(data);
+ ///<inheritdoc/>
+ public readonly bool TryComputeHash(ReadOnlySpan<byte> data, Span<byte> output, out int count) => SHA512.TryHashData(data, output, out count);
+
+ ///<inheritdoc/>
+ public readonly byte[] ComputeHmac(ReadOnlySpan<byte> key, ReadOnlySpan<byte> data) => HMACSHA512.HashData(key, data);
+ ///<inheritdoc/>
+ public readonly bool TryComputeHmac(ReadOnlySpan<byte> key, ReadOnlySpan<byte> data, Span<byte> output, out int count) => HMACSHA512.TryHashData(key, data, output, out count);
+ }
+
+ private readonly struct Md5 : IHashAlgorithm
+ {
+ ///<inheritdoc/>
+ public readonly int HashSize => (int)HashAlg.MD5;
+ ///<inheritdoc/>
+ public readonly byte[] ComputeHash(ReadOnlySpan<byte> data) => MD5.HashData(data);
+ ///<inheritdoc/>
+ public readonly bool TryComputeHash(ReadOnlySpan<byte> data, Span<byte> output, out int count) => MD5.TryHashData(data, output, out count);
+
+ ///<inheritdoc/>
+ public readonly byte[] ComputeHmac(ReadOnlySpan<byte> key, ReadOnlySpan<byte> data) => HMACMD5.HashData(key, data);
+ ///<inheritdoc/>
+ public readonly bool TryComputeHmac(ReadOnlySpan<byte> key, ReadOnlySpan<byte> data, Span<byte> output, out int count) => HMACMD5.TryHashData(key, data, output, out count);
+ }
+
+ private readonly struct Blake2b : IHashAlgorithm
+ {
+ const byte DefaultBlake2HashSize = 64;
+
+ internal static int MaxHashSize => MCBlake2Module.MaxHashSize;
+ internal static int MaxKeySize => MCBlake2Module.MaxKeySize;
+
+ ///<inheritdoc/>
+ public readonly int HashSize => DefaultBlake2HashSize;
+
+ ///<inheritdoc/>
+ public readonly byte[] ComputeHash(ReadOnlySpan<byte> data)
+ {
+ //Stack buffer for output hash
+ byte[] output = new byte[DefaultBlake2HashSize];
+
+ if (!TryComputeHash(data, output, out int count))
+ {
+ throw new ArgumentException("Failed to compute Blake2 hash of desired data");
+ }
+
+ //Count must be exact same (sanity check)
+ Debug.Assert(count == DefaultBlake2HashSize);
+
+ //Return the hash as a new array
+ return output;
+ }
+
+ ///<inheritdoc/>
+ public readonly byte[] ComputeHmac(ReadOnlySpan<byte> key, ReadOnlySpan<byte> data)
+ {
+ //Alloc output buffer
+ byte[] output = new byte[DefaultBlake2HashSize];
+
+ if (!TryComputeHmac(key, data, output, out int count))
+ {
+ throw new ArgumentException("Failed to compute Blake2 hash of desired data");
+ }
+
+ //Count must be exact same (sanity check)
+ Debug.Assert(count == DefaultBlake2HashSize);
+
+ //Return the hash as a new array
+ return output;
+
+ }
+
+ ///<inheritdoc/>
+ public readonly bool TryComputeHash(ReadOnlySpan<byte> data, Span<byte> output, out int count)
+ {
+ if (output.Length > MCBlake2Module.MaxHashSize)
+ {
+ count = 0;
+ return false;
+ }
+
+ //Compute one-shot hash
+ ERRNO result = MonoCypherLibrary.Shared.Blake2ComputeHash(data, output);
+
+ if(result < output.Length)
+ {
+ count = 0;
+ return false;
+ }
+
+ count = output.Length;
+ return true;
+ }
+
+ ///<inheritdoc/>
+ public readonly bool TryComputeHmac(ReadOnlySpan<byte> key, ReadOnlySpan<byte> data, Span<byte> output, out int count)
+ {
+ count = 0;
+
+ if (output.Length > MCBlake2Module.MaxHashSize)
+ {
+ return false;
+ }
+
+ //Test key size
+ if (key.Length > MCBlake2Module.MaxKeySize)
+ {
+ return false;
+ }
+
+ //Compute one-shot hash
+ ERRNO result = MonoCypherLibrary.Shared.Blake2ComputeHmac(key, data, output);
+
+ if (result < output.Length)
+ {
+ count = 0;
+ return false;
+ }
+
+ count = output.Length;
+ return true;
+ }
+ }
+ }
+}
diff --git a/lib/Hashing.Portable/src/Native/MonoCypher/IHashStream.cs b/lib/Hashing.Portable/src/Native/MonoCypher/IHashStream.cs
new file mode 100644
index 0000000..29def42
--- /dev/null
+++ b/lib/Hashing.Portable/src/Native/MonoCypher/IHashStream.cs
@@ -0,0 +1,54 @@
+/*
+* Copyright (c) 2023 Vaughn Nugent
+*
+* Library: VNLib
+* Package: VNLib.Hashing.Portable
+* File: IHashStream.cs
+*
+* IHashStream.cs is part of VNLib.Hashing.Portable which is part of the larger
+* VNLib collection of libraries and utilities.
+*
+* VNLib.Hashing.Portable is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published
+* by the Free Software Foundation, either version 2 of the License,
+* or (at your option) any later version.
+*
+* VNLib.Hashing.Portable is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with VNLib.Hashing.Portable. If not, see http://www.gnu.org/licenses/.
+*/
+
+using System;
+
+namespace VNLib.Hashing.Native.MonoCypher
+{
+ /// <summary>
+ /// A base interface for a streaming (incremental) hash
+ /// function
+ /// </summary>
+ public interface IHashStream : IDisposable
+ {
+ /// <summary>
+ /// The configured hash size of this stream
+ /// </summary>
+ byte HashSize { get; }
+
+ /// <summary>
+ /// Updates the hash of this stream with the specified message
+ /// </summary>
+ /// <param name="mRef">A reference to the first byte of the sequence</param>
+ /// <param name="mSize">The size of the sequence</param>
+ void Update(ref byte mRef, uint mSize);
+
+ /// <summary>
+ /// Flushes the hash of this stream to the specified buffer
+ /// </summary>
+ /// <param name="hashOut">A reference to the first byte in the output sequence</param>
+ /// <param name="hashSize">The size of the output sequence</param>
+ void Flush(ref byte hashOut, byte hashSize);
+ }
+} \ No newline at end of file
diff --git a/lib/Hashing.Portable/src/Native/MonoCypher/IHmacStream.cs b/lib/Hashing.Portable/src/Native/MonoCypher/IHmacStream.cs
new file mode 100644
index 0000000..0ddc236
--- /dev/null
+++ b/lib/Hashing.Portable/src/Native/MonoCypher/IHmacStream.cs
@@ -0,0 +1,46 @@
+/*
+* Copyright (c) 2023 Vaughn Nugent
+*
+* Library: VNLib
+* Package: VNLib.Hashing.Portable
+* File: IHmacStream.cs
+*
+* IHmacStream.cs is part of VNLib.Hashing.Portable which is part of the larger
+* VNLib collection of libraries and utilities.
+*
+* VNLib.Hashing.Portable is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published
+* by the Free Software Foundation, either version 2 of the License,
+* or (at your option) any later version.
+*
+* VNLib.Hashing.Portable is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with VNLib.Hashing.Portable. If not, see http://www.gnu.org/licenses/.
+*/
+
+namespace VNLib.Hashing.Native.MonoCypher
+{
+ /// <summary>
+ /// A base interface for a streaming (incremental) HMAC
+ /// authenticated hash function
+ /// </summary>
+ public interface IHmacStream: IHashStream
+ {
+ /// <summary>
+ /// The maximum key size allowed for this stream
+ /// </summary>
+ int MaxKeySize { get; }
+
+ /// <summary>
+ /// Initializes this stream with the specified key
+ /// </summary>
+ /// <param name="key">A reference to the first byte of key data to import</param>
+ /// <param name="keySize">The size of the key buffer</param>
+ /// <exception cref="System.ArgumentException"></exception>
+ void Initialize(ref byte key, byte keySize);
+ }
+} \ No newline at end of file
diff --git a/lib/Hashing.Portable/src/Native/MonoCypher/MCBlake2Module.cs b/lib/Hashing.Portable/src/Native/MonoCypher/MCBlake2Module.cs
new file mode 100644
index 0000000..e8f0156
--- /dev/null
+++ b/lib/Hashing.Portable/src/Native/MonoCypher/MCBlake2Module.cs
@@ -0,0 +1,420 @@
+/*
+* Copyright (c) 2023 Vaughn Nugent
+*
+* Library: VNLib
+* Package: VNLib.Hashing.Portable
+* File: MCBlake2Module.cs
+*
+* MCBlake2Module.cs is part of VNLib.Hashing.Portable which is part of the larger
+* VNLib collection of libraries and utilities.
+*
+* VNLib.Hashing.Portable is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published
+* by the Free Software Foundation, either version 2 of the License,
+* or (at your option) any later version.
+*
+* VNLib.Hashing.Portable is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with VNLib.Hashing.Portable. If not, see http://www.gnu.org/licenses/.
+*/
+
+
+using System;
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+using VNLib.Utils;
+using VNLib.Utils.Memory;
+using VNLib.Utils.Extensions;
+
+namespace VNLib.Hashing.Native.MonoCypher
+{
+ /// <summary>
+ /// Adds Blake2b hashing support to the <see cref="MonoCypherLibrary"/>
+ /// </summary>
+ public static unsafe class MCBlake2Module
+ {
+ [SafeMethodName("Blake2GetContextSize")]
+ internal delegate uint Blake2GetContextSize();
+
+ [SafeMethodName("Blake2Init")]
+ internal delegate int Blake2Init(IntPtr context, byte hashSize, void* key = null, uint keyLen = 0);
+
+ [SafeMethodName("Blake2Update")]
+ internal delegate int Blake2Update(IntPtr context, void* data, uint dataLen);
+
+ [SafeMethodName("Blake2Final")]
+ internal delegate int Blake2Final(IntPtr context, void* hash, uint hashLen);
+
+ [SafeMethodName("Blake2GetHashSize")]
+ internal delegate uint Blake2GetHashSize(IntPtr context);
+
+
+ public const int MaxHashSize = 64;
+ public const int MaxKeySize = 64;
+ public const int MinSuggestedKDFHashSize = 32;
+ public const int MinSuggestedMACHashSize = 16;
+
+ /// <summary>
+ /// Creates a new <see cref="IHashStream"/> instance with the specified hash size
+ /// which must be between 1 and <see cref="MaxHashSize"/> inclusive.
+ /// </summary>
+ /// <remarks>
+ /// A hash size greater than 32 is recommended for KDFs and a value greater than 16 is recommended for MACs.
+ /// <para>
+ /// <seealso href="https://monocypher.org/manual/blake2b"/>
+ /// </para>
+ /// </remarks>
+ /// <param name="library"></param>
+ /// <param name="hashSize">The hash size between 1 and <see cref="MaxHashSize"/> inclusive</param>
+ /// <param name="heap">The heap to allocate the stream on</param>
+ /// <returns>The initialzied <see cref="IHashStream"/> instance</returns>
+ /// <exception cref="ArgumentNullException"></exception>
+ /// <exception cref="ArgumentOutOfRangeException"></exception>
+ public static IHashStream Blake2CreateStream(this MonoCypherLibrary library, byte hashSize, IUnmangedHeap? heap)
+ {
+ _ = library ?? throw new ArgumentNullException(nameof(library));
+ if(hashSize == 0 || hashSize > MaxHashSize)
+ {
+ throw new ArgumentOutOfRangeException(nameof(hashSize), $"The hash size must be between 1 and {MaxHashSize} inclusive");
+ }
+ //Fall back to the shared heap if none is provided
+ heap ??= MemoryUtil.Shared;
+
+ //Alloc stream and initialize it as a non-hmac stream
+ Blake2Stream stream = new(library, heap, hashSize);
+ try
+ {
+ //Initialize the stream
+ stream.Initialize();
+ return stream;
+ }
+ catch
+ {
+ stream.Dispose();
+ throw;
+ }
+ }
+
+ /// <summary>
+ /// Creates a new <see cref="IHmacStream"/> keyed MAC instance with the specified hash size
+ /// and key which must be between 1 and <see cref="MaxHashSize"/> inclusive. You must
+ /// initialize the instance before use, otherwise results are undefined.
+ /// </summary>
+ /// <remarks>
+ /// A hash size greater than 32 is recommended for KDFs and a value greater than 16 is recommended for MACs.
+ /// <para>
+ /// <seealso href="https://monocypher.org/manual/blake2b"/>
+ /// </para>
+ /// </remarks>
+ /// <param name="library"></param>
+ /// <param name="hashSize">The hash size between 1 and <see cref="MaxHashSize"/> inclusive</param>
+ /// <param name="heap">The heap to allocate the stream on</param>
+ /// <exception cref="ArgumentNullException"></exception>
+ /// <exception cref="ArgumentOutOfRangeException"></exception>
+ public static IHmacStream Blake2CreateHmacStream(this MonoCypherLibrary library, byte hashSize, IUnmangedHeap? heap)
+ {
+ _ = library ?? throw new ArgumentNullException(nameof(library));
+ if (hashSize == 0 || hashSize > MaxHashSize)
+ {
+ throw new ArgumentOutOfRangeException(nameof(hashSize), $"The hash size must be between 1 and {MaxHashSize} inclusive");
+ }
+ //Fall back to the shared heap if none is provided
+ heap ??= MemoryUtil.Shared;
+
+ //Return the raw stream, it will be initialized later
+ return new Blake2Stream(library, heap, hashSize);
+ }
+
+ /// <summary>
+ /// Computes a Blake2b one-shot hash of the specified data and writes it to the variable-length output buffer.
+ /// The output buffer must be between 1 and <see cref="MaxHashSize"/> inclusive.
+ /// <para>
+ /// See <see href="https://monocypher.org/manual/blake2b"></see> for more information.
+ /// </para>
+ /// </summary>
+ /// <param name="library"></param>
+ /// <param name="data">The data buffer to compute the hash of</param>
+ /// <param name="output">The hash output buffer</param>
+ /// <returns>The number of bytes written to the output buffer or the error code from the native library</returns>
+ public static ERRNO Blake2ComputeHash(this MonoCypherLibrary library, ReadOnlySpan<byte> data, Span<byte> output)
+ {
+ ArgumentNullException.ThrowIfNull(library, nameof(library));
+
+ if(output.Length > MaxHashSize)
+ {
+ return ERRNO.E_FAIL;
+ }
+
+ if(output.IsEmpty)
+ {
+ return ERRNO.E_FAIL;
+ }
+
+ //Get context size
+ int contextSize = (int)library.Functions.Blake2GetContextSize();
+
+ //Allocate context on the stack
+ void* ctx = stackalloc byte[contextSize];
+
+ //Init context
+ if(library.Functions.Blake2Init((IntPtr)ctx, (byte)output.Length) != 0)
+ {
+ return ERRNO.E_FAIL;
+ }
+
+ //initialize the context for the stream with hmac key
+ fixed (byte* keyPtr = &MemoryMarshal.GetReference(data),
+ hashPtr = &MemoryMarshal.GetReference(output)
+ )
+ {
+ //Update with data
+ if(library.Functions.Blake2Update((IntPtr)ctx, keyPtr, (uint)data.Length) != 0)
+ {
+ return ERRNO.E_FAIL;
+ }
+ //Copy hash to output
+ if (library.Functions.Blake2Final((IntPtr)ctx, hashPtr, (uint)output.Length) != 0)
+ {
+ return ERRNO.E_FAIL;
+ }
+ }
+
+ return output.Length;
+ }
+
+ /// <summary>
+ /// Computes a Blake2b one-shot keyed MAC of the specified data and writes it to the variable-length output buffer.
+ /// The output buffer must be between 1 and <see cref="MaxHashSize"/> inclusive.
+ /// The key must be between 1 and <see cref="MaxKeySize"/> inclusive.
+ /// <para>
+ /// See <see href="https://monocypher.org/manual/blake2b"></see> for more information.
+ /// </para>
+ /// </summary>
+ /// <param name="library"></param>
+ /// <param name="key">The HMAC key</param>
+ /// <param name="data">The data buffer to compute the hash of</param>
+ /// <param name="output">The hash output buffer</param>
+ /// <returns>The number of bytes written to the output buffer or the error code from the native library</returns>
+ public static ERRNO Blake2ComputeHmac(this MonoCypherLibrary library, ReadOnlySpan<byte> key, ReadOnlySpan<byte> data, Span<byte> output)
+ {
+ ArgumentNullException.ThrowIfNull(library, nameof(library));
+
+ if (output.Length > MaxHashSize)
+ {
+ return ERR_HASH_LEN_INVLID;
+ }
+
+ if (output.IsEmpty)
+ {
+ return ERR_NULL_PTR;
+ }
+
+ if(key.IsEmpty)
+ {
+ return ERR_KEY_PTR_INVALID;
+ }
+
+ if(key.Length > MaxKeySize)
+ {
+ return ERR_KEY_LEN_INVALID;
+ }
+
+ //Get context size
+ int contextSize = (int)library.Functions.Blake2GetContextSize();
+
+ //Allocate context on the stack
+ void* ctx = stackalloc byte[contextSize];
+
+ fixed(byte* keyPtr = &MemoryMarshal.GetReference(key))
+ {
+ //Init context with hmac parameters
+ if (library.Functions.Blake2Init((IntPtr)ctx, (byte)output.Length, keyPtr, (uint)key.Length) != 0)
+ {
+ return ERRNO.E_FAIL;
+ }
+ }
+
+ //initialize the context for the stream with hmac key
+ fixed (byte* keyPtr = &MemoryMarshal.GetReference(data))
+ {
+ //Update with data
+ if (library.Functions.Blake2Update((IntPtr)ctx, keyPtr, (uint)data.Length) != 0)
+ {
+ return ERRNO.E_FAIL;
+ }
+ }
+
+ //Finalize/copy the current hash
+ fixed (byte* hashPtr = &MemoryMarshal.GetReference(output))
+ {
+ if (library.Functions.Blake2Final((IntPtr)ctx, hashPtr, (uint)output.Length) != 0)
+ {
+ return ERRNO.E_FAIL;
+ }
+ }
+
+ //Clear the context before returning
+ MemoryUtil.InitializeBlock((byte*)ctx, contextSize);
+
+ return output.Length;
+ }
+
+ const int ERR_NULL_PTR = -1;
+ const int ERR_HASH_LEN_INVLID = -16;
+ const int ERR_KEY_LEN_INVALID = -17;
+ const int ERR_KEY_PTR_INVALID = -18;
+
+ private static void ThrowOnBlake2Error(int result)
+ {
+ switch (result)
+ {
+ //Success
+ case 0:
+ break;
+ //Null pointer
+ case ERR_NULL_PTR:
+ throw new ArgumentException("An illegal null pointer was passed to the function");
+ //Invalid hash length
+ case ERR_HASH_LEN_INVLID:
+ throw new ArgumentOutOfRangeException("hashLen", "The hash length is invalid");
+ //Invalid key length
+ case ERR_KEY_LEN_INVALID:
+ throw new ArgumentOutOfRangeException("keyLen", "The key length is invalid");
+
+ case ERR_KEY_PTR_INVALID:
+ throw new ArgumentException("The key pointer is null");
+
+ default:
+ throw new Exception($"An unknown error occured while hashing: {result}");
+
+ }
+ }
+
+ private sealed class Blake2Stream : SafeHandle, IHashStream, IHmacStream
+ {
+ private readonly MonoCypherLibrary _library;
+ private readonly IUnmangedHeap _heap;
+
+ ///<inheritdoc/>
+ public override bool IsInvalid => handle == IntPtr.Zero;
+
+ internal Blake2Stream(MonoCypherLibrary library, IUnmangedHeap heap, byte hashSize) :base(IntPtr.Zero, true)
+ {
+ Debug.Assert(hashSize > 0 && hashSize <= MaxHashSize, "Hash size must be between 1 and 64 inclusive");
+ Debug.Assert(library != null, "Library argument passed to internal blake2 stream constructur is null");
+ _library = library;
+ _heap = heap;
+ HashSize = hashSize;
+ }
+
+ internal void Initialize()
+ {
+ //Make sure context is initialized
+ InitContextHandle();
+
+ //Init non-hmac
+ int initResult = _library.Functions.Blake2Init(handle, HashSize);
+ ThrowOnBlake2Error(initResult);
+ }
+
+ ///<inheritdoc/>
+ public byte HashSize { get; }
+
+ ///<inheritdoc/>
+ public int MaxKeySize => MaxKeySize;
+
+ ///<inheritdoc/>
+ public void Flush(ref byte hashOut, byte hashSize)
+ {
+ this.ThrowIfClosed();
+
+ if(Unsafe.IsNullRef(ref hashOut))
+ {
+ throw new ArgumentNullException(nameof(hashOut));
+ }
+
+ //Guard for hash size
+ if(hashSize != HashSize)
+ {
+ throw new ArgumentException("The hash output must be the configured hash size", nameof(hashSize));
+ }
+ //get the address of our context and the hash output reference
+
+ fixed(byte* hashOutPtr = &hashOut)
+ {
+ _library.Functions.Blake2Final(handle, hashOutPtr, hashSize);
+ }
+ }
+
+ ///<inheritdoc/>
+ public void Initialize(ref byte key, byte keySize)
+ {
+ if (Unsafe.IsNullRef(ref key))
+ {
+ throw new ArgumentNullException(nameof(key));
+ }
+
+ if(keySize > MaxKeySize)
+ {
+ throw new ArgumentOutOfRangeException(nameof(keySize), $"The key size must be between 1 and {MaxKeySize} inclusive bytes");
+ }
+
+ //Make sure context is initialized
+ InitContextHandle();
+
+ //initialize the context for the stream with hmac key
+ fixed (byte* keyPtr = &key)
+ {
+ int result = _library.Functions.Blake2Init(handle, HashSize, keyPtr, keySize);
+ ThrowOnBlake2Error(result);
+ }
+ }
+
+ ///<inheritdoc/>
+ public void Update(ref byte mRef, uint mSize)
+ {
+ this.ThrowIfClosed();
+
+ if (Unsafe.IsNullRef(ref mRef))
+ {
+ throw new ArgumentNullException(nameof(mRef));
+ }
+
+ if (mSize == 0)
+ {
+ return;
+ }
+
+ //get the address of the message reference
+ fixed (byte* message = &mRef)
+ {
+ int result = _library.Functions.Blake2Update(handle, message, mSize);
+ ThrowOnBlake2Error(result);
+ }
+ }
+
+ private void InitContextHandle()
+ {
+ if (IsClosed)
+ {
+ throw new ObjectDisposedException(nameof(Blake2Stream));
+ }
+
+ //alloc buffer on the heap if not allocated
+ if (handle == IntPtr.Zero)
+ {
+ handle = _heap.Alloc(1, _library.Functions.Blake2GetContextSize(), true);
+ }
+ }
+
+ ///<inheritdoc/>
+ protected override bool ReleaseHandle() => _heap.Free(ref handle);
+ }
+ }
+} \ No newline at end of file
diff --git a/lib/Hashing.Portable/src/Native/MonoCypher/MCHashingStreamExtensions.cs b/lib/Hashing.Portable/src/Native/MonoCypher/MCHashingStreamExtensions.cs
new file mode 100644
index 0000000..3f27539
--- /dev/null
+++ b/lib/Hashing.Portable/src/Native/MonoCypher/MCHashingStreamExtensions.cs
@@ -0,0 +1,292 @@
+/*
+* Copyright (c) 2023 Vaughn Nugent
+*
+* Library: VNLib
+* Package: VNLib.Hashing.Portable
+* File: MCHashingStreamExtensions.cs
+*
+* MCHashingStreamExtensions.cs is part of VNLib.Hashing.Portable which is part of the larger
+* VNLib collection of libraries and utilities.
+*
+* VNLib.Hashing.Portable is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published
+* by the Free Software Foundation, either version 2 of the License,
+* or (at your option) any later version.
+*
+* VNLib.Hashing.Portable is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with VNLib.Hashing.Portable. If not, see http://www.gnu.org/licenses/.
+*/
+
+using System;
+using System.Buffers;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+
+
+namespace VNLib.Hashing.Native.MonoCypher
+{
+ /// <summary>
+ /// Provides extension methods for <see cref="IHashStream"/> instances
+ /// </summary>
+ public static unsafe class MCHashingStreamExtensions
+ {
+ /// <summary>
+ /// Updates the hash of this stream with the specified message
+ /// </summary>
+ /// <param name="hashStream"></param>
+ /// <param name="message">A pointer to the message memory sequence</param>
+ /// <param name="mSize">The size of the sequence</param>
+ /// <exception cref="ArgumentException"></exception>
+ /// <exception cref="ArgumentNullException"></exception>
+ public static void Update(this IHashStream hashStream, IntPtr message, uint mSize) => Update(hashStream, message.ToPointer(), mSize);
+
+ /// <summary>
+ /// Updates the hash of this stream with the specified message
+ /// </summary>
+ /// <param name="hashStream"></param>
+ /// <param name="message">A pointer to the message memory sequence</param>
+ /// <param name="mSize">The size of the sequence</param>
+ /// <exception cref="ArgumentException"></exception>
+ /// <exception cref="ArgumentNullException"></exception>
+ public static void Update(this IHashStream hashStream, void* message, uint mSize)
+ {
+ if (message == null)
+ {
+ throw new ArgumentNullException(nameof(message));
+ }
+ _ = hashStream ?? throw new ArgumentNullException(nameof(hashStream));
+
+ //get ref from pointer
+ ref byte mRef = ref Unsafe.AsRef<byte>(message);
+ hashStream.Update(ref mRef, mSize);
+ }
+
+ /// <summary>
+ /// Updates the hash of this stream with the specified message
+ /// </summary>
+ /// <param name="hashStream"></param>
+ /// <param name="message">The message memory sequence</param>
+ /// <exception cref="ArgumentException"></exception>
+ /// <exception cref="ArgumentNullException"></exception>
+ public static void Update(this IHashStream hashStream, ReadOnlySpan<byte> message)
+ {
+ _ = hashStream ?? throw new ArgumentNullException(nameof(hashStream));
+
+ if(message.Length == 0)
+ {
+ return;
+ }
+
+ //Marshal reference to span
+ ref byte mRef = ref MemoryMarshal.GetReference(message);
+ hashStream.Update(ref mRef, (uint)message.Length);
+ }
+
+ /// <summary>
+ /// Updates the hash of this stream with the specified message
+ /// </summary>
+ /// <param name="hashStream"></param>
+ /// <param name="message">The message memory sequence</param>
+ /// <exception cref="ArgumentException"></exception>
+ /// <exception cref="ArgumentNullException"></exception>
+ public static void Update(this IHashStream hashStream, ReadOnlyMemory<byte> message)
+ {
+ _ = hashStream ?? throw new ArgumentNullException(nameof(hashStream));
+ if (message.Length == 0)
+ {
+ return;
+ }
+
+ //Pin memory block instead of span marshalling
+ using MemoryHandle mHandle = message.Pin();
+
+ hashStream.Update(mHandle.Pointer, (uint)message.Length);
+ }
+
+ /// <summary>
+ /// Writes the internal hash state to the specified memory location. The hash size
+ /// must be at least the size of <see cref="IHashStream.HashSize"/>
+ /// </summary>
+ /// <param name="hashStream"></param>
+ /// <param name="hashOut">A pointer to the memory sequence to write the hash to</param>
+ /// <param name="hashSize">The size of the hash memory sequence, must be exactly <see cref="IHashStream.HashSize"/></param>
+ /// <exception cref="ArgumentException"></exception>
+ /// <exception cref="ArgumentNullException"></exception>
+ public static void Flush(this IHashStream hashStream, IntPtr hashOut, byte hashSize) => Flush(hashStream, hashOut.ToPointer(), hashSize);
+
+ /// <summary>
+ /// Writes the internal hash state to the specified memory location. The hash size
+ /// must be at least the size of <see cref="IHashStream.HashSize"/>
+ /// </summary>
+ /// <param name="hashStream"></param>
+ /// <param name="hashOut">A pointer to the memory sequence to write the hash to</param>
+ /// <param name="hashSize">The size of the hash memory sequence, must be exactly <see cref="IHashStream.HashSize"/></param>
+ /// <exception cref="ArgumentException"></exception>
+ /// <exception cref="ArgumentNullException"></exception>
+ public static void Flush(this IHashStream hashStream, void* hashOut, byte hashSize)
+ {
+ if (hashOut == null)
+ {
+ throw new ArgumentNullException(nameof(hashOut));
+ }
+ _ = hashStream ?? throw new ArgumentNullException(nameof(hashStream));
+
+ //get ref from pointer
+ ref byte hashOutRef = ref Unsafe.AsRef<byte>(hashOut);
+ hashStream.Flush(ref hashOutRef, hashSize);
+ }
+
+ /// <summary>
+ /// Writes the internal hash state to the specified memory location. The hash size
+ /// must be at least the size of <see cref="IHashStream.HashSize"/>
+ /// </summary>
+ /// <param name="hashStream"></param>
+ /// <param name="hashOut">The memory sequence to write the hash to, must be exactly <see cref="IHashStream.HashSize"/></param>
+ /// <exception cref="ArgumentException"></exception>
+ /// <exception cref="ArgumentNullException"></exception>
+ public static void Flush(this IHashStream hashStream, Span<byte> hashOut)
+ {
+ _ = hashStream ?? throw new ArgumentNullException(nameof(hashStream));
+
+ if (hashOut.Length != hashStream.HashSize)
+ {
+ throw new ArgumentException("The hash output must be the configured hash size", nameof(hashOut));
+ }
+
+ //Marshal reference to span and flush
+ ref byte hashOutRef = ref MemoryMarshal.GetReference(hashOut);
+ hashStream.Flush(ref hashOutRef, (byte)hashOut.Length);
+ }
+
+ /// <summary>
+ /// Writes the internal hash state to the specified memory location. The hash size
+ /// must be at least the size of <see cref="IHashStream.HashSize"/>
+ /// </summary>
+ /// <param name="hashStream"></param>
+ /// <param name="hashOut">The memory sequence to write the hash to, must be exactly <see cref="IHashStream.HashSize"/></param>
+ /// <exception cref="ArgumentException"></exception>
+ /// <exception cref="ArgumentNullException"></exception>
+ public static void Flush(this IHashStream hashStream, Memory<byte> hashOut)
+ {
+ _ = hashStream ?? throw new ArgumentNullException(nameof(hashStream));
+
+ if (hashOut.Length != hashStream.HashSize)
+ {
+ throw new ArgumentException("The hash output must be the configured hash size", nameof(hashOut));
+ }
+
+ //Pin memory block instead of span marshalling
+ using MemoryHandle hashOutHandle = hashOut.Pin();
+ hashStream.Flush(hashOutHandle.Pointer, (byte)hashOut.Length);
+ }
+
+ /// <summary>
+ /// Creates a new <see cref="IHmacStream"/> keyed MAC instance with the specified hash size.
+ /// </summary>
+ /// <remarks>
+ /// A value greater than 32 is recommended for KDFs and a value greater than 16 is recommended for MACs.
+ /// <para>
+ /// <seealso href="https://monocypher.org/manual/blake2b"/>
+ /// </para>
+ /// </remarks>
+ /// <param name="stream"></param>
+ /// <param name="key">A pointer to the HMAC key buffer</param>
+ /// <param name="keySize">The HMAC key must be between 1 and <see cref="IHmacStream.MaxKeySize"/> inclusive</param>
+ /// <exception cref="ArgumentNullException"></exception>
+ /// <exception cref="ArgumentOutOfRangeException"></exception>
+ public static void Initialize(this IHmacStream stream, IntPtr key, byte keySize) => Initialize(stream, (byte*)key.ToPointer(), keySize);
+
+ /// <summary>
+ /// Creates a new <see cref="IHmacStream"/> keyed MAC instance with the specified hash size.
+ /// </summary>
+ /// <remarks>
+ /// A value greater than 32 is recommended for KDFs and a value greater than 16 is recommended for MACs.
+ /// <para>
+ /// <seealso href="https://monocypher.org/manual/blake2b"/>
+ /// </para>
+ /// </remarks>
+ /// <param name="stream"></param>
+ /// <param name="key">A pointer to the HMAC key buffer</param>
+ /// <param name="keySize">The HMAC key must be between 1 and <see cref="IHmacStream.MaxKeySize"/> inclusive</param>
+ /// <exception cref="ArgumentNullException"></exception>
+ /// <exception cref="ArgumentOutOfRangeException"></exception>
+ public static void Initialize(this IHmacStream stream, byte* key, byte keySize)
+ {
+ _ = stream ?? throw new ArgumentNullException(nameof(stream));
+
+ if (key == null)
+ {
+ throw new ArgumentNullException(nameof(key));
+ }
+ if (keySize == 0 || keySize > stream.MaxKeySize)
+ {
+ throw new ArgumentOutOfRangeException(nameof(keySize), $"The key size must be between 1 and {stream.MaxKeySize} inclusive");
+ }
+
+ //Get reference to key
+ ref byte asRef = ref Unsafe.AsRef<byte>(key);
+ stream.Initialize(ref asRef, keySize);
+ }
+
+ /// <summary>
+ /// Creates a new <see cref="IHmacStream"/> keyed MAC instance with the specified hash size.
+ /// </summary>
+ /// <remarks>
+ /// A value greater than 32 is recommended for KDFs and a value greater than 16 is recommended for MACs.
+ /// <para>
+ /// <seealso href="https://monocypher.org/manual/blake2b"/>
+ /// </para>
+ /// </remarks>
+ /// <param name="stream"></param>
+ /// <param name="key">The HMAC key buffer</param>
+ /// <exception cref="ArgumentNullException"></exception>
+ /// <exception cref="ArgumentOutOfRangeException"></exception>
+ public static void Initialize(this IHmacStream stream, ReadOnlySpan<byte> key)
+ {
+ _ = stream ?? throw new ArgumentNullException(nameof(stream));
+
+ if (key.Length > stream.MaxKeySize)
+ {
+ throw new ArgumentOutOfRangeException(nameof(key), $"The hash size must be less than or equal to {stream.MaxKeySize}");
+ }
+
+ //Get span ref and call interface method
+ ref byte asRef = ref MemoryMarshal.GetReference(key);
+ stream.Initialize(ref asRef, (byte)key.Length);
+ }
+
+ /// <summary>
+ /// Creates a new <see cref="IHmacStream"/> keyed MAC instance with the specified hash size.
+ /// </summary>
+ /// <remarks>
+ /// A value greater than 32 is recommended for KDFs and a value greater than 16 is recommended for MACs.
+ /// <para>
+ /// <seealso href="https://monocypher.org/manual/blake2b"/>
+ /// </para>
+ /// </remarks>
+ /// <param name="stream"></param>
+ /// <param name="key">The HMAC key buffer</param>
+ /// <exception cref="ArgumentNullException"></exception>
+ /// <exception cref="ArgumentOutOfRangeException"></exception>
+ public static void Initialize(this IHmacStream stream, ReadOnlyMemory<byte> key)
+ {
+ _ = stream ?? throw new ArgumentNullException(nameof(stream));
+
+ if (key.Length > stream.MaxKeySize)
+ {
+ throw new ArgumentOutOfRangeException(nameof(key), $"The hash size must be less than or equal to {stream.MaxKeySize}");
+ }
+
+ //If key is default, then h.Pointer will be null, which is handled
+ using MemoryHandle h = key.Pin();
+
+ //Get address of ref
+ Initialize(stream, (byte*)h.Pointer, (byte)key.Length);
+ }
+ }
+} \ No newline at end of file
diff --git a/lib/Hashing.Portable/src/Native/MonoCypher/MCPasswordModule.cs b/lib/Hashing.Portable/src/Native/MonoCypher/MCPasswordModule.cs
new file mode 100644
index 0000000..9dbcb41
--- /dev/null
+++ b/lib/Hashing.Portable/src/Native/MonoCypher/MCPasswordModule.cs
@@ -0,0 +1,159 @@
+/*
+* Copyright (c) 2023 Vaughn Nugent
+*
+* Library: VNLib
+* Package: VNLib.Hashing.Portable
+* File: MCPasswordModule.cs
+*
+* MCPasswordModule.cs is part of VNLib.Hashing.Portable which is part of the larger
+* VNLib collection of libraries and utilities.
+*
+* VNLib.Hashing.Portable is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published
+* by the Free Software Foundation, either version 2 of the License,
+* or (at your option) any later version.
+*
+* VNLib.Hashing.Portable is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with VNLib.Hashing.Portable. If not, see http://www.gnu.org/licenses/.
+*/
+
+using System;
+using System.Diagnostics;
+
+using VNLib.Utils.Memory;
+using VNLib.Utils.Extensions;
+
+namespace VNLib.Hashing.Native.MonoCypher
+{
+
+ /// <summary>
+ /// Provides argon2 hashing functionality using the MonoCypher library.
+ /// <para>
+ /// <seealso href="https://monocypher.org/manual/argon2"/>
+ /// </para>
+ /// </summary>
+ public static unsafe class MCPasswordModule
+ {
+
+ const uint MC_ARGON2_WA_MEM_ALIGNMENT = sizeof(ulong);
+ const ulong MC_BLOCK_MULTIPLIER = 1024UL;
+
+ [SafeMethodName("Argon2CalcWorkAreaSize")]
+ internal delegate uint Argon2CalcWorkArea(Argon2Context* context);
+
+ [SafeMethodName("Argon2ComputeHash")]
+ internal delegate Argon2_ErrorCodes Argon2Hash(Argon2Context* context, void* workArea);
+
+
+ /// <summary>
+ /// Creates a new <see cref="IArgon2Library"/> instance using the provided <paramref name="heap"/>.
+ /// </summary>
+ /// <param name="Library"></param>
+ /// <param name="heap">The heap to allocate internal buffers from</param>
+ /// <returns>The <see cref="IArgon2Library"/> wrapper instance</returns>
+ /// <exception cref="ArgumentNullException"></exception>
+ public static IArgon2Library Argon2CreateLibrary(this MonoCypherLibrary Library, IUnmangedHeap heap)
+ {
+ //Validate arguments
+ _ = Library ?? throw new ArgumentNullException(nameof(Library));
+ _ = heap ?? throw new ArgumentNullException(nameof(heap));
+ return new Argon2HashLib(Library, heap);
+ }
+
+ private static void Hash(this MonoCypherLibrary library, IUnmangedHeap heap, Argon2Context* context)
+ {
+ _ = library ?? throw new ArgumentNullException(nameof(library));
+ _ = heap ?? throw new ArgumentNullException(nameof(heap));
+
+ //Validate context
+ ValidateContext(context);
+
+ CalcWorkAreaSize(context, out uint elements, out uint alignment);
+
+ //Allocate work area
+ IntPtr workArea = heap.Alloc(elements, alignment, true);
+
+ try
+ {
+ //Compute the hash using the allocated work area
+ Argon2_ErrorCodes result = library.Functions.Argon2Hash(context, workArea.ToPointer());
+ VnArgon2.ThrowOnArgonErr(result);
+ }
+ finally
+ {
+ //Free work area
+ bool free = heap.Free(ref workArea);
+ Debug.Assert(free, "Failed to free work area pointer after allocation");
+ }
+ }
+
+ /*
+ * Since unmanaged heaps are being utilized and they support alignment args, we can compute
+ * a proper alignment value and element count for the work area that best matches the native
+ * impl.
+ *
+ * Currently the blocks are broken into a struct array of 128 u64 elements. So currently
+ * using sizeof(ulong) as the alignment value so we can pass that to the heap for better
+ * alignment
+ */
+
+ private static void CalcWorkAreaSize(Argon2Context* ctx, out uint elements, out uint alignment)
+ {
+ ulong mCost = ctx->m_cost;
+ ulong size = mCost * MC_BLOCK_MULTIPLIER;
+
+ //Calculate element size after alignment
+ elements = checked((uint)(size / MC_ARGON2_WA_MEM_ALIGNMENT));
+ alignment = MC_ARGON2_WA_MEM_ALIGNMENT;
+
+ //Sanity check
+ Debug.Assert(((ulong)elements * (ulong)alignment) == size);
+ }
+
+ private static void ValidateContext(Argon2Context* context)
+ {
+ if(context == null)
+ {
+ throw new ArgumentNullException(nameof(context));
+ }
+
+ if (context->outptr == null || context->outlen == 0)
+ {
+ throw new ArgumentException("Output buffer is null or empty");
+ }
+
+ if (context->pwd == null || context->pwdlen == 0)
+ {
+ throw new ArgumentException("Password buffer is null or empty");
+ }
+
+ if (context->salt == null || context->saltlen == 0)
+ {
+ throw new ArgumentException("Salt buffer is null or empty");
+ }
+ }
+
+ private sealed record class Argon2HashLib(MonoCypherLibrary Library, IUnmangedHeap BufferHeap) : IArgon2Library
+ {
+
+ ///<inheritdoc/>
+ public int Argon2Hash(IntPtr context)
+ {
+ if(context == IntPtr.Zero)
+ {
+ throw new ArgumentNullException(nameof(context), "");
+ }
+
+ //Invoke hash with argon2 context pointer
+ Hash(Library, BufferHeap, (Argon2Context*)context);
+ return 0;
+ }
+ }
+ }
+
+} \ No newline at end of file
diff --git a/lib/Hashing.Portable/src/Native/MonoCypher/MonoCypherLibrary.cs b/lib/Hashing.Portable/src/Native/MonoCypher/MonoCypherLibrary.cs
new file mode 100644
index 0000000..ff517ef
--- /dev/null
+++ b/lib/Hashing.Portable/src/Native/MonoCypher/MonoCypherLibrary.cs
@@ -0,0 +1,169 @@
+/*
+* Copyright (c) 2023 Vaughn Nugent
+*
+* Library: VNLib
+* Package: VNLib.Hashing.Portable
+* File: MonoCypherLibrary.cs
+*
+* MonoCypherLibrary.cs is part of VNLib.Hashing.Portable which is part of the larger
+* VNLib collection of libraries and utilities.
+*
+* VNLib.Hashing.Portable is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published
+* by the Free Software Foundation, either version 2 of the License,
+* or (at your option) any later version.
+*
+* VNLib.Hashing.Portable is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with VNLib.Hashing.Portable. If not, see http://www.gnu.org/licenses/.
+*/
+
+using System;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using System.Threading;
+
+using VNLib.Utils;
+using VNLib.Utils.Native;
+using VNLib.Utils.Extensions;
+
+namespace VNLib.Hashing.Native.MonoCypher
+{
+
+ /// <summary>
+ /// Wraps a safe library handle to the MonoCypher library and
+ /// provides access to the MonoCypher functions
+ /// </summary>
+ public unsafe class MonoCypherLibrary : VnDisposeable
+ {
+ public const string MONOCYPHER_LIB_ENVIRONMENT_VAR_NAME = "VNLIB_MONOCYPHER_DLL_PATH";
+ public const string MONOCYPHER_LIB_DEFAULT_NAME = "vnlib_monocypher";
+
+ /// <summary>
+ /// Determines if the default MonoCypher library can be loaded into
+ /// the current process.
+ /// </summary>
+ /// <returns>true if the user enabled the default library, false otherwise</returns>
+ public static bool CanLoadDefaultLibrary() => string.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable(MONOCYPHER_LIB_ENVIRONMENT_VAR_NAME)) == false;
+
+ private static readonly Lazy<MonoCypherLibrary> _defaultLib = new (LoadDefaultLibraryInternal, LazyThreadSafetyMode.PublicationOnly);
+
+ /// <summary>
+ /// Gets the default MonoCypher library for the current process
+ /// <para>
+ /// You should call <see cref="CanLoadDefaultLibrary"/> before accessing
+ /// this property to ensure that the default library can be loaded
+ /// </para>
+ /// </summary>
+ public static MonoCypherLibrary Shared => _defaultLib.Value;
+
+ /// <summary>
+ /// Loads a new instance of the MonoCypher library with environment defaults
+ /// <para>
+ /// You should call <see cref="CanLoadDefaultLibrary"/> before calling this
+ /// function
+ /// </para>
+ /// </summary>
+ /// <returns>The new library instance</returns>
+ /// <exception cref="DllNotFoundException"></exception>
+ /// <exception cref="MissingMemberException"></exception>
+ public static MonoCypherLibrary LoadNewInstance() => LoadDefaultLibraryInternal();
+
+ /// <summary>
+ /// Loads the MonoCypher library from the specified shared library path
+ /// </summary>
+ /// <param name="path">The file path or library name to search for</param>
+ /// <param name="searchPath">The directory search flags</param>
+ /// <returns>The new <see cref="MonoCypherLibrary"/> instance</returns>
+ public static MonoCypherLibrary LoadLibrary(string path, DllImportSearchPath searchPath)
+ {
+ SafeLibraryHandle lib = SafeLibraryHandle.LoadLibrary(path, searchPath);
+ return new(lib, true);
+ }
+
+ private static MonoCypherLibrary LoadDefaultLibraryInternal()
+ {
+ //Get the path to the library or default
+ string? monoCypherLibPath = Environment.GetEnvironmentVariable(MONOCYPHER_LIB_ENVIRONMENT_VAR_NAME) ?? MONOCYPHER_LIB_DEFAULT_NAME;
+
+ Trace.WriteLine("Attempting to load global native MonoCypher library from: " + monoCypherLibPath, "MonoCypher");
+
+ SafeLibraryHandle lib = SafeLibraryHandle.LoadLibrary(monoCypherLibPath, DllImportSearchPath.SafeDirectories);
+ return new(lib, true);
+ }
+
+
+ private readonly SafeLibraryHandle _library;
+ private readonly FunctionTable _functions;
+ private readonly bool _ownsHandle;
+
+ internal ref readonly FunctionTable Functions
+ {
+ get
+ {
+ Check();
+ return ref _functions;
+ }
+ }
+
+ /// <summary>
+ /// Creates a new instance of <see cref="MonoCypherLibrary"/> consuming the
+ /// specified library handle
+ /// </summary>
+ /// <param name="library">The safe MonoCypher library handle</param>
+ /// <param name="ownsHandle">A value that indicates if the current instance owns the library handle</param>
+ /// <exception cref="ArgumentNullException"></exception>
+ public MonoCypherLibrary(SafeLibraryHandle library, bool ownsHandle)
+ {
+ _library = library ?? throw new ArgumentNullException(nameof(library));
+ _ownsHandle = ownsHandle;
+
+ //Init the function table
+ InitFunctionTable(library, out _functions);
+ }
+
+ private static void InitFunctionTable(SafeLibraryHandle library, out FunctionTable functions)
+ {
+ functions = new FunctionTable
+ {
+ //Argon2
+ Argon2Hash = library.DangerousGetMethod<MCPasswordModule.Argon2Hash>(),
+ Argon2CalcWorkArea = library.DangerousGetMethod<MCPasswordModule.Argon2CalcWorkArea>(),
+
+ //Blake2b
+ Blake2GetContextSize = library.DangerousGetMethod<MCBlake2Module.Blake2GetContextSize>(),
+ Blake2Init = library.DangerousGetMethod<MCBlake2Module.Blake2Init>(),
+ Blake2Update = library.DangerousGetMethod<MCBlake2Module.Blake2Update>(),
+ Blake2Final = library.DangerousGetMethod<MCBlake2Module.Blake2Final>(),
+ Blake2GethashSize = library.DangerousGetMethod<MCBlake2Module.Blake2GetHashSize>(),
+ };
+ }
+
+ ///<inheritdoc/>
+ protected override void Free()
+ {
+ if(_ownsHandle)
+ {
+ _library.Dispose();
+ }
+ }
+
+ internal readonly struct FunctionTable
+ {
+ //Argon2 module
+ public readonly MCPasswordModule.Argon2Hash Argon2Hash { get; init; }
+ public readonly MCPasswordModule.Argon2CalcWorkArea Argon2CalcWorkArea { get; init; }
+
+ //Blake2 module
+ public readonly MCBlake2Module.Blake2GetContextSize Blake2GetContextSize { get; init; }
+ public readonly MCBlake2Module.Blake2Init Blake2Init { get; init; }
+ public readonly MCBlake2Module.Blake2Update Blake2Update { get; init; }
+ public readonly MCBlake2Module.Blake2Final Blake2Final { get; init; }
+ public readonly MCBlake2Module.Blake2GetHashSize Blake2GethashSize { get; init; }
+ }
+ }
+} \ No newline at end of file
diff --git a/lib/Hashing.Portable/tests/.runsettings b/lib/Hashing.Portable/tests/.runsettings
new file mode 100644
index 0000000..0b2d635
--- /dev/null
+++ b/lib/Hashing.Portable/tests/.runsettings
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RunSettings>
+ <RunConfiguration>
+ <EnvironmentVariables>
+ <VNLIB_MONOCYPHER_DLL_PATH>../../../../../Utils.Cryptography/monocypher/build/Debug/vnlib_monocypher.dll</VNLIB_MONOCYPHER_DLL_PATH>
+ </EnvironmentVariables>
+ </RunConfiguration>
+</RunSettings> \ No newline at end of file
diff --git a/lib/Hashing.Portable/tests/ManagedHashTests.cs b/lib/Hashing.Portable/tests/ManagedHashTests.cs
new file mode 100644
index 0000000..01b3336
--- /dev/null
+++ b/lib/Hashing.Portable/tests/ManagedHashTests.cs
@@ -0,0 +1,95 @@
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+using System.Text;
+
+using VNLib.Utils.Memory;
+using VNLib.Utils;
+
+
+namespace VNLib.Hashing.Tests
+{
+ [TestClass()]
+ public class ManagedHashTests
+ {
+ [TestMethod()]
+ public void ComputeHashTest()
+ {
+ byte[] testData = Encoding.UTF8.GetBytes("Hello World!");
+ using UnsafeMemoryHandle<byte> heapBuffer = MemoryUtil.UnsafeAlloc(64, false);
+
+ //Test all supported algorithms
+ foreach (HashAlg alg in Enum.GetValues<HashAlg>())
+ {
+ if (alg == HashAlg.None) continue;
+
+ //Skip unsupported algorithms
+ if (alg == HashAlg.BlAKE2B && !ManagedHash.SupportsBlake2b) continue;
+
+ //Compute hash
+ ERRNO hashSize = ManagedHash.ComputeHash(testData, heapBuffer.Span, alg);
+ Assert.IsTrue(hashSize == Math.Abs(hashSize));
+
+ //With input string and heap buffer
+ hashSize = ManagedHash.ComputeHash("test", heapBuffer.Span, alg);
+ Assert.IsTrue(hashSize == Math.Abs(hashSize));
+
+ //Compute string and byte array
+ byte[] testdata = ManagedHash.ComputeHash(testData, alg);
+ Assert.IsTrue(testdata.Length == Math.Abs(hashSize));
+
+ //With input string
+ testdata = ManagedHash.ComputeHash("test", alg);
+ Assert.IsTrue(testdata.Length == Math.Abs(hashSize));
+
+ //Compute hash as string
+ string testEnc = ManagedHash.ComputeHash(testdata, alg, HashEncodingMode.Hexadecimal);
+ Assert.IsTrue(testEnc.Length == Math.Abs(hashSize) * 2);
+
+ //With input string
+ testEnc = ManagedHash.ComputeHash("test", alg, HashEncodingMode.Hexadecimal);
+ Assert.IsTrue(testEnc.Length == Math.Abs(hashSize) * 2);
+ }
+ }
+
+ [TestMethod()]
+ public void ComputeHmacTest()
+ {
+ byte[] testData = Encoding.UTF8.GetBytes("Hello World!");
+ byte[] testKey = RandomHash.GetRandomBytes(32);
+ using UnsafeMemoryHandle<byte> heapBuffer = MemoryUtil.UnsafeAlloc(64, false);
+
+ //Test all supported algorithms
+ foreach (HashAlg alg in Enum.GetValues<HashAlg>())
+ {
+ if (alg == HashAlg.None) continue;
+
+ //Skip unsupported algorithms
+ if (alg == HashAlg.BlAKE2B && !ManagedHash.SupportsBlake2b) continue;
+
+ //Compute hash
+ ERRNO hashSize = ManagedHash.ComputeHmac(testKey, testData, heapBuffer.Span, alg);
+ Assert.IsTrue(hashSize == Math.Abs(hashSize));
+
+ //With input string and heap buffer
+ hashSize = ManagedHash.ComputeHmac(testKey, "test", heapBuffer.Span, alg);
+ Assert.IsTrue(hashSize == Math.Abs(hashSize));
+
+ //Compute string and byte array
+ byte[] testdata = ManagedHash.ComputeHmac(testKey, testData, alg);
+ Assert.IsTrue(testdata.Length == Math.Abs(hashSize));
+
+ //With input string
+ testdata = ManagedHash.ComputeHmac(testKey, "test", alg);
+ Assert.IsTrue(testdata.Length == Math.Abs(hashSize));
+
+ //Compute hash as string
+ string testEnc = ManagedHash.ComputeHmac(testKey, testdata, alg, HashEncodingMode.Hexadecimal);
+ Assert.IsTrue(testEnc.Length == Math.Abs(hashSize) * 2);
+
+ //With input string
+ testEnc = ManagedHash.ComputeHmac(testKey, "test", alg, HashEncodingMode.Hexadecimal);
+ Assert.IsTrue(testEnc.Length == Math.Abs(hashSize) * 2);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/lib/Hashing.Portable/tests/VNLib.Hashing.PortableTests.csproj b/lib/Hashing.Portable/tests/VNLib.Hashing.PortableTests.csproj
new file mode 100644
index 0000000..45a5589
--- /dev/null
+++ b/lib/Hashing.Portable/tests/VNLib.Hashing.PortableTests.csproj
@@ -0,0 +1,27 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+ <PropertyGroup>
+ <TargetFramework>net6.0</TargetFramework>
+ <ImplicitUsings>enable</ImplicitUsings>
+ <Nullable>enable</Nullable>
+
+ <IsPackable>false</IsPackable>
+ <IsTestProject>true</IsTestProject>
+ </PropertyGroup>
+
+ <PropertyGroup>
+ <RunSettingsFilePath>$(MSBuildProjectDirectory)\.runsettings</RunSettingsFilePath>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
+ <PackageReference Include="MSTest.TestAdapter" Version="3.1.1" />
+ <PackageReference Include="MSTest.TestFramework" Version="3.1.1" />
+ <PackageReference Include="coverlet.collector" Version="6.0.0" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <ProjectReference Include="..\src\VNLib.Hashing.Portable.csproj" />
+ </ItemGroup>
+
+</Project>
diff --git a/lib/Net.Compression/readme.md b/lib/Net.Compression/readme.md
index d0074ab..e5d60e5 100644
--- a/lib/Net.Compression/readme.md
+++ b/lib/Net.Compression/readme.md
@@ -6,7 +6,7 @@ The native library relies on source code (which are statically compiled) for Bro
## Builds
-Debug build w/ symbols & xml docs, release builds, NuGet packages, and individually packaged source code are available on my website (link below). All tar-gzip (.tgz) files will have an associated .sha384 appended checksum of the desired download file.
+Debug build w/ symbols & xml docs, release builds, NuGet packages, and individually packaged source code are available on my website (link below).All tar-gzip (.tgz) files will have an associated checksum and PGP signature of the desired download file.
## Docs and Guides
Documentation, specifications, and setup guides are available on my website.
diff --git a/lib/Net.Rest.Client/src/VNLib.Net.Rest.Client.csproj b/lib/Net.Rest.Client/src/VNLib.Net.Rest.Client.csproj
index 552563b..d5ee1cf 100644
--- a/lib/Net.Rest.Client/src/VNLib.Net.Rest.Client.csproj
+++ b/lib/Net.Rest.Client/src/VNLib.Net.Rest.Client.csproj
@@ -16,7 +16,7 @@
<Authors>Vaughn Nugent</Authors>
<Copyright>Copyright © 2023 Vaughn Nugent</Copyright>
<Description>Provides a RestClient connection pool using the Utils.ObjectRental framework for reusing RestClients with a common configuration to execute RestRequests against. This library also implements an OAuth2 authenticator for the RestSharp IAuthenticator using the client credentials method.</Description>
- <PackageProjectUrl>https://www.vaughnnugent.com/resources/modules/VNLib.Core</PackageProjectUrl>
+ <PackageProjectUrl>https://www.vaughnnugent.com/resources/software/modules/VNLib.Core</PackageProjectUrl>
<RepositoryUrl>https://github.com/VnUgE/VNLib.Core/tree/main/lib/Net.Rest.Client</RepositoryUrl>
<PackageReadmeFile>README.md</PackageReadmeFile>
<PackageLicenseFile>LICENSE</PackageLicenseFile>
diff --git a/lib/Plugins.Essentials/src/Accounts/PasswordHashing.cs b/lib/Plugins.Essentials/src/Accounts/PasswordHashing.cs
index d80ee06..e6b9f24 100644
--- a/lib/Plugins.Essentials/src/Accounts/PasswordHashing.cs
+++ b/lib/Plugins.Essentials/src/Accounts/PasswordHashing.cs
@@ -184,7 +184,7 @@ namespace VNLib.Plugins.Essentials.Accounts
}
finally
{
- MemoryUtil.InitializeBlock(ref buffer.GetReference(),buffer.IntLength);
+ MemoryUtil.InitializeBlock(ref buffer.GetReference(), buffer.IntLength);
}
}
@@ -214,7 +214,7 @@ namespace VNLib.Plugins.Essentials.Accounts
}
finally
{
- MemoryUtil.InitializeBlock(buffer.Span);
+ MemoryUtil.InitializeBlock(ref buffer.GetReference(), buffer.IntLength);
}
}
@@ -242,7 +242,7 @@ namespace VNLib.Plugins.Essentials.Accounts
finally
{
//Erase secret buffer
- MemoryUtil.InitializeBlock(secretBuffer.Span);
+ MemoryUtil.InitializeBlock(ref secretBuffer.GetReference(), secretBuffer.IntLength);
}
}
@@ -265,7 +265,7 @@ namespace VNLib.Plugins.Essentials.Accounts
Argon2CostParams costParams = GetCostParams();
//Alloc heap buffer
- using UnsafeMemoryHandle<byte> buffer = MemoryUtil.UnsafeAllocNearestPage<byte>(minBufferSize, true);
+ using UnsafeMemoryHandle<byte> buffer = MemoryUtil.UnsafeAllocNearestPage(minBufferSize, true);
//Segment the buffer
HashBufferSegments segments = new(buffer.Span, _secret.BufferSize, _config.SaltLen, (int)_config.HashLen);
@@ -286,7 +286,7 @@ namespace VNLib.Plugins.Essentials.Accounts
}
finally
{
- MemoryUtil.InitializeBlock(buffer.Span);
+ MemoryUtil.InitializeBlock(ref buffer.GetReference(), buffer.IntLength);
}
}
diff --git a/lib/Plugins.Essentials/src/Extensions/EssentialHttpEventExtensions.cs b/lib/Plugins.Essentials/src/Extensions/EssentialHttpEventExtensions.cs
index b09924f..638b52a 100644
--- a/lib/Plugins.Essentials/src/Extensions/EssentialHttpEventExtensions.cs
+++ b/lib/Plugins.Essentials/src/Extensions/EssentialHttpEventExtensions.cs
@@ -908,7 +908,7 @@ namespace VNLib.Plugins.Essentials.Extensions
entity.Server.Headers[HttpResponseHeader.Connection] = "Upgrade";
//Hash accept string
- entity.Server.Headers["Sec-WebSocket-Accept"] = ManagedHash.ComputeBase64Hash($"{key.Trim()}{HttpHelpers.WebsocketRFC4122Guid}", HashAlg.SHA1);
+ entity.Server.Headers["Sec-WebSocket-Accept"] = ManagedHash.ComputeHash($"{key.Trim()}{HttpHelpers.WebsocketRFC4122Guid}", HashAlg.SHA1, HashEncodingMode.Base64);
//Protocol if user specified it
if (!string.IsNullOrWhiteSpace(subProtocol))
diff --git a/lib/Plugins.Essentials/src/Extensions/ICookieController.cs b/lib/Plugins.Essentials/src/Extensions/ICookieController.cs
index b88e648..e14f710 100644
--- a/lib/Plugins.Essentials/src/Extensions/ICookieController.cs
+++ b/lib/Plugins.Essentials/src/Extensions/ICookieController.cs
@@ -22,6 +22,8 @@
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
+using VNLib.Net.Http;
+
namespace VNLib.Plugins.Essentials.Extensions
{
/// <summary>
@@ -34,14 +36,14 @@ namespace VNLib.Plugins.Essentials.Extensions
/// </summary>
/// <param name="entity">The http connection to set the cookie value for</param>
/// <param name="value">The cookie value</param>
- void SetCookie(HttpEntity entity, string value);
+ void SetCookie(IHttpEvent entity, string value);
/// <summary>
/// Gets the cookie value for the given entity
/// </summary>
/// <param name="entity">The entity to get the cookie for</param>
/// <returns>The cookie value if set, null otherwise</returns>
- string? GetCookie(HttpEntity entity);
+ string? GetCookie(IHttpEvent entity);
/// <summary>
/// Expires an existing request cookie for the given entity, avoiding
@@ -49,6 +51,6 @@ namespace VNLib.Plugins.Essentials.Extensions
/// </summary>
/// <param name="entity">The http connection to expire the cookie on</param>
/// <param name="force">Forcibly set the response cookie regardless of it's existence</param>
- void ExpireCookie(HttpEntity entity, bool force);
+ void ExpireCookie(IHttpEvent entity, bool force);
}
} \ No newline at end of file
diff --git a/lib/Plugins.Essentials/src/Extensions/SingleCookieController.cs b/lib/Plugins.Essentials/src/Extensions/SingleCookieController.cs
index 1893b6e..74d23f7 100644
--- a/lib/Plugins.Essentials/src/Extensions/SingleCookieController.cs
+++ b/lib/Plugins.Essentials/src/Extensions/SingleCookieController.cs
@@ -32,22 +32,10 @@ namespace VNLib.Plugins.Essentials.Extensions
/// <summary>
/// Implements a sinlge cookie controller
/// </summary>
- public class SingleCookieController : ICookieController
+ /// <param name="Name">The name of the cookie to manage</param>
+ /// <param name="ValidFor">The max-age cookie value</param>
+ public record class SingleCookieController(string Name, TimeSpan ValidFor) : ICookieController
{
- private readonly string _cookieName;
- private readonly TimeSpan _validFor;
-
- /// <summary>
- /// Creates a new <see cref="SingleCookieController"/> instance
- /// </summary>
- /// <param name="cookieName">The name of the cookie to manage</param>
- /// <param name="validFor">The max-age cookie value</param>
- public SingleCookieController(string cookieName, TimeSpan validFor)
- {
- _cookieName = cookieName;
- _validFor = validFor;
- }
-
/// <summary>
/// The domain of the cookie
/// </summary>
@@ -78,40 +66,40 @@ namespace VNLib.Plugins.Essentials.Extensions
/// Optionally clears the cookie (does not force)
/// </summary>
/// <param name="entity">The entity to clear the cookie for</param>
- public void ExpireCookie(HttpEntity entity) => ExpireCookie(entity, false);
+ public void ExpireCookie(IHttpEvent entity) => ExpireCookie(entity, false);
///<inheritdoc/>
- public void ExpireCookie(HttpEntity entity, bool force)
+ public void ExpireCookie(IHttpEvent entity, bool force)
{
_ = entity ?? throw new ArgumentNullException(nameof(entity));
SetCookieInternal(entity, string.Empty, force);
}
///<inheritdoc/>
- public string? GetCookie(HttpEntity entity)
+ public string? GetCookie(IHttpEvent entity)
{
_ = entity ?? throw new ArgumentNullException(nameof(entity));
- return entity.Server.RequestCookies.GetValueOrDefault(_cookieName);
+ return entity.Server.RequestCookies.GetValueOrDefault(Name);
}
///<inheritdoc/>
- public void SetCookie(HttpEntity entity, string value)
+ public void SetCookie(IHttpEvent entity, string value)
{
_ = entity ?? throw new ArgumentNullException(nameof(entity));
SetCookieInternal(entity, value, true);
}
- private void SetCookieInternal(HttpEntity entity, string value, bool force)
+ private void SetCookieInternal(IHttpEvent entity, string value, bool force)
{
//Only set cooke if already exists or force is true
if (entity.Server.RequestCookies.ContainsKey(value) || force)
{
//Build and set cookie
- HttpCookie cookie = new(_cookieName, value)
+ HttpCookie cookie = new(Name, value)
{
Secure = Secure,
HttpOnly = HttpOnly,
- ValidFor = _validFor,
+ ValidFor = ValidFor,
SameSite = SameSite,
Path = Path,
Domain = Domain
diff --git a/lib/Plugins.Runtime/src/LoaderExtensions.cs b/lib/Plugins.Runtime/src/LoaderExtensions.cs
index c553f4b..2c3caf5 100644
--- a/lib/Plugins.Runtime/src/LoaderExtensions.cs
+++ b/lib/Plugins.Runtime/src/LoaderExtensions.cs
@@ -157,7 +157,7 @@ namespace VNLib.Plugins.Runtime
/// <exception cref="ArgumentNullException"></exception>
public static void InitializeAll(this IPluginStack runtime)
{
- _ = runtime ?? throw new ArgumentNullException(nameof(runtime));
+ ArgumentNullException.ThrowIfNull(runtime, nameof(runtime));
foreach(RuntimePluginLoader loader in runtime.Plugins)
{
@@ -173,7 +173,7 @@ namespace VNLib.Plugins.Runtime
/// <exception cref="AggregateException"></exception>
public static void InvokeLoad(this IPluginStack runtime)
{
- _ = runtime ?? throw new ArgumentNullException(nameof(runtime));
+ ArgumentNullException.ThrowIfNull(runtime, nameof(runtime));
//try loading all plugins
runtime.Plugins.TryForeach(static p => p.LoadPlugins());
@@ -216,7 +216,7 @@ namespace VNLib.Plugins.Runtime
/// <exception cref="AggregateException"></exception>
public static void ReloadAll(this IPluginStack runtime)
{
- _ = runtime ?? throw new ArgumentNullException(nameof(runtime));
+ ArgumentNullException.ThrowIfNull(runtime, nameof(runtime));
//try reloading all plugins
runtime.Plugins.TryForeach(static p => p.ReloadPlugins());
@@ -231,8 +231,8 @@ namespace VNLib.Plugins.Runtime
/// <exception cref="ArgumentNullException"></exception>
public static void RegsiterListener(this IPluginStack runtime, IPluginEventListener listener, object? state = null)
{
- _ = runtime ?? throw new ArgumentNullException(nameof(runtime));
- _ = listener ?? throw new ArgumentNullException(nameof(listener));
+ ArgumentNullException.ThrowIfNull(runtime, nameof(runtime));
+ ArgumentNullException.ThrowIfNull(listener, nameof(listener));
//Register for all plugins
foreach (PluginController controller in runtime.Plugins.Select(static p => p.Controller))
@@ -249,8 +249,8 @@ namespace VNLib.Plugins.Runtime
/// <exception cref="ArgumentNullException"></exception>
public static void UnregsiterListener(this IPluginStack runtime, IPluginEventListener listener)
{
- _ = runtime ?? throw new ArgumentNullException(nameof(runtime));
- _ = listener ?? throw new ArgumentNullException(nameof(listener));
+ ArgumentNullException.ThrowIfNull(runtime, nameof(runtime));
+ ArgumentNullException.ThrowIfNull(listener, nameof(listener));
//Unregister for all plugins
foreach (PluginController controller in runtime.Plugins.Select(static p => p.Controller))
@@ -268,7 +268,7 @@ namespace VNLib.Plugins.Runtime
/// <returns>The current builder instance for chaining</returns>
public static PluginStackBuilder WithLocalJsonConfig(this PluginStackBuilder builder, in JsonElement? hostConfig)
{
- _ = builder ?? throw new ArgumentNullException(nameof(builder));
+ ArgumentNullException.ThrowIfNull(builder, nameof(builder));
LocalFilePluginConfigReader reader;
@@ -297,6 +297,19 @@ namespace VNLib.Plugins.Runtime
}
/// <summary>
+ /// Sets an empty/null configuration reader for the plugin stack. No
+ /// configuration will be passed to plugins.
+ /// </summary>
+ /// <param name="builder"></param>
+ /// <returns>The current builder instance for chaining</returns>
+ /// <exception cref="ArgumentNullException"></exception>
+ public static PluginStackBuilder WithNullConfig(this PluginStackBuilder builder)
+ {
+ ArgumentNullException.ThrowIfNull(builder, nameof(builder));
+ return builder.WithConfigurationReader(new NullPluginConfigReader());
+ }
+
+ /// <summary>
/// Specifies the directory that the plugin loader will search for plugins in
/// </summary>
/// <param name="path">The search directory path</param>
@@ -314,8 +327,8 @@ namespace VNLib.Plugins.Runtime
/// <exception cref="ArgumentNullException"></exception>
public static PluginStackBuilder WithSearchDirectory(this PluginStackBuilder builder, DirectoryInfo dir)
{
- _ = builder ?? throw new ArgumentNullException(nameof(builder));
- _ = dir ?? throw new ArgumentNullException(nameof(dir));
+ ArgumentNullException.ThrowIfNull(builder, nameof(builder));
+ ArgumentNullException.ThrowIfNull(dir, nameof(dir));
PluginDirectorySearcher dirSearcher = new (dir);
builder.WithDiscoveryManager(dirSearcher);
@@ -415,5 +428,14 @@ namespace VNLib.Plugins.Runtime
}
}
}
+
+ private sealed class NullPluginConfigReader : IPluginConfigReader
+ {
+ ///<inheritdoc/>
+ public void ReadPluginConfigData(IPluginAssemblyLoadConfig asmConfig, Stream outputStream)
+ {
+ //Do nothing
+ }
+ }
}
}
diff --git a/lib/Plugins.Runtime/src/RuntimePluginLoader.cs b/lib/Plugins.Runtime/src/RuntimePluginLoader.cs
index a1231c9..cef4d47 100644
--- a/lib/Plugins.Runtime/src/RuntimePluginLoader.cs
+++ b/lib/Plugins.Runtime/src/RuntimePluginLoader.cs
@@ -57,7 +57,6 @@ namespace VNLib.Plugins.Runtime
/// Creates a new <see cref="RuntimePluginLoader"/> with the specified config and host config dom.
/// </summary>
/// <param name="loader">The plugin's assembly loader</param>
- /// <param name="hostConfig">The host/process configuration DOM</param>
/// <param name="log">A log provider to write plugin unload log events to</param>
/// <exception cref="ArgumentNullException"></exception>
public RuntimePluginLoader(IPluginAssemblyLoader loader, ILogProvider? log)
diff --git a/lib/Utils.Cryptography/argon2/Taskfile.yaml b/lib/Utils.Cryptography/argon2/Taskfile.yaml
index 48c3d6c..a2f43b3 100644
--- a/lib/Utils.Cryptography/argon2/Taskfile.yaml
+++ b/lib/Utils.Cryptography/argon2/Taskfile.yaml
@@ -53,19 +53,19 @@ tasks:
postbuild_success:
vars:
#required files to include in tar
- TAR_FILES: "license.txt readme.txt"
+ TAR_FILES: "license.txt readme.txt argon2.h"
cmds:
#make bin dir
- cmd: powershell -Command "New-Item -Type Directory -Force -Path './bin'"
ignore_error: true
- #get licenses for debug
- - task: licenses
+ #add embeded resources to output dirs
+ - task: embed
vars:
TARGET: './build/Debug'
- - task: licenses
+ - task: embed
vars:
TARGET: './build/Release'
@@ -83,12 +83,14 @@ tasks:
#source code
- task: pack_source
- licenses:
+ embed:
cmds:
#add license file
- powershell -Command "Copy-Item -Path ./license -Destination '{{.TARGET}}/license.txt'"
#add readme file
- powershell -Command "Copy-Item -Path ./build.readme.txt -Destination '{{.TARGET}}/readme.txt'"
+ #add argon2 header file
+ - powershell -Command "Copy-Item -Path ./include/argon2.h -Destination '{{.TARGET}}/argon2.h'"
pack_source:
dir: '{{.USER_WORKING_DIR}}'
diff --git a/lib/Utils.Cryptography/monocypher/CMakeLists.txt b/lib/Utils.Cryptography/monocypher/CMakeLists.txt
new file mode 100644
index 0000000..9b17ea7
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/CMakeLists.txt
@@ -0,0 +1,105 @@
+cmake_minimum_required(VERSION 3.0)
+
+project(vnlib_monocypher C)
+
+#export header files to the main project
+file(GLOB HEADERS *.h)
+list(APPEND HEADERS vendor/src/monocypher.h)
+
+#Add indepednent source files to the project
+set(VNLIB_MONOCYPHER_SOURCES
+ "vnlib_monocypher.c"
+ "argon2.c"
+ "blake2b.c"
+ "vendor/src/monocypher.c"
+)
+
+#add monocypher includes, there will only be one library
+include_directories(vendor/src)
+
+
+#create my shared library
+add_library(${CMAKE_PROJECT_NAME} SHARED ${VNLIB_MONOCYPHER_SOURCES} ${HEADERS})
+#also create static library
+add_library(${CMAKE_PROJECT_NAME}_static STATIC ${VNLIB_MONOCYPHER_SOURCES} ${HEADERS})
+
+#if on unix lib will be appended, so we can adjust
+if(UNIX)
+ set_target_properties(${CMAKE_PROJECT_NAME} ${CMAKE_PROJECT_NAME}_static PROPERTIES OUTPUT_NAME _vnmonocypher)
+endif()
+
+#Setup the compiler options
+set(CMAKE_C_STANDARD 90)
+set(CMAKE_C_STANDARD_REQUIRED ON)
+
+#enable position independent code (for shared libraries with exports)
+set(CMAKE_POSITION_INDEPENDENT_CODE ON)
+
+message(STATUS "Build type is '${CMAKE_BUILD_TYPE}'")
+
+#if debug
+add_compile_definitions($<$<CONFIG:Debug>:DEBUG>)
+
+
+#setup flags for windows compilation
+if(MSVC)
+
+ #global windows cl flags
+ add_compile_options(
+ /Qspectre
+ /sdl
+ /TC
+ /GS
+ /machine:x64
+
+ $<$<CONFIG:Debug>:/FC>
+ $<$<CONFIG:Debug>:/showIncludes>
+ )
+
+ #only target our project
+ target_compile_options(
+ ${CMAKE_PROJECT_NAME}
+ PRIVATE
+
+ #disable warnings for struct padding and spectre mitigation wuen WX is enabled
+ $<$<CONFIG:Debug>:/wd5045>
+ $<$<CONFIG:Debug>:/wd4820>
+ $<$<CONFIG:Debug>:/wd4574>
+
+ #for debug configs
+ $<$<CONFIG:Debug>:/options:strict>
+ #disable warnings for struct padding and spectre mitigation wuen WX is enabled
+ $<$<CONFIG:Debug>:/Wall>
+ $<$<CONFIG:Debug>:/WX> #warnings as errors (only for our project)
+ $<$<CONFIG:Debug>:/Zi>
+ $<$<CONFIG:Debug>:/Zo>
+ )
+
+ #set build macros
+ add_compile_definitions(
+ $<$<CONFIG:DEBUG>:DEBUG>
+ $<$<CONFIG:RELEASE>:RELEASE>
+ )
+
+#configure gcc flags
+elseif(CMAKE_COMPILER_IS_GNUCC)
+
+ add_compile_options(
+ -Wextra
+ -fstack-protector
+
+ $<$<CONFIG:Debug>:-g>
+ $<$<CONFIG:Debug>:-Og>
+ $<$<CONFIG:Debug>:-Wall>
+ $<$<CONFIG:Debug>:-Werror>
+ )
+
+ #only target our project
+ target_compile_options(
+ ${CMAKE_PROJECT_NAME}
+ PRIVATE
+ $<$<CONFIG:Debug>:-Wall>
+ $<$<CONFIG:Debug>:-pedantic>
+ )
+
+endif() \ No newline at end of file
diff --git a/lib/Utils.Cryptography/monocypher/LICENSE b/lib/Utils.Cryptography/monocypher/LICENSE
new file mode 100644
index 0000000..ce09686
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/LICENSE
@@ -0,0 +1,293 @@
+Copyright (c) 2023 Vaughn Nugent
+
+Contact information
+ Name: Vaughn Nugent
+ Email: vnpublic[at]proton.me
+ Website: https://www.vaughnnugent.com
+
+The software in this repository is licensed under the GNU GPL version 2.0 (or any later version).
+
+SPDX-License-Identifier: GPL-2.0-or-later
+
+License-Text:
+
+GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS \ No newline at end of file
diff --git a/lib/Utils.Cryptography/monocypher/Taskfile.yaml b/lib/Utils.Cryptography/monocypher/Taskfile.yaml
new file mode 100644
index 0000000..64a4461
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/Taskfile.yaml
@@ -0,0 +1,105 @@
+# https://taskfile.dev
+
+#Called by the vnbuild system to produce builds for my website
+#https://www.vaughnnugent.com/resources/software
+
+#This taskfile is called in this directory and is specific to the vnlib_monocypher project
+#that handles the MSBuild outside of the solution file
+
+version: '3'
+
+vars:
+ MS_ARGS: '/p:Platform=x64 /p:RunAnalyzersDuringBuild=false /p:BuildInParallel=true /p:MultiProcessorCompilation=true'
+ PROJECT_NAME: 'vnlib_monocypher'
+ MODULE_NAME: 'vnlib.core'
+
+tasks:
+
+ default:
+ desc: "Builds the entire project from source code without using the VNBuild build system for target machines"
+ cmds:
+ #build with defaults
+ - task: build
+ - cmd: echo "Your vnlib_monocypher dll file can be found in '{{.USER_WORKING_DIR}}/build'"
+ silent: true
+
+ build:
+ cmds:
+ #init cmake build
+ - cmake -B./build
+
+ #build the monocypher library in debug mode first
+ - task: build-monocypher-win
+ - task: build-monocypher-gnumake
+
+ #build using msbuild for monocypher libraries for debug and release modes
+ build-monocypher-win:
+ platforms: ['windows']
+ internal: true
+ cmds:
+ #build solution in debug mode
+ - cd build && msbuild {{.PROJECT_NAME}}.sln /p:Configuration=debug {{.BUILD_FLAGS}} {{.MS_ARGS}}
+ #build in release
+ - cd build && msbuild {{.PROJECT_NAME}}.sln /p:Configuration=release {{.BUILD_FLAGS}} {{.MS_ARGS}}
+
+ #build using gnu make
+ build-monocypher-gnumake:
+ platforms: ['linux']
+ internal: true
+ cmds:
+ #build project with make
+ - cd build && make
+
+ postbuild_success:
+ vars:
+ #required files to include in tar
+ TAR_FILES: "license.txt readme.txt"
+
+ cmds:
+ #make bin dir
+ - cmd: powershell -Command "New-Item -Type Directory -Force -Path './bin'"
+ ignore_error: true
+
+ #get licenses for debug
+ - task: licenses
+ vars:
+ TARGET: './build/Debug'
+
+ - task: licenses
+ vars:
+ TARGET: './build/Release'
+
+
+ #static debug lib
+ - cd build/Debug && tar -czf '../../bin/win-x64-debug-{{.PROJECT_NAME}}-static.tgz' {{.PROJECT_NAME}}_static.lib {{.TAR_FILES}} {{.PROJECT_NAME}}_static.pdb
+ #dynamic debug lib
+ - cd build/Debug && tar -czf '../../bin/win-x64-debug-{{.PROJECT_NAME}}.tgz' {{.PROJECT_NAME}}.dll {{.TAR_FILES}} {{.PROJECT_NAME}}.pdb
+
+ #release static lib
+ - cd build/Release && tar -czf '../../bin/win-x64-release-{{.PROJECT_NAME}}-static.tgz' {{.PROJECT_NAME}}_static.lib {{.TAR_FILES}}
+ #release dll
+ - cd build/Release && tar -czf '../../bin/win-x64-release-{{.PROJECT_NAME}}.tgz' {{.PROJECT_NAME}}.dll {{.TAR_FILES}}
+
+ #source code
+ - task: pack_source
+
+ licenses:
+ cmds:
+ #add monocypher license to binary output (wrong on purpose see source code)
+ - powershell -Command "Copy-Item -Path vendor/LICENCE.md -Destination '{{.TARGET}}/license.md'"
+ #add my license file
+ - powershell -Command "Copy-Item -Path license -Destination '{{.TARGET}}/license.txt'"
+ #add readme file
+ - powershell -Command "Copy-Item -Path build.readme.txt -Destination '{{.TARGET}}/readme.txt'"
+
+ pack_source:
+ dir: '{{.USER_WORKING_DIR}}'
+ cmds:
+ #pack monocypher source code and create the archive
+ - powershell -Command "tar --exclude build/* --exclude bin/* --exclude .git/* -cvf 'bin/src.tar' ."
+
+ clean:
+ ignore_error: true
+ cmds:
+ - cmd: powershell -Command "Remove-Item -Recurse './bin'"
+ - cmd: powershell -Command "Remove-Item -Recurse './build'" \ No newline at end of file
diff --git a/lib/Utils.Cryptography/monocypher/argon2.c b/lib/Utils.Cryptography/monocypher/argon2.c
new file mode 100644
index 0000000..9b13ce0
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/argon2.c
@@ -0,0 +1,102 @@
+/*
+* Copyright (c) 2023 Vaughn Nugent
+*
+* vnlib_monocypher is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published
+* by the Free Software Foundation, either version 2 of the License,
+* or (at your option) any later version.
+*
+* vnlib_monocypher is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with vnlib_monocypher. If not, see http://www.gnu.org/licenses/.
+*/
+
+#include "argon2.h"
+#include <monocypher.h>
+
+VNLIB_EXPORT uint32_t VNLIB_CC Argon2CalcWorkAreaSize(const argon2Ctx* context)
+{
+ return context->m_cost * 1024;
+}
+
+/*
+* The purpose of this function is to remap the Argon2 context/function call
+* interface to the Monocypher library version. Also performing some basic
+* input validation that also matches the Argon2 library.
+*/
+
+VNLIB_EXPORT argon2_error_codes VNLIB_CC Argon2ComputeHash(const argon2Ctx* context, void* workArea)
+{
+ crypto_argon2_config config;
+ crypto_argon2_inputs inputs;
+ crypto_argon2_extras extras;
+
+ if (!context || !workArea)
+ {
+ return ERR_INVALID_PTR;
+ }
+
+ config.algorithm = context->version;
+ config.nb_blocks = context->m_cost;
+ config.nb_passes = context->t_cost;
+ config.nb_lanes = context->threads;
+
+ inputs.pass_size = context->pwdlen;
+ inputs.pass = context->pwd;
+
+ inputs.salt_size = context->saltlen;
+ inputs.salt = context->salt;
+
+ /* must specify a password input */
+ if (inputs.pass_size < 1)
+ {
+ return ARGON2_PWD_TOO_SHORT;
+ }
+
+ if (!inputs.pass)
+ {
+ return ARGON2_PWD_PTR_MISMATCH;
+ }
+
+ if (inputs.salt_size < 1)
+ {
+ return ARGON2_SALT_TOO_SHORT;
+ }
+
+ /* Verify salt pointer 1is not invalid */
+ if (!inputs.salt)
+ {
+ return ARGON2_SALT_PTR_MISMATCH;
+ }
+
+ extras.ad = context->ad;
+ extras.ad_size = context->adlen;
+
+ extras.key = context->secret;
+ extras.key_size = context->secretlen;
+
+ //If key is set, verify a valid pointer
+ if (extras.key_size > 0 && !extras.key)
+ {
+ return ARGON2_SECRET_PTR_MISMATCH;
+ }
+
+ if (context->outlen < 1)
+ {
+ return ARGON2_OUTPUT_TOO_SHORT;
+ }
+
+ if (!context->out)
+ {
+ return ARGON2_OUTPUT_PTR_NULL;
+ }
+
+ /* invoke lib function */
+ crypto_argon2(context->out, context->outlen, workArea, config, inputs, extras);
+
+ return ARGON2_OK;
+} \ No newline at end of file
diff --git a/lib/Utils.Cryptography/monocypher/argon2.h b/lib/Utils.Cryptography/monocypher/argon2.h
new file mode 100644
index 0000000..700e582
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/argon2.h
@@ -0,0 +1,135 @@
+/*
+* Copyright (c) 2023 Vaughn Nugent
+*
+* vnlib_monocypher is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published
+* by the Free Software Foundation, either version 2 of the License,
+* or (at your option) any later version.
+*
+* vnlib_monocypher is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with vnlib_monocypher. If not, see http://www.gnu.org/licenses/.
+*/
+
+
+#ifndef VN_MONOCYPHER_ARGON2_H
+#define VN_MONOCYPHER_ARGON2_H
+
+#include <stdint.h>
+#include "util.h"
+
+/*
+ The following types are 1:1 with the Argon2 reference library,
+ this allows for a common api interface between the two libraries for
+ dynamic linking
+*/
+
+typedef enum Argon2Type
+{
+ Argon2_d = 0,
+ Argon2_i = 1,
+ Argon2_id = 2
+
+} Argon2Type;
+
+/* Error codes */
+typedef enum Argon2_ErrorCodes {
+ ARGON2_OK = 0,
+
+ ARGON2_OUTPUT_PTR_NULL = -1,
+
+ ARGON2_OUTPUT_TOO_SHORT = -2,
+ ARGON2_OUTPUT_TOO_LONG = -3,
+
+ ARGON2_PWD_TOO_SHORT = -4,
+ ARGON2_PWD_TOO_LONG = -5,
+
+ ARGON2_SALT_TOO_SHORT = -6,
+ ARGON2_SALT_TOO_LONG = -7,
+
+ ARGON2_AD_TOO_SHORT = -8,
+ ARGON2_AD_TOO_LONG = -9,
+
+ ARGON2_SECRET_TOO_SHORT = -10,
+ ARGON2_SECRET_TOO_LONG = -11,
+
+ ARGON2_TIME_TOO_SMALL = -12,
+ ARGON2_TIME_TOO_LARGE = -13,
+
+ ARGON2_MEMORY_TOO_LITTLE = -14,
+ ARGON2_MEMORY_TOO_MUCH = -15,
+
+ ARGON2_LANES_TOO_FEW = -16,
+ ARGON2_LANES_TOO_MANY = -17,
+
+ ARGON2_PWD_PTR_MISMATCH = -18, /* NULL ptr with non-zero length */
+ ARGON2_SALT_PTR_MISMATCH = -19, /* NULL ptr with non-zero length */
+ ARGON2_SECRET_PTR_MISMATCH = -20, /* NULL ptr with non-zero length */
+ ARGON2_AD_PTR_MISMATCH = -21, /* NULL ptr with non-zero length */
+
+ ARGON2_MEMORY_ALLOCATION_ERROR = -22,
+
+ ARGON2_FREE_MEMORY_CBK_NULL = -23,
+ ARGON2_ALLOCATE_MEMORY_CBK_NULL = -24,
+
+ ARGON2_INCORRECT_PARAMETER = -25,
+ ARGON2_INCORRECT_TYPE = -26,
+
+ ARGON2_OUT_PTR_MISMATCH = -27,
+
+ ARGON2_THREADS_TOO_FEW = -28,
+ ARGON2_THREADS_TOO_MANY = -29,
+
+ ARGON2_MISSING_ARGS = -30,
+
+ ARGON2_ENCODING_FAIL = -31,
+
+ ARGON2_DECODING_FAIL = -32,
+
+ ARGON2_THREAD_FAIL = -33,
+
+ ARGON2_DECODING_LENGTH_FAIL = -34,
+
+ ARGON2_VERIFY_MISMATCH = -35
+} argon2_error_codes;
+
+typedef struct Argon2_Context {
+
+ uint8_t* out; /* output array */
+ const uint32_t outlen; /* digest length */
+
+ const uint8_t* pwd; /* password array */
+ const uint32_t pwdlen; /* password length */
+
+ const uint8_t* salt; /* salt array */
+ const uint32_t saltlen; /* salt length */
+
+ const uint8_t* secret; /* key array */
+ const uint32_t secretlen; /* key length */
+
+ const uint8_t* ad; /* associated data array */
+ const uint32_t adlen; /* associated data length */
+
+ const uint32_t t_cost; /* number of passes */
+ const uint32_t m_cost; /* amount of memory requested (KB) */
+ const uint32_t lanes; /* number of lanes */
+ const uint32_t threads; /* maximum number of threads */
+
+ const Argon2Type version; /* version number */
+
+ const void* allocate_cbk; /* pointer to memory allocator */
+ const void* free_cbk; /* pointer to memory deallocator */
+
+ const uint32_t flags; /* array of bool options */
+} argon2Ctx;
+
+
+VNLIB_EXPORT uint32_t VNLIB_CC Argon2CalcWorkAreaSize(const argon2Ctx* context);
+
+VNLIB_EXPORT argon2_error_codes VNLIB_CC Argon2ComputeHash(const argon2Ctx* context, void* workArea);
+
+#endif /* VN_MONOCYPHER_ARGON2_H */ \ No newline at end of file
diff --git a/lib/Utils.Cryptography/monocypher/blake2b.c b/lib/Utils.Cryptography/monocypher/blake2b.c
new file mode 100644
index 0000000..3d9a1d1
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/blake2b.c
@@ -0,0 +1,90 @@
+/*
+* Copyright (c) 2023 Vaughn Nugent
+*
+* vnlib_monocypher is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published
+* by the Free Software Foundation, either version 2 of the License,
+* or (at your option) any later version.
+*
+* vnlib_monocypher is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with vnlib_monocypher. If not, see http://www.gnu.org/licenses/.
+*/
+
+#include <stdlib.h>
+#include <monocypher.h>
+#include "blake2b.h"
+
+VNLIB_EXPORT uint32_t VNLIB_CC Blake2GetContextSize(void)
+{
+ return sizeof(crypto_blake2b_ctx);
+}
+
+VNLIB_EXPORT int32_t VNLIB_CC Blake2Init(void* context, uint32_t hashlen, const void* key, uint32_t keylen)
+{
+ crypto_blake2b_ctx* ctx;
+ ctx = (crypto_blake2b_ctx*)context;
+
+ VALIDATE_PTR(ctx);
+
+ /* validate key pointer if set */
+ if (keylen > 0 && !key)
+ {
+ return ERR_KEY_PTR_INVALID;
+ }
+
+ if (keylen > MC_MAX_KEY_SIZE)
+ {
+ return ERR_KEY_LEN_INVALID;
+ }
+
+ /* validate hash length */
+ if (hashlen > MC_MAX_HASH_SIZE)
+ {
+ return ERR_HASH_LEN_INVALID;
+ }
+
+ /* initialize context, non-keyed just calls the keyed funciton */
+ crypto_blake2b_keyed_init(ctx, hashlen, key, keylen);
+
+ return BLAKE2B_RESULT_SUCCESS;
+}
+
+VNLIB_EXPORT int32_t VNLIB_CC Blake2Update(void* context, const void* data, uint32_t datalen)
+{
+ crypto_blake2b_ctx* ctx;
+ ctx = (crypto_blake2b_ctx*)context;
+ VALIDATE_PTR(ctx);
+ VALIDATE_PTR(data);
+
+ crypto_blake2b_update(ctx, data, datalen);
+ return BLAKE2B_RESULT_SUCCESS;
+}
+
+VNLIB_EXPORT int32_t VNLIB_CC Blake2Final(void* context, void* hash, uint32_t hashlen)
+{
+ crypto_blake2b_ctx* ctx;
+ ctx = (crypto_blake2b_ctx*)context;
+ VALIDATE_PTR(ctx);
+ VALIDATE_PTR(hash);
+
+ /* validate hash length */
+ if (hashlen != ctx->hash_size)
+ {
+ return ERR_HASH_LEN_INVALID;
+ }
+ crypto_blake2b_final(ctx, hash);
+ return BLAKE2B_RESULT_SUCCESS;
+}
+
+VNLIB_EXPORT int32_t VNLIB_CC Blake2GetHashSize(void* context)
+{
+ crypto_blake2b_ctx* ctx;
+ ctx = (crypto_blake2b_ctx*)context;
+ VALIDATE_PTR(ctx);
+ return (int32_t)ctx->hash_size;
+}
diff --git a/lib/Utils.Cryptography/monocypher/blake2b.h b/lib/Utils.Cryptography/monocypher/blake2b.h
new file mode 100644
index 0000000..4167aca
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/blake2b.h
@@ -0,0 +1,43 @@
+/*
+* Copyright (c) 2023 Vaughn Nugent
+*
+* vnlib_monocypher is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published
+* by the Free Software Foundation, either version 2 of the License,
+* or (at your option) any later version.
+*
+* vnlib_monocypher is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with vnlib_monocypher. If not, see http://www.gnu.org/licenses/.
+*/
+
+#pragma once
+#ifndef VN_MONOCYPHER_BLAKE2_H
+
+#include <stdint.h>
+#include "util.h"
+
+#define ERR_HASH_LEN_INVALID -16
+#define ERR_KEY_LEN_INVALID -17
+#define ERR_KEY_PTR_INVALID -18
+
+#define MC_MAX_HASH_SIZE 64
+#define MC_MAX_KEY_SIZE 64
+
+#define BLAKE2B_RESULT_SUCCESS 0
+
+VNLIB_EXPORT uint32_t VNLIB_CC Blake2GetContextSize(void);
+
+VNLIB_EXPORT int32_t VNLIB_CC Blake2Init(void* context, uint32_t hashlen, const void* key, uint32_t keylen);
+
+VNLIB_EXPORT int32_t VNLIB_CC Blake2Update(void* context, const void* data, uint32_t datalen);
+
+VNLIB_EXPORT int32_t VNLIB_CC Blake2Final(void* context, void* hash, uint32_t hashlen);
+
+VNLIB_EXPORT int32_t VNLIB_CC Blake2GetHashSize(void* context);
+
+#endif
diff --git a/lib/Utils.Cryptography/monocypher/build.readme.txt b/lib/Utils.Cryptography/monocypher/build.readme.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/build.readme.txt
diff --git a/lib/Utils.Cryptography/monocypher/package.json b/lib/Utils.Cryptography/monocypher/package.json
new file mode 100644
index 0000000..2ce626d
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/package.json
@@ -0,0 +1,10 @@
+{
+ "name": "vnlib_monocypher",
+ "version": "0.1.0",
+ "output_dir": "bin",
+ "author": "Vaughn Nugent",
+ "description": "Integrates the MonoCypher native library into a wrapper utility library for usage in VNLib.Hashing.Portable for Blake2, Argon2 and more coming",
+ "copyright": "Copyright \u00A9 2023 Vaughn Nugent",
+ "company": "Vaughn Nugent",
+ "repository": "https://github.com/VnUgE/VNLib.Core/tree/main/lib/Utils.Cryptography/monocypher"
+} \ No newline at end of file
diff --git a/lib/Utils.Cryptography/monocypher/readme.md b/lib/Utils.Cryptography/monocypher/readme.md
new file mode 100644
index 0000000..940c95f
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/readme.md
@@ -0,0 +1,17 @@
+# VNLib.Utils.Cryptography
+Contains vendored packages that are (optionally)used with VNLib applications such as Argon2 and MonoCypher, as well as build files for compiling the projects cross-platform using CMake and Taskfile.dev.
+
+Pre-build Windows binaries are available on my website (link below).
+Source code blobs are also packaged and ready for building. See the docs link below for building instructions.
+
+## Builds
+Debug build w/ symbols & xml docs, release builds, NuGet packages, and individually packaged source code are available on my website (link below). All tar-gzip (.tgz) files will have an associated checksum and PGP signature of the desired download file.
+
+## Docs and Guides
+Documentation, specifications, and setup guides are available on my website.
+
+[Docs and Articles](https://www.vaughnnugent.com/resources/software/articles?tags=docs,_vnlib.utils.cryptography)
+[Builds and Source](https://www.vaughnnugent.com/resources/software/modules/VNLib.Core)
+
+## License
+Code is individually licensed. See the `LICENSE` file in each subdirectory for more information. \ No newline at end of file
diff --git a/lib/Utils.Cryptography/monocypher/util.h b/lib/Utils.Cryptography/monocypher/util.h
new file mode 100644
index 0000000..68b3e51
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/util.h
@@ -0,0 +1,77 @@
+/*
+* Copyright (c) 2023 Vaughn Nugent
+*
+* vnlib_monocypher is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published
+* by the Free Software Foundation, either version 2 of the License,
+* or (at your option) any later version.
+*
+* vnlib_monocypher is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with vnlib_monocypher. If not, see http://www.gnu.org/licenses/.
+*/
+
+#pragma once
+#ifndef VN_MONOCYPHER_UTIL_H
+
+#if defined(__GNUC__)
+ #define inline __inline__
+ #define VNLIB_EXPORT __attribute__((visibility("default")))
+ #define VNLIB_CC
+#elif defined(_MSC_VER)
+ #define VNLIB_EXPORT __declspec(dllexport)
+ #define VNLIB_CC __cdecl
+#endif /* WIN32 */
+
+#ifdef USE_MEM_UTIL
+
+ /* Include stdlib for malloc */
+ #include <stdlib.h>
+
+ /* If a custom allocator is not defined, set macros for built-in function */
+ #ifndef CUSTOM_ALLOCATOR
+
+ /* malloc and friends fallback if not defined */
+ #define vnmalloc(size) malloc(size)
+ #define vncalloc(count, size) calloc(count, size)
+ #define vnrealloc(ptr, size) realloc(ptr, size)
+ #define vnfree(ptr) free(ptr)
+
+ #endif /* !CUSTOM_ALLOCATOR */
+
+ #ifdef WIN32
+
+ /* required for memove on windows */
+ #include <memory.h>
+
+ #define _memmove(dst, src, size) memmove_s(dst, size, src, size)
+ #else
+ /* use string.h posix on non-win platforms */
+ #include <string.h>
+
+ #define _memmove memmove
+ #endif /* WIN32 */
+
+#endif // USE_MEM_UTIL
+
+#ifndef _In_
+#define _In_
+#endif
+
+#define ERR_INVALID_PTR -1
+#define ERR_OUT_OF_MEMORY -2
+
+#define TRUE 1
+#define FALSE 0
+
+#ifndef NULL
+#define NULL 0
+#endif /* !NULL */
+
+#define VALIDATE_PTR(ptr) if (!ptr) return ERR_INVALID_PTR
+
+#endif /* !VN_MONOCYPHER_UTIL_H */ \ No newline at end of file
diff --git a/lib/Utils.Cryptography/monocypher/vendor/.editorconfig b/lib/Utils.Cryptography/monocypher/vendor/.editorconfig
new file mode 100644
index 0000000..b791d00
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/.editorconfig
@@ -0,0 +1,16 @@
+# https://EditorConfig.org
+
+root = true
+
+# UNIX style line ending rulez
+# End all files with a single line ending OCD
+[*]
+end_of_line = lf
+insert_final_newline = true
+
+# Tabs for indentation for accessibility reasons.
+# Indent size of 4 because that's my preference.
+# Note: line lengths limits (80 columns) assume tabs are 4 columns wide.
+[*.{c,h}]
+indent_style = tab
+indent_size = 4
diff --git a/lib/Utils.Cryptography/monocypher/vendor/.gitignore b/lib/Utils.Cryptography/monocypher/vendor/.gitignore
new file mode 100644
index 0000000..2a1e6fe
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/.gitignore
@@ -0,0 +1,29 @@
+*~
+*.o
+*.a
+*.so
+*.so.*
+*.out
+*.vec
+*.gch
+*.sav
+*.profraw
+*.profdata
+*.creator
+*.creator.*
+*.config
+*.cflags
+*.cxxflags
+*.files
+*.includes
+*.su
+*.su.*
+*.gen.*
+tests/formal-analysis/*
+tests/formal-analysis
+*.tar.gz
+monocypher-*/
+**/__pycache__/**
+doc/html/
+doc/man3/
+tests/vectors.h
diff --git a/lib/Utils.Cryptography/monocypher/vendor/AUTHORS.md b/lib/Utils.Cryptography/monocypher/vendor/AUTHORS.md
new file mode 100644
index 0000000..65e2c01
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/AUTHORS.md
@@ -0,0 +1,63 @@
+Designers
+---------
+
+- **ChaCha20:** Daniel J. Bernstein.
+- **Poly1305:** Daniel J. Bernstein.
+- **BLAKE2:** Jean-Philippe Aumasson, Christian Winnerlein, Samuel Neves,
+ and Zooko Wilcox-O'Hearn.
+- **Argon2:** Alex Biryukov, Daniel Dinu, and Dmitry Khovratovich.
+- **X25519:** Daniel J. Bernstein.
+- **EdDSA:** Daniel J. Bernstein, Bo-Yin Yang, Niels Duif, Peter
+ Schwabe, and Tanja Lange.
+
+Implementors
+------------
+
+- **ChaCha20:** Loup Vaillant, implemented from spec.
+- **Poly1305:** Loup Vaillant, implemented from spec.
+- **BLAKE2b:** Loup Vaillant, implemented from spec.
+- **Argon2i:** Loup Vaillant, implemented from spec.
+- **X25519:** Daniel J. Bernstein, taken and packaged from SUPERCOP
+ ref10.
+- **EdDSA:** Loup Vaillant, with bits and pieces from SUPERCOP ref10.
+
+Test suite
+----------
+
+Designed and implemented by Loup Vaillant, using _libsodium_ (by many
+authors), and _ed25519-donna_ (by Andrew Moon —floodyberry).
+
+Manual
+------
+
+Loup Vaillant, Fabio Scotoni, and Michael Savage.
+
+- Loup Vaillant did a first draft.
+- Fabio Scotoni rewrote the manual into proper man pages (and
+ substantially changed it in the process).
+- Michael Savage did extensive editing and proofreading.
+
+Thanks
+------
+
+Fabio Scotoni provided much needed advice about testing, interface,
+packaging, and the general direction of the whole project. He also
+redesigned the monocypher.org style sheets.
+
+Mike Pechkin and André Maroneze found bugs in earlier versions of
+Monocypher.
+
+Andrew Moon clarified carry propagation in modular arithmetic, and
+provided advice and code that significantly simplified and improved
+Elligator2 mappings.
+
+Mike Hamburg explained comb algorithms, including the signed
+all-bits-set comb described in his 2012 paper, Fast and compact
+elliptic-curve cryptography. This made EdDSA signatures over twice as
+fast.
+
+Samuel Lucas found many typos in both the manual and the website.
+
+Jens Alfke added some #ifdefs that enabled Monocypher to compile into
+a C++ namespace, preventing symbol collisions with similarly-named
+functions in other crypto libraries.
diff --git a/lib/Utils.Cryptography/monocypher/vendor/CHANGELOG.md b/lib/Utils.Cryptography/monocypher/vendor/CHANGELOG.md
new file mode 100644
index 0000000..b109b2d
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/CHANGELOG.md
@@ -0,0 +1,295 @@
+4.0.2
+-----
+2023/08/24
+
+- Fixed multiple-lanes Argon2.
+- Improved Poly1305 performance.
+- Improved Argon2 performance.
+- Makefiles no longer override standard environment variables.
+
+
+4.0.1
+-----
+2023/03/06
+
+- Fixed Ed25519 secret key size in function prototype.
+- Fixed soname (should have been changed in 4.0.0)
+- Added convenience sub-targets to makefile.
+- Briefly specified wire format of Elligator and incremental AEAD.
+
+
+4.0.0
+-----
+2023/02/20
+
+- Fixed unsafe signature API.
+- Simpler, more flexible low-level signature API.
+- Fully specified, consensus-friendly signatures.
+- Added Argon2d and Argon2id, support multiple lanes.
+- Added safe and fast streaming AEAD.
+- Added HKDF-SHA-512 and documented BLAKE2b KDF.
+- More consistent and memorable function names.
+- POSIX makefile.
+
+
+3.1.3
+-----
+2022/04/25
+
+- Fixed many typos in the documentation.
+- Fixed buffer overflow in speed benchmarks.
+- Fixed some MSVC warnings.
+- Fixed a minor violation of the Elligator2 reverse map specs.
+- Added `change-prefix.sh` to help changing the `crypto_` prefix.
+- Added the `MONOCYPHER_CPP_NAMESPACE` preprocessor definition to
+ support namespaces for C++.
+- Deprecated `crypto_key_exchange()`
+- Use GitHub actions to automate the regular test suite.
+
+
+3.1.2
+-----
+2020/12/27
+
+- Addressed issues from Cure53's audit:
+ - MON-01-001: Clarified which CSPRNG to use on Darwin.
+ - MON-01-002: Won't fix (nonce handling is a core design decision).
+ - MON-01-004: Compared with Kleshni's implementation.
+ - MON-01-005: Split a dedicated "advanced" folder in the manual.
+- Quality assurance for 2^255-19 arithmetic (elliptic curves):
+ - Documented carry propagation.
+ - Enforced slightly safer invariants.
+- Improved the speed of EdDSA signature generation.
+- Made the vectors.h header more compact and easier to modify.
+- TIS-CI integration.
+- Added speed benchmark for ed25519-donna.
+- Documented lengths limits of `crypto_ietf_chacha20()`
+
+
+3.1.1
+-----
+2020/06/15
+
+- Various documentation fixes.
+- Fixed various compiler warnings.
+- Fixed some integer overflows (16-bit platforms only).
+
+
+3.1.0
+-----
+2020/04/03
+
+- Added Elligator 2 mappings (hash to curve, curve to hash).
+- Added OPRF support (with scalar inversion).
+- Added Edwards25519 -> Curve25519 conversions.
+
+
+3.0.0
+-----
+2020/01/19
+
+- Deprecated the incremental AEAD interface.
+- Deprecated the incremental Chacha20, added a direct interface.
+- Added IETF Chacha20 (96-bit nonce), as described in RFC 8439.
+- Moved deprecated interfaces to a separate `src/deprecated` folder.
+- Removed the `ED25519_SHA512` preprocessor flag.
+- `crypto_x25519()` and `crypto_key_exchange()` now return `void`.
+- Added a custom hash interface to EdDSA. Several instances of EdDSA
+ can share the same binary.
+- Added optional support for HMAC SHA-512.
+- Moved SHA-512 operations to `src/optional/monocypher-ed25519.(h|c)`.
+- Optional support for Ed25519 no longer requires a preprocessor flag.
+ Add `src/optional/monocypher-ed25519.(h|c)` to your project instead.
+
+
+2.0.6
+-----
+2019/10/21
+
+- Added the `BLAKE2_NO_UNROLLING` preprocessor definition. Activating
+ it makes the binary about 5KB smaller and speeds up processing times
+ on many embedded processors.
+- Reduced the stack usage of signature verification by about
+ 40%. Signature verification now fits in smaller machines.
+- Fixed many implicit casts warnings.
+- Fixed the manual here and there.
+- Lots of small nitpicks.
+
+
+2.0.5
+-----
+2018/08/23
+
+- Faster EdDSA signatures and verification. Like, 4 times as fast.
+
+
+2.0.4
+-----
+2018/06/24
+
+- Corrected a critical vulnerability found by Mike Pechkin in EdDSA,
+ where crypto_check() was accepting invalid signatures. The current
+ fix removes a buggy optimisation, effectively halving the performance
+ of EdDSA.
+- The test suite no longer tries to allocate zero bytes (some platforms
+ fail such an allocation).
+
+2.0.3
+-----
+2018/06/16
+
+- Corrected undefined behaviour in BLAKE2b.
+- Improved the test suite (faster, better coverage).
+
+2.0.2
+-----
+2018/04/23
+
+- Corrected a couple failures to wipe secret buffers.
+- Corrected a bug that prevented compilation in Ed25519 mode.
+- Adjusted the number of test vectors in the test suite.
+- Improved tests for incremental interfaces.
+- Replaced the GNU all permissive licence by a public domain dedication
+ (Creative Commons CC-0). The BSD licence remains as a fallback.
+
+2.0.1
+-----
+2018/03/07
+
+- Followed a systematic pattern for the loading code of symmetric
+ crypto. It is now easier to review.
+- Tweaked Poly1305 code to make it easier to prove correct.
+
+2.0.0
+-----
+2018/02/14
+
+- Changed the authenticated encryption format. It now conforms to
+ RFC 7539, with one exception: it uses XChacha20 initialisation instead
+ of the IETF version of Chacha20. This new format conforms to
+ libsodium's `crypto_aead_xchacha20poly1305_ietf_encrypt`.
+- Removed `crypto_lock_encrypt()` and `crypto_lock_auth()`.
+- Renamed `crypto_lock_aead_auth()` to `crypto_lock_auth_ad()`.
+- Renamed `crypto_unlock_aead_auth()` to `crypto_unlock_auth_ad()`.
+- Added `crypto_lock_auth_message()` and `crypto_unlock_auth_message()`.
+- Renamed `crypto_aead_lock` to `crypto_lock_aead`.
+- Renamed `crypto_aead_unlock` to `crypto_unlock_aead`.
+
+The format change facilitates optimisation by aligning data to block
+boundaries. The API changes increase consistency.
+
+1.1.0
+-----
+2018/02/06
+
+- Rewrote the manual into proper man pages.
+- Added incremental interfaces for authenticated encryption and
+ signatures.
+- Replaced `crypto_memcmp()` by 3 fixed size buffer comparisons (16, 32,
+ and 64 bytes), to make sure the generated code remains constant time.
+- A couple breaking API changes, easily fixed by renaming the affected
+ functions.
+
+1.0.1
+-----
+2017/07/23
+
+- Optimised the loading and unloading code of the symmetric crypto
+ (BLAKE2b, SHA-512, Chacha20, and Poly1305).
+- Fused self-contained tests together for easier analysis with Frama-C
+ and the TIS interpreter.
+
+1.0
+---
+2017/07/18
+
+- Renamed `crypto_chacha20_Xinit` to `crypto_chacha20_x_init`, for
+ consistency reasons (snake case everywhere).
+- Fixed signed integer overflow detected by UBSan.
+- Doubled the speed of EdDSA by performing the scalar product in
+ Montgomery space.
+
+0.8
+---
+2017/07/06
+
+- Added about a hundred lines of code to improve performance of public
+ key cryptography. Diffie-Hellman is now 20% faster than before.
+ The effects are less pronounced for EdDSA.
+- Added random self-consistency tests.
+- Added a speed benchmark against libsodium.
+
+0.7
+---
+2017/06/07
+
+- Slightly changed the authenticated encryption API. Functions are
+ now all in "detached" mode. The reason is better support for
+ authenticated encryption _without_ additional data.
+- Rewrote BLAKE2b from spec so it can use the same licence as
+ everything else.
+- Added random tests that compare Monocypher with libsodium and
+ ed25519-donna.
+- Added explicit support for Frama-C analysis (this doesn't affect the
+ source code).
+
+0.6
+---
+2017/03/17
+
+- Fixed incorrect Poly1305 output on empty messages. (Found by Mike
+ Pechkin.)
+
+0.5
+---
+2017/03/10
+
+- Fixed many undefined behaviours in Curve25519 that occur whenever
+ we perform a left shift on a signed negative integer. It doesn't
+ affect the generated code, but you never know. (Found with Frama-C
+ by André Maroneze.)
+
+Fun fact: TweetNaCl and ref10 have the same bug. Libsodium has
+corrected the issue, though.
+
+For those who don't comprehend the magnitude of this madness, the
+expression `-1 << 3` is undefined in C. This is explained in
+section 6.5.7(§4) of the C11 standard.
+
+0.4
+---
+2017/03/09
+
+- Fixed critical bug causing Argon2i to fail whenever it uses more
+ than 512 blocks. It was reading uninitialised memory and the
+ results were incorrect. (Found by Mike Pechkin.)
+- Fixed an undefined behaviour in Curve25519 (`fe_tobytes()`). It was
+ accessing uninitialised memory before throwing it away. It didn't
+ affect the compiled code nor the results, but you never know.
+ (Found with [Frama-C](http://frama-c.com) by André Maroneze.)
+
+0.3
+---
+2017/02/27
+
+- Got the invariants of Poly1305 right and put them in the comments.
+ There was no bug, but that was lucky (turned out the IETF test
+ vectors were designed to trigger the bugs I was afraid of).
+- Simplified Poly1305 finalisation (replaced conditional subtraction
+ by a carry propagation).
+- Made a few cosmetic changes here and there.
+
+0.2
+---
+????/??/??
+
+- Public interface significantly reworked. Removed redundant, hard to
+ mess up constructions.
+- Added AEAD.
+- Sped up Curve25519 by a factor of more than 6 (switched to ref10
+ arithmetic).
+- Added various test vectors and completed the consistency tests.
+
+0.1
+---
+2016/??/??
diff --git a/lib/Utils.Cryptography/monocypher/vendor/CMakeLists.txt b/lib/Utils.Cryptography/monocypher/vendor/CMakeLists.txt
new file mode 100644
index 0000000..31a1428
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/CMakeLists.txt
@@ -0,0 +1,82 @@
+cmake_minimum_required(VERSION 3.0)
+
+project(Monocypher C)
+
+#export header files to the main project
+file(GLOB HEADERS src/*.h)
+
+#Add indepednent source files to the project
+set(MONOCYPHER_SRCS
+ src/monocypher.c
+)
+
+#create shared library
+add_library(${CMAKE_PROJECT_NAME} SHARED ${MONOCYPHER_SRCS} ${HEADERS})
+#also create static library
+add_library(${CMAKE_PROJECT_NAME}_static STATIC ${MONOCYPHER_SRCS} ${HEADERS})
+
+#if on unix lib will be appended, so we can adjust
+if(UNIX)
+ set_target_properties(${CMAKE_PROJECT_NAME} ${CMAKE_PROJECT_NAME}_static PROPERTIES OUTPUT_NAME _monocypher)
+endif()
+
+#Setup the compiler options
+set(CMAKE_C_STANDARD 99)
+set(CMAKE_C_STANDARD_REQUIRED ON)
+
+#enable position independent code (for shared libraries with exports)
+set(CMAKE_POSITION_INDEPENDENT_CODE ON)
+
+message(STATUS "Build type is '${CMAKE_BUILD_TYPE}'")
+
+#if debug
+add_compile_definitions($<$<CONFIG:Debug>:DEBUG>)
+
+#setup flags for windows compilation
+if(MSVC)
+
+ #global windows cl flags
+ add_compile_options(
+ /sdl
+ /TC
+ /GS
+ /machine:x64
+
+ $<$<CONFIG:Debug>:/FC>
+ $<$<CONFIG:Debug>:/showIncludes>
+
+ #disable warnings for struct padding and spectre mitigation wuen WX is enabled
+ $<$<CONFIG:Debug>:/wd5045>
+ $<$<CONFIG:Debug>:/wd4820>
+ $<$<CONFIG:Debug>:/wd4574>
+
+ #for debug configs
+ $<$<CONFIG:Debug>:/options:strict>
+ #disable warnings for struct padding and spectre mitigation wuen WX is enabled
+ $<$<CONFIG:Debug>:/Wall>
+ $<$<CONFIG:Debug>:/Zi>
+ $<$<CONFIG:Debug>:/Zo>
+ )
+
+ #set build macros
+ add_compile_definitions(
+ $<$<CONFIG:DEBUG>:DEBUG>
+ $<$<CONFIG:RELEASE>:RELEASE>
+ )
+
+#configure gcc flags
+elseif(CMAKE_COMPILER_IS_GNUCC)
+
+ #global gcc cl flags
+ add_compile_options(
+ -Wextra
+ -fstack-protector
+ -march=native
+
+ $<$<CONFIG:Debug>:-g>
+ $<$<CONFIG:Debug>:-Og>
+ $<$<CONFIG:Debug>:-Wall>
+ $<$<CONFIG:Debug>:-pedantic>
+ )
+
+endif()
diff --git a/lib/Utils.Cryptography/monocypher/vendor/LICENCE.md b/lib/Utils.Cryptography/monocypher/vendor/LICENCE.md
new file mode 100644
index 0000000..9d69ad7
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/LICENCE.md
@@ -0,0 +1,173 @@
+Monocypher as a whole is dual-licensed. Choose whichever licence you
+want from the two licences listed below.
+
+The first licence is a regular 2-clause BSD licence. The second licence
+is the CC-0 from Creative Commons. It is intended to release Monocypher
+to the public domain. The BSD licence serves as a fallback option.
+
+See the individual files for specific information about who contributed
+to what file during which years. See below for special notes.
+
+Licence 1 (2-clause BSD)
+------------------------
+
+Copyright (c) 2017-2023, Loup Vaillant
+Copyright (c) 2017-2019, Michael Savage
+Copyright (c) 2017-2023, Fabio Scotoni
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the
+ distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Licence 2 (CC-0)
+----------------
+
+> CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
+> LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
+> ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
+> INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
+> REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
+> PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
+> THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
+> HEREUNDER.
+
+### Statement of Purpose
+
+The laws of most jurisdictions throughout the world automatically confer
+exclusive Copyright and Related Rights (defined below) upon the creator
+and subsequent owner(s) (each and all, an "owner") of an original work
+of authorship and/or a database (each, a "Work").
+
+Certain owners wish to permanently relinquish those rights to a Work for
+the purpose of contributing to a commons of creative, cultural and
+scientific works ("Commons") that the public can reliably and without
+fear of later claims of infringement build upon, modify, incorporate in
+other works, reuse and redistribute as freely as possible in any form
+whatsoever and for any purposes, including without limitation commercial
+purposes. These owners may contribute to the Commons to promote the
+ideal of a free culture and the further production of creative, cultural
+and scientific works, or to gain reputation or greater distribution for
+their Work in part through the use and efforts of others.
+
+For these and/or other purposes and motivations, and without any
+expectation of additional consideration or compensation, the person
+associating CC0 with a Work (the "Affirmer"), to the extent that he or
+she is an owner of Copyright and Related Rights in the Work, voluntarily
+elects to apply CC0 to the Work and publicly distribute the Work under
+its terms, with knowledge of his or her Copyright and Related Rights in
+the Work and the meaning and intended legal effect of CC0 on those
+rights.
+
+1. **Copyright and Related Rights.** A Work made available under CC0 may
+ be protected by copyright and related or neighboring rights
+ ("Copyright and Related Rights"). Copyright and Related Rights
+ include, but are not limited to, the following:
+
+ - the right to reproduce, adapt, distribute, perform, display,
+ communicate, and translate a Work;
+ - moral rights retained by the original author(s) and/or
+ performer(s); publicity and privacy rights pertaining to a person's
+ image or likeness depicted in a Work;
+ - rights protecting against unfair competition in regards to a Work,
+ subject to the limitations in paragraph 4(a), below;
+ - rights protecting the extraction, dissemination, use and reuse of
+ data in a Work;
+ - database rights (such as those arising under Directive 96/9/EC of
+ the European Parliament and of the Council of 11 March 1996 on the
+ legal protection of databases, and under any national
+ implementation thereof, including any amended or successor version
+ of such directive); and
+ - other similar, equivalent or corresponding rights throughout the
+ world based on applicable law or treaty, and any national
+ implementations thereof.
+
+2. **Waiver.** To the greatest extent permitted by, but not in
+ contravention of, applicable law, Affirmer hereby overtly, fully,
+ permanently, irrevocably and unconditionally waives, abandons, and
+ surrenders all of Affirmer's Copyright and Related Rights and
+ associated claims and causes of action, whether now known or unknown
+ (including existing as well as future claims and causes of action),
+ in the Work (i) in all territories worldwide, (ii) for the maximum
+ duration provided by applicable law or treaty (including future time
+ extensions), (iii) in any current or future medium and for any number
+ of copies, and (iv) for any purpose whatsoever, including without
+ limitation commercial, advertising or promotional purposes (the
+ "Waiver"). Affirmer makes the Waiver for the benefit of each member
+ of the public at large and to the detriment of Affirmer's heirs and
+ successors, fully intending that such Waiver shall not be subject to
+ revocation, rescission, cancellation, termination, or any other legal
+ or equitable action to disrupt the quiet enjoyment of the Work by the
+ public as contemplated by Affirmer's express Statement of Purpose.
+
+3. **Public License Fallback.** Should any part of the Waiver for any
+ reason be judged legally invalid or ineffective under applicable law,
+ then the Waiver shall be preserved to the maximum extent permitted
+ taking into account Affirmer's express Statement of Purpose. In
+ addition, to the extent the Waiver is so judged Affirmer hereby
+ grants to each affected person a royalty-free, non transferable, non
+ sublicensable, non exclusive, irrevocable and unconditional license
+ to exercise Affirmer's Copyright and Related Rights in the Work (i)
+ in all territories worldwide, (ii) for the maximum duration provided
+ by applicable law or treaty (including future time extensions), (iii)
+ in any current or future medium and for any number of copies, and
+ (iv) for any purpose whatsoever, including without limitation
+ commercial, advertising or promotional purposes (the "License"). The
+ License shall be deemed effective as of the date CC0 was applied by
+ Affirmer to the Work. Should any part of the License for any reason
+ be judged legally invalid or ineffective under applicable law, such
+ partial invalidity or ineffectiveness shall not invalidate the
+ remainder of the License, and in such case Affirmer hereby affirms
+ that he or she will not (i) exercise any of his or her remaining
+ Copyright and Related Rights in the Work or (ii) assert any
+ associated claims and causes of action with respect to the Work, in
+ either case contrary to Affirmer's express Statement of Purpose.
+
+4. **Limitations and Disclaimers.**
+
+ - No trademark or patent rights held by Affirmer are waived,
+ abandoned, surrendered, licensed or otherwise affected by this
+ document.
+ - Affirmer offers the Work as-is and makes no representations or
+ warranties of any kind concerning the Work, express, implied,
+ statutory or otherwise, including without limitation warranties of
+ title, merchantability, fitness for a particular purpose, non
+ infringement, or the absence of latent or other defects, accuracy,
+ or the present or absence of errors, whether or not discoverable,
+ all to the greatest extent permissible under applicable law.
+ - Affirmer disclaims responsibility for clearing rights of other
+ persons that may apply to the Work or any use thereof, including
+ without limitation any person's Copyright and Related Rights in the
+ Work. Further, Affirmer disclaims responsibility for obtaining any
+ necessary consents, permissions or other rights required for any
+ use of the Work.
+ - Affirmer understands and acknowledges that Creative Commons is not
+ a party to this document and has no duty or obligation with respect
+ to this CC0 or use of the Work.
+
+Special notes
+-------------
+
+The files in `tests/externals/` were placed in the public domain by
+their respective authors. See the `AUTHORS.md` files in each directory.
diff --git a/lib/Utils.Cryptography/monocypher/vendor/README.md b/lib/Utils.Cryptography/monocypher/vendor/README.md
new file mode 100644
index 0000000..f0c28df
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/README.md
@@ -0,0 +1,196 @@
+[![TrustInSoft CI](https://ci.trust-in-soft.com/projects/LoupVaillant/Monocypher.svg?branch=master)](https://ci.trust-in-soft.com/projects/LoupVaillant/Monocypher)
+
+[![Github Actions CI](https://github.com/LoupVaillant/Monocypher/actions/workflows/ci.yml/badge.svg)](https://github.com/LoupVaillant/Monocypher/actions/workflows/ci.yml)
+
+
+Monocypher (Developer Edition)
+------------------------------
+
+_(This is the bleeding edge, not yet released version. If you just want
+to use Monocypher, grab the [latest version][latest], or download the
+[source][] and [header][] files directly. If you want to contribute, see
+the notes at the end.)_
+
+[source]: https://monocypher.org/download/monocypher.c
+[header]: https://monocypher.org/download/monocypher.h
+[latest]: https://monocypher.org/download/monocypher-latest.tar.gz
+
+---
+
+Monocypher is an easy to use, easy to deploy, auditable crypto library
+written in portable C. It approaches the size of [TweetNaCl][] and the
+speed of [libsodium][].
+
+[Official site.](https://monocypher.org/)
+[Official releases.](https://monocypher.org/download/)
+
+[libsodium]: https://libsodium.org
+[TweetNaCl]: https://tweetnacl.cr.yp.to/
+
+
+Features
+--------
+
+- [Authenticated Encryption][AEAD] with XChaCha20 and Poly1305
+ (RFC 8439).
+- [Hashing and key derivation][HASH] with BLAKE2b (and [SHA-512][]).
+- [Password Hashing][PWH] with Argon2.
+- [Public Key Cryptography][PKC] with X25519 key exchanges.
+- [Public Key Signatures][EDDSA] with EdDSA and [Ed25519][].
+- [Steganography and PAKE][STEG] with [Elligator 2][ELLI].
+
+[AEAD]: https://monocypher.org/manual/aead
+[HASH]: https://monocypher.org/manual/blake2
+[SHA-512]: https://monocypher.org/manual/sha-512
+[PWH]: https://monocypher.org/manual/argon2
+[PKC]: https://monocypher.org/manual/x25519
+[EDDSA]: https://monocypher.org/manual/eddsa
+[Ed25519]: https://monocypher.org/manual/ed25519
+[STEG]: https://monocypher.org/manual/elligator
+[ELLI]: https://elligator.org
+
+
+Manual
+------
+
+The manual can be found at https://monocypher.org/manual/, and in the
+`doc/` folder.
+
+
+Installation
+------------
+
+### Option 1: grab the sources
+
+The easiest way to use Monocypher is to include `src/monocypher.h` and
+`src/monocypher.c` directly into your project. They compile as C (since
+C99) and C++ (since C++98).
+
+If you need the optional SHA-512 or Ed25519, grab
+`src/optional/monocypher-ed25519.h` and
+`src/optional/monocypher-ed25519.c` as well.
+
+### Option 2: grab the library
+
+Run `make`, then grab the `src/monocypher.h` header and either the
+`lib/libmonocypher.a` or `lib/libmonocypher.so` library. The default
+compiler is `gcc -std=c99`, and the default flags are `-pedantic -Wall
+-Wextra -O3 -march=native`. If they don't work on your platform, you
+can change them like this:
+
+ $ make CC="clang -std=c11" CFLAGS="-O2"
+
+### Option 3: install it on your system
+
+Run `make`, then `make install` as root. This will install Monocypher in
+`/usr/local` by default. This can be changed with `PREFIX` and
+`DESTDIR`:
+
+ $ make install PREFIX="/opt"
+
+Once installed, you may use `pkg-config` to compile and link your
+program. For instance:
+
+ $ gcc program.c $(pkg-config monocypher --cflags) -c
+ $ gcc program.o $(pkg-config monocypher --libs) -o program
+
+If for any reason you wish to avoid installing the man pages or the
+`pkg-config` file, you can use the following installation sub targets
+instead: `install-lib`, `install-doc`, and `install-pc`.
+
+
+Test suite
+----------
+
+ $ make test
+
+It should display a nice printout of all the tests, ending with "All
+tests OK!". If you see "failure" or "Error" anywhere, something has gone
+wrong.
+
+*Do not* use Monocypher without running those tests at least once.
+
+The same test suite can be run under Clang sanitisers and Valgrind, and
+be checked for code coverage:
+
+ $ tests/test.sh
+ $ tests/coverage.sh
+
+
+### Serious auditing
+
+The code may be analysed more formally with [Frama-c][] and the
+[TIS interpreter][TIS]. To analyse the code with Frama-c, run:
+
+ $ tests/formal-analysis.sh
+ $ tests/frama-c.sh
+
+This will have Frama-c parse, and analyse the code, then launch a GUI.
+You must have Frama-c installed. See `frama-c.sh` for the recommended
+settings. To run the code under the TIS interpreter, run
+
+ $ tests/formal-analysis.sh
+ $ tis-interpreter.sh --cc -Dvolatile= tests/formal-analysis/*.c
+
+Notes:
+
+- `tis-interpreter.sh` is part of TIS. If it is not in your path,
+ adjust the command accordingly.
+
+- The TIS interpreter sometimes fails to evaluate correct programs when
+ they use the `volatile` keyword (which is only used as an attempt to
+ prevent dead store elimination for memory wipes). The `-cc
+ -Dvolatile=` option works around that bug by ignoring `volatile`
+ altogether.
+
+[Frama-c]:https://frama-c.com/
+[TIS]: https://trust-in-soft.com/tis-interpreter/
+
+
+Customisation
+-------------
+
+Monocypher has optional compatibility with Ed25519. To have that, add
+`monocypher-ed25519.h` and `monocypher-ed25519.c` provided in
+`src/optional` to your project. If you compile or install Monocypher
+with the makefile, they will be automatically included.
+
+Monocypher also has the `BLAKE2_NO_UNROLLING` preprocessor flag, which
+is activated by compiling monocypher.c with the `-DBLAKE2_NO_UNROLLING`
+option.
+
+The `-DBLAKE2_NO_UNROLLING` option is a performance tweak. By default,
+Monocypher unrolls the BLAKE2b inner loop, because doing so is over 25%
+faster on modern processors. Some embedded processors however, run the
+unrolled loop _slower_ (possibly because of the cost of fetching 5KB of
+additional code). If you're using an embedded platform, try this
+option. The binary will be about 5KB smaller, and in some cases faster.
+
+The `MONOCYPHER_CPP_NAMESPACE` preprocessor definition allows C++ users
+who compile Monocypher as C++ to wrap it in a namespace. When it is not
+defined (the default), we assume Monocypher is compiled as C, and an
+`extern "C"` declaration is added when we detect that the header is
+included in C++ code.
+
+The `change-prefix.sh` script can rename all functions by replacing
+`crypto_` by a chosen prefix, so you can avoid name clashes. For
+instance, the following command changes all instances of `crypto_` by
+`foobar_` (note the absence of the underscore):
+
+ ./change-prefix.sh foobar
+
+
+Contributor notes
+-----------------
+
+If you are reading this, you cloned the GitHub repository. You miss a
+couple files that ship with the tarball releases:
+
+- The `tests/vectors.h` header. Generating it requires libsodium. Go
+ to `tests/gen/`, then run `make`.
+- The html version of the manual, generated by the `doc/doc_gen.sh`
+ script. You will need mandoc and Python 3.
+
+To generate a tarball, simply type `make dist`. It will make a tarball
+with a name that matches the current version (using `git describe`), in
+the current directory.
diff --git a/lib/Utils.Cryptography/monocypher/vendor/change-prefix.sh b/lib/Utils.Cryptography/monocypher/vendor/change-prefix.sh
new file mode 100644
index 0000000..63ef535
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/change-prefix.sh
@@ -0,0 +1,70 @@
+#! /bin/sh
+
+# This file is dual-licensed. Choose whichever licence you want from
+# the two licences listed below.
+#
+# The first licence is a regular 2-clause BSD licence. The second licence
+# is the CC-0 from Creative Commons. It is intended to release Monocypher
+# to the public domain. The BSD licence serves as a fallback option.
+#
+# SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+#
+# ------------------------------------------------------------------------
+#
+# Copyright (c) 2022, Loup Vaillant
+# All rights reserved.
+#
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# ------------------------------------------------------------------------
+#
+# Written in 2022 by Loup Vaillant
+#
+# To the extent possible under law, the author(s) have dedicated all copyright
+# and related neighboring rights to this software to the public domain
+# worldwide. This software is distributed without any warranty.
+#
+# You should have received a copy of the CC0 Public Domain Dedication along
+# with this software. If not, see
+# <https://creativecommons.org/publicdomain/zero/1.0/>
+
+
+# Usage:
+# ./change-prefix.sh foobar
+#
+# The above changes the default "crypto_" prefix of all Monocypher
+# functions by the "foobar_" prefix instead.
+#
+# This can be used to avoid name clashes with other libraries.
+# This also renames the test code, so the tests should still pass.
+
+set -e
+
+find . -name "*.*" \
+ | egrep "\.(c|h)$" \
+ | egrep -v "^\./tests/(gen|externals|speed/speed-)" \
+ | xargs sed -i "s/crypto_/$1_/g" \
+ tests/externals/ed25519-donna/ed25519-hash-custom.h
diff --git a/lib/Utils.Cryptography/monocypher/vendor/dist.sh b/lib/Utils.Cryptography/monocypher/vendor/dist.sh
new file mode 100644
index 0000000..d0db2ff
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/dist.sh
@@ -0,0 +1,119 @@
+#! /bin/sh
+
+# This file is dual-licensed. Choose whichever licence you want from
+# the two licences listed below.
+#
+# The first licence is a regular 2-clause BSD licence. The second licence
+# is the CC-0 from Creative Commons. It is intended to release Monocypher
+# to the public domain. The BSD licence serves as a fallback option.
+#
+# SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+#
+# ------------------------------------------------------------------------
+#
+# Copyright (c) 2019, Loup Vaillant
+# Copyright (c) 2019-2020, Fabio Scotoni
+# All rights reserved.
+#
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# ------------------------------------------------------------------------
+#
+# Written in 2019-2020 by Loup Vaillant and Fabio Scotoni
+#
+# To the extent possible under law, the author(s) have dedicated all copyright
+# and related neighboring rights to this software to the public domain
+# worldwide. This software is distributed without any warranty.
+#
+# You should have received a copy of the CC0 Public Domain Dedication along
+# with this software. If not, see
+# <https://creativecommons.org/publicdomain/zero/1.0/>
+
+set -e
+
+VERSION=`git describe --tags`
+FOLDER=monocypher-$VERSION
+TARBALL=$FOLDER.tar
+
+# Generate documentation
+doc/doc_gen.sh
+
+# Delete the destination folder just to make sure everything is clean.
+# May be needed if we unpack the tarball in place for testing purposes,
+# then run the release script again.
+rm -rf $FOLDER
+
+# copy everything except ignored files to the
+rsync -ad --exclude-from=dist_ignore ./ $FOLDER
+
+# Replace version markers by the actual version number (from tags)
+find $FOLDER -type f -exec sed -i "s/__git__/$VERSION/g" \{\} \;
+
+# Remove the dist target from the makefile (no recursive releases!),
+# and the tests/vector.h target, which ships with the tarball.
+sed -i '/# Remove lines below for the tarball/,$d' $FOLDER/makefile
+sed -i 's/clean uninstall dist/clean uninstall/' $FOLDER/makefile
+sed -i 's| doc/man3/intro.3monocypher||' $FOLDER/makefile
+sed -i 's|rm -rf lib/ doc/html/ doc/man3/|rm -rf lib/|' $FOLDER/makefile
+
+# Remove contributor notes from the README
+sed -e '/Contributor notes/,$d' -e '1,/^---$/d' -i $FOLDER/README.md
+sed -e '$d' -i $FOLDER/README.md
+sed -e '$d' -i $FOLDER/README.md
+sed -e '1i\
+Monocypher\
+----------' -i $FOLDER/README.md
+
+# Remove special notes from the LICENCE
+sed -e '/Special notes/,$d' -i $FOLDER/LICENCE.md
+sed -e '$d' -i $FOLDER/LICENCE.md
+
+# Make the actual tarball. The options here were taken from:
+# https://reproducible-builds.org/docs/archives/#full-example
+# This requires GNU tar.
+# The --mtime value was chosen arbitrarily, but the date is chosen such
+# that it is after the release 3.1.0, the last one without reproducible
+# tarballs.
+tar --sort=name \
+ --mtime=@1587513600 \
+ --owner=0 --group=0 --numeric-owner \
+ --pax-option=exthdr.name=%d/PaxHeaders/%f,delete=atime,delete=ctime \
+ -cvf $TARBALL $FOLDER
+# Compress separately so that we can set the -n option to avoid any kind
+# of timestamp metadata
+gzip -n $TARBALL
+
+# Remove the temporary folder
+rm -rf $FOLDER
+
+# Run tests in the tarball, to make sure we didn't screw up anything
+# important. We're missing the TIS interpreter run, but that's a good
+# quick check.
+tar -xzf $TARBALL.gz
+cd $FOLDER # Extracting from the tarball, just to make sure
+tests/test.sh
+make clean
+make
diff --git a/lib/Utils.Cryptography/monocypher/vendor/dist_ignore b/lib/Utils.Cryptography/monocypher/vendor/dist_ignore
new file mode 100644
index 0000000..9aa4940
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/dist_ignore
@@ -0,0 +1,36 @@
+*~
+*.o
+*.a
+*.so
+*.so.*
+*.out
+*.vec
+*.gch
+*.sav
+*.profraw
+*.profdata
+*.creator
+*.creator.*
+*.config
+*.cflags
+*.cxxflags
+*.files
+*.includes
+*.su
+*.su.*
+*.gen.*
+tests/formal-analysis/*
+tests/formal-analysis
+*.tar.gz
+monocypher-*/
+**/__pycache__/**
+doc/*.*
+tests/speed*
+tests/externals*
+lib*
+.git*
+dist.sh
+dist_ignore
+tests/gen*
+tis.config
+tests/tis-ci-gen-config.sh
diff --git a/lib/Utils.Cryptography/monocypher/vendor/doc/crypto_aead_lock.3monocypher b/lib/Utils.Cryptography/monocypher/vendor/doc/crypto_aead_lock.3monocypher
new file mode 100644
index 0000000..348c3bf
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/doc/crypto_aead_lock.3monocypher
@@ -0,0 +1,507 @@
+.\" This file is dual-licensed. Choose whichever you want.
+.\"
+.\" The first licence is a regular 2-clause BSD licence. The second licence
+.\" is the CC-0 from Creative Commons. It is intended to release Monocypher
+.\" to the public domain. The BSD licence serves as a fallback option.
+.\"
+.\" SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+.\"
+.\" ----------------------------------------------------------------------------
+.\"
+.\" Copyright (c) 2017-2019, 2023 Loup Vaillant
+.\" Copyright (c) 2017-2018 Michael Savage
+.\" Copyright (c) 2017, 2019-2022 Fabio Scotoni
+.\" All rights reserved.
+.\"
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions are
+.\" met:
+.\"
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\"
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the
+.\" distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+.\" HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" ----------------------------------------------------------------------------
+.\"
+.\" Written in 2017-2023 by Loup Vaillant, Michael Savage and Fabio Scotoni
+.\"
+.\" To the extent possible under law, the author(s) have dedicated all copyright
+.\" and related neighboring rights to this software to the public domain
+.\" worldwide. This software is distributed without any warranty.
+.\"
+.\" You should have received a copy of the CC0 Public Domain Dedication along
+.\" with this software. If not, see
+.\" <https://creativecommons.org/publicdomain/zero/1.0/>
+.\"
+.Dd March 6, 2023
+.Dt CRYPTO_LOCK 3MONOCYPHER
+.Os
+.Sh NAME
+.Nm crypto_aead_lock ,
+.Nm crypto_aead_unlock ,
+.Nm crypto_aead_init_x ,
+.Nm crypto_aead_init_djb ,
+.Nm crypto_aead_init_ietf ,
+.Nm crypto_aead_write ,
+.Nm crypto_aead_read
+.Nd authenticated encryption with additional data
+.Sh SYNOPSIS
+.In monocypher.h
+.Ft void
+.Fo crypto_aead_lock
+.Fa "uint8_t *cipher_text"
+.Fa "uint8_t mac[16]"
+.Fa "const uint8_t key[32]"
+.Fa "const uint8_t nonce[24]"
+.Fa "const uint8_t *ad"
+.Fa "size_t ad_size"
+.Fa "const uint8_t *plain_text"
+.Fa "size_t text_size"
+.Fc
+.Ft int
+.Fo crypto_aead_unlock
+.Fa "uint8_t *plain_text"
+.Fa "const uint8_t mac[16]"
+.Fa "const uint8_t key[32]"
+.Fa "const uint8_t nonce[24]"
+.Fa "const uint8_t *ad"
+.Fa "size_t ad_size"
+.Fa "const uint8_t *cipher_text"
+.Fa "size_t text_size"
+.Fc
+.Ft void
+.Fo crypto_aead_init_x
+.Fa "crypto_aead_ctx *ctx"
+.Fa "const uint8_t key[32]"
+.Fa "const uint8_t nonce[24]"
+.Fc
+.Ft void
+.Fo crypto_aead_init_djb
+.Fa "crypto_aead_ctx *ctx"
+.Fa "const uint8_t key[32]"
+.Fa "const uint8_t nonce[8]"
+.Fc
+.Ft void
+.Fo crypto_aead_init_ietf
+.Fa "crypto_aead_ctx *ctx"
+.Fa "const uint8_t key[32]"
+.Fa "const uint8_t nonce[12]"
+.Fc
+.Ft void
+.Fo crypto_aead_write
+.Fa "crypto_aead_ctx *ctx"
+.Fa "uint8_t *cipher_text"
+.Fa "uint8_t mac[16]"
+.Fa "const uint8_t *ad"
+.Fa "size_t ad_size"
+.Fa "const uint8_t *plain_text"
+.Fa "size_t text_size"
+.Fc
+.Ft int
+.Fo crypto_aead_read
+.Fa "crypto_aead_ctx *ctx"
+.Fa "uint8_t *plain_text"
+.Fa "const uint8_t mac[16]"
+.Fa "const uint8_t *ad"
+.Fa "size_t ad_size"
+.Fa "const uint8_t *cipher_text"
+.Fa "size_t text_size"
+.Fc
+.Sh DESCRIPTION
+.Fn crypto_aead_lock
+encrypts and authenticates a plaintext.
+It can be decrypted by
+.Fn crypto_aead_unlock .
+The arguments are:
+.Bl -tag -width Ds
+.It Fa key
+A 32-byte session key shared between the sender and the recipient.
+It must be secret and random.
+Different methods can be used to produce and exchange this key,
+such as Diffie-Hellman key exchange,
+password-based key derivation
+(the password must be communicated on a secure channel),
+or even meeting physically.
+See
+.Xr crypto_x25519 3monocypher
+for a building block for a key exchange protocol and
+.Xr crypto_argon2 3monocypher
+for password-based key derivation.
+.It Fa nonce
+A 24-byte number, used only once with any given session key.
+It does not need to be secret or random, but it does have to be
+unique.
+.Em Never
+use the same nonce twice with the same key.
+This would basically reveal the affected messages
+and leave you vulnerable to forgeries.
+The easiest (and recommended) way to generate this nonce is to
+select it at random.
+See
+.Xr intro 3monocypher
+about random number generation (use your operating system's random
+number generator).
+.Pp
+Note:
+.Fn crypto_aead_init_djb
+and
+.Fn crypto_aead_init_ietf
+use shorter nonces
+(8 and 12 bytes respectively),
+which
+.Em cannot
+be selected at random without risking a catastrophic reuse.
+For those shorter nonces, use a counter instead.
+.It Fa mac
+A 16-byte
+.Em message authentication code
+(MAC) that can only be produced by someone who knows the session key.
+This guarantee cannot be upheld if a nonce has been reused with the
+session key because doing so allows the attacker to learn the
+authentication key associated with that nonce.
+The MAC is intended to be sent along with the ciphertext.
+.It Fa ad
+Additional data to authenticate.
+It will
+.Em not
+be encrypted.
+This is used to authenticate relevant data that cannot be encrypted.
+May be
+.Dv NULL
+if
+.Fa ad_size
+is zero.
+.It Fa ad_size
+Length of the additional data, in bytes.
+.It Fa plain_text
+The secret message.
+Its contents will be kept hidden from attackers.
+Its length, however, will
+.Em not .
+Be careful when combining encryption with compression.
+See
+.Xr intro 3monocypher
+for details.
+.It Fa cipher_text
+The encrypted message.
+.It Fa text_size
+Length of both
+.Fa plain_text and
+.Fa cipher_text ,
+in bytes.
+.El
+.Pp
+The
+.Fa cipher_text
+and
+.Fa plain_text
+arguments may point to the same buffer for in-place encryption.
+Otherwise, the buffers they point to must not overlap.
+.Pp
+.Fn crypto_aead_unlock
+first checks the integrity of an encrypted message.
+If it has been corrupted,
+.Fn crypto_aead_unlock
+does nothing and returns -1 immediately.
+Otherwise it decrypts the message then returns zero.
+.Em Always check the return value .
+.Ss Incremental interface
+For long messages that may not fit in memory,
+first initialise a context with
+.Fn crypto_aead_init_x ,
+then encrypt each chunk with
+.Fn crypto_aead_write .
+The receiving end will initialise its own context with
+.Fn crypto_aead_init_x ,
+then decrypt each chunk with
+.Fn crypto_aead_read .
+.Pp
+Just like
+.Fn crypto_aead_unlock ,
+.Fn crypto_aead_read
+first checks the integrity of the encrypted chunk,
+then returns -1 immediately if it has been corrupted.
+Otherwise it decrypts the chunk then returns zero.
+.Em Always check the return value .
+.Pp
+The encryption key is changed between each chunk,
+providing a symmetric ratchet that enforces the order of the messages.
+Attackers cannot reorder chunks without
+.Fn crypto_aead_read
+noticing.
+.Sy Truncation however is not detected .
+You must detect the last chunk manually.
+Possible methods include using
+.Fa ad
+to mark the last chunk differently,
+prefixing all plaintext messages with a marking byte
+(and use a different marking byte for the last chunk),
+or sending the total message size up front and encode the remaining size
+in
+.Fa ad .
+Once the last chunk is sent or received, wipe the context with
+.Xr crypto_wipe 3monocypher .
+.Pp
+.Fn crypto_aead_init_djb
+and
+.Fn crypto_aead_init_ietf
+are variants of
+.Fn crypto_aead_init_x
+with a shorter nonce.
+.Em Those nonces are too short to be selected at random .
+Use a counter instead.
+.Pp
+In addition to its short nonce,
+.Fn crypto_aead_init_ietf
+has a smaller internal counter that limits the size of chunks to
+256GiB.
+Exceeding this size leaks the contents of the chunk.
+It is provided strictly for compatibility with RFC 8439.
+.Sh RETURN VALUES
+.Fn crypto_aead_lock ,
+.Fn crypto_aead_init_x ,
+.Fn crypto_aead_init_djb ,
+.Fn crypto_aead_init_ietf ,
+and
+.Fn crypto_aead_write
+return nothing.
+.Fn crypto_aead_unlock
+and
+.Fn crypto_aead_read
+return 0 on success or -1 if the message was corrupted (i.e.
+.Fa mac
+mismatched the combination of
+.Fa key ,
+.Fa nonce ,
+.Fa ad ,
+and
+.Fa cipher_text ) .
+Corruption can be caused by transmission errors, programmer error, or an
+attacker's interference.
+.Fa plain_text
+does not need to be wiped if the decryption fails.
+.Sh EXAMPLES
+The following examples assume the existence of
+.Fn arc4random_buf ,
+which fills the given buffer with cryptographically secure random bytes.
+If
+.Fn arc4random_buf
+does not exist on your system, see
+.Xr intro 3monocypher
+for advice about how to generate cryptographically secure random bytes.
+.Pp
+Encryption:
+.Bd -literal -offset indent
+uint8_t key [32]; /* Random, secret session key */
+uint8_t nonce [24]; /* Use only once per key */
+uint8_t plain_text [12] = "Lorem ipsum"; /* Secret message */
+uint8_t mac [16]; /* Message authentication code */
+uint8_t cipher_text[12]; /* Encrypted message */
+arc4random_buf(key, 32);
+arc4random_buf(nonce, 24);
+crypto_aead_lock(cipher_text, mac,
+ key, nonce,
+ NULL, 0,
+ plain_text, sizeof(plain_text));
+/* Wipe secrets if they are no longer needed */
+crypto_wipe(plain_text, 12);
+crypto_wipe(key, 32);
+/* Transmit cipher_text, nonce, and mac over the network,
+ * store them in a file, etc.
+ */
+.Ed
+.Pp
+To decrypt the above:
+.Bd -literal -offset indent
+uint8_t key [32]; /* Same as the above */
+uint8_t nonce [24]; /* Same as the above */
+const uint8_t cipher_text[12]; /* Encrypted message */
+const uint8_t mac [16]; /* Received along with text */
+uint8_t plain_text [12]; /* Secret message */
+if (crypto_aead_unlock(plain_text, mac,
+ key, nonce,
+ NULL, 0,
+ cipher_text, sizeof(plain_text))) {
+ /* The message is corrupted.
+ * Wipe key if it is no longer needed,
+ * and abort the decryption.
+ */
+ crypto_wipe(key, 32);
+} else {
+ /* ...do something with the decrypted text here... */
+ /* Finally, wipe secrets if they are no longer needed */
+ crypto_wipe(plain_text, 12);
+ crypto_wipe(key, 32);
+}
+.Ed
+.Pp
+In-place encryption:
+.Bd -literal -offset indent
+uint8_t key [32]; /* Random, secret session key */
+uint8_t nonce[24]; /* Use only once per key */
+uint8_t text [12] = "Lorem ipsum"; /* Secret message */
+uint8_t mac [16]; /* Message authentication code */
+arc4random_buf(key, 32);
+arc4random_buf(nonce, 24);
+crypto_aead_lock(text, mac,
+ key, nonce,
+ NULL, 0,
+ text, sizeof(text));
+/* Wipe secrets if they are no longer needed */
+crypto_wipe(key, 32);
+/* Transmit cipher_text, nonce, and mac over the network,
+ * store them in a file, etc.
+ */
+.Ed
+.Pp
+In-place decryption:
+.Bd -literal -offset indent
+uint8_t key [32]; /* Same as the above */
+const uint8_t nonce[24]; /* Same as the above */
+const uint8_t mac [16]; /* Received from along with text */
+uint8_t text [12]; /* Message to decrypt */
+if (crypto_aead_unlock(text, mac, key, nonce,
+ NULL, 0,
+ text, sizeof(text))) {
+ /* The message is corrupted.
+ * Wipe key if it is no longer needed,
+ * and abort the decryption.
+ */
+ crypto_wipe(key, 32);
+} else {
+ /* ...do something with the decrypted text here... */
+ /* Finally, wipe secrets if they are no longer needed */
+ crypto_wipe(text, 12);
+ crypto_wipe(key, 32);
+}
+.Ed
+.Pp
+Encrypt one message with the incremental interface:
+.Bd -literal -offset indent
+uint8_t key [32]; /* Random, secret session key */
+uint8_t nonce [24]; /* Use only once per key */
+uint8_t plain_text [12] = "Lorem ipsum"; /* Secret message */
+uint8_t mac [16]; /* Message authentication code */
+uint8_t cipher_text[12]; /* Encrypted message */
+arc4random_buf(key, 32);
+arc4random_buf(nonce, 24);
+crypto_aead_ctx ctx;
+crypto_aead_init_x(&ctx, key, nonce);
+crypto_aead_write(&ctx, cipher_text, mac,
+ NULL, 0,
+ plain_text, sizeof(plain_text));
+/* Wipe secrets if they are no longer needed */
+crypto_wipe(plain_text, 12);
+crypto_wipe(key, 32);
+crypto_wipe(&ctx, sizeof(ctx));
+/* Transmit cipher_text, nonce, and mac over the network,
+ * store them in a file, etc.
+ */
+.Ed
+.Pp
+To decrypt the above:
+.Bd -literal -offset indent
+uint8_t key [32]; /* Same as the above */
+uint8_t nonce [24]; /* Same as the above */
+const uint8_t cipher_text[12]; /* Encrypted message */
+const uint8_t mac [16]; /* Received along with text */
+uint8_t plain_text [12]; /* Secret message */
+crypto_aead_ctx ctx;
+crypto_aead_init_x(&ctx, key, nonce);
+if (crypto_aead_read(&ctx, plain_text, mac,
+ NULL, 0,
+ cipher_text, sizeof(plain_text))) {
+ /* The message is corrupted.
+ * Wipe key if it is no longer needed,
+ * and abort the decryption.
+ */
+ crypto_wipe(key, 32);
+ crypto_wipe(&ctx, sizeof(ctx));
+} else {
+ /* ...do something with the decrypted text here... */
+ /* Finally, wipe secrets if they are no longer needed */
+ crypto_wipe(plain_text, 12);
+ crypto_wipe(key, 32);
+ crypto_wipe(&ctx, sizeof(ctx));
+}
+.Ed
+.Sh SEE ALSO
+.Xr crypto_x25519 3monocypher ,
+.Xr crypto_wipe 3monocypher ,
+.Xr intro 3monocypher
+.Sh STANDARDS
+These functions implement RFC 8439.
+.Fn crypto_aead_lock
+and
+.Fn crypto_aead_init_x ,
+use XChaCha20 instead of ChaCha20.
+.Fn crypto_aead_init_djb
+uses a 64-bit nonce and a 64-bit counter.
+.Fn crypto_aead_init_ietf
+is fully compatible with the RFC.
+Note that XChaCha20 derives from ChaCha20 the same way XSalsa20 derives
+from Salsa20 and benefits from the same security reduction
+(proven secure as long as ChaCha20 itself is secure).
+.Pp
+.Fn crypto_aead_read
+and
+.Fn crypto_aead_write
+preserve the nonce and counter defined in
+.Fn crypto_aead_init_x ,
+.Fn crypto_aead_init_djb ,
+or
+.Fn crypto_aead_init_ietf ,
+and instead change the session key.
+The new session key is made from bytes [32..63] of the ChaCha20 stream
+used to generate the authentication key and encrypt the message.
+(Recall that bytes [0..31] are the authentication key, and bytes [64..]
+are used to encrypt the message.)
+.Sh HISTORY
+The
+.Fn crypto_lock
+and
+.Fn crypto_unlock
+functions first appeared in Monocypher 0.1.
+.Fn crypto_lock_aead
+and
+.Fn crypto_unlock_aead
+were introduced in Monocypher 1.1.0.
+In Monocypher 2.0.0, the underlying algorithms for these functions were
+changed from a custom XChaCha20/Poly1305 construction to an
+implementation of RFC 7539 (now RFC 8439) with XChaCha20 instead of
+ChaCha20.
+The
+.Fn crypto_lock_encrypt
+and
+.Fn crypto_lock_auth
+functions were removed in Monocypher 2.0.0.
+In Monocypher 4.0.0, the
+.Fn crypto_lock
+and
+.Fn crypto_unlock
+were removed,
+Functions were renamed and arguments reordered for consistency,
+and the incremental interface was added.
+.Sh CAVEATS
+Monocypher does not perform any input validation.
+Any deviation from the specified input and output length ranges results
+in
+.Sy undefined behaviour .
+Make sure your inputs are correct.
diff --git a/lib/Utils.Cryptography/monocypher/vendor/doc/crypto_argon2.3monocypher b/lib/Utils.Cryptography/monocypher/vendor/doc/crypto_argon2.3monocypher
new file mode 100644
index 0000000..a84f3d9
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/doc/crypto_argon2.3monocypher
@@ -0,0 +1,400 @@
+.\" This file is dual-licensed. Choose whichever you want.
+.\"
+.\" The first licence is a regular 2-clause BSD licence. The second licence
+.\" is the CC-0 from Creative Commons. It is intended to release Monocypher
+.\" to the public domain. The BSD licence serves as a fallback option.
+.\"
+.\" SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+.\"
+.\" ----------------------------------------------------------------------------
+.\"
+.\" Copyright (c) 2017-2019, 2023 Loup Vaillant
+.\" Copyright (c) 2018 Michael Savage
+.\" Copyright (c) 2017, 2019-2021, 2023 Fabio Scotoni
+.\" All rights reserved.
+.\"
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions are
+.\" met:
+.\"
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\"
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the
+.\" distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+.\" HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" ----------------------------------------------------------------------------
+.\"
+.\" Written in 2017-2021, 2023 by Loup Vaillant, Michael Savage and Fabio Scotoni
+.\"
+.\" To the extent possible under law, the author(s) have dedicated all copyright
+.\" and related neighboring rights to this software to the public domain
+.\" worldwide. This software is distributed without any warranty.
+.\"
+.\" You should have received a copy of the CC0 Public Domain Dedication along
+.\" with this software. If not, see
+.\" <https://creativecommons.org/publicdomain/zero/1.0/>
+.\"
+.Dd February 25, 2023
+.Dt CRYPTO_ARGON2 3MONOCYPHER
+.Os
+.Sh NAME
+.Nm crypto_argon2
+.Nd password-based key derivation
+.Sh SYNOPSIS
+.In monocypher.h
+.Ft void
+.Fo crypto_argon2
+.Fa "uint8_t *hash"
+.Fa "uint32_t hash_size"
+.Fa "void *work_area"
+.Fa "crypto_argon2_config config"
+.Fa "crypto_argon2_inputs inputs"
+.Fa "crypto_argon2_extras extras"
+.Fc
+.Pp
+.Fa "extern const crypto_argon2_extras crypto_argon2_no_extras;"
+.Sh DESCRIPTION
+Argon2 is a resource intensive password-based key derivation scheme
+optimised for the typical x86-like processor.
+It runs in constant time with respect to the contents of the password.
+.Pp
+Typical applications are password checking (for online services) and
+key derivation (for encryption).
+Derived keys can be used to encrypt, for example, private keys or
+password databases.
+.Pp
+The version provided by Monocypher has no threading support, so the
+degree of parallelism is limited to 1.
+This is considered good enough for most purposes.
+.Pp
+The arguments to
+.Fn crypto_argon2
+are:
+.Bl -tag -width Ds
+.It Fa hash
+The output hash.
+If all parameters to
+.Fn crypto_argon2
+are identical between two calls,
+then the output
+.Fa hash
+is also identical.
+In other words, all input parameters passed to the function influence
+the output value.
+.It Fa hash_size
+Length of
+.Fa hash ,
+in bytes.
+This argument should be set to 32 or 64 for compatibility with the
+.Xr crypto_verify32 3monocypher
+or
+.Xr crypto_verify64 3monocypher
+constant time comparison functions.
+.It Fa work_area
+Temporary buffer for the algorithm, allocated by the caller.
+It must be
+.Fa config.nb_blocks
+× 1024 bytes big and suitably aligned for 64-bit integers.
+If you are not sure how to allocate that buffer, just use
+.Xr malloc 3 .
+.Pp
+The work area is automatically wiped by
+.Fn crypto_argon2 .
+.It Fa config
+A struct of type
+.Vt crypto_argon2_config
+that determines the base parameters of this particular
+instance of Argon2.
+These are domain parameters and remain constant between
+multiple invocations of
+.Fn crypto_argon2 .
+.It Fa inputs
+A struct of type
+.Vt crypto_argon2_inputs
+that contains the actual input parameters.
+.It Fa extras
+A struct of type
+.Vt crypto_argon2_extras
+that contains optional extra input parameters,
+which are not commonly used.
+.El
+.Pp
+The
+.Vt crypto_argon2_config
+struct is defined as follows:
+.Bd -literal -offset indent
+typedef struct {
+ uint32_t algorithm;
+ uint32_t nb_blocks;
+ uint32_t nb_passes;
+ uint32_t nb_lanes;
+} crypto_argon2_config;
+.Ed
+.Pp
+Its members are:
+.Bl -tag -width Ds
+.It Fa algorithm
+This value determines which variant of Argon2 should be used.
+.Dv CRYPTO_ARGON2_D
+indicates Argon2d,
+.Dv CRYPTO_ARGON2_I
+indicates Argon2i,
+.Dv CRYPTO_ARGON2_ID
+indicates Argon2id.
+.It Fa nb_blocks
+The number of blocks for the work area.
+Must be at least 8 ×
+.Fa nb_lanes .
+A value of 100000 (one hundred megabytes) is a good starting point.
+If the computation takes too long, reduce this number.
+If it is too fast, increase it.
+If it is still too fast with all available memory, increase
+.Fa nb_passes .
+.It Fa nb_passes
+The number of passes.
+Must be at least 1.
+A value of 3 is
+.Em strongly
+recommended when using Argon2i;
+any value lower than 3 enables significantly more efficient attacks.
+.It Fa nb_lanes
+The level of parallelism.
+Must be at least 1.
+Since Monocypher does not support threads,
+this does not actually increase the number of threads.
+It is only provided for completeness to match the Argon2 specification.
+Otherwise, leaving it to 1 is strongly recommended.
+.Pp
+Users who want to take actual advantage of parallelism should instead
+call several instances of Argon2 in parallel.
+The
+.Fa extras
+parameter may be used to differentiate the inputs and produce
+independent digests that can be hashed together.
+.El
+.Pp
+The
+.Vt crypto_argon2_inputs
+struct is defined as follows:
+.Bd -literal -offset indent
+typedef struct {
+ const uint8_t *pass;
+ const uint8_t *salt;
+ uint32_t pass_size;
+ uint32_t salt_size;
+} crypto_argon2_inputs;
+.Ed
+.Pp
+Its members are:
+.Bl -tag -width Ds
+.It Fa pass
+The password to hash.
+It should be wiped with
+.Xr crypto_wipe 3monocypher
+after being hashed.
+.It Fa pass_size
+Length of
+.Fa pass ,
+in bytes.
+.It Fa salt
+A password salt.
+This should be filled with random bytes, generated separately for each
+password to be hashed.
+See
+.Xr intro 3monocypher
+for advice about generating random bytes (use the operating system's
+random number generator).
+.It Fa salt_size
+Length of
+.Fa salt ,
+in bytes.
+Must be at least 8.
+16 is recommended.
+.El
+.Pp
+The
+.Vt crypto_argon2_extras
+struct is defined as follows:
+.Bd -literal -offset indent
+typedef struct {
+ const uint8_t *key;
+ const uint8_t *ad;
+ uint32_t key_size;
+ uint32_t ad_size;
+} crypto_argon2_extras;
+.Ed
+.Pp
+Its members are:
+.Bl -tag -width Ds
+.It Fa key
+A key to use in the hash.
+May be
+.Dv NULL
+if
+.Fa key_size
+is zero.
+The key is generally not needed, but it does have some uses.
+In the context of password derivation, it would be stored separately
+from the password database and would remain secret even if an
+attacker were to steal the database.
+Note that changing the key requires rehashing the user's password,
+which can only be done when the user logs in.
+.It Fa key_size
+Length of
+.Fa key ,
+in bytes.
+Must be zero if there is no key.
+.It Fa ad
+Additional data.
+May be
+.Dv NULL
+if
+.Fa ad_size
+is zero.
+This is additional data that goes into the hash, similar to the
+authenticated encryption construction in
+.Xr crypto_aead_lock 3monocypher .
+Can be used to differentiate inputs when invoking several Argon2
+instances in parallel:
+each instance gets a different thread number as additional data,
+generating as many independent digests as we need.
+We can then hash those digests with
+.Xr crypto_blake2b 3monocypher .
+.It Fa ad_size
+Length of
+.Fa ad ,
+in bytes.
+Must be zero if there is no additional data.
+.El
+.Pp
+The arguments in the
+.Fa config
+and
+.Fa extras
+structs may overlap or point at the same buffer.
+.Pp
+Use
+.Xr crypto_verify16 3monocypher ,
+.Xr crypto_verify32 3monocypher ,
+or
+.Xr crypto_verify64 3monocypher
+to compare password hashes to prevent timing attacks.
+.Pp
+To select the
+.Fa nb_blocks
+and
+.Fa nb_passes
+parameters, it should first be decided how long the computation should
+take.
+For user authentication, values somewhere between half a second
+(convenient) and several seconds (paranoid) are recommended.
+The computation should use as much memory as can be spared.
+.Pp
+Since parameter selection depends on your hardware, some trial and error
+will be required in order to determine the ideal settings.
+Argon2i with three iterations and 100000 blocks
+(one hundred megabytes of memory)
+is a good starting point.
+So is Argon2id with one iteration and 300000 blocks.
+Adjust
+.Fa nb_blocks
+first.
+If using all available memory is not slow enough, increase
+.Fa nb_passes .
+.Sh RETURN VALUES
+.Fn crypto_argon2
+returns nothing.
+.Sh EXAMPLES
+The following example assumes the existence of
+.Fn arc4random_buf ,
+which fills the given buffer with cryptographically secure random bytes.
+If
+.Fn arc4random_buf
+does not exist on your system, see
+.Xr intro 3monocypher
+for advice about how to generate cryptographically secure random bytes.
+.Pp
+This example shows how to hash a password with the recommended baseline
+parameters:
+.Bd -literal -offset indent
+uint8_t hash[32]; /* Output hash */
+uint8_t salt[16]; /* Random salt */
+crypto_argon2_config config = {
+ .algorithm = CRYPTO_ARGON2_I, /* Argon2i */
+ .nb_blocks = 100000, /* 100 megabytes */
+ .nb_passes = 3, /* 3 iterations */
+ .nb_lanes = 1 /* Single-threaded */
+};
+uint8_t password[] = "Okay Password!";
+crypto_argon2_inputs inputs = {
+ .pass = password, /* User password */
+ .salt = salt, /* Salt for the password */
+ .pass_size = sizeof(password) - 1, /* Password length */
+ .salt_size = 16
+};
+crypto_argon2_extras extras = {0}; /* Extra parameters unused */
+
+/* Allocate work area.
+ * Note the conversion to size_t.
+ * Without it we cannot allocate more than 4GiB.
+ */
+void *work_area = malloc((size_t)config.nb_blocks * 1024);
+if (work_area == NULL) {
+ /* Handle malloc() failure */
+ /* Wipe secrets if they are no longer needed */
+ crypto_wipe(password, sizeof(password));
+} else {
+ arc4random_buf(salt, 16);
+ crypto_argon2(hash, 32, work_area,
+ config, inputs, extras);
+ /* Wipe secrets if they are no longer needed */
+ crypto_wipe(password, sizeof(password));
+ free(work_area);
+}
+
+
+.Ed
+.Sh SEE ALSO
+.Xr crypto_aead_lock 3monocypher ,
+.Xr crypto_verify16 3monocypher ,
+.Xr crypto_wipe 3monocypher ,
+.Xr intro 3monocypher
+.Sh STANDARDS
+.Fn crypto_argon2
+implements Argon2 as described in RFC 9106,
+but does not support actual parallelism.
+.Sh HISTORY
+In Monocypher 0.1,
+.Fn crypto_argon2i
+implemented Argon2i and had all extra parameters as input.
+It was then split into a
+.Fn crypto_argon2i_general
+and a simplified
+.Fn crypto_argon2i
+function in Monocypher 1.1.0.
+Both were replaced by
+.Fn crypto_argon2
+in Monocypher 4.0.0.
+.Sh CAVEATS
+Monocypher does not perform any input validation.
+Any deviation from the algorithm constants,
+specified input and output length ranges results
+in
+.Sy undefined behaviour .
+Make sure your inputs are correct.
diff --git a/lib/Utils.Cryptography/monocypher/vendor/doc/crypto_blake2b.3monocypher b/lib/Utils.Cryptography/monocypher/vendor/doc/crypto_blake2b.3monocypher
new file mode 100644
index 0000000..86ff25b
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/doc/crypto_blake2b.3monocypher
@@ -0,0 +1,544 @@
+.\" This file is dual-licensed. Choose whichever you want.
+.\"
+.\" The first licence is a regular 2-clause BSD licence. The second licence
+.\" is the CC-0 from Creative Commons. It is intended to release Monocypher
+.\" to the public domain. The BSD licence serves as a fallback option.
+.\"
+.\" SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+.\"
+.\" ----------------------------------------------------------------------------
+.\"
+.\" Copyright (c) 2017-2023 Loup Vaillant
+.\" Copyright (c) 2018 Michael Savage
+.\" Copyright (c) 2017, 2020-2023 Fabio Scotoni
+.\" All rights reserved.
+.\"
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions are
+.\" met:
+.\"
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\"
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the
+.\" distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+.\" HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" ----------------------------------------------------------------------------
+.\"
+.\" Written in 2017-2023 by Loup Vaillant, Michael Savage and Fabio Scotoni
+.\"
+.\" To the extent possible under law, the author(s) have dedicated all copyright
+.\" and related neighboring rights to this software to the public domain
+.\" worldwide. This software is distributed without any warranty.
+.\"
+.\" You should have received a copy of the CC0 Public Domain Dedication along
+.\" with this software. If not, see
+.\" <https://creativecommons.org/publicdomain/zero/1.0/>
+.\"
+.Dd February 2, 2023
+.Dt CRYPTO_BLAKE2B 3MONOCYPHER
+.Os
+.Sh NAME
+.Nm crypto_blake2b ,
+.Nm crypto_blake2b_keyed ,
+.Nm crypto_blake2b_init ,
+.Nm crypto_blake2b_keyed_init ,
+.Nm crypto_blake2b_update ,
+.Nm crypto_blake2b_final
+.Nd hashing, message authentication, and key derivation with BLAKE2b
+.Sh SYNOPSIS
+.In monocypher.h
+.Ft void
+.Fo crypto_blake2b
+.Fa "uint8_t hash[64]"
+.Fa "size_t hash_size"
+.Fa "const uint8_t *message"
+.Fa "size_t message_size"
+.Fc
+.Fo crypto_blake2b_keyed
+.Fa "uint8_t hash[64]"
+.Fa "size_t hash_size"
+.Fa "uint8_t key[64]"
+.Fa "size_t key_size"
+.Fa "const uint8_t *message"
+.Fa "size_t message_size"
+.Fc
+.Ft void
+.Fo crypto_blake2b_init
+.Fa "crypto_blake2b_ctx *ctx"
+.Fa "size_t hash_size"
+.Fc
+.Ft void
+.Fo crypto_blake2b_keyed_init
+.Fa "crypto_blake2b_ctx *ctx"
+.Fa "size_t hash_size"
+.Fa "uint8_t key[64]"
+.Fa "size_t key_size"
+.Fc
+.Ft void
+.Fo crypto_blake2b_update
+.Fa "crypto_blake2b_ctx *ctx"
+.Fa "const uint8_t *message"
+.Fa "size_t message_size"
+.Fc
+.Ft void
+.Fo crypto_blake2b_final
+.Fa "crypto_blake2b_ctx *ctx"
+.Fa "uint8_t *hash"
+.Fc
+.Sh DESCRIPTION
+.Ss Hashing
+.Fn crypto_blake2b ,
+.Fn crypto_blake2b_init ,
+.Fn crypto_blake2b_update ,
+and
+.Fn crypto_blake2b_final
+implement BLAKE2b,
+a cryptographically secure hash based on the ideas of ChaCha20.
+It is faster than MD5, yet just as secure as SHA-3.
+.Pp
+Note that BLAKE2b itself is not suitable for hashing passwords and
+deriving keys from them;
+use the
+.Xr crypto_argon2 3monocypher
+family of functions for that purpose instead.
+.Pp
+While BLAKE2b is immune to length extension attacks,
+and as such requires fewer precautions than older hashes,
+we do recommend avoiding prefix-MAC and using keyed mode with
+.Fn crypto_blake2b_keyed
+instead.
+Doing so enables better security arguments when using BLAKE2b as a
+random oracle.
+.Pp
+The arguments are:
+.Bl -tag -width Ds
+.It Fa config
+The configuration parameter structure, see below.
+.It Fa hash
+The output hash.
+.It Fa hash_size
+Length of
+.Fa hash ,
+in bytes.
+Must be between 1 and 64.
+Anything below 32 is discouraged when using BLAKE2b as a general-purpose
+hash function.
+.It Fa message
+The message to hash.
+May overlap with
+.Fa hash .
+May be
+.Dv NULL
+if
+.Fa message_size
+is 0.
+.It Fa message_size
+Length of
+.Fa message ,
+in bytes.
+.El
+.Ss Message authentication codes
+.Fn crypto_blake2b_keyed ,
+.Fn crypto_blake2b_keyed_init ,
+.Fn crypto_blake2b_update ,
+and
+.Fn crypto_blake2b_final
+implement keyed BLAKE2b,
+and can be used for message authentication codes or as a random oracle,
+just like HMAC.
+The arguments are:
+.Bl -tag -width Ds
+.It Fa hash
+The output message authentication code (MAC).
+To avoid timing attacks,
+use
+.Xr crypto_verify16 3monocypher ,
+.Xr crypto_verify32 3monocypher ,
+or
+.Xr crypto_verify64 3monocypher
+to compare (possibly truncated) MACs.
+.It Fa hash_size
+Length of
+.Fa hash ,
+in bytes.
+Must be between 1 and 64.
+Anything below 16 is discouraged when using BLAKE2b as a message
+authentication code.
+Anything below 32 is discouraged when using BLAKE2b as a key derivation
+function (KDF).
+.It Fa key
+Some secret key.
+When uniformly random,
+one cannot predict the final hash without it.
+Users may want to wipe the key with
+.Xr crypto_wipe 3monocypher
+once they are done with it.
+May overlap with
+.Fa hash or
+.Fa message .
+May be
+.Dv NULL
+if
+.Fa key_size
+is 0, in which case no key is used.
+Can also be used as a random salt in the context of KDF extraction,
+or as pre-shared-key in the context of KDF expansion.
+.It Fa key_size
+Length of
+.Fa key ,
+in bytes.
+Must be between 0 and 64.
+32 is a good default.
+.It Fa message
+The message to compute the MAC for.
+May overlap with
+.Fa hash or
+.Fa key .
+May be
+.Dv NULL
+if
+.Fa message_size
+is 0.
+Can also be used as input key material in the context of KDF extraction,
+or to host a counter and domain separation string in the context of KDF
+expansion.
+.It Fa message_size
+Length of
+.Fa message ,
+in bytes.
+.El
+.Ss Key derivation
+BLAKE2b can be used to implement
+.Dq key derivation functions
+(KDF) very similar to HKDF.
+The typical parameters of a KDF are:
+.Bl -tag -width Ds
+.It Em IKM
+Input key material containing enough secret entropy to derive uniformly
+random keys from,
+such as the shared secret of a key exchange performed with
+.Xr crypto_x25519 3monocypher .
+Passwords do
+.Sy not
+contain enough entropy to be used as input key material.
+Hash them with
+.Xr crypto_argon2 3monocypher
+instead.
+.It Em salt
+An optional random salt,
+used to increase the security of the output key material (OKM) in some
+settings.
+It should be either absent,
+constant,
+or contain at least 16 random bytes.
+.It Em info
+Optional domain separation string for key derivation.
+.El
+.Pp
+From these parameters,
+the KDF derives an arbitrary amount of independent random bytes,
+also called
+.Dq output key material
+(OKM),
+that can be used as regular encryption or secret keys.
+.Pp
+In practice, KDFs are often separated in two steps:
+.Dq extraction
+and
+.Dq expansion .
+The extraction step reads the IKM (and optional salt) to derive a
+.Dq pseudo-random key
+(PRK),
+which can be used either directly as a regular key,
+.Em or
+as an input for the extraction step.
+The expansion step then reads the PRK (and optional info) to make the
+OKM.
+.Pp
+To implement KDF extraction,
+just call
+.Fn crypto_blake2b_keyed
+with the
+.Fa message
+as the IKM and
+.Fa key
+as the salt,
+or
+.Fn crypto_blake2b
+if there is no salt.
+This is unintuitive,
+but having the IKM in the
+.Fa message
+argument lets us input arbitrary amounts of data.
+It is also the HMAC and HKDF way.
+.Pp
+For KDF expansion any pseudo-random-function (PRF) can be used.
+You can call
+.Fn crypto_blake2b_keyed
+in counter mode with
+.Fa key
+as the PRK
+(though doing it manually is a bit tedious),
+or
+.Xr crypto_chacha20_djb 3monocypher
+with its
+.Fa key
+as the PRK and its
+.Fa nonce
+for domain separation.
+.Ss Incremental interface
+An incremental interface is provided.
+It is useful for handling streams of data or
+large files without using too much memory.
+This interface uses three steps:
+.Bl -bullet
+.It
+Initialisation with
+.Fn crypto_blake2b_init
+or
+.Fn crypto_blake2b_keyed_init ,
+which set up a context with the hashing parameters;
+.It
+Update with
+.Fn crypto_blake2b_update ,
+which hashes the message chunk by chunk and keeps the intermediary
+result in the context;
+.It
+and Finalisation with
+.Fn crypto_blake2b_final ,
+which produces the final hash.
+The
+.Ft crypto_blake2b_ctx
+is automatically wiped upon finalisation.
+.El
+.Pp
+Calling
+.Fn crypto_blake2b
+is the same as calling
+.Fn crypto_blake2b_init ,
+.Fn crypto_blake2b_update ,
+and
+.Fn crypto_blake2b_final .
+Calling
+.Fn crypto_blake2b_keyed
+is the same as calling
+.Fn crypto_blake2b_keyed_init ,
+.Fn crypto_blake2b_update ,
+and
+.Fn crypto_blake2b_final .
+.Pp
+Calling
+.Fn crypto_blake2b
+is the same as calling
+.Fn crypto_blake2b_keyed
+with an empty key.
+.Sh RETURN VALUES
+These functions return nothing.
+.Sh EXAMPLES
+The following examples assume the existence of
+.Fn arc4random_buf ,
+which fills the given buffer with cryptographically secure random bytes.
+If
+.Fn arc4random_buf
+does not exist on your system, see
+.Xr intro 3monocypher
+for advice about how to generate cryptographically secure random bytes.
+.Pp
+Hashing a message all at once:
+.Bd -literal -offset indent
+uint8_t hash [64]; /* Output hash (64 bytes) */
+uint8_t message[12] = "Lorem ipsum"; /* Message to hash */
+crypto_blake2b(hash, sizeof(hash), message, sizeof(message));
+.Ed
+.Pp
+Computing a message authentication code all at once:
+.Bd -literal -offset indent
+uint8_t hash [16];
+uint8_t key [32];
+uint8_t message[11] = "Lorem ipsu"; /* Message to authenticate */
+arc4random_buf(key, sizeof(key));
+crypto_blake2b_keyed(hash , sizeof(hash),
+ key , sizeof(key),
+ message, sizeof(message));
+/* Wipe secrets if they are no longer needed */
+crypto_wipe(message, sizeof(message));
+crypto_wipe(key, sizeof(key));
+.Ed
+.Pp
+Hashing a message incrementally (without a key):
+.Bd -literal -offset indent
+uint8_t hash [ 64]; /* Output hash (64 bytes) */
+uint8_t message[500] = {1}; /* Message to hash */
+crypto_blake2b_ctx ctx;
+crypto_blake2b_init(&ctx, sizeof(hash));
+for (size_t i = 0; i < 500; i += 100) {
+ crypto_blake2b_update(&ctx, message + i, 100);
+}
+crypto_blake2b_final(&ctx, hash);
+.Ed
+.Pp
+Computing a message authentication code incrementally:
+.Bd -literal -offset indent
+uint8_t hash [ 16];
+uint8_t key [ 32];
+uint8_t message[500] = {1}; /* Message to authenticate */
+arc4random_buf(key, sizeof(key));
+crypto_blake2b_ctx ctx;
+crypto_blake2b_keyed_init(&ctx, sizeof(hash), key,
+ sizeof(key));
+/* Wipe the key */
+crypto_wipe(key, sizeof(key));
+for (size_t i = 0; i < 500; i += 100) {
+ crypto_blake2b_update(&ctx, message + i, 100);
+ /* Wipe secrets if they are no longer needed */
+ crypto_wipe(message + i, 100);
+}
+crypto_blake2b_final(&ctx, hash);
+.Ed
+.Pp
+Computing key derivation with BLAKE2b and ChaCha20:
+.Bd -literal -offset indent
+void kdf(uint8_t *okm, size_t okm_size, /* unlimited */
+ uint8_t *ikm, size_t ikm_size, /* unlimited */
+ uint8_t *salt, size_t salt_size, /* <= 64 bytes */
+ uint8_t info[8]) /* == 8 bytes */
+{
+ /* Extract */
+ uint8_t prk[32];
+ crypto_blake2b_keyed(prk , sizeof(prk),
+ salt, salt_size,
+ ikm , ikm_size);
+ /* Expand */
+ crypto_chacha20_djb(okm, NULL, okm_size, prk, info, 0);
+}
+.Ed
+.Pp
+Computing key derivation with BLAKE2b and XChaCha20:
+.Bd -literal -offset indent
+void xkdf(uint8_t *okm, size_t okm_size, /* unlimited */
+ uint8_t *ikm, size_t ikm_size, /* unlimited */
+ uint8_t *salt, size_t salt_size, /* <= 64 bytes */
+ uint8_t *info, size_t info_size) /* unlimited */
+{
+ /* Extract */
+ uint8_t prk[32];
+ crypto_blake2b_keyed(prk , sizeof(prk),
+ salt, salt_size,
+ ikm , ikm_size);
+ /* Expand */
+ uint8_t nonce[24];
+ crypto_blake2b(nonce, sizeof(nonce), info, info_size);
+ crypto_chacha20_x(okm, NULL, okm_size, prk, nonce, 0);
+}
+.Ed
+.Pp
+Computing key derivation with BLAKE2b alone
+(a little tedious indeed):
+.Bd -literal -offset indent
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+
+void b2kdf(uint8_t *okm, size_t okm_size, /* unlimited */
+ uint8_t *ikm, size_t ikm_size, /* unlimited */
+ uint8_t *salt, size_t salt_size, /* <= 64 bytes */
+ uint8_t *info, size_t info_size) /* unlimited */
+{
+ /* Extract */
+ uint8_t prk[64];
+ crypto_blake2b_keyed(prk , sizeof(prk),
+ salt, salt_size,
+ ikm , ikm_size);
+ /* Expand */
+ uint8_t ctr[8] = {0};
+ while(okm_size > 0) {
+ size_t size = MIN(okm_size, 64);
+ crypto_blake2b_ctx ctx;
+ crypto_blake2b_keyed_init(&ctx, size, prk, 64);
+ crypto_blake2b_update(&ctx, ctr, sizeof(ctr));
+ crypto_blake2b_update(&ctx, info, info_size);
+ crypto_blake2b_final(&ctx, okm);
+ okm += size;
+ okm_size -= size;
+ /* increment ctr */
+ unsigned acc = 1;
+ for (size_t i = 0; i < sizeof(ctr); i++) {
+ acc = ctr[i] + acc;
+ ctr[i] = acc & 0xff;
+ acc >>= 8;
+ }
+ }
+}
+.Ed
+.Sh SEE ALSO
+.Xr crypto_x25519 3monocypher ,
+.Xr crypto_aead_lock 3monocypher ,
+.Xr intro 3monocypher
+.Sh STANDARDS
+These functions implement BLAKE2b, described in RFC 7693.
+.Sh HISTORY
+The
+.Fn crypto_blake2b ,
+.Fn crypto_blake2b_init ,
+.Fn crypto_blake2b_update ,
+and
+.Fn crypto_blake2b_final
+functions first appeared in Monocypher 0.1.
+In Monocypher 4.0.0,
+.Fn crypto_blake2b_general
+and
+.Fn crypto_blake2b_general_init
+were removed,
+.Fn crypto_blake2b_keyed
+and
+.Fn crypto_blake2b_keyed_init
+were added,
+and the
+.Fa hash_size
+argument were added to
+.Fn crypto_blake2b
+and
+.Fn crypto_blake2b_init .
+.Sh CAVEATS
+Monocypher does not perform any input validation.
+Any deviation from the specified input and output length ranges results
+in
+.Sy undefined behaviour .
+Make sure your inputs are correct.
+.Sh SECURITY CONSIDERATIONS
+BLAKE2b is a general-purpose cryptographic hash function;
+this means that it is not suited for hashing passwords and deriving
+cryptographic keys from passwords.
+While cryptographic keys usually have hundreds of bits of entropy,
+passwords are often much less complex.
+When storing passwords as hashes or when deriving keys from them,
+the goal is normally to prevent attackers from quickly iterating all
+possible passwords.
+Because passwords tend to be simple,
+it is important to artificially slow down attackers by using
+computationally difficult hashing algorithms.
+Monocypher therefore provides
+.Xr crypto_argon2 3monocypher
+for password hashing and deriving keys from passwords.
+.Sh IMPLEMENTATION DETAILS
+The core loop is unrolled by default.
+This speeds up BLAKE2b by about 20% on modern processors.
+On the other hand,
+this inflates the binary size by several kilobytes,
+and is slower on some embedded platforms.
+To roll the loop and generate a smaller binary,
+compile Monocypher with the -DBLAKE2_NO_UNROLLING option.
diff --git a/lib/Utils.Cryptography/monocypher/vendor/doc/crypto_chacha20_djb.3monocypher b/lib/Utils.Cryptography/monocypher/vendor/doc/crypto_chacha20_djb.3monocypher
new file mode 100644
index 0000000..84bcff2
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/doc/crypto_chacha20_djb.3monocypher
@@ -0,0 +1,447 @@
+.\" This file is dual-licensed. Choose whichever you want.
+.\"
+.\" The first licence is a regular 2-clause BSD licence. The second licence
+.\" is the CC-0 from Creative Commons. It is intended to release Monocypher
+.\" to the public domain. The BSD licence serves as a fallback option.
+.\"
+.\" SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+.\"
+.\" ----------------------------------------------------------------------------
+.\"
+.\" Copyright (c) 2017-2019, 2023 Loup Vaillant
+.\" Copyright (c) 2017-2018 Michael Savage
+.\" Copyright (c) 2017, 2019-2021, 2023 Fabio Scotoni
+.\" All rights reserved.
+.\"
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions are
+.\" met:
+.\"
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\"
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the
+.\" distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+.\" HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" ----------------------------------------------------------------------------
+.\"
+.\" Written in 2017-2023 by Loup Vaillant, Michael Savage and Fabio Scotoni
+.\"
+.\" To the extent possible under law, the author(s) have dedicated all copyright
+.\" and related neighboring rights to this software to the public domain
+.\" worldwide. This software is distributed without any warranty.
+.\"
+.\" You should have received a copy of the CC0 Public Domain Dedication along
+.\" with this software. If not, see
+.\" <https://creativecommons.org/publicdomain/zero/1.0/>
+.\"
+.Dd February 25, 2023
+.Dt CRYPTO_CHACHA20 3MONOCYPHER
+.Os
+.Sh NAME
+.Nm crypto_chacha20_djb ,
+.Nm crypto_chacha20_ietf ,
+.Nm crypto_chacha20_x ,
+.Nm crypto_chacha20_h
+.Nd ChaCha20 and XChaCha20 encryption functions
+.Sh SYNOPSIS
+.In monocypher.h
+.Ft uint64_t
+.Fo crypto_chacha20_djb
+.Fa "uint8_t *cipher_text"
+.Fa "const uint8_t *plain_text"
+.Fa "size_t text_size"
+.Fa "const uint8_t key[32]"
+.Fa "const uint8_t nonce[8]"
+.Fa "uint64_t ctr"
+.Fc
+.Ft uint32_t
+.Fo crypto_chacha20_ietf
+.Fa "uint8_t *cipher_text"
+.Fa "const uint8_t *plain_text"
+.Fa "size_t text_size"
+.Fa "const uint8_t key[32]"
+.Fa "const uint8_t nonce[12]"
+.Fa "uint32_t ctr"
+.Fc
+.Ft uint64_t
+.Fo crypto_chacha20_x
+.Fa "uint8_t *cipher_text"
+.Fa "const uint8_t *plain_text"
+.Fa "size_t text_size"
+.Fa "const uint8_t key[32]"
+.Fa "const uint8_t nonce[24]"
+.Fa "uint64_t ctr"
+.Fc
+.Ft void
+.Fo crypto_chacha20_h
+.Fa "uint8_t out[32]"
+.Fa "const uint8_t key[32]"
+.Fa "const uint8_t in[16]"
+.Fc
+.Sh DESCRIPTION
+These functions provide an interface for the ChaCha20 encryption
+primitive.
+.Pp
+ChaCha20 is a low-level primitive.
+Consider using authenticated encryption, implemented by
+.Xr crypto_aead_lock 3monocypher .
+.Pp
+The arguments are:
+.Bl -tag -width Ds
+.It Fa key
+A 32-byte secret key.
+.It Fa nonce
+An 8-byte, 12-byte, or 24-byte number used only once with any given key.
+It does not need to be secret or random, but it does have to be unique.
+Repeating a nonce with the same key reveals the XOR of two different
+messages, which allows decryption.
+24-byte nonces can be selected at random.
+8-byte and 12-byte nonces
+.Em cannot
+because they are too small and the same nonce may be selected twice by
+accident.
+See
+.Xr intro 3monocypher
+for advice about generating random numbers (use the operating system's
+random number generator).
+.It Fa plain_text
+The message to encrypt.
+It is allowed to be
+.Dv NULL ,
+in which case it will be interpreted as an all-zero input.
+.Fa cipher_text
+will then contain the raw ChaCha20 stream.
+.It Fa cipher_text
+The encrypted message.
+.It Fa text_size
+Length of both
+.Fa plain_text
+and
+.Fa cipher_text ,
+in bytes.
+.It Fa ctr
+The number of 64-byte blocks we skip from the beginning of the stream.
+This can be used to encrypt (or decrypt) part of a long message or to
+implement some AEAD constructions such as the one described in RFC
+8439.
+Should be zero by default.
+When using this, be careful not to accidentally reuse parts of the
+random stream as that would destroy confidentiality.
+The return value can help here.
+.El
+.Pp
+The
+.Fa key
+and
+.Fa nonce
+buffers may overlap.
+.Fa plain_text
+and
+.Fa cipher_text
+must either be the same buffer (for in-place encryption) or
+non-overlapping.
+.Pp
+.Fn crypto_chacha20_djb ,
+.Fn crypto_chacha20_ietf ,
+and
+.Fn crypto_chacha20_x
+perform a ChaCha20 operation.
+Their main difference is the size of their nonce and counter.
+.Fn crypto_chacha20_ietf
+in particular implements RFC 8439,
+and is provided strictly for compatibility with existing systems or
+standards compliance.
+.Pp
+.Fn crypto_chacha20_x
+Is the only function that uses a nonce long enough to be random.
+This makes it easier to use securely,
+and the performance hit of the extended nonce is often negligible in
+practice.
+Use it instead of
+.Fn crypto_chacha20_djb
+and
+.Fn crypto_chacha20_ietf
+if possible.
+.Pp
+The
+.Fn crypto_chacha20_djb ,
+.Fn crypto_chacha20_ietf ,
+and
+.Fn crypto_chacha20_x
+encrypt
+.Fa plain_text
+by XORing it with a pseudo-random stream of
+numbers, seeded by the provided
+.Fa key
+and
+.Fa nonce .
+.Pp
+Since XOR is its own inverse, decryption is the same operation as
+encryption.
+To decrypt the cipher text,
+.Dq encrypt
+it again with the same key and nonce.
+You will likely want to wipe the key when you are done with
+encryption or decryption.
+Use
+.Xr crypto_wipe 3monocypher
+to wipe them.
+.Pp
+The
+.Fa plain_text
+pointer is allowed to be
+.Dv NULL ,
+in which case it will be interpreted as an all-zero input.
+This is useful as a user space random number generator.
+While
+.Sy this should not be used as a random number generator for secrets ,
+for which the operating system random number generator should be
+preferred,
+it can be handy outside of a security context.
+Deterministic procedural generation and reproducible property-based
+tests come to mind.
+Additionally, it
+.Em can
+be used to generate large amounts of random-looking data quickly
+\(en for example to generate padding.
+.Sh RETURN VALUES
+.Fn crypto_chacha20_djb ,
+.Fn crypto_chacha20_ietf ,
+and
+.Fn crypto_chacha20_x
+return the next
+.Fa ctr
+to use with the same key and nonce values;
+this is the previous
+.Fa ctr ,
+plus
+.Fa text_size
+divided by 64 (rounded up).
+.Sh EXAMPLES
+The following examples assume the existence of
+.Fn arc4random_buf ,
+which fills the given buffer with cryptographically secure random bytes.
+If
+.Fn arc4random_buf
+does not exist on your system, see
+.Xr intro 3monocypher
+for advice about how to generate cryptographically secure random bytes.
+.Pp
+Simple encryption:
+.Bd -literal -offset indent
+uint8_t key [ 32]; /* Secret random key */
+uint8_t nonce [ 24]; /* Unique nonce (possibly random) */
+uint8_t plain_text [500] = {1}; /* Secret message */
+uint8_t cipher_text[500]; /* Encrypted message */
+arc4random_buf(key, 32);
+arc4random_buf(nonce, 24);
+crypto_chacha20_x(cipher_text, plain_text, 500, key, nonce, 0);
+/* Wipe secrets if they are no longer needed */
+crypto_wipe(key, 32);
+crypto_wipe(plain_text, 500);
+.Ed
+.Pp
+To decrypt the above:
+.Bd -literal -offset indent
+uint8_t key [ 32]; /* Same key as above */
+const uint8_t nonce [ 24]; /* Same nonce as above */
+uint8_t plain_text [500]; /* Message to decrypt */
+uint8_t cipher_text[500]; /* Secret message */
+crypto_chacha20_x(cipher_text, plain_text, 500, key, nonce, 0);
+/* Wipe secrets if they are no longer needed */
+crypto_wipe(key, 32);
+/* The plaintext likely needs to be processed before you wipe it */
+crypto_wipe(plain_text, 12);
+.Ed
+.Pp
+Incremental encryption (in blocks of 64 bytes):
+.Bd -literal -offset indent
+uint8_t key [ 32]; /* Secret random key */
+uint8_t nonce [ 24]; /* Unique nonce (possibly random) */
+uint8_t plain_text [500]; /* Secret message */
+uint8_t cipher_text[500]; /* Encrypted message */
+uint64_t ctr = 0; /* Block counter */
+unsigned int i;
+arc4random_buf(key, 32);
+arc4random_buf(nonce, 24);
+for(i = 0; i < 500; i += 64) {
+ ctr = crypto_chacha20_x(cipher_text+i, plain_text+i, 64,
+ key, nonce, ctr);
+}
+/* Process data that didn't fit into 64-byte pieces */
+crypto_chacha20_x(cipher_text+500-(i-64),
+ plain_text+500-(i-64),
+ 500-(i-64),
+ key, nonce, ctr);
+/* Wipe secrets if they are no longer needed */
+crypto_wipe(key, 32);
+crypto_wipe(plain_text, 500);
+.Ed
+.Pp
+Encryption by jumping around (do not do this, this is only meant to show
+how the counter works):
+.Bd -literal -offset indent
+uint8_t key [ 32]; /* Secret random key */
+uint8_t nonce [ 24]; /* Unique nonce (possibly random) */
+uint8_t plain_text [500] = {1}; /* Message to be encrypted */
+uint8_t cipher_text[500]; /* Will be the encrypted message */
+arc4random_buf(key, 32);
+arc4random_buf(nonce, 24);
+/* Encrypt the second part of the message first... */
+crypto_chacha20_x(cipher_text + (3 * 64),
+ plain_text + (3 * 64),
+ 500 - (3 * 64),
+ key, nonce, 3);
+/* ...then encrypt the first part */
+crypto_chacha20_x(cipher_text, plain_text, 3 * 64, key, nonce, 0);
+/* Wipe secrets if they are no longer needed */
+crypto_wipe(key, 32);
+crypto_wipe(plain_text, 500);
+.Ed
+.Sh HCHACHA20
+.Fn crypto_chacha20_h
+provides a not-so-cryptographic hash.
+.Sy This is not a general-purpose cryptographic hash function .
+It may be used for some specific purposes such as X25519 key
+derivation or XChaCha20 initialisation.
+If in doubt, do not use directly.
+Use
+.Xr crypto_blake2b 3monocypher
+instead.
+.Pp
+The arguments are:
+.Bl -tag -width Ds
+.It Fa key
+A sufficiently random key, such as the output of
+.Xr crypto_x25519 3monocypher .
+.It Fa in
+The space reserved for the ChaCha20 nonce and counter.
+It does not have to be random.
+.It Fa out
+A cryptographically secure random number
+.Em if
+there is enough entropy in
+.Fa key .
+X25519 shared secrets have enough entropy.
+.El
+.Pp
+For instance:
+.Bd -literal -offset indent
+uint8_t key[32]; /* Must have enough entropy */
+uint8_t in [16]; /* Does not have to be random */
+uint8_t out[32]; /* Will be random iff the above holds */
+arc4random_buf(key, 32);
+crypto_chacha20_h(out, key, in);
+/* Wipe secrets if they are no longer needed */
+crypto_wipe(key, 32);
+crypto_wipe(in , 16);
+.Ed
+.Sh SEE ALSO
+.Xr crypto_aead_lock 3monocypher ,
+.Xr crypto_wipe 3monocypher ,
+.Xr intro 3monocypher
+.Sh STANDARDS
+These functions implement ChaCha20, XChaCha20, and HChaCha20.
+ChaCha20 is described in:
+.Rs
+.%A Daniel J. Bernstein
+.%J SASC 2008 \(en The State of the Art of Stream Ciphers
+.%P pp. 273\(en278
+.%T ChaCha, a variant of Salsa20
+.Re
+The nonce and counter sizes were modified in RFC 8439.
+XChaCha20 derives from ChaCha20 the same way XSalsa20 derives from
+Salsa20 and benefits from the same security reduction (proven secure
+as long as ChaCha20 itself is secure).
+.Sh HISTORY
+.Fn crypto_chacha20 ,
+.Fn crypto_chacha20_ctr ,
+.Fn crypto_ietf_chacha20 ,
+.Fn crypto_ietf_chacha20_ctr ,
+.Fn crypto_xchacha20 ,
+and
+.Fn crypto_xchacha20_ctr
+were added in Monocypher 3.0.0.
+They replace
+.Fn crypto_chacha20_encrypt ,
+.Fn crypto_chacha20_init ,
+.Fn crypto_chacha20_stream ,
+.Fn crypto_chacha20_x_init ,
+and
+.Fn crypto_chacha20_set_ctr
+that were deprecated in Monocypher 3.0.0.
+In Monocypher 4.0.0, only the ctr variants have been kept,
+and were renamed
+.Fn crypto_chacha20_djb ,
+.Fn crypto_chacha20_ietf ,
+and
+.Fn crypto_chacha20_x
+respectively.
+.Pp
+.Fn crypto_chacha20_h
+function first appeared in Monocypher 0.1 as
+.Fn crypto_chacha20_H .
+It was renamed to
+.Fn crypto_hchacha20
+in Monocypher 3.0.0, then
+.Fn crypto_chacha20_h
+in Monocypher 4.0.0.
+.Sh CAVEATS
+Monocypher does not perform any input validation.
+Any deviation from the specified input and output length ranges results
+in
+.Sy undefined behaviour .
+Make sure your inputs are correct.
+.Sh SECURITY CONSIDERATIONS
+.Ss Encrypted does not mean secure
+ChaCha20 only protects against eavesdropping, not forgeries.
+Most applications need protection against forgeries to be properly
+secure.
+To ensure the integrity of a message, use BLAKE2b in keyed mode or
+authenticated encryption; see
+.Xr crypto_blake2b 3monocypher
+and
+.Xr crypto_aead_lock 3monocypher .
+.Ss Nonce reuse
+Repeating a nonce with the same key exposes the XOR of two or more
+plaintext messages, effectively destroying confidentiality.
+.Pp
+For the same reason,
+.Sy do not select small nonces at random .
+The
+.Fn crypto_chacha20_djb
+nonce spans only 64 bits, which is small enough to trigger accidental
+reuses.
+A message counter should be used instead.
+If multiple parties send out messages,
+each can start with an initial nonce of 0, 1, 2 (...) n-1 respectively,
+and increment them by n for each new message.
+Make sure the counters never wrap around.
+.Ss Secure random number generation
+Do not use these functions as a cryptographic random number generator.
+Always use the operating system's random number generator for
+cryptographic purposes; see
+.Xr intro 3monocypher .
+.Ss Protection against side channels
+Secrets should not dwell in memory longer than needed.
+Use
+.Xr crypto_wipe 3monocypher
+to erase secrets you no longer need.
+For ChaCha20, this means the key and in some cases the
+plaintext itself.
diff --git a/lib/Utils.Cryptography/monocypher/vendor/doc/crypto_ed25519_sign.3monocypher b/lib/Utils.Cryptography/monocypher/vendor/doc/crypto_ed25519_sign.3monocypher
new file mode 100644
index 0000000..6418c94
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/doc/crypto_ed25519_sign.3monocypher
@@ -0,0 +1,189 @@
+.\" This file is dual-licensed. Choose whichever you want.
+.\"
+.\" The first licence is a regular 2-clause BSD licence. The second licence
+.\" is the CC-0 from Creative Commons. It is intended to release Monocypher
+.\" to the public domain. The BSD licence serves as a fallback option.
+.\"
+.\" SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+.\"
+.\" ----------------------------------------------------------------------------
+.\"
+.\" Copyright (c) 2019-2020, 2022-2023 Fabio Scotoni
+.\" Copyright (c) 2023 Loup Vaillant
+.\" All rights reserved.
+.\"
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions are
+.\" met:
+.\"
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\"
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the
+.\" distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+.\" HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" ----------------------------------------------------------------------------
+.\"
+.\" Written in 2019-2020 and 2022-2023 by Fabio Scotoni and Loup Vaillant
+.\"
+.\" To the extent possible under law, the author(s) have dedicated all copyright
+.\" and related neighboring rights to this software to the public domain
+.\" worldwide. This software is distributed without any warranty.
+.\"
+.\" You should have received a copy of the CC0 Public Domain Dedication along
+.\" with this software. If not, see
+.\" <https://creativecommons.org/publicdomain/zero/1.0/>
+.\"
+.Dd March 01, 2022
+.Dt CRYPTO_ED25519_SIGN 3MONOCYPHER
+.Os
+.Sh NAME
+.Nm crypto_ed25519_sign ,
+.Nm crypto_ed25519_check ,
+.Nm crypto_ed25519_key_pair ,
+.Nm crypto_ed25519_ph_sign ,
+.Nm crypto_ed25519_ph_check
+.Nd public key signatures
+.Sh SYNOPSIS
+.In monocypher-ed25519.h
+.Ft void
+.Fo crypto_ed25519_sign
+.Fa "uint8_t signature[64]"
+.Fa "const uint8_t secret_key[64]"
+.Fa "const uint8_t *message"
+.Fa "size_t message_size"
+.Fc
+.Ft int
+.Fo crypto_ed25519_check
+.Fa "const uint8_t signature[64]"
+.Fa "const uint8_t public_key[32]"
+.Fa "const uint8_t *message"
+.Fa "size_t message_size"
+.Fc
+.Ft void
+.Fo crypto_ed25519_key_pair
+.Fa "uint8_t secret_key[64]"
+.Fa "uint8_t public_key[32]"
+.Fa "uint8_t seed[32]"
+.Fc
+.Ft void
+.Fo crypto_ed25519_ph_sign
+.Fa "uint8_t signature[64]"
+.Fa "const uint8_t secret_key[64]"
+.Fa "const uint8_t message_hash[64]"
+.Fc
+.Ft int
+.Fo crypto_ed25519_ph_check
+.Fa "const uint8_t signature[64]"
+.Fa "const uint8_t public_key[32]"
+.Fa "const uint8_t message_hash[64]"
+.Fc
+.Sh DESCRIPTION
+The
+.Fn crypto_ed25519_sign
+and
+.Fn crypto_ed25519_check
+functions provide Ed25519 public key signatures and verification
+with SHA-512 as the underlying hash function.
+They are interoperable with other Ed25519 implementations.
+If you have no interoperability requirements, prefer
+.Xr crypto_eddsa_sign 3monocypher .
+.Pp
+The arguments and security considerations are the same as those
+described in
+.Xr crypto_eddsa_sign 3monocypher .
+.Pp
+.Fn crypto_ed25519_ph_sign
+and
+.Fn crypto_ed25519_ph_check
+implement Ed25519ph.
+To sign or check a message,
+first hash the message with
+.Xr crypto_sha512 3monocypher ,
+then process the resulting
+.Fa message_hash .
+.Sh RETURN VALUES
+.Fn crypto_ed25519_key_pair ,
+.Fn crypto_ed25519_sign ,
+and
+.Fn crypto_ed25519_ph_sign
+return nothing.
+.Pp
+.Fn crypto_ed25519_check
+and
+.Fn crypto_ed25519_ph_check
+returns 0 for legitimate messages and -1 for forgeries.
+.Sh SEE ALSO
+.Xr crypto_eddsa_sign 3monocypher ,
+.Xr crypto_x25519 3monocypher ,
+.Xr crypto_aead_lock 3monocypher ,
+.Xr crypto_sha512 3monocypher ,
+.Xr intro 3monocypher
+.Sh STANDARDS
+These functions implement Ed25519 as described in RFC 8032.
+.Sh HISTORY
+The
+.Fn crypto_ed25519_sign ,
+.Fn crypto_ed25519_check ,
+and
+.Fn crypto_ed25519_public_key
+functions appeared in Monocypher 3.0.0.
+They replace recompilation of Monocypher with the
+.Dv ED25519_SHA512
+preprocessor definition.
+.Pp
+In Monocypher 4.0.0,
+the incremental and custom hash API removed.
+The main interface was also reworked to avoid misuse,
+and
+.Fn crypto_ed25519_key_pair
+replaced
+.Fn crypto_ed25519_public_key .
+.Sh CAVEATS
+Monocypher does not perform any input validation.
+Any deviation from the specified input and output length ranges results
+in
+.Sy undefined behaviour .
+Make sure your inputs are correct.
+.Sh SECURITY CONSIDERATIONS
+.Ss Signature malleability
+Signature malleability is the ability of an attacker to produce a valid
+signature with knowledge of only an existing signature and the public
+key.
+Monocypher prevents that by checking the encoding of the signature,
+and guarantees that generating new signatures requires the private key.
+.Pp
+On the other hand, EdDSA signatures are not unique like cryptographic
+hashes.
+The signing procedure is deterministic by specification and
+.Fn crypto_ed25519_sign
+follows this specification.
+However, someone with the private key can generate arbitrarily many
+valid, canonical, and different signatures of the same message.
+Because of this, never assume that signatures are unique.
+.Ss Fault injection and power analysis
+Fault injection (also known as glitching) and power analysis may be used
+to manipulate the resulting signature and recover the secret key in
+some cases.
+This requires hardware access.
+We can try to mitigate this attack by prefixing all hashes a random data
+block,
+in a construction similar to Ed25519ctx.
+Note that there may still be other power-related side channels (such as
+if the CPU leaks information when an operation overflows a register)
+that must be considered.
diff --git a/lib/Utils.Cryptography/monocypher/vendor/doc/crypto_eddsa_sign.3monocypher b/lib/Utils.Cryptography/monocypher/vendor/doc/crypto_eddsa_sign.3monocypher
new file mode 100644
index 0000000..e3b2179
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/doc/crypto_eddsa_sign.3monocypher
@@ -0,0 +1,522 @@
+.\" This file is dual-licensed. Choose whichever you want.
+.\"
+.\" The first licence is a regular 2-clause BSD licence. The second licence
+.\" is the CC-0 from Creative Commons. It is intended to release Monocypher
+.\" to the public domain. The BSD licence serves as a fallback option.
+.\"
+.\" SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+.\"
+.\" ----------------------------------------------------------------------------
+.\"
+.\" Copyright (c) 2017-2019, 2022-2023 Loup Vaillant
+.\" Copyright (c) 2017-2018 Michael Savage
+.\" Copyright (c) 2017, 2019-2023 Fabio Scotoni
+.\" All rights reserved.
+.\"
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions are
+.\" met:
+.\"
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\"
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the
+.\" distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+.\" HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" ----------------------------------------------------------------------------
+.\"
+.\" Written in 2017-2023 by Loup Vaillant, Michael Savage and Fabio Scotoni
+.\"
+.\" To the extent possible under law, the author(s) have dedicated all copyright
+.\" and related neighboring rights to this software to the public domain
+.\" worldwide. This software is distributed without any warranty.
+.\"
+.\" You should have received a copy of the CC0 Public Domain Dedication along
+.\" with this software. If not, see
+.\" <https://creativecommons.org/publicdomain/zero/1.0/>
+.\"
+.Dd February 25, 2023
+.Dt CRYPTO_SIGN 3MONOCYPHER
+.Os
+.Sh NAME
+.Nm crypto_eddsa_sign ,
+.Nm crypto_eddsa_check ,
+.Nm crypto_eddsa_key_pair ,
+.Nm crypto_eddsa_to_x25519 ,
+.Nm crypto_eddsa_trim_scalar ,
+.Nm crypto_eddsa_reduce ,
+.Nm crypto_eddsa_mul_add ,
+.Nm crypto_eddsa_scalarbase ,
+.Nm crypto_eddsa_check_equation
+.Nd public key signatures
+.Sh SYNOPSIS
+.In monocypher.h
+.Ft void
+.Fo crypto_eddsa_sign
+.Fa "uint8_t signature[64]"
+.Fa "const uint8_t secret_key[64]"
+.Fa "const uint8_t *message"
+.Fa "size_t message_size"
+.Fc
+.Ft int
+.Fo crypto_eddsa_check
+.Fa "const uint8_t signature[64]"
+.Fa "const uint8_t public_key[32]"
+.Fa "const uint8_t *message"
+.Fa "size_t message_size"
+.Fc
+.Ft void
+.Fo crypto_eddsa_key_pair
+.Fa "uint8_t secret_key[64]"
+.Fa "uint8_t public_key[32]"
+.Fa "uint8_t seed[32]"
+.Fc
+.Ft void
+.Fo crypto_eddsa_to_x25519
+.Fa "uint8_t x25519[32]"
+.Fa "const uint8_t eddsa[32]"
+.Fc
+.Ft void
+.Fo crypto_eddsa_trim_scalar
+.Fa "uint8_t out[32]"
+.Fa "const uint8_t in[32]"
+.Fc
+.Ft void
+.Fo crypto_eddsa_reduce
+.Fa "uint8_t reduced[32]"
+.Fa "const uint8_t expanded[64]"
+.Fc
+.Ft void
+.Fo crypto_eddsa_mul_add
+.Fa "uint8_t r[32]"
+.Fa "const uint8_t a[32]"
+.Fa "const uint8_t b[32]"
+.Fa "const uint8_t c[32]"
+.Fc
+.Ft void
+.Fo crypto_eddsa_scalarbase
+.Fa "uint8_t point[32]"
+.Fa "const uint8_t scalar[32]"
+.Fc
+.Ft int
+.Fo crypto_eddsa_check_equation
+.Fa "const uint8_t Rs[64]"
+.Fa "const uint8_t A[32]"
+.Fa "const uint8_t h[32]"
+.Fc
+.Sh DESCRIPTION
+.Ss High level API
+.Fn crypto_eddsa_sign
+and
+.Fn crypto_eddsa_check
+provide EdDSA public key signatures and verification.
+.Fn crypto_eddsa_key_pair
+computes the private and public keys from a random seed.
+The arguments are:
+.Bl -tag -width Ds
+.It Fa seed
+Random seed, freshly generated and used only once.
+It is automatically wiped by
+.Fn crypto_eddsa_key_pair .
+See
+.Xr intro 3monocypher
+about random number generation (use your operating system's random
+number generator).
+.It Fa signature
+The signature.
+.It Fa secret_key
+A secret key generated by
+.Fn crypto_eddsa_key_pair ,
+known only to you.
+Internally the secret key is made up of the seed and the public key.
+They are bundled together to avoid misuse,
+and should be treated as a unit.
+.It Fa public_key
+The associated public key,
+known to everyone.
+.It Fa message
+The message to sign.
+.It Fa message_size
+Length of
+.Fa message ,
+in bytes.
+.El
+.Pp
+.Fa signature
+and
+.Fa message
+may overlap.
+.Pp
+.Fn crypto_eddsa_sign
+signs a message with
+.Fa secret_key .
+.Pp
+.Fn crypto_eddsa_check
+checks that a given signature is genuine.
+Meaning, only someone who had the private key could have signed the
+message.
+.Sy \&It does not run in constant time .
+It does not have to in most threat models because nothing is secret:
+everyone knows the public key, and the signature and message are
+rarely secret.
+If the message needs to be secret, use
+a key exchange protocol involving
+.Xr crypto_x25519 3monocypher
+and then
+.Xr crypto_aead_lock 3monocypher
+instead.
+.Ss Conversion to X25519
+.Fn crypto_eddsa_to_x25519
+Converts and EdDSA public key to an X25519 public key.
+Note that it ignores the sign of the
+.Em x
+coordinate of the EdDSA input.
+The inverse operation is provided by
+.Xr crypto_x25519_to_eddsa 3monocypher .
+.Ss Low-level building blocks
+.Fn crypto_eddsa_trim_scalar ,
+.Fn crypto_eddsa_reduce ,
+.Fn crypto_eddsa_mul_add ,
+.Fn crypto_eddsa_scalarbase ,
+and
+.Fn crypto_eddsa_check_equation
+provide low-level functionality to implement specialised APIs and
+variants of EdDSA.
+Monocypher uses them to implement all high-level EdDSA and Ed25519
+functions.
+.Pp
+These functions are
+.Sy dangerous ,
+using them directly allows many kinds of catastrophic misuse.
+The following descriptions are kept concise and technical on purpose.
+If you do not understand them, do not not use those functions.
+.Pp
+.Fn crypto_eddsa_trim_scalar
+reads a 256-bit number represented in little-endian,
+and outputs the same number modified as follows:
+the 3 least significant bits are cleared;
+the most significant bit is cleared;
+and the second most significant bit is set.
+.Pp
+.Fn crypto_eddsa_reduce
+reads a 512-bit number represented in little-endian,
+and outputs the same number reduced modulo the prime order of
+Curve25519.
+.Pp
+.Fn crypto_eddsa_mul_add
+reads three 256-bit numbers represented in little-endian,
+and outputs
+.Fa a
+.Fa b
++
+.Fa c ,
+reduced modulo the prime order of Curve25519.
+.Pp
+.Fn crypto_eddsa_scalarbase
+reads a 256-bit number represented in little-endian,
+and outputs the result of the scalar multiplication between that number
+and the twisted Edwards base point of Curve25519.
+The output uses the same compressed representation as regular EdDSA
+public keys:
+the most significant bit represents the sign of the
+.Em x
+coordinate (1 if it is odd, 0 if it is even),
+and the 255 other bits represent the
+.Em y
+coordinate in little-endian.
+.Pp
+.Fn crypto_eddsa_check_equation
+reads a signature
+.Fa \&Rs ,
+a public_key
+.Fa A ,
+and hash
+.Fa h ,
+then checks the following:
+.Bl -dash
+.It
+.Fa A
+and
+.Fa R
+are both on the curve.
+.It
+.Fa s
+is below the prime order of Curve25519.
+.It
+[8×s]B = [8]R + [8×h]A
+.El
+.Pp
+It then returns 0 if all checks hold,
+-1 otherwise.
+Note that
+.Fa A
+and
+.Fa R
+are allowed to have low order,
+and their encoding is allowed to be non-canonical.
+.Sy This function does not run in constant time ,
+do not use it with secret inputs.
+.Sh RETURN VALUES
+.Ss High level API
+.Fn crypto_eddsa_key_pair
+and
+.Fn crypto_eddsa_sign
+return nothing.
+.Pp
+.Fn crypto_eddsa_check
+returns 0 for legitimate signatures and -1 for forgeries.
+.Ss Conversion to X25519
+.Fn crypto_eddsa_to_x25519
+returns nothing.
+.Ss Low-level building blocks
+.Fn crypto_eddsa_trim_scalar ,
+.Fn crypto_eddsa_reduce ,
+.Fn crypto_eddsa_mul_add ,
+and
+.Fn crypto_eddsa_scalarbase
+return nothing.
+.Pp
+.Fn crypto_eddsa_check_equation
+returns 0 for legitimate signatures and -1 for forgeries.
+.Sh EXAMPLES
+The following examples assume the existence of
+.Fn arc4random_buf ,
+which fills the given buffer with cryptographically secure random bytes.
+If
+.Fn arc4random_buf
+does not exist on your system, see
+.Xr intro 3monocypher
+for advice about how to generate cryptographically secure random bytes.
+.Pp
+Generate a key pair:
+.Bd -literal -offset indent
+uint8_t seed[32]; /* Random seed */
+uint8_t sk [64]; /* secret key */
+uint8_t pk [32]; /* Matching public key */
+arc4random_buf(seed, 32);
+crypto_eddsa_key_pair(sk, pk, seed);
+/* Wipe the secret key if it is no longer needed */
+/* The seed is wiped automatically */
+crypto_wipe(sk, 32);
+.Ed
+.Pp
+Sign a message:
+.Bd -literal -offset indent
+uint8_t sk [64]; /* Secret key from above */
+const uint8_t message [11] = "Lorem ipsu"; /* Message to sign */
+uint8_t signature[64];
+crypto_eddsa_sign(signature, sk, message, 10);
+/* Wipe the secret key if it is no longer needed */
+crypto_wipe(sk, 32);
+.Ed
+.Pp
+Check the above:
+.Bd -literal -offset indent
+const uint8_t pk [32]; /* Their public key */
+const uint8_t message [11] = "Lorem ipsu"; /* Signed message */
+const uint8_t signature[64]; /* Signature to check */
+if (crypto_eddsa_check(signature, pk, message, 10)) {
+ /* Message is corrupted, do not trust it */
+} else {
+ /* Message is genuine */
+}
+.Ed
+.Pp
+Implement XEdDSA
+(signatures with X25519 keys normally used for key exchange)
+with the low-level building blocks
+.Bd -literal -offset indent
+#include <monocypher.h>
+#include <monocypher-ed25519.h>
+#include <string.h>
+
+void xed25519_sign(uint8_t signature[64],
+ const uint8_t secret_key[32],
+ const uint8_t random[64],
+ const uint8_t *message, size_t message_size)
+{
+ static const uint8_t zero [32] = {0};
+ static const uint8_t minus_1[32] = {
+ 0xec, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58,
+ 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+ };
+ static const uint8_t prefix[32] = {
+ 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ };
+
+ /* Key pair (a, A) */
+ uint8_t A[32]; /* XEdDSA public key */
+ uint8_t a[32]; /* XEdDSA private key */
+ crypto_eddsa_trim_scalar(a, secret_key);
+ crypto_eddsa_scalarbase(A, a);
+ int is_negative = A[31] & 0x80; /* Retrieve sign bit */
+ A[31] &= 0x7f; /* Clear sign bit */
+ if (is_negative) {
+ /* a = -a */
+ crypto_eddsa_mul_add(a, a, minus_1, zero);
+ }
+
+ /* Secret nonce r */
+ uint8_t r[64];
+ crypto_sha512_ctx ctx;
+ crypto_sha512_init (&ctx);
+ crypto_sha512_update(&ctx, prefix , 32);
+ crypto_sha512_update(&ctx, a , 32);
+ crypto_sha512_update(&ctx, message, message_size);
+ crypto_sha512_update(&ctx, random , 64);
+ crypto_sha512_final (&ctx, r);
+ crypto_eddsa_reduce(r, r);
+
+ /* First half of the signature R */
+ uint8_t R[32];
+ crypto_eddsa_scalarbase(R, r);
+
+ /* hash(R || A || M) */
+ uint8_t H[64];
+ crypto_sha512_init (&ctx);
+ crypto_sha512_update(&ctx, R , 32);
+ crypto_sha512_update(&ctx, A , 32);
+ crypto_sha512_update(&ctx, message, message_size);
+ crypto_sha512_final (&ctx, H);
+ crypto_eddsa_reduce(H, H);
+
+ /* Signature */
+ memcpy(signature, R, 32);
+ crypto_eddsa_mul_add(signature + 32, a, H, r);
+
+ /* Wipe secrets (A, R, and H are not secret) */
+ crypto_wipe(a, 32);
+ crypto_wipe(r, 32);
+}
+
+int xed25519_verify(const uint8_t signature[64],
+ const uint8_t public_key[32],
+ const uint8_t *message, size_t message_size)
+{
+ /* Convert X25519 key to EdDSA */
+ uint8_t A[32];
+ crypto_x25519_to_eddsa(A, public_key);
+
+ /* hash(R || A || M) */
+ uint8_t H[64];
+ crypto_sha512_ctx ctx;
+ crypto_sha512_init (&ctx);
+ crypto_sha512_update(&ctx, signature, 32);
+ crypto_sha512_update(&ctx, A , 32);
+ crypto_sha512_update(&ctx, message , message_size);
+ crypto_sha512_final (&ctx, H);
+ crypto_eddsa_reduce(H, H);
+
+ /* Check signature */
+ return crypto_eddsa_check_equation(signature, A, H);
+}
+.Ed
+.Sh SEE ALSO
+.Xr crypto_blake2b 3monocypher ,
+.Xr crypto_x25519 3monocypher ,
+.Xr crypto_aead_lock 3monocypher ,
+.Xr intro 3monocypher
+.Sh STANDARDS
+.Fn crypto_eddsa_sign ,
+.Fn crypto_eddsa_check ,
+and
+.Fn crypto_eddsa_key_pair
+implement PureEdDSA with Curve25519 and BLAKE2b,
+as described in RFC 8032.
+This is the same as Ed25519, with BLAKE2b instead of SHA-512.
+.Pp
+.Fn crypto_eddsa_trim_scalar ,
+.Fn crypto_eddsa_reduce ,
+.Fn crypto_eddsa_mul_add ,
+.Fn crypto_eddsa_scalarbase ,
+and
+.Fn crypto_eddsa_check_equation
+can be used to implement any Curve25519 based EdDSA variant,
+including Ed25519 and Ed25519ph.
+.Sh HISTORY
+The
+.Fn crypto_sign ,
+.Fn crypto_check ,
+and
+.Fn crypto_sign_public_key
+functions appeared in Monocypher 0.2.
+.Pp
+Starting with Monocypher 2.0.5, modified signatures abusing the inherent
+signature malleability property of EdDSA now cause a non-zero return
+value of
+.Fn crypto_check ;
+in prior versions, such signatures would be accepted.
+.Pp
+.Sy A critical security vulnerability
+that caused all-zero signatures to be accepted was introduced in
+Monocypher 0.3;
+it was fixed in Monocypher 1.1.1 and 2.0.4.
+.Pp
+In Monocypher 4.0.0
+.Fn crypto_eddsa_trim_scalar ,
+.Fn crypto_eddsa_reduce ,
+.Fn crypto_eddsa_mul_add ,
+.Fn crypto_eddsa_scalarbase ,
+and
+.Fn crypto_eddsa_check_equation
+were added,
+and the incremental and custom hash API removed.
+The main interface was also reworked to avoid misuse,
+and
+.Fn crypto_eddsa_key_pair
+replaced
+.Fn crypto_sign_public_key .
+.Sh CAVEATS
+Monocypher does not perform any input validation.
+Any deviation from the specified input and output length ranges results
+in
+.Sy undefined behaviour .
+Make sure your inputs are correct.
+.Sh SECURITY CONSIDERATIONS
+.Ss Signature malleability
+Signature malleability is the ability of an attacker to produce a valid
+signature with knowledge of only an existing signature and the public
+key.
+Monocypher prevents that by checking the encoding of the signature,
+and guarantees that generating new signatures requires the private key.
+.Pp
+On the other hand, EdDSA signatures are not unique like cryptographic
+hashes.
+The signing procedure is deterministic by specification and
+.Fn crypto_eddsa_sign
+follows this specification.
+However, someone with the private key can generate arbitrarily many
+valid, canonical, and different signatures of the same message.
+Because of this, never assume that signatures are unique.
+.Ss Fault injection and power analysis
+Fault injection (also known as glitching) and power analysis may be used
+to manipulate the resulting signature and recover the secret key in
+some cases.
+This requires hardware access.
+We can try to mitigate this attack by prefixing all hashes a random data
+block,
+in a construction similar to Ed25519ctx.
+Note that there may still be other power-related side channels (such as
+if the CPU leaks information when an operation overflows a register)
+that must be considered.
diff --git a/lib/Utils.Cryptography/monocypher/vendor/doc/crypto_elligator_map.3monocypher b/lib/Utils.Cryptography/monocypher/vendor/doc/crypto_elligator_map.3monocypher
new file mode 100644
index 0000000..5c0f943
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/doc/crypto_elligator_map.3monocypher
@@ -0,0 +1,316 @@
+.\" This file is dual-licensed. Choose whichever you want.
+.\"
+.\" The first licence is a regular 2-clause BSD licence. The second licence
+.\" is the CC-0 from Creative Commons. It is intended to release Monocypher
+.\" to the public domain. The BSD licence serves as a fallback option.
+.\"
+.\" SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+.\"
+.\" ----------------------------------------------------------------------------
+.\"
+.\" Copyright (c) 2020, 2022 Fabio Scotoni
+.\" Copyright (c) 2023 Loup Vaillant
+.\" All rights reserved.
+.\"
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions are
+.\" met:
+.\"
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\"
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the
+.\" distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+.\" HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" ----------------------------------------------------------------------------
+.\"
+.\" Written in 2020, 2022, and 2023 by Fabio Scotoni and Loup Vaillant
+.\"
+.\" To the extent possible under law, the author(s) have dedicated all copyright
+.\" and related neighboring rights to this software to the public domain
+.\" worldwide. This software is distributed without any warranty.
+.\"
+.\" You should have received a copy of the CC0 Public Domain Dedication along
+.\" with this software. If not, see
+.\" <https://creativecommons.org/publicdomain/zero/1.0/>
+.\"
+.Dd March 6, 2023
+.Dt CRYPTO_ELLIGATOR_MAP 3MONOCYPHER
+.Os
+.Sh NAME
+.Nm crypto_elligator_map ,
+.Nm crypto_elligator_rev ,
+.Nm crypto_elligator_key_pair
+.Nd hiding of X25519 public keys
+.Sh SYNOPSIS
+.In monocypher.h
+.Ft void
+.Fo crypto_elligator_map
+.Fa "uint8_t curve[32]"
+.Fa "const uint8_t hidden[32]"
+.Fc
+.Ft int
+.Fo crypto_elligator_rev
+.Fa "uint8_t hidden[32]"
+.Fa "const uint8_t curve[32]"
+.Fa "uint8_t tweak"
+.Fc
+.Ft void
+.Fo crypto_elligator_key_pair
+.Fa "uint8_t hidden[32]"
+.Fa "uint8_t secret_key[32]"
+.Fa "uint8_t seed[32]"
+.Fc
+.Sh DESCRIPTION
+These functions allow obfuscating X25519 public keys by making
+them appear effectively indistinguishable from random noise.
+This is of interest for key exchange protocols that require
+indistinguishability from randomness, such as padded uniform random
+blobs (PURBs).
+They are intended for ephemeral (short-lived, possibly just one-time)
+X25519 keys, not for long-term public keys.
+After an initial key exchange involving hidden keys,
+subsequent key exchange messages should be encrypted instead;
+see, for example, the Noise Protocol Framework.
+This is an
+.Em advanced feature .
+Unless you are implementing an protocol that requires
+indistinguishability of all communications from random noise,
+consider
+.Xr crypto_x25519 3monocypher
+instead.
+Both this family of functions and
+.Xr crypto_x25519 3monocypher
+should be used as a building block to implement a key exchange protocol.
+.Pp
+For understanding what these functions do, it is important to note that
+a
+.Dq public key
+in this context refers to a
+.Em point on Curve25519 .
+This also means that these functions are not compatible with
+.Xr crypto_eddsa_sign 3monocypher
+and related functions.
+.Pp
+.Fn crypto_elligator_rev
+takes a public key
+.Fa curve
+and a
+.Fa tweak ,
+hiding the public key so that it is effectively indistinguishable
+from random noise.
+Note that only
+.Xr crypto_x25519_dirty_fast 3monocypher
+or
+.Xr crypto_x25519_dirty_small 3monocypher
+can generate a suitable public key;
+the
+.Xr crypto_x25519 3monocypher
+function is insufficient.
+The
+.Fa tweak
+must be chosen at random.
+Even then, this operation
+.Em may
+fail because
+not all curve points are capable of being hidden.
+In this case,
+.Fn crypto_elligator_rev
+must be tried again with a new key pair,
+though
+.Fa tweak
+does not need to be changed.
+On average, two attempts are needed.
+Once a suitable public key has been found,
+.Fn crypto_elligator_rev
+always succeeds for it.
+Given the same values for
+.Fa tweak
+and
+.Fa curve ,
+.Fn crypto_elligator_rev
+yields the same output value
+.Fa hidden .
+.Pp
+.Fn crypto_elligator_map
+performs the inverse operation:
+It decodes a hidden point to a curve point on Curve25519.
+.Pp
+.Fn crypto_elligator_key_pair
+is a convenience function that generates a secret key and its
+corresponding public key, which is effectively indistinguishable from
+random noise, from a random seed.
+.Em The execution time of this function is unpredictable
+because it may take many failures until a key pair could be generated
+successfully.
+.Fn crypto_elligator_key_pair
+uses
+.Xr crypto_x25519_dirty_fast 3monocypher
+internally;
+if code size is an important concern,
+its functionality can be replicated with
+.Xr crypto_x25519_dirty_small 3monocypher
+instead.
+.Pp
+The arguments are:
+.Bl -tag -width Ds
+.It Fa curve
+A point on the curve which is a Curve25519 public key generated with
+either
+.Xr crypto_x25519_dirty_fast 3monocypher
+or
+.Xr crypto_x25519_dirty_small 3monocypher .
+.It Fa hidden
+The hidden encoding of a point on the curve which is effectively
+indistinguishable from random.
+.It Fa secret_key
+The secret key that was generated from the given
+.Fa seed .
+.It Fa seed
+A 32-byte random number from which to derive a key pair.
+See
+.Xr intro 3monocypher
+for advice about generating random bytes (use the operating system's
+random number generator).
+The
+.Fa seed
+is wiped automatically.
+.It Fa tweak
+A 1-byte random number,
+which influences the final output of
+.Fn crypto_elligator_rev .
+.El
+.Pp
+The
+.Fa hidden
+and
+.Fa curve
+arguments may overlap or point at the same buffer.
+.Sh RETURN VALUES
+.Fn crypto_elligator_rev
+returns 0 on success and -1 if the given
+.Fa curve
+argument is unsuitable for hiding.
+.Pp
+.Fn crypto_elligator_map
+and
+.Fn crypto_elligator_key_pair
+return nothing.
+They cannot fail.
+.Sh EXAMPLES
+Generate a key pair manually using
+.Xr crypto_x25519_dirty_small 3monocypher
+instead of its fast variant:
+.Bd -literal -offset indent
+uint8_t sk [32]; /* Secret key output */
+uint8_t pk [32]; /* Hidden public key output */
+uint8_t tweak; /* Random tweak input */
+arc4random_buf(&tweak, 1);
+for (;;) {
+ arc4random_buf(sk, 32);
+ crypto_x25519_dirty_small(pk, sk);
+ if (crypto_elligator_rev(pk, pk, tweak) == 0)
+ break;
+}
+/* Now save the secret key and send the hidden public key. */
+.Ed
+.Pp
+Performing a key exchange with the other party's public key having been
+hidden:
+.Bd -literal -offset indent
+uint8_t hidden_pk [32]; /* Their hidden public key */
+uint8_t their_pk [32]; /* Their unhidden public key */
+uint8_t your_sk [32]; /* Your secret key */
+uint8_t shared_key[32]; /* Shared session key */
+crypto_elligator_map(their_pk, hidden_pk);
+crypto_x25519(shared_key, your_sk, their_pk);
+/* Wipe secrets if they are no longer needed */
+crypto_wipe(your_sk, 32);
+.Ed
+.Sh SEE ALSO
+.Xr crypto_x25519 3monocypher ,
+.Xr crypto_x25519_dirty_small 3monocypher ,
+.Xr intro 3monocypher
+.Sh STANDARDS
+These functions implement the Elligator 2 mapping for Curve25519.
+This mapping is incompatible with both the hash-to-curve Internet draft
+and the implementation of Elligator 2 in libsodium.
+Elligator 2 was described in:
+.Rs
+.%A Daniel J. Bernstein
+.%A Mike Hamburg
+.%A Anna Krasnova
+.%A Tanja Lange
+.%T Elligator: Elliptic-curve points indistinguishable from uniform random strings
+.%J CCS '13: Proceedings of the 2013 ACM SIGSAC conference on Computer & communications security
+.%I Association for Computing Machinery
+.%D 2013
+.%P pp. 967\(en980
+.Re
+.Pp
+Monocypher's Elligator 2 representatives are encoded as little-endian
+254-bit numbers.
+The two most significant bits (254 and 255) are not used.
+.Fn crypto_elligator_map
+ignores them,
+and
+.Fn crypto_elligator_rev
+sets them at random.
+The mapping uses 2 as the non-square
+.Va Z ,
+and [0..2^254-10] as the set of non-negative field elements.
+See
+.Lk https://elligator.org/map
+for more details.
+.Sh HISTORY
+The
+.Fn crypto_curve_to_hidden ,
+.Fn crypto_hidden_to_curve ,
+and
+.Fn crypto_hidden_key_pair
+functions first appeared in Monocypher 3.1.0.
+In Monocypher 4.1.0,
+they were renamed
+.Fn crypto_elligator_rev ,
+.Fn crypto_elligator_map ,
+and
+.Fn crypto_elligator_key_pair
+respectively.
+.Sh CAVEATS
+Monocypher does not perform any input validation.
+Any deviation from the specified input and output length ranges results
+in
+.Sy undefined behaviour .
+Make sure your inputs are correct.
+.Sh SECURITY CONSIDERATIONS
+The secret keys for the public keys fed into
+.Fn crypto_elligator_rev
+.Sy must be chosen randomly
+rather than deterministically.
+Otherwise, the timing information given by the required number of
+retries also leaks information on the secret keys.
+.Pp
+These functions
+.Em help
+build highly difficult-to-analyse protocols
+but are insufficient by themselves:
+Other metadata, such as the number of bytes sent in a packet or the size
+of the 32-byte random looking string that represents the curve point
+itself, can be very strong indicators of the use of cryptography.
+Consider using appropriate padding algorithms, such as PADME,
+and obscure other metadata as much as possible.
diff --git a/lib/Utils.Cryptography/monocypher/vendor/doc/crypto_poly1305.3monocypher b/lib/Utils.Cryptography/monocypher/vendor/doc/crypto_poly1305.3monocypher
new file mode 100644
index 0000000..5fb3e25
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/doc/crypto_poly1305.3monocypher
@@ -0,0 +1,279 @@
+.\" This file is dual-licensed. Choose whichever you want.
+.\"
+.\" The first licence is a regular 2-clause BSD licence. The second licence
+.\" is the CC-0 from Creative Commons. It is intended to release Monocypher
+.\" to the public domain. The BSD licence serves as a fallback option.
+.\"
+.\" SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+.\"
+.\" ----------------------------------------------------------------------------
+.\"
+.\" Copyright (c) 2017-2019 Loup Vaillant
+.\" Copyright (c) 2017-2018 Michael Savage
+.\" Copyright (c) 2017-2021 Fabio Scotoni
+.\" All rights reserved.
+.\"
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions are
+.\" met:
+.\"
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\"
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the
+.\" distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+.\" HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" ----------------------------------------------------------------------------
+.\"
+.\" Written in 2017-2021 by Loup Vaillant, Michael Savage and Fabio Scotoni
+.\"
+.\" To the extent possible under law, the author(s) have dedicated all copyright
+.\" and related neighboring rights to this software to the public domain
+.\" worldwide. This software is distributed without any warranty.
+.\"
+.\" You should have received a copy of the CC0 Public Domain Dedication along
+.\" with this software. If not, see
+.\" <https://creativecommons.org/publicdomain/zero/1.0/>
+.\"
+.Dd June 11, 2021
+.Dt CRYPTO_POLY1305 3MONOCYPHER
+.Os
+.Sh NAME
+.Nm crypto_poly1305 ,
+.Nm crypto_poly1305_init ,
+.Nm crypto_poly1305_update ,
+.Nm crypto_poly1305_final
+.Nd Poly1305 one-time message authentication codes
+.Sh SYNOPSIS
+.In monocypher.h
+.Ft void
+.Fo crypto_poly1305
+.Fa "uint8_t mac[16]"
+.Fa "const uint8_t *message"
+.Fa "size_t message_size"
+.Fa "const uint8_t key[32]"
+.Fc
+.Ft void
+.Fo crypto_poly1305_init
+.Fa "crypto_poly1305_ctx *ctx"
+.Fa "const uint8_t key[32]"
+.Fc
+.Ft void
+.Fo crypto_poly1305_update
+.Fa "crypto_poly1305_ctx *ctx"
+.Fa "const uint8_t *message"
+.Fa "size_t message_size"
+.Fc
+.Ft void
+.Fo crypto_poly1305_final
+.Fa "crypto_poly1305_ctx *ctx"
+.Fa "uint8_t mac[16]"
+.Fc
+.Sh DESCRIPTION
+Poly1305 is a one-time message authentication code.
+.Dq One-time
+means the authentication key can be used only once.
+.Sy This makes Poly1305 easy to misuse .
+On the other hand, Poly1305 is fast and provably secure if used
+correctly.
+.Pp
+Poly1305 is a low-level primitive.
+Consider using authenticated encryption, implemented by
+.Xr crypto_aead_lock 3monocypher .
+.Pp
+The arguments are:
+.Bl -tag -width Ds
+.It Fa mac
+The message authentication code.
+.It Fa key
+The secret authentication key.
+Use only once per message.
+Do not use the session key to authenticate messages.
+It should be wiped with
+.Xr crypto_wipe 3monocypher
+after use.
+.It Fa message
+The message to authenticate.
+May overlap with the
+.Fa mac
+argument.
+.It Fa message_size
+Length of
+.Fa message ,
+in bytes.
+.El
+.Ss Direct interface
+.Fn crypto_poly1305
+produces a message authentication code for the given message and
+authentication key.
+To verify the integrity of a message, use
+.Xr crypto_verify16 3monocypher
+to compare the received MAC to the output
+.Fa mac .
+.Ss Incremental interface
+.Fn crypto_poly1305_init
+initialises a context.
+.Fa key
+should be wiped once the context is initialised.
+Then
+.Fn crypto_poly1305_update
+authenticates the message chunk by chunk.
+Once the message is entirely processed,
+.Fn crypto_poly1305_final
+yields the message authentication code.
+.Sh RETURN VALUES
+These functions return nothing.
+.Sh EXAMPLES
+The following examples assume the existence of
+.Fn arc4random_buf ,
+which fills the given buffer with cryptographically secure random bytes.
+If
+.Fn arc4random_buf
+does not exist on your system, see
+.Xr intro 3monocypher
+for advice about how to generate cryptographically secure random bytes.
+.Pp
+To authenticate a message:
+.Bd -literal -offset indent
+const uint8_t msg[ 5] = "Lorem"; /* Message to authenticate */
+uint8_t key[32]; /* Random secret key (use only once) */
+uint8_t mac[16]; /* Message authentication code (MAC) */
+arc4random_buf(key, 32);
+crypto_poly1305(mac, msg, 5, key);
+/* Wipe the key */
+crypto_wipe(key, 32);
+.Ed
+.Pp
+To verify the above message:
+.Bd -literal -offset indent
+const uint8_t msg [ 5] = "Lorem"; /* Message to verify */
+uint8_t key [32]; /* The above key */
+const uint8_t mac [16]; /* The above MAC */
+uint8_t real_mac[16]; /* The actual MAC */
+crypto_poly1305(real_mac, msg, 5, key);
+/* Wipe the key */
+crypto_wipe(key, 32);
+if (crypto_verify16(mac, real_mac)) {
+ /* Corrupted message, abort processing */
+} else {
+ /* Genuine message */
+}
+/* The real mac is secret. Wipe it */
+crypto_wipe(real_mac, 16);
+.Ed
+.Pp
+Incremental authentication:
+.Bd -literal -offset indent
+const uint8_t msg[500]= {1}; /* Message to authenticate */
+uint8_t key[ 32]; /* Random secret key (use only once) */
+uint8_t mac[ 16]; /* Message authentication code (MAC) */
+crypto_poly1305_ctx ctx;
+arc4random_buf(key, 32);
+crypto_poly1305_init(&ctx, key);
+/* Wipe the key */
+crypto_wipe(key, 32);
+for (int i = 0; i < 500; i += 100) {
+ crypto_poly1305_update(&ctx, msg, 100);
+}
+crypto_poly1305_final(&ctx, mac);
+.Ed
+.Sh SEE ALSO
+.Xr crypto_blake2b 3monocypher ,
+.Xr crypto_aead_lock 3monocypher ,
+.Xr crypto_verify16 3monocypher ,
+.Xr intro 3monocypher
+.Sh STANDARDS
+These functions implement Poly1305, described in RFC 8439.
+.Sh HISTORY
+The
+.Fn crypto_poly1305_init ,
+.Fn crypto_poly1305_update ,
+and
+.Fn crypto_poly1305_final
+functions first appeared in Monocypher 0.1.
+.Fn crypto_poly1305
+first appeared in Monocypher 1.1.0.
+.Sh CAVEATS
+Monocypher does not perform any input validation.
+Any deviation from the specified input and output length ranges results
+in
+.Sy undefined behaviour .
+Make sure your inputs are correct.
+.Sh SECURITY CONSIDERATIONS
+Poly1305 is difficult to use correctly.
+Do not use it unless you are absolutely sure what you are doing.
+Use authenticated encryption instead; see
+.Xr crypto_aead_lock 3monocypher .
+If you are certain you do not want encryption, refer to
+.Xr crypto_blake2b 3monocypher
+on how to use BLAKE2b to generate message authentication codes.
+.Ss Authentication key requirements
+Poly1305 is a
+.Em one-time
+authenticator.
+This puts rather stringent constraints on the authentication key:
+.Bl -bullet
+.It
+Any given key must be used only once.
+Using the same key for two different messages reveals it to the
+attacker.
+Do not use the session key, or it will void all security.
+.It
+Authentication keys must be random, and independent from each other.
+Do not use non-random nonces.
+Do not use related keys.
+Use fresh, unpredictable, uniformly distributed random numbers.
+.It
+The key must be transmitted to the recipient without revealing it to the
+attacker.
+Somehow.
+.El
+.Pp
+The only practical source for the authentication key is a chunk of the
+encryption stream used to encrypt the message.
+That chunk must be
+.Em dedicated
+to the authentication key:
+if it is reused to encrypt the message itself, the attacker may recover
+that chunk by guessing the message then forge arbitrary messages.
+.Pp
+To get this right, you need a session key, a
+.Em unique
+nonce, and a
+stream cipher.
+Generate a stream with the session key and nonce.
+Take the first 32 bytes of that stream as your authentication key, then
+use the
+.Em rest
+of the stream to encrypt your message.
+This is the approach used by
+.Xr crypto_aead_lock 3monocypher .
+.Ss Protection against side channels
+Use
+.Xr crypto_verify16 3monocypher
+to compare message authentication codes.
+Avoid standard buffer comparison functions:
+they may not run in constant time, enabling an attacker to exploit timing
+attacks to recover the MAC.
+.Pp
+The authentication key should be wiped with
+.Xr crypto_wipe 3monocypher
+after use.
+.Pp
+The incremental interface automatically wipes its context when finished,
+so users do not need to do it themselves.
diff --git a/lib/Utils.Cryptography/monocypher/vendor/doc/crypto_sha512.3monocypher b/lib/Utils.Cryptography/monocypher/vendor/doc/crypto_sha512.3monocypher
new file mode 100644
index 0000000..d03578e
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/doc/crypto_sha512.3monocypher
@@ -0,0 +1,578 @@
+.\" This file is dual-licensed. Choose whichever you want.
+.\"
+.\" The first licence is a regular 2-clause BSD licence. The second licence
+.\" is the CC-0 from Creative Commons. It is intended to release Monocypher
+.\" to the public domain. The BSD licence serves as a fallback option.
+.\"
+.\" SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+.\"
+.\" ----------------------------------------------------------------------------
+.\"
+.\" Copyright (c) 2019-2020, 2023 Fabio Scotoni
+.\" Copyright (c) 2023 Loup Vaillant
+.\" All rights reserved.
+.\"
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions are
+.\" met:
+.\"
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\"
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the
+.\" distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+.\" HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" ----------------------------------------------------------------------------
+.\"
+.\" Written in 2019-2020, 2023 by Fabio Scotoni and Loup Vaillant
+.\"
+.\" To the extent possible under law, the author(s) have dedicated all copyright
+.\" and related neighboring rights to this software to the public domain
+.\" worldwide. This software is distributed without any warranty.
+.\"
+.\" You should have received a copy of the CC0 Public Domain Dedication along
+.\" with this software. If not, see
+.\" <https://creativecommons.org/publicdomain/zero/1.0/>
+.\"
+.Dd February 25, 2023
+.Dt CRYPTO_SHA512 3MONOCYPHER
+.Os
+.Sh NAME
+.Nm crypto_sha512 ,
+.Nm crypto_sha512_init ,
+.Nm crypto_sha512_update ,
+.Nm crypto_sha512_final
+.Nm crypto_sha512_hmac ,
+.Nm crypto_sha512_hmac_init ,
+.Nm crypto_sha512_hmac_update ,
+.Nm crypto_sha512_hmac_final ,
+.Nm crypto_sha512_hkdf ,
+.Nm crypto_sha512_hkdf_expand
+.Nd hashing, message authentication, and key derivation with SHA-512
+.Sh SYNOPSIS
+.In monocypher-ed25519.h
+.Ft void
+.Fo crypto_sha512
+.Fa "uint8_t hash[64]"
+.Fa "const uint8_t *message"
+.Fa "size_t message_size"
+.Fc
+.Ft void
+.Fo crypto_sha512_init
+.Fa "crypto_sha512_ctx *ctx"
+.Fc
+.Ft void
+.Fo crypto_sha512_update
+.Fa "crypto_sha512_ctx *ctx"
+.Fa "const uint8_t *message"
+.Fa "size_t message_size"
+.Fc
+.Ft void
+.Fo crypto_sha512_final
+.Fa "crypto_sha512_ctx *ctx"
+.Fa "uint8_t hash[64]"
+.Fc
+.Ft void
+.Fo crypto_sha512_hmac
+.Fa "uint8_t hmac[64]"
+.Fa "const uint8_t *key"
+.Fa "size_t key_size"
+.Fa "const uint8_t *message"
+.Fa "size_t message_size"
+.Fc
+.Ft void
+.Fo crypto_sha512_hmac_init
+.Fa "crypto_sha512_hmac_ctx *ctx"
+.Fa "const uint8_t *key"
+.Fa "size_t key_size"
+.Fc
+.Ft void
+.Fo crypto_sha512_hmac_update
+.Fa "crypto_sha512_hmac_ctx *ctx"
+.Fa "const uint8_t *message"
+.Fa "size_t message_size"
+.Fc
+.Ft void
+.Fo crypto_sha512_hmac_final
+.Fa "crypto_sha512_hmac_ctx *ctx"
+.Fa "uint8_t hmac[64]"
+.Fc
+.Fo crypto_sha512_hkdf
+.Fa "uint8_t *okm"
+.Fa "size_t okm_size"
+.Fa "const uint8_t *ikm"
+.Fa "size_t ikm_size"
+.Fa "const uint8_t *salt"
+.Fa "size_t salt_size"
+.Fa "const uint8_t *info"
+.Fa "size_t info_size"
+.Fc
+.Ft void
+.Fo crypto_sha512_hkdf_expand
+.Fa "uint8_t *okm"
+.Fa "size_t okm_size"
+.Fa "const uint8_t *prk"
+.Fa "size_t prk_size"
+.Fa "const uint8_t *info"
+.Fa "size_t info_size"
+.Fc
+.Ft void
+.Sh DESCRIPTION
+.Ss Hashing
+.Fn crypto_sha512 ,
+.Fn crypto_sha512_init ,
+.Fn crypto_sha512_update ,
+and
+.Fn crypto_sha512_final
+implement SHA-512,
+a cryptographically secure hash.
+They are provided to enable compatibility with other cryptographic
+systems.
+It is generally recommended to use
+.Xr crypto_blake2b 3monocypher
+instead,
+as it both performs faster on x86_64 CPUs and
+lacks many of the pitfalls of SHA-512.
+.Pp
+Note that SHA-512 itself is not suitable for hashing passwords and
+deriving keys from them;
+use the
+.Xr crypto_argon2 3monocypher
+family of functions for that purpose instead.
+.Pp
+SHA-512 is
+.Em vulnerable to length extension attacks ,
+and thus cannot directly be used for message authentication codes (MAC),
+nor as a random oracle.
+For those, use the
+.Fn crypto_sha512_hmac
+family of functions instead.
+.Pp
+The arguments are:
+.Bl -tag -width Ds
+.It Fa hash
+The output SHA-512 hash,
+which is always 64-bytes long.
+.It Fa message
+The message to hash.
+May be
+.Dv NULL
+if
+.Fa message_size
+is 0.
+.It Fa message_size
+Length of
+.Fa message ,
+in bytes.
+.El
+.Ss Message authentication codes
+.Fn crypto_sha512_hmac ,
+.Fn crypto_sha512_hmac_init ,
+.Fn crypto_sha512_hmac_update ,
+and
+.Fn crypto_sha512_hmac_final
+implement HMAC with SHA-512,
+and can be used for message authentication codes or as a random oracle.
+They are provided to enable compatibility with other cryptographic
+systems.
+It is generally recommended to use keyed
+.Xr crypto_blake2b 3monocypher
+instead,
+as it performs faster on x86_64 CPUs.
+.Pp
+The arguments are:
+.Bl -tag -width Ds
+.It Fa hmac
+The output MAC,
+which is always 64-bytes long.
+When used as a message authentication code,
+it can safely be truncated down to 16 bytes.
+To avoid timing attacks,
+use
+.Xr crypto_verify16 3monocypher ,
+.Xr crypto_verify32 3monocypher ,
+or
+.Xr crypto_verify64 3monocypher
+to compare (possibly truncated) MACs.
+.It Fa key
+Some secret key.
+When uniformly random,
+one cannot predict the final HMAC without it.
+Users may want to wipe the key with
+.Xr crypto_wipe 3monocypher
+once they are done with it.
+Also stands for the
+.Fa salt
+argument when using
+.Fn crypto_sha512_hmac
+for HKDF extraction.
+.It Fa key_size
+Length of
+.Fa key ,
+in bytes.
+32 is a good default.
+Keys longer than 128 bytes will be reduced to 64 bytes by hashing
+the key with SHA-512.
+.It Fa message
+The message to compute the HMAC for.
+May be
+.Dv NULL
+if
+.Fa message_size
+is 0.
+Also stands for the
+.Fa ikm
+argument when using
+.Fn crypto_sha512_hmac
+for HKDF extraction.
+.It Fa message_size
+Length of
+.Fa message ,
+in bytes.
+.El
+.Ss Key derivation
+.Fn crypto_sha512_hkdf
+and
+.Fn crypto_sha512_hkdf_expand
+implement HKDF key derivation on top of SHA-512.
+HKDF is divided in two phases:
+first we
+.Em extract
+entropy from some input key material to produce a
+.Em pseudo-random key
+(PRK) which is indistinguishable from uniform random bytes.
+Then we
+.Em expand
+that pseudo-random key into a longer stream of independent random bytes
+called
+.Em output key material
+(OKM).
+.Pp
+HKDF extraction is already implemented in
+.Fn crypto_sha512_hmac ,
+so there is no dedicated function.
+HKDF expansion is implemented by
+.Fn crypto_sha512_hkdf_expand .
+Note that expansion works with any uniformly random key,
+the PRK does not have to come from
+.Fn crypto_sha512_hmac
+specifically.
+Likewise,
+if compatibility or standard compliance is not an issue,
+expansion could in principle use any pseudo-random function,
+such as
+.Xr crypto_chacha20_djb 3monocypher .
+.Pp
+.Fn crypto_sha512_hkdf
+is a convenience function that performs
+.Fn crypto_sha512_hmac
+and
+.Fn crypto_sha512_hkdf_expand .
+.Pp
+Contrary to most functions in Monocypher,
+the inputs of
+.Fn crypto_sha512_hkdf
+and
+.Fn crypto_sha512_hkdf_expand
+.Em cannot overlap
+with their output.
+The unlimited size of both inputs and output prevents us from from
+caching one of them in a local variable.
+.Pp
+The arguments are:
+.Bl -tag -width Ds
+.It Fa okm
+The output key material of HKDF or HKDF expansion,
+usable as a symmetric encryption key,
+or set thereof.
+.It Fa okm_size
+Length of
+.Fa okm ,
+in bytes.
+.It Fa ikm
+Input key material containing enough secret entropy to derive uniformly
+random keys from,
+such as the shared secret of a key exchange performed with
+.Xr crypto_x25519 3monocypher .
+Passwords do
+.Sy not
+contain enough entropy to be used as input key material.
+Hash them with
+.Xr crypto_argon2 3monocypher
+instead.
+.It Fa ikm_size
+Length of
+.Fa ikm ,
+in bytes.
+.It Fa prk
+Pseudo-random key.
+Typically comes from an HKDF extraction with
+.Fn crypto_sha512_hmac ,
+but can come from any source as long as it is uniformly random.
+Should be at least 32 bytes long.
+.It Fa prk_size
+Length of
+.Fa prk ,
+in bytes.
+.It Fa salt
+An optional random salt,
+used to increase the security of the output key material
+.Fa okm
+in some settings.
+Can be NULL if
+.Fa salt_size
+is zero.
+Otherwise it should contain at least 16 bytes.
+.It Fa salt_size
+Length of
+.Fa salt ,
+in bytes.
+.It Fa info
+Optional domain separation string for key derivation.
+Can be NULL if
+.Fa info_size
+is zero.
+.It Fa info_size
+Length of
+.Fa info ,
+in bytes.
+.El
+.Ss Incremental interface
+An incremental interface is provided.
+It is useful for handling streams of data or
+large files without using too much memory.
+This interface uses three steps:
+.Bl -bullet
+.It
+initialisation with
+.Fn crypto_sha512_init
+or
+.Fn crypto_sha512_hmac_init ,
+which sets up a context with the hashing parameters;
+.It
+update with
+.Fn crypto_sha512_update
+or
+.Fn crypto_sha512_hmac_update ,
+which hashes the message chunk by chunk and keeps the intermediary
+result in the context;
+.It
+and finalisation with
+.Fn crypto_sha512_final
+or
+.Fn crypto_sha512_hmac_final ,
+which produces the final hash.
+The
+.Ft crypto_sha512_ctx
+or
+.Ft crypto_sha512_hmac_ctx
+is automatically wiped upon finalisation.
+.El
+.Pp
+.Fn crypto_sha512
+is a convenience function that
+performs
+.Fn crypto_sha512_init ,
+.Fn crypto_sha512_update ,
+and
+.Fn crypto_sha512_final .
+.Pp
+.Fn crypto_sha512_hmac
+is a convenience function that
+performs
+.Fn crypto_sha512_hmac_init ,
+.Fn crypto_sha512_hmac_update ,
+and
+.Fn crypto_sha512_hmac_final .
+.Sh RETURN VALUES
+These functions return nothing.
+.Sh EXAMPLES
+Hashing a message all at once:
+.Bd -literal -offset indent
+uint8_t hash [64]; /* Output hash (64 bytes) */
+uint8_t message[12] = "Lorem ipsum"; /* Message to hash */
+crypto_sha512(hash, message, 12);
+.Ed
+.Pp
+Hashing a message incrementally:
+.Bd -literal -offset indent
+uint8_t hash [ 64]; /* Output hash (64 bytes) */
+uint8_t message[500] = {1}; /* Message to hash */
+crypto_sha512_ctx ctx;
+crypto_sha512_init(&ctx);
+for (size_t i = 0; i < 500; i += 100) {
+ crypto_sha512_update(&ctx, message + i, 100);
+}
+crypto_sha512_final(&ctx, hash);
+.Ed
+.Pp
+Computing a message authentication code all at once:
+.Bd -literal -offset indent
+uint8_t hash [64]; /* Output hash */
+uint8_t key [32]; /* Key */
+uint8_t message[10] = "Lorem ipsu"; /* Message to authenticate */
+arc4random_buf(key, 32);
+crypto_sha512_hmac(hash, key, 32, message, 10);
+/* Wipe secrets if they are no longer needed */
+crypto_wipe(message, 10);
+crypto_wipe(key, 32);
+.Ed
+.Pp
+Computing a message authentication code incrementally:
+.Bd -literal -offset indent
+uint8_t hash [64]; /* Output hash */
+uint8_t key [32]; /* Key */
+uint8_t message[500] = {1}; /* Message to authenticate */
+crypto_sha512_hmac_ctx ctx;
+arc4random_buf(key, 32);
+crypto_sha512_hmac_init(&ctx, key, 32);
+/* Wipe the key */
+crypto_wipe(key, 32);
+for (size_t i = 0; i < 500; i += 100) {
+ crypto_sha512_hmac_update(&ctx, message + i, 100);
+ /* Wipe secrets if they are no longer needed */
+ crypto_wipe(message + i, 100);
+}
+crypto_sha512_hmac_final(&ctx, hash);
+.Ed
+.Pp
+Deriving keys from input key material:
+.Bd -literal -offset indent
+uint8_t okm[128]; /* Output random keys */
+uint8_t ikm [96]; /* Input key material */
+uint8_t salt[16]; /* Random salt */
+uint8_t info[11] = "Lorem ipsum"; /* Domain separation */
+arc4random_buf(salt, sizeof(salt));
+crypto_sha512_hkdf(okm, sizeof(okm),
+ ikm, sizeof(ikm),
+ salt, sizeof(salt),
+ info, sizeof(info));
+uint8_t *key1 = okm + 0;
+uint8_t *key2 = okm + 32;
+uint8_t *key3 = okm + 64;
+uint8_t *key4 = okm + 96;
+/* Wipe okm when it is no longer needed */
+.Ed
+.Pp
+Deriving keys from several bits of input key material:
+.Bd -literal -offset indent
+uint8_t okm [96]; /* Output secret keys */
+uint8_t pk_a[32]; /* Alice public X25519 key */
+uint8_t pk_b[32]; /* Bob public X25519 key */
+uint8_t skab[32]; /* Alice & bob shared secret */
+uint8_t ikm [96]; /* Input key material */
+uint8_t salt[16]; /* Random salt */
+uint8_t info[ 6] = "X25519"; /* Domain separation */
+arc4random_buf(salt, sizeof(salt));
+
+/* Extract */
+uint8_t prk[64]; /* pseudo-random key */
+crypto_sha512_hmac_ctx ctx;
+crypto_sha512_hmac_init (&ctx, salt, sizeof(salt));
+crypto_sha512_hmac_update(&ctx, pk_a, sizeof(pk_a));
+crypto_sha512_hmac_update(&ctx, pk_b, sizeof(pk_b));
+crypto_sha512_hmac_update(&ctx, skab, sizeof(skab));
+crypto_sha512_hmac_final (&ctx, prk);
+
+/* Expand */
+crypto_sha512_hkdf_expand(okm, sizeof(okm),
+ prk, sizeof(prk),
+ info, sizeof(info));
+uint8_t *key1 = okm + 0;
+uint8_t *key2 = okm + 32;
+uint8_t *key3 = okm + 64;
+/* Wipe okm when it is no longer needed */
+.Ed
+.Sh SEE ALSO
+.Xr crypto_blake2b 3monocypher ,
+.Xr crypto_aead_lock 3monocypher ,
+.Xr crypto_poly1305 3monocypher ,
+.Xr intro 3monocypher
+.Sh STANDARDS
+These functions implement SHA-512,
+HMAC with SHA-512,
+and HKDF with SHA-512.
+HMAC and SHA-512 are described in RFC 6234;
+SHA-512 is also described in the Federal Information Processing Standard
+(FIPS) 180-4;
+HMAC is also described in FIPS 198-1.
+HKDF is described in RFC 5869.
+.Sh HISTORY
+The
+.Fn crypto_sha512 ,
+.Fn crypto_sha512_init ,
+.Fn crypto_sha512_update ,
+and
+.Fn crypto_sha512_final
+functions first appeared in Monocypher 0.3,
+but were not intended for use outside Monocypher itself and thus
+undocumented.
+They became part of the official API in Monocypher 3.0.0.
+.Pp
+The
+.Fn crypto_hmac_sha512 ,
+.Fn crypto_hmac_sha512_init ,
+.Fn crypto_hmac_sha512_update ,
+and
+.Fn crypto_hmac_sha512_final
+functions first appeared in Monocypher 3.0.0,
+then renamed
+.Fn crypto_sha512_hmac ,
+.Fn crypto_sha512_hmac_init ,
+.Fn crypto_sha512_hmac_update ,
+and
+.Fn crypto_sha512_hmac_final
+in Monocypher 4.0.0.
+.Pp
+.Fn crypto_sha512_hkdf
+and
+.Fn crypto_sha512_hkdf_expand
+were added in Monocypher 4.0.0.
+.Sh CAVEATS
+Monocypher does not perform any input validation.
+Any deviation from the specified input and output length ranges results
+in
+.Sy undefined behaviour .
+Make sure your inputs are correct.
+.Sh SECURITY CONSIDERATIONS
+SHA-512 is a general-purpose cryptographic hash function;
+this means that it is not suited for hashing passwords and deriving
+cryptographic keys from passwords.
+While cryptographic keys usually have hundreds of bits of entropy,
+passwords are often much less complex.
+When storing passwords as hashes or when deriving keys from them,
+the goal is normally to prevent attackers from quickly iterating all
+possible passwords.
+Because passwords tend to be simple,
+it is important to artificially slow down attackers by using especially
+computationally difficult hashing algorithms.
+Monocypher therefore provides
+.Xr crypto_argon2 3monocypher
+for password hashing and deriving keys from passwords.
+.Pp
+While HKDF and HMAC are proper key derivation functions (KDF),
+the HKDF expand step alone is
+.Em not .
+It is a
+.Em pseudo-random function
+(PRF),
+that only works with a
+.Em uniformly
+random key.
+We cannot simply input regular (non uniform) input key material
+without making unusually strong assumptions about the security of HMAC.
diff --git a/lib/Utils.Cryptography/monocypher/vendor/doc/crypto_verify16.3monocypher b/lib/Utils.Cryptography/monocypher/vendor/doc/crypto_verify16.3monocypher
new file mode 100644
index 0000000..09a7dcd
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/doc/crypto_verify16.3monocypher
@@ -0,0 +1,132 @@
+.\" This file is dual-licensed. Choose whichever you want.
+.\"
+.\" The first licence is a regular 2-clause BSD licence. The second licence
+.\" is the CC-0 from Creative Commons. It is intended to release Monocypher
+.\" to the public domain. The BSD licence serves as a fallback option.
+.\"
+.\" SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+.\"
+.\" ----------------------------------------------------------------------------
+.\"
+.\" Copyright (c) 2017-2019 Loup Vaillant
+.\" Copyright (c) 2017-2018 Michael Savage
+.\" Copyright (c) 2017, 2019-2020 Fabio Scotoni
+.\" All rights reserved.
+.\"
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions are
+.\" met:
+.\"
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\"
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the
+.\" distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+.\" HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" ----------------------------------------------------------------------------
+.\"
+.\" Written in 2017-2020 by Loup Vaillant, Michael Savage and Fabio Scotoni
+.\"
+.\" To the extent possible under law, the author(s) have dedicated all copyright
+.\" and related neighboring rights to this software to the public domain
+.\" worldwide. This software is distributed without any warranty.
+.\"
+.\" You should have received a copy of the CC0 Public Domain Dedication along
+.\" with this software. If not, see
+.\" <https://creativecommons.org/publicdomain/zero/1.0/>
+.\"
+.Dd March 31, 2020
+.Dt CRYPTO_VERIFY16 3MONOCYPHER
+.Os
+.Sh NAME
+.Nm crypto_verify16 ,
+.Nm crypto_verify32 ,
+.Nm crypto_verify64
+.Nd timing-safe data comparison
+.Sh SYNOPSIS
+.In monocypher.h
+.Ft int
+.Fo crypto_verify16
+.Fa "const uint8_t a[16]"
+.Fa "const uint8_t b[16]"
+.Fc
+.Ft int
+.Fo crypto_verify32
+.Fa "const uint8_t a[32]"
+.Fa "const uint8_t b[32]"
+.Fc
+.Ft int
+.Fo crypto_verify64
+.Fa "const uint8_t a[64]"
+.Fa "const uint8_t b[64]"
+.Fc
+.Sh DESCRIPTION
+Cryptographic operations often require comparison of secrets or values
+derived from secrets.
+Standard comparison functions like
+.Xr memcmp 3
+tend to exit when they find the first difference, leaking information
+through timing differences.
+.Pp
+As an example, say a message authentication code (MAC) is sent over the
+network along with a message, but the correct MAC is secret.
+If the attacker attempts a forgery, one does not want to reveal
+.Dq your MAC is wrong, Em and it took 384 microseconds to tell .
+If the next attempt takes 462 microseconds instead, it tells the
+attacker that they just guessed a byte correctly.
+That way, an attacker can derive the correct MAC byte by byte
+and successfully forge a message.
+This has led to practical attacks in the past.
+.Pp
+To avoid such catastrophic failure,
+.Fn crypto_verify16 ,
+.Fn crypto_verify32 ,
+and
+.Fn crypto_verify64
+provide comparison functions whose timing is independent from
+the content of their input.
+They compare the first
+16, 32, or 64 bytes of the two byte arrays
+.Fa a
+and
+.Fa b .
+.Pp
+When in doubt, prefer these functions over
+.Xr memcmp 3 .
+.Sh RETURN VALUES
+These functions return 0 if the two memory chunks are the same and -1
+otherwise.
+.Sh SEE ALSO
+.Xr intro 3monocypher
+.Sh HISTORY
+The
+.Fn crypto_verify16 ,
+.Fn crypto_verify32 ,
+.Fn crypto_verify64 ,
+functions first appeared in Monocypher 1.1.0.
+They replaced the
+.Fn crypto_memcmp
+and
+.Fn crypto_zerocmp
+functions that were present until Monocypher 1.0.1.
+.Sh CAVEATS
+Monocypher does not perform any input validation.
+Any deviation from the specified input and output length ranges results
+in
+.Sy undefined behaviour .
+Make sure your inputs are correct.
diff --git a/lib/Utils.Cryptography/monocypher/vendor/doc/crypto_wipe.3monocypher b/lib/Utils.Cryptography/monocypher/vendor/doc/crypto_wipe.3monocypher
new file mode 100644
index 0000000..4f299fb
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/doc/crypto_wipe.3monocypher
@@ -0,0 +1,116 @@
+.\" This file is dual-licensed. Choose whichever you want.
+.\"
+.\" The first licence is a regular 2-clause BSD licence. The second licence
+.\" is the CC-0 from Creative Commons. It is intended to release Monocypher
+.\" to the public domain. The BSD licence serves as a fallback option.
+.\"
+.\" SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+.\"
+.\" ----------------------------------------------------------------------------
+.\"
+.\" Copyright (c) 2017-2019 Loup Vaillant
+.\" Copyright (c) 2017-2018 Michael Savage
+.\" Copyright (c) 2017, 2019 Fabio Scotoni
+.\" All rights reserved.
+.\"
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions are
+.\" met:
+.\"
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\"
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the
+.\" distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+.\" HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" ----------------------------------------------------------------------------
+.\"
+.\" Written in 2017-2019 by Loup Vaillant, Michael Savage and Fabio Scotoni
+.\"
+.\" To the extent possible under law, the author(s) have dedicated all copyright
+.\" and related neighboring rights to this software to the public domain
+.\" worldwide. This software is distributed without any warranty.
+.\"
+.\" You should have received a copy of the CC0 Public Domain Dedication along
+.\" with this software. If not, see
+.\" <https://creativecommons.org/publicdomain/zero/1.0/>
+.\"
+.Dd December 12, 2019
+.Dt CRYPTO_WIPE 3MONOCYPHER
+.Os
+.Sh NAME
+.Nm crypto_wipe
+.Nd wipe data from memory
+.Sh SYNOPSIS
+.In monocypher.h
+.Ft void
+.Fo crypto_wipe
+.Fa "void *secret"
+.Fa "size_t secret_size"
+.Fc
+.Sh DESCRIPTION
+.Fn crypto_wipe
+securely erases sensitive data in memory.
+.Pp
+Sensitive data (such as cryptographic keys or secret plaintexts) should
+be erased from memory as early as possible to minimise the window in
+which it can be leaked.
+Standard functions like memset and bzero are not safe to use as the
+compiler may decide they have no effect and optimise them out.
+.Pp
+The arguments are:
+.Bl -tag -width Ds
+.It Fa secret
+The buffer to erase.
+.It Fa secret_size
+The number of bytes to erase from the buffer.
+This is normally the size of the entire buffer.
+.El
+.Pp
+Monocypher will wipe its context structs when finalizing an operation
+such as signing or decrypting.
+When using direct interfaces like
+.Xr crypto_aead_lock 3monocypher ,
+these context structs are invisible to you.
+However, they are exposed in incremental interfaces like
+.Xr crypto_blake2b_init 3monocypher .
+The original key buffer does not get automatically wiped.
+When using incremental interfaces, you may want to wipe the original key
+buffers immediately after calling the respective init function.
+.Pp
+Using
+.Fn crypto_wipe
+alone may not be enough for security.
+It is recommended to lock down relevant memory regions as well.
+Refer to
+.Xr intro 3monocypher
+for instructions on how to lock down memory on common operating systems.
+.Sh RETURN VALUES
+This function returns nothing.
+.Sh SEE ALSO
+.Xr intro 3monocypher
+.Sh HISTORY
+The
+.Fn crypto_wipe
+function first appeared in Monocypher 1.1.0.
+.Sh CAVEATS
+Monocypher does not perform any input validation.
+Any deviation from the specified input and output length ranges results
+in
+.Sy undefined behaviour .
+Make sure your inputs are correct.
diff --git a/lib/Utils.Cryptography/monocypher/vendor/doc/crypto_x25519.3monocypher b/lib/Utils.Cryptography/monocypher/vendor/doc/crypto_x25519.3monocypher
new file mode 100644
index 0000000..d9abbe3
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/doc/crypto_x25519.3monocypher
@@ -0,0 +1,329 @@
+.\" This file is dual-licensed. Choose whichever you want.
+.\"
+.\" The first licence is a regular 2-clause BSD licence. The second licence
+.\" is the CC-0 from Creative Commons. It is intended to release Monocypher
+.\" to the public domain. The BSD licence serves as a fallback option.
+.\"
+.\" SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+.\"
+.\" ----------------------------------------------------------------------------
+.\"
+.\" Copyright (c) 2017-2021, 2022-2023 Loup Vaillant
+.\" Copyright (c) 2017-2018 Michael Savage
+.\" Copyright (c) 2017, 2019-2020, 2022 Fabio Scotoni
+.\" Copyright (c) 2020 Richard Walmsley
+.\" Copyright (c) 2022 Samuel Lucas
+.\" All rights reserved.
+.\"
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions are
+.\" met:
+.\"
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\"
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the
+.\" distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+.\" HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" ----------------------------------------------------------------------------
+.\"
+.\" Written in 2017-2023 by Loup Vaillant, Michael Savage, Fabio Scotoni,
+.\" Richard Walmsley and Samuel Lucas
+.\"
+.\" To the extent possible under law, the author(s) have dedicated all copyright
+.\" and related neighboring rights to this software to the public domain
+.\" worldwide. This software is distributed without any warranty.
+.\"
+.\" You should have received a copy of the CC0 Public Domain Dedication along
+.\" with this software. If not, see
+.\" <https://creativecommons.org/publicdomain/zero/1.0/>
+.\"
+.Dd January 26, 2023
+.Dt CRYPTO_X25519 3MONOCYPHER
+.Os
+.Sh NAME
+.Nm crypto_x25519 ,
+.Nm crypto_x25519_public_key ,
+.Nm crypto_x25519_dirty_fast ,
+.Nm crypto_x25519_dirty_small ,
+.Nm crypto_x25519_inverse ,
+.Nm crypto_x25519_to_eddsa
+.Nd X25519 key exchange (Public Key Cryptography)
+.Sh SYNOPSIS
+.In monocypher.h
+.Ft void
+.Fo crypto_x25519
+.Fa "uint8_t raw_shared_secret[32]"
+.Fa "const uint8_t your_secret_key[32]"
+.Fa "const uint8_t their_public_key[32]"
+.Fc
+.Ft void
+.Fo crypto_x25519_public_key
+.Fa "uint8_t your_public_key[32]"
+.Fa "const uint8_t your_secret_key[32]"
+.Fc
+.Ft void
+.Fo crypto_x25519_dirty_fast
+.Fa "uint8_t your_public_key[32]"
+.Fa "const uint8_t your_secret_key[32]"
+.Fc
+.Ft void
+.Fo crypto_x25519_dirty_small
+.Fa "uint8_t your_public_key[32]"
+.Fa "const uint8_t your_secret_key[32]"
+.Fc
+.Ft void
+.Fo crypto_x25519_inverse
+.Fa "uint8_t blind_salt[32]"
+.Fa "const uint8_t private_key[32]"
+.Fa "const uint8_t curve_point[32]"
+.Fc
+.Ft void
+.Fo crypto_x25519_to_eddsa
+.Fa "uint8_t eddsa[32]"
+.Fa "const uint8_t x25519[32]"
+.Fc
+.Sh DESCRIPTION
+.Fn crypto_x25519
+performs an X25519 key exchange between
+.Fa your_secret_key
+and
+.Fa their_public_key .
+It is a low-level building block for protocols such as X3DH.
+.Fn crypto_x25519_public_key
+Generates a public key from a secret key.
+The arguments are:
+.Bl -tag -width Ds
+.It Fa raw_shared_secret
+The shared secret, known only to those who know a relevant secret key
+(yours or theirs).
+It is not cryptographically random.
+Do not use it directly as a key.
+Hash it concatenated with
+.Fa your_public_key
+and
+.Fa their_public_key
+using
+.Xr crypto_blake2b 3monocypher
+for key derivation.
+.It Fa your_secret_key
+A 32-byte secret random number.
+See
+.Xr intro 3monocypher
+for advice about generating random bytes (use the operating system's
+random number generator).
+.It Fa your_public_key
+Your public key, generated by
+.Fn crypto_x25519_public_key .
+.It Fa their_public_key
+The public key of the other party.
+.El
+.Pp
+.Fa raw_shared_secret
+and
+.Fa your_secret_key
+may overlap if your secret is no longer required.
+.Pp
+Some protocols,
+such as some password-authenticated key exchange (PAKE) protocols
+and oblivious pseudo-random functions (OPRF),
+may require
+.Dq contributory
+behaviour, which ensures that no untrusted party forces the shared
+secret to a known constant.
+If a protocol requires contributory behaviour,
+compare the output of
+.Fn crypto_x25519
+to an all-zero buffer using
+.Xr crypto_verify32 3monocypher ,
+then abort the protocol if the output and the all-zero buffer are equal.
+.Pp
+Do not use the same secret key for both key exchanges and signatures.
+The public keys are different and revealing both may leak information.
+If there really is no room to store or derive two different secret keys,
+consider generating a key pair for signatures and then converting the
+private half with
+.Xr crypto_blake2b 3monocypher
+or
+.Xr crypto_sha512 3monocypher ,
+and the public half with
+.Xr crypto_eddsa_to_x25519 3monocypher .
+Or go the other way and implement XEdDSA with the help of
+.Fn crypto_x25519_to_eddsa .
+.Sh RETURN VALUES
+.Fn crypto_x25519
+and
+.Fn crypto_x25519_public_key
+return nothing.
+.Sh EXAMPLES
+The following example assumes the existence of
+.Fn arc4random_buf ,
+which fills the given buffer with cryptographically secure random bytes.
+If
+.Fn arc4random_buf
+does not exist on your system, see
+.Xr intro 3monocypher
+for advice about how to generate cryptographically secure random bytes.
+.Pp
+Generate a pair of shared keys with your secret key and their public
+key
+(this can help nonce management for full duplex communications).
+.Bd -literal -offset indent
+const uint8_t their_pk [32]; /* Their public key */
+uint8_t your_sk [32]; /* Your secret key */
+uint8_t your_pk [32]; /* Your public key */
+uint8_t shared_secret[32]; /* Shared secret (NOT a key) */
+arc4random_buf(your_sk, 32);
+crypto_x25519_public_key(your_pk, your_sk);
+crypto_x25519(shared_secret, your_sk, their_pk);
+/* Wipe secrets if they are no longer needed */
+crypto_wipe(your_sk, 32);
+
+uint8_t shared_keys[64]; /* Two shared session keys */
+crypto_blake2b_ctx ctx;
+crypto_blake2b_init (&ctx, 64);
+crypto_blake2b_update(&ctx, shared_secret, 32);
+crypto_blake2b_update(&ctx, your_pk , 32);
+crypto_blake2b_update(&ctx, their_pk , 32);
+crypto_blake2b_final (&ctx, shared_keys);
+const uint8_t *key_1 = shared_keys; /* Shared key 1 */
+const uint8_t *key_2 = shared_keys + 32; /* Shared key 2 */
+/* Wipe secrets if they are no longer needed */
+crypto_wipe(shared_secret, 32);
+.Ed
+.Sh INVERSE SCALAR MULTIPLICATION
+The
+.Fn crypto_x25519_inverse
+function performs the scalar multiplication of the multiplicative
+inverse of a scalar for X25519.
+It is basically the reverse of
+.Fn crypto_x25519 :
+.Bd -literal -offset indent
+uint8_t b [32]; /* Random scalar */
+uint8_t base [32]; /* Point on the prime order subgroup */
+crypto_x25519_public_key(base, b);
+
+uint8_t private_key[32]; /* Random secret key */
+uint8_t curve_point[32]; /* Point on the prime order subgroup */
+uint8_t blind_salt [32];
+crypto_x25519(curve_point, private_key, base);
+crypto_x25519_inverse(blind_salt, private_key, curve_point);
+assert(memcmp(blind_salt, base, 32) == 0); /* blind_salt == base */
+.Ed
+.Pp
+We can think of it as a scalar division that also clears the cofactor.
+The arguments are:
+.Bl -tag -width Ds
+.It Fa blind_salt
+The output point.
+Guaranteed to be on the prime order subgroup.
+The only possible low order result is a buffer full of zeroes.
+.It Fa private_key
+The private key (scalar) to use.
+It is clamped,
+inverted modulo the prime order of Curve25519,
+cleared of its cofactor,
+and finally used to multiply
+.Fa curve_point .
+.It Fa curve_point
+The curve point to divide by
+.Fa private_key .
+.El
+.Sh DIRTY PUBLIC KEY GENERATION
+.Fn crypto_x25519_dirty_fast
+and
+.Fn crypto_x25519_dirty_small
+do the same as
+.Fn crypto_x25519_public_key ,
+with one key difference:
+they also add a low order point to the public key.
+Such public keys can be on the
+.Em whole
+curve, rather than just the main prime-order subgroup.
+Yet they are fully compatible with
+.Fn crypto_x25519 ,
+and will generate the same shared secrets as regular public keys.
+.Em They do however leak information about the private key .
+Only use them for ephemeral keys that need to be hidden as random noise,
+in conjunction with
+.Xr crypto_elligator_rev 3monocypher .
+.Pp
+Both functions do the same with different code size and memory
+characteristics:
+.Fn crypto_x25519_dirty_fast
+uses multiple large temporary variables and functions that are
+normally used internally for
+.Xr crypto_eddsa_sign 3monocypher .
+Accordingly, it uses both more stack memory and more code
+(unless the signing code is already compiled in elsewhere).
+.Fn crypto_x25519_dirty_small
+yields the same result with less code, less memory,
+and about twice as much time as
+.Fn crypto_x25519_dirty_fast .
+.Sh CONVERSION TO EDDSA
+The
+.Fn crypto_x25519_to_eddsa
+converts an X25519 public key to the corresponding EdDSA public key.
+The sign bit of the resulting EdDSa key is set to zero (positive).
+This can be used to implement the XEdDSA protocol from Signal.
+.Sh SEE ALSO
+.Xr intro 3monocypher
+.Sh STANDARDS
+This function implements X25519, described in RFC 7748.
+.Sh HISTORY
+The
+.Fn crypto_x25519
+and
+.Fn crypto_x25519_public_key
+functions first appeared in Monocypher 0.1.
+The
+.Fn crypto_x25519_inverse ,
+.Fn crypto_x25519_dirty_fast ,
+.Fn crypto_x25519_dirty_small ,
+and
+.Fn crypto_x25519_to_eddsa
+functions first appeared in Monocypher 3.1.0.
+.Sh CAVEATS
+Monocypher does not perform any input validation.
+Any deviation from the specified input and output length ranges results
+in
+.Sy undefined behaviour .
+Make sure your inputs are correct.
+.Sh SECURITY CONSIDERATIONS
+If either of the long-term secret keys leaks, it may compromise
+.Em all past messages .
+This can be avoided by using protocols that provide forward secrecy,
+such as the X3DH key agreement protocol.
+.Pp
+Many (private, public) key pairs produce the same shared secret.
+Therefore, not including the public keys in the key derivation can
+lead to subtle vulnerabilities.
+This can be avoided by hashing the shared secret concatenated with
+both public keys.
+For example,
+.D1 BLAKE2b(shared_secret || your_pk || their_pk)
+using
+.Xr crypto_blake2b 3monocypher .
+.Sh IMPLEMENTATION DETAILS
+The most significant bit of the public key is systematically ignored.
+It is not needed because every public key should be smaller than
+2^255-19, which fits in 255 bits.
+If another implementation of X25519 gives you a key that is not fully
+reduced and has its high bit set, the computation will fail.
+On the other hand, it also means you may use this bit for other purposes
+(such as parity flipping for Ed25519 compatibility).
diff --git a/lib/Utils.Cryptography/monocypher/vendor/doc/doc_check.py b/lib/Utils.Cryptography/monocypher/vendor/doc/doc_check.py
new file mode 100644
index 0000000..3e9d1a8
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/doc/doc_check.py
@@ -0,0 +1,138 @@
+#! /usr/bin/env python3
+
+# This file is dual-licensed. Choose whichever licence you want from
+# the two licences listed below.
+#
+# The first licence is a regular 2-clause BSD licence. The second licence
+# is the CC-0 from Creative Commons. It is intended to release Monocypher
+# to the public domain. The BSD licence serves as a fallback option.
+#
+# SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+#
+# ------------------------------------------------------------------------
+#
+# Copyright (c) 2023, Loup Vaillant
+# All rights reserved.
+#
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# ------------------------------------------------------------------------
+#
+# Written in 2023 by Loup Vaillant
+#
+# To the extent possible under law, the author(s) have dedicated all copyright
+# and related neighboring rights to this software to the public domain
+# worldwide. This software is distributed without any warranty.
+#
+# You should have received a copy of the CC0 Public Domain Dedication along
+# with this software. If not, see
+# <https://creativecommons.org/publicdomain/zero/1.0/>
+
+import sys
+
+def map_prepend(s, l):
+ return [s + ": " + x for x in l]
+
+def extract(lines, start='', sub=''):
+ return [line.split(' ')[1].strip()
+ for line in lines
+ if (line.startswith(start) and line.__contains__(sub))]
+
+def without(item, list):
+ return [x for x in list if x != item]
+
+def check_inside(lines, all_functions):
+ errors = []
+
+ no_history = []
+ in_history = False
+ for line in lines:
+ if line.startswith('.Sh HISTORY'): in_history = True
+ elif line.startswith('.Sh') : in_history = False
+ if not in_history : no_history.append(line)
+
+ nm = extract(no_history, '.Nm')
+ fo = extract(no_history, '.Fo')
+ fn = extract(no_history, '.Fn')
+ fn = without('arc4random_buf', sorted(set(fn)))
+
+ dupes_nm = sorted(set([x for x in nm if nm.count(x) > 1]))
+ dupes_fo = sorted(set([x for x in fo if fo.count(x) > 1]))
+
+ only_fo = [x for x in fo if nm .count(x) == 0]
+ only_nm = [x for x in nm if fo .count(x) == 0]
+ only_fn = [x for x in fn if fo .count(x) == 0]
+ no_src = [x for x in fn if all_functions.count(x) == 0]
+
+ if len(dupes_nm) > 0: errors.append('Duplicates in .Nm: ' + str(dupes_nm))
+ if len(dupes_fo) > 0: errors.append('Duplicates in .Fo: ' + str(dupes_fo))
+ if len(only_fo) > 0: errors.append('Missing in .Nm: ' + str(only_fo))
+ if len(only_nm) > 0: errors.append('Only in .Nm: ' + str(only_nm))
+ if len(only_fn) > 0: errors.append('Only in .Fn: ' + str(only_fn))
+ if len(no_src) > 0: errors.append('Not in sources: ' + str(no_src))
+
+ return errors
+
+def check_xr(lines, all_nm):
+ errors = []
+ xr = sorted(set(extract(lines, '.Xr', '3monocypher')))
+ dead_xr = [x for x in xr if all_nm.count(x) == 0]
+ if len(dead_xr) > 0:
+ errors.append('Dead .Xr: ' + str(dead_xr))
+ return errors
+
+# Every line from every doc file
+all_lines = {}
+for file_name in sys.argv[1:]:
+ name = file_name.split('.')[0]
+ with open(file_name) as file:
+ all_lines[name] = file.readlines()
+
+# All .Nm (to spot .Xr dead references)
+all_nm = []
+for lines in all_lines.values():
+ all_nm += extract(lines, '.Nm')
+
+# All functions from source files
+all_functions = [x.strip()for x in sys.stdin.readlines()]
+
+# Errors
+errors = []
+for name, lines in all_lines.items():
+ if name != "intro": # skip internal checks for the intro page
+ errors += map_prepend(name, check_inside(lines, all_functions))
+ errors += map_prepend(name, check_xr(lines, all_nm))
+
+# Undocumented functions
+undocumented = [x for x in all_functions if all_nm.count(x) == 0]
+if len(undocumented) > 0:
+ errors.append('Undocumented functions: ' + str(undocumented))
+
+# Print any error, then exit accordingly
+if len(errors) != 0:
+ for e in errors:
+ print(e)
+ exit(1)
diff --git a/lib/Utils.Cryptography/monocypher/vendor/doc/doc_extract_examples.sh b/lib/Utils.Cryptography/monocypher/vendor/doc/doc_extract_examples.sh
new file mode 100644
index 0000000..8fd0736
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/doc/doc_extract_examples.sh
@@ -0,0 +1,78 @@
+#! /bin/sh
+
+# This file is dual-licensed. Choose whichever licence you want from
+# the two licences listed below.
+#
+# The first licence is a regular 2-clause BSD licence. The second licence
+# is the CC-0 from Creative Commons. It is intended to release Monocypher
+# to the public domain. The BSD licence serves as a fallback option.
+#
+# SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+#
+# ------------------------------------------------------------------------
+#
+# Copyright (c) 2019 Michael Savage
+# Copyright (c) 2020 Fabio Scotoni
+# All rights reserved.
+#
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# ------------------------------------------------------------------------
+#
+# Written in 2019-2020 by Michael Savage and Fabio Scotoni
+#
+# To the extent possible under law, the author(s) have dedicated all copyright
+# and related neighboring rights to this software to the public domain
+# worldwide. This software is distributed without any warranty.
+#
+# You should have received a copy of the CC0 Public Domain Dedication along
+# with this software. If not, see
+# <https://creativecommons.org/publicdomain/zero/1.0/>
+
+cat << END
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "../src/monocypher.h"
+#include "../src/optional/monocypher-ed25519.h"
+
+void arc4random_buf(void*, size_t);
+
+int main() {
+END
+
+for f in *.3monocypher
+do
+ if [ ! -h "$f" ]
+ then
+ echo "// $f"
+ cat "$f" | sed -n "/^\.Bd/,/^\.Ed/p" | sed "s/\.Bd.*/{/" | sed "s/\.Ed/}/"
+ fi
+done
+
+echo "return 0;"
+echo "}"
diff --git a/lib/Utils.Cryptography/monocypher/vendor/doc/doc_gen.sh b/lib/Utils.Cryptography/monocypher/vendor/doc/doc_gen.sh
new file mode 100644
index 0000000..804f602
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/doc/doc_gen.sh
@@ -0,0 +1,93 @@
+#! /bin/sh
+
+# This file is dual-licensed. Choose whichever licence you want from
+# the two licences listed below.
+#
+# The first licence is a regular 2-clause BSD licence. The second licence
+# is the CC-0 from Creative Commons. It is intended to release Monocypher
+# to the public domain. The BSD licence serves as a fallback option.
+#
+# SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+#
+# ------------------------------------------------------------------------
+#
+# Copyright (c) 2017, 2023, Loup Vaillant
+# Copyright (c) 2017, 2019, Fabio Scotoni
+# All rights reserved.
+#
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# ------------------------------------------------------------------------
+#
+# Written in 2017, 2019 and 2023 by Loup Vaillant and Fabio Scotoni
+#
+# To the extent possible under law, the author(s) have dedicated all copyright
+# and related neighboring rights to this software to the public domain
+# worldwide. This software is distributed without any warranty.
+#
+# You should have received a copy of the CC0 Public Domain Dedication along
+# with this software. If not, see
+# <https://creativecommons.org/publicdomain/zero/1.0/>
+
+set -e
+
+cd $(dirname "$0")
+
+# clean before
+rm -rf "html"
+rm -rf "man3"
+find . -type l | xargs rm -f
+
+mkdir -p man3
+mkdir -p html
+cp style.css html/
+
+cat ../src/monocypher.h ../src/optional/monocypher-ed25519.h |\
+ egrep -v "^(//|\}| | |extern)" |\
+ grep crypto_ |\
+ sed 's|[a-z0-9_]* *\([a-z0-9_]*\).*|\1|' |\
+ ./doc_check.py *.3monocypher
+
+for source in $(find . -name "*.3monocypher" | sed 's|^\./||' | sort)
+do
+ name=$(echo "$source" | sed 's/.3monocypher//')
+
+ # Copy source file to the final man page directory
+ cp "$source" "man3/$source"
+
+ # Generate HTML version,
+ mandoc \
+ -Oman=%N.html,style=style.css \
+ -Thtml "$source" \
+ > "./html/$name.html"
+
+ # Add all symbolic links
+ for link in $(grep "^\.Fo " "$source" | tail -n+2 | sed 's/^\.Fo //')
+ do
+ ln -s "$source" "man3/$link.3monocypher"
+ ln -s "$name.html" "html/$link.html"
+ done
+done
diff --git a/lib/Utils.Cryptography/monocypher/vendor/doc/intro.3monocypher b/lib/Utils.Cryptography/monocypher/vendor/doc/intro.3monocypher
new file mode 100644
index 0000000..a02863e
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/doc/intro.3monocypher
@@ -0,0 +1,335 @@
+.\" This file is dual-licensed. Choose whichever you want.
+.\"
+.\" The first licence is a regular 2-clause BSD licence. The second licence
+.\" is the CC-0 from Creative Commons. It is intended to release Monocypher
+.\" to the public domain. The BSD licence serves as a fallback option.
+.\"
+.\" SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+.\"
+.\" ----------------------------------------------------------------------------
+.\"
+.\" Copyright (c) 2017-2021 Loup Vaillant
+.\" Copyright (c) 2018 Michael Savage
+.\" Copyright (c) 2017, 2019-2022 Fabio Scotoni
+.\" All rights reserved.
+.\"
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions are
+.\" met:
+.\"
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\"
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the
+.\" distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+.\" HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" ----------------------------------------------------------------------------
+.\"
+.\" Written in 2017-2022 by Loup Vaillant, Michael Savage and Fabio Scotoni
+.\"
+.\" To the extent possible under law, the author(s) have dedicated all copyright
+.\" and related neighboring rights to this software to the public domain
+.\" worldwide. This software is distributed without any warranty.
+.\"
+.\" You should have received a copy of the CC0 Public Domain Dedication along
+.\" with this software. If not, see
+.\" <https://creativecommons.org/publicdomain/zero/1.0/>
+.\"
+.Dd February 20, 2022
+.Dt INTRO 3MONOCYPHER
+.Os
+.Sh NAME
+.Nm intro
+.Nd introduction to Monocypher
+.Sh DESCRIPTION
+Monocypher is a cryptographic library.
+It provides functions for authenticated encryption, hashing, password
+hashing and key derivation, key exchange, and public key signatures.
+.Ss Authenticated encryption
+.Xr crypto_aead_lock 3monocypher
+and
+.Xr crypto_aead_unlock 3monocypher
+use the ChaCha20 cipher and the Poly1305 one-time authenticator.
+There is also an incremental interface to facilitate
+file encryption and encrypted streams.
+.Pp
+ChaCha20 is a stream cipher based on a cryptographic hash function.
+It runs efficiently on a wide variety of hardware, and unlike AES
+naturally runs in constant time on all hardware.
+.Pp
+Poly1305 is a one-time authenticator, derived from Carter & Wegman
+universal hashing.
+It is very fast and very simple.
+.Ss Hashing
+.Xr crypto_blake2b 3monocypher
+implements the BLAKE2b hash.
+BLAKE2b combines the security of SHA-3 and the speed of MD5.
+It is immune to length extension attacks and provides a keyed mode
+that makes it a safe, easy to use authenticator.
+.Ss Password hashing and key derivation
+.Xr crypto_argon2 3monocypher
+implements the Argon2 resource intensive hash algorithm,
+which can be used to hash passwords for storage and to derive keys
+from passwords.
+Argon2 won the password hashing competition in 2015.
+Unlike scrypt, the Argon2i variant is immune to timing attacks.
+.Ss Key exchange (Public Key Cryptography)
+.Xr crypto_x25519 3monocypher
+implements X25519, an elliptic curve Diffie Hellman key exchange
+algorithm based on Curve25519.
+X25519 derives a shared secret from two private/public key pairs.
+It is fast, simple, and relatively easy to implement securely.
+.Pp
+For specialised protocols that require indistinguishability from random
+noise,
+.Xr crypto_elligator_rev 3monocypher
+gives the option to disguise ephemeral (one-time use) X25519 public keys
+as random noise.
+.Ss Public key signatures
+.Xr crypto_eddsa_sign 3monocypher
+and
+.Xr crypto_eddsa_check 3monocypher
+implement EdDSA, with Curve25519 and BLAKE2b.
+This is the same as the more famous Ed25519, with SHA-512 replaced by
+the faster BLAKE2b.
+.Ss Constant time comparison
+.Xr crypto_verify16 3monocypher ,
+.Xr crypto_verify32 3monocypher ,
+and
+.Xr crypto_verify64 3monocypher
+compare buffers in constant time.
+They should be used to compare secrets to prevent timing attacks.
+.Ss Memory wipe
+.Xr crypto_wipe 3monocypher
+wipes a buffer.
+It is meant to erase secrets when they are no longer needed, to reduce
+the chances of leaks.
+.Ss Optional code
+If Monocypher was compiled and installed with the provided makefile,
+SHA-512 functions become available as well.
+See
+.Xr crypto_ed25519_sign 3monocypher ,
+and
+.Xr crypto_sha512 3monocypher .
+.Sh SEE ALSO
+.Xr crypto_aead_init_djb 3monocypher ,
+.Xr crypto_aead_init_ietf 3monocypher ,
+.Xr crypto_aead_init_x 3monocypher ,
+.Xr crypto_aead_lock 3monocypher ,
+.Xr crypto_aead_read 3monocypher ,
+.Xr crypto_aead_unlock 3monocypher ,
+.Xr crypto_aead_write 3monocypher ,
+.Xr crypto_argon2 3monocypher ,
+.Xr crypto_blake2b 3monocypher ,
+.Xr crypto_blake2b_final 3monocypher ,
+.Xr crypto_blake2b_init 3monocypher ,
+.Xr crypto_blake2b_keyed 3monocypher ,
+.Xr crypto_blake2b_keyed_init 3monocypher ,
+.Xr crypto_blake2b_update 3monocypher ,
+.Xr crypto_chacha20_djb 3monocypher ,
+.Xr crypto_chacha20_h 3monocypher ,
+.Xr crypto_chacha20_ietf 3monocypher ,
+.Xr crypto_chacha20_x 3monocypher ,
+.Xr crypto_eddsa_check 3monocypher ,
+.Xr crypto_eddsa_check_equation 3monocypher ,
+.Xr crypto_eddsa_key_pair 3monocypher ,
+.Xr crypto_eddsa_mul_add 3monocypher ,
+.Xr crypto_eddsa_reduce 3monocypher ,
+.Xr crypto_eddsa_scalarbase 3monocypher ,
+.Xr crypto_eddsa_sign 3monocypher ,
+.Xr crypto_eddsa_to_x25519 3monocypher ,
+.Xr crypto_eddsa_trim_scalar 3monocypher ,
+.Xr crypto_elligator_key_pair 3monocypher ,
+.Xr crypto_elligator_map 3monocypher ,
+.Xr crypto_elligator_rev 3monocypher ,
+.Xr crypto_poly1305 3monocypher ,
+.Xr crypto_poly1305_final 3monocypher ,
+.Xr crypto_poly1305_init 3monocypher ,
+.Xr crypto_poly1305_update 3monocypher ,
+.Xr crypto_verify16 3monocypher ,
+.Xr crypto_verify32 3monocypher ,
+.Xr crypto_verify64 3monocypher ,
+.Xr crypto_wipe 3monocypher ,
+.Xr crypto_x25519 3monocypher ,
+.Xr crypto_x25519_dirty_fast 3monocypher ,
+.Xr crypto_x25519_dirty_small 3monocypher ,
+.Xr crypto_x25519_inverse 3monocypher ,
+.Xr crypto_x25519_public_key 3monocypher ,
+.Xr crypto_x25519_to_eddsa 3monocypher
+.Ss Optional code
+.Xr crypto_ed25519_check 3monocypher ,
+.Xr crypto_ed25519_key_pair 3monocypher ,
+.Xr crypto_ed25519_ph_check 3monocypher ,
+.Xr crypto_ed25519_ph_sign 3monocypher ,
+.Xr crypto_ed25519_sign 3monocypher ,
+.Xr crypto_sha512 3monocypher ,
+.Xr crypto_sha512_final 3monocypher ,
+.Xr crypto_sha512_hkdf 3monocypher ,
+.Xr crypto_sha512_hkdf_expand 3monocypher ,
+.Xr crypto_sha512_hmac 3monocypher ,
+.Xr crypto_sha512_hmac_final 3monocypher ,
+.Xr crypto_sha512_hmac_init 3monocypher ,
+.Xr crypto_sha512_hmac_update 3monocypher ,
+.Xr crypto_sha512_init 3monocypher ,
+.Xr crypto_sha512_update 3monocypher
+.Sh CAVEATS
+Monocypher does not perform any input validation.
+Any deviation from the specified input and output length ranges results
+in
+.Sy undefined behaviour .
+Make sure your inputs are correct.
+.Sh SECURITY CONSIDERATIONS
+Using cryptography securely is difficult.
+Flaws that never manifest under normal use might be exploited by a
+clever adversary.
+Cryptographic libraries are easy to catastrophically misuse,
+and Monocypher is no exception.
+.Pp
+Users should follow a formal introduction to cryptography.
+We currently recommend the
+.Lk https://www.crypto101.io/ "Crypto 101 online course" .
+.Ss Random number generation
+Use the facilities of your operating system.
+Avoid user space random number generators,
+whose misuse has led to countless vulnerabilities in the past.
+For instance, the random stream may be repeated if one is not careful
+with multi-threading, and forward secrecy is lost without proper key
+erasure.
+.Pp
+Different system calls are available on different systems:
+.Bl -bullet
+.It
+Recent versions of Linux (glibc >= 2.25, Linux >= 3.17), provide
+.Fn getrandom
+in
+.In sys/random.h .
+Do not set any flag.
+.It
+BSD, Darwin/macOS, illumos, and Solaris provide
+.Fn arc4random_buf
+in
+.In stdlib.h
+or
+.In bsd/stdlib.h .
+This is easier to use than
+.Fn getrandom .
+.It
+Windows provides
+.Fn BCryptGenRandom .
+.El
+.Pp
+The
+.Pa /dev/urandom
+special file may be used on systems that do not provide an easy-to-use
+system call.
+Be careful though, being a file makes
+.Pa /dev/urandom
+hard to use correctly and securely.
+Reads may be interrupted, and more attacks are possible on a file than
+on a system call.
+.Ss Timing attacks
+Monocypher runs in
+.Dq constant time .
+There is no flow from secrets to timings.
+No secret dependent indices, no secret dependent branches.
+Nevertheless, there are a couple important caveats.
+.Pp
+Comparing secrets should be done with constant-time comparison
+functions, such as
+.Xr crypto_verify16 3monocypher ,
+.Xr crypto_verify32 3monocypher ,
+or
+.Xr crypto_verify64 3monocypher .
+Do not use standard comparison functions.
+They tend to stop as soon as a difference is spotted.
+In many cases this enables attackers to recover the secrets and
+destroy all security.
+.Pp
+The Poly1305 authenticator, X25519, and EdDSA use multiplication.
+Some older processors do not multiply in constant time.
+If the target platform is something other than Intel or AMD x86_64,
+double check how it handles multiplication.
+In particular,
+.Em ARM Cortex-M CPUs may lack constant-time multiplication .
+Some VIA Nano x86 and x86_64 CPUs may lack constant-time multiplication
+as well.
+.Ss Data compression
+Encryption does not hide the length of the input plaintext.
+Most compression algorithms work by using fewer bytes to encode
+previously seen data or common characters.
+If an attacker can add data to the input before it is compressed and
+encrypted, they can observe changes to the ciphertext length to recover
+secrets from the input.
+Researchers have demonstrated an attack on HTTPS to steal session
+cookies when compression is enabled, dubbed
+.Dq CRIME .
+.Ss Forward secrecy
+Long-term secrets cannot be expected to stay safe indefinitely.
+Users may reveal them by mistake, or the host computer might have a
+vulnerability and be compromised.
+To mitigate this problem, some protocols guarantee that past messages
+are not compromised even if the long-term keys are.
+This is done by generating temporary keys, then encrypting messages
+using them.
+.Pp
+In general, secrets that went through a computer should not be
+compromised when this computer is stolen or infected at a later point.
+.Pp
+A first layer of defence is to explicitly wipe secrets as soon as
+they are no longer used.
+Monocypher already wipes its own temporary buffers, and contexts are
+erased with the
+.Fn crypto_*_final
+functions.
+The secret keys and messages however are the responsibility of the
+user.
+Use
+.Xr crypto_wipe 3monocypher
+to erase them.
+.Pp
+A second layer of defence is to ensure those secrets are not swapped
+to disk while they are used.
+There are several ways to do this.
+The most secure is to disable swapping entirely.
+Doing so is recommended on sensitive machines.
+Another way is to encrypt the swap partition (this is less safe).
+Finally, swap can be disabled locally \(en this is often the only
+way.
+.Pp
+UNIX systems can disable swap for specific buffers with
+.Fn mlock
+and disable swap for the whole process with
+.Fn mlockall .
+Windows can disable swap for specific buffers with
+.Fn VirtualLock .
+.Pp
+Core dumps cause similar problems.
+Disable them.
+Also beware of suspend to disk (deep sleep mode), which writes all RAM
+to disk regardless of swap policy, as well as virtual machine snapshots.
+Erasing secrets with
+.Xr crypto_wipe 3monocypher
+is often the only way to mitigate these dangers.
+.Ss Undefined behaviour
+Monocypher is a C library.
+C is notoriously unsafe.
+Using Monocypher incorrectly can trigger undefined behaviour.
+This can lead to data corruption, data theft, or even arbitrary code
+execution.
+.Pp
+Consider binding to a safe language if possible.
diff --git a/lib/Utils.Cryptography/monocypher/vendor/doc/style.css b/lib/Utils.Cryptography/monocypher/vendor/doc/style.css
new file mode 100644
index 0000000..0c930dd
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/doc/style.css
@@ -0,0 +1,292 @@
+/*
+ * This file is dual-licensed. Choose whichever licence you want from
+ * the two licences listed below.
+ *
+ * The first licence is a regular 2-clause BSD licence. The second licence
+ * is the CC-0 from Creative Commons. It is intended to release Monocypher
+ * to the public domain. The BSD licence serves as a fallback option.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+ *
+ * ------------------------------------------------------------------------
+ *
+ * Copyright (c) 2017-2019, Loup Vaillant
+ * All rights reserved.
+ *
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ------------------------------------------------------------------------
+ *
+ * Written in 2017-2019 by Loup Vaillant
+ *
+ * To the extent possible under law, the author(s) have dedicated all copyright
+ * and related neighboring rights to this software to the public domain
+ * worldwide. This software is distributed without any warranty.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication along
+ * with this software. If not, see
+ * <https://creativecommons.org/publicdomain/zero/1.0/>
+ */
+
+/*
+ * This file has been engineered to be compatible with both older mandoc and
+ * newer mandoc.
+ *
+ * mandoc 1.14.1 changed the class named for emph/symb/lit/spacer to
+ * Em/Sy/Li/Pp.
+ * The classes here account for that and are duplicated as necessary.
+ *
+ * The formatting was taken from mandoc.css (mandoc 1.14.5). Assorted changes:
+ * - Liberation Sans was added to the font-family in body.
+ * - added to body:
+ * margin: 1em auto; max-width: 40em; padding: 0 .62em; font-size: 1.1em;
+ * line-height: 1.62;
+ * - Removed .Sh and .Ss from h1 (not present in older mandoc)
+ * - Removed html styling breaking centering in body. It was:
+ * html { max-width: 100ex; }
+ *
+ * Much of the markup that got moved to CSS (e.g. .Ft) was pure HTML in older
+ * versions (<i class="ftype">) so that few adjustments are necessary.
+ *
+ * Upstream mandoc.css was placed in the public domain in CVS revision 1.39:
+ * ----------------------------------------------------------------------------
+ * Written by Ingo Schwarze <schwarze@openbsd.org>.
+ * I place this file into the public domain.
+ * Permission to use, copy, modify, and distribute it for any purpose
+ * with or without fee is hereby granted, without any conditions.
+ * ----------------------------------------------------------------------------
+ */
+body { margin: 1em auto;
+ max-width: 40em;
+ padding: 0 .62em;
+ font-size: 1.1em;
+ line-height: 1.62;
+ font-size: 125%;
+ font-family: "Liberation Sans", Arial, sans-serif; }
+table { margin-top: 0em;
+ margin-bottom: 0em; }
+td { vertical-align: top; }
+ul, ol, dl { margin-top: 0em;
+ margin-bottom: 0em; }
+li, dt { margin-top: 1em; }
+
+a.selflink { border-bottom: thin dotted;
+ color: inherit;
+ font: inherit;
+ text-decoration: inherit; }
+* { clear: both }
+
+/* Search form and search results. */
+
+fieldset { border: thin solid silver;
+ border-radius: 1em;
+ text-align: center; }
+input[name=expr] {
+ width: 25%; }
+
+table.results { margin-top: 1em;
+ margin-left: 2em;
+ font-size: smaller; }
+
+/* Header and footer lines. */
+
+table.head { width: 100%;
+ border-bottom: 1px dotted #808080;
+ margin-bottom: 1em;
+ font-size: smaller; }
+td.head-vol { text-align: center; }
+td.head-rtitle {
+ text-align: right; }
+span.Nd { }
+
+table.foot { width: 100%;
+ border-top: 1px dotted #808080;
+ margin-top: 1em;
+ font-size: smaller; }
+td.foot-os { text-align: right; }
+
+/* Sections and paragraphs. */
+
+div.manual-text {
+ margin-left: 5ex; }
+h1 { margin-top: 2ex;
+ margin-bottom: 1ex;
+ margin-left: -4ex;
+ font-size: 110%; }
+h2 { margin-top: 2ex;
+ margin-bottom: 1ex;
+ margin-left: -2ex;
+ font-size: 105%; }
+div.Pp { margin: 1ex 0ex; }
+div.spacer { margin: 1ex 0ex; }
+a.Sx { }
+a.Xr { }
+
+/* Displays and lists. */
+
+div.Bd { }
+div.D1 { margin-left: 5ex; }
+
+ul.Bl-bullet { list-style-type: disc;
+ padding-left: 1em; }
+li.It-bullet { }
+ul.Bl-dash { list-style-type: none;
+ padding-left: 0em; }
+li.It-dash:before {
+ content: "\2014 "; }
+ul.Bl-item { list-style-type: none;
+ padding-left: 0em; }
+li.It-item { }
+ul.Bl-compact > li {
+ margin-top: 0ex; }
+
+ol.Bl-enum { padding-left: 2em; }
+li.It-enum { }
+ol.Bl-compact > li {
+ margin-top: 0ex; }
+
+dl.Bl-diag { }
+dt.It-diag { }
+dd.It-diag { margin-left: 0ex; }
+b.It-diag { font-style: normal; }
+dl.Bl-hang { }
+dt.It-hang { }
+dd.It-hang { margin-left: 10.2ex; }
+dl.Bl-inset { }
+dt.It-inset { }
+dd.It-inset { margin-left: 0ex; }
+dl.Bl-ohang { }
+dt.It-ohang { }
+dd.It-ohang { margin-left: 0ex; }
+dl.Bl-tag { margin-left: 10.2ex; }
+dt.It-tag { float: left;
+ margin-top: 0ex;
+ margin-left: -10.2ex;
+ padding-right: 2ex;
+ vertical-align: top; }
+dd.It-tag { clear: right;
+ width: 100%;
+ margin-top: 0ex;
+ margin-left: 0ex;
+ vertical-align: top;
+ overflow: auto; }
+dl.Bl-compact > dt {
+ margin-top: 0ex; }
+
+table.Bl-column { }
+tr.It-column { }
+td.It-column { margin-top: 1em; }
+table.Bl-compact > tbody > tr > td {
+ margin-top: 0ex; }
+
+cite.Rs { font-style: normal;
+ font-weight: normal; }
+span.RsA { }
+i.RsB { font-weight: normal; }
+span.RsC { }
+span.RsD { }
+i.RsI { font-weight: normal; }
+i.RsJ { font-weight: normal; }
+span.RsN { }
+span.RsO { }
+span.RsP { }
+span.RsQ { }
+span.RsR { }
+span.RsT { text-decoration: underline; }
+a.RsU { }
+span.RsV { }
+
+span.eqn { }
+table.tbl { }
+
+/* Semantic markup for command line utilities. */
+
+table.Nm { }
+b.Nm { font-style: normal; }
+b.Fl { font-style: normal; }
+b.Cm { font-style: normal; }
+var.Ar { font-style: italic;
+ font-weight: normal; }
+span.Op { }
+b.Ic { font-style: normal; }
+code.Ev { font-style: normal;
+ font-weight: normal;
+ font-family: monospace; }
+i.Pa { font-weight: normal; }
+
+/* Semantic markup for function libraries. */
+
+span.Lb { }
+b.In { font-style: normal; }
+a.In { }
+b.Fd { font-style: normal; }
+var.Ft { font-style: italic;
+ font-weight: normal; }
+b.Fn { font-style: normal; }
+var.Fa { font-style: italic;
+ font-weight: normal; }
+var.Vt { font-style: italic;
+ font-weight: normal; }
+var.Va { font-style: italic;
+ font-weight: normal; }
+code.Dv { font-style: normal;
+ font-weight: normal;
+ font-family: monospace; }
+code.Er { font-style: normal;
+ font-weight: normal;
+ font-family: monospace; }
+
+/* Various semantic markup. */
+
+span.An { }
+a.Lk { }
+a.Mt { }
+b.Cd { font-style: normal; }
+i.Ad { font-weight: normal; }
+b.Ms { font-style: normal; }
+span.St { }
+a.Ux { }
+
+/* Physical markup. */
+
+.No { font-style: normal;
+ font-weight: normal; }
+.none { font-style: normal;
+ font-weight: normal; }
+.Em { font-style: italic;
+ font-weight: normal; }
+.emph { font-style: italic;
+ font-weight: normal; }
+.Sy { font-style: normal;
+ font-weight: bold; }
+.symb { font-style: normal;
+ font-weight: bold; }
+.Li { font-style: normal;
+ font-weight: normal;
+ font-family: monospace; }
+.lit { font-style: normal;
+ font-weight: normal;
+ font-family: monospace; }
diff --git a/lib/Utils.Cryptography/monocypher/vendor/makefile b/lib/Utils.Cryptography/monocypher/vendor/makefile
new file mode 100644
index 0000000..d747ff2
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/makefile
@@ -0,0 +1,211 @@
+# This file is dual-licensed. Choose whichever licence you want from
+# the two licences listed below.
+#
+# The first licence is a regular 2-clause BSD licence. The second licence
+# is the CC-0 from Creative Commons. It is intended to release Monocypher
+# to the public domain. The BSD licence serves as a fallback option.
+#
+# SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+#
+# ------------------------------------------------------------------------
+#
+# Copyright (c) 2017-2019, Loup Vaillant
+# Copyright (c) 2017, 2019, Fabio Scotoni
+# All rights reserved.
+#
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# ------------------------------------------------------------------------
+#
+# Written in 2017-2019 by Loup Vaillant and Fabio Scotoni
+#
+# To the extent possible under law, the author(s) have dedicated all copyright
+# and related neighboring rights to this software to the public domain
+# worldwide. This software is distributed without any warranty.
+#
+# You should have received a copy of the CC0 Public Domain Dedication along
+# with this software. If not, see
+# <https://creativecommons.org/publicdomain/zero/1.0/>
+.POSIX:
+.SUFFIXES:
+
+CC ?= gcc -std=c99
+CFLAGS ?= -pedantic -Wall -Wextra -O3 -march=native
+DESTDIR ?=
+PREFIX ?= /usr/local
+LIBDIR ?= $(PREFIX)/lib
+INCLUDEDIR ?= $(PREFIX)/include
+PKGCONFIGDIR ?= $(LIBDIR)/pkgconfig
+MANDIR ?= $(PREFIX)/share/man/man3
+SONAME = libmonocypher.so.4
+
+.PHONY: all library static-library dynamic-library \
+ install install-lib install-pc install-doc \
+ check test tis-ci ctgrind \
+ clean uninstall dist
+
+##################
+## Main targets ##
+##################
+all : library doc/man3/intro.3monocypher
+check: test
+
+test: test.out
+ ./test.out
+
+tis-ci: tis-ci.out
+ ./tis-ci.out
+
+ctgrind: ctgrind.out
+ valgrind ./ctgrind.out
+
+clean:
+ rm -rf lib/ doc/html/ doc/man3/
+ rm -f *.out
+
+#############
+## Install ##
+#############
+install: install-lib install-pc install-doc
+
+install-lib: library
+ mkdir -p $(DESTDIR)$(INCLUDEDIR)
+ mkdir -p $(DESTDIR)$(LIBDIR)
+ cp -P lib/libmonocypher.a lib/libmonocypher.so* $(DESTDIR)$(LIBDIR)
+ cp -P src/monocypher.h $(DESTDIR)$(INCLUDEDIR)
+ cp -P src/optional/monocypher-ed25519.h $(DESTDIR)$(INCLUDEDIR)
+
+install-pc: monocypher.pc
+ mkdir -p $(DESTDIR)$(PKGCONFIGDIR)
+ sed "s|PREFIX|$(PREFIX)|" monocypher.pc \
+ > $(DESTDIR)$(PKGCONFIGDIR)/monocypher.pc
+
+install-doc: doc/man3/intro.3monocypher
+ mkdir -p $(DESTDIR)$(MANDIR)
+ cp -PR doc/man3/*.3monocypher $(DESTDIR)$(MANDIR)
+
+uninstall:
+ rm -f $(DESTDIR)$(LIBDIR)/libmonocypher.a
+ rm -f $(DESTDIR)$(LIBDIR)/libmonocypher.so*
+ rm -f $(DESTDIR)$(INCLUDEDIR)/monocypher.h
+ rm -f $(DESTDIR)$(INCLUDEDIR)/monocypher-ed25519.h
+ rm -f $(DESTDIR)$(PKGCONFIGDIR)/monocypher.pc
+ rm -f $(DESTDIR)$(MANDIR)/*.3monocypher
+
+##################
+## Main library ##
+##################
+library: static-library dynamic-library
+static-library : lib/libmonocypher.a
+dynamic-library: lib/libmonocypher.so lib/$(SONAME)
+
+MAIN_O=lib/monocypher.o lib/monocypher-ed25519.o
+MAIN_I=-I src -I src/optional
+
+lib/libmonocypher.a: $(MAIN_O)
+ $(AR) cr $@ $(MAIN_O)
+
+lib/libmonocypher.so: lib/$(SONAME)
+ ln -sf `basename lib/$(SONAME)` $@
+
+lib/$(SONAME): $(MAIN_O)
+ $(CC) $(CFLAGS) $(LDFLAGS) -shared -Wl,-soname,$(SONAME) -o $@ $(MAIN_O)
+
+lib/monocypher.o: src/monocypher.c src/monocypher.h
+ @mkdir -p $(@D)
+ $(CC) $(CFLAGS) $(MAIN_I) -fPIC -c -o $@ src/monocypher.c
+
+lib/monocypher-ed25519.o: src/optional/monocypher-ed25519.c \
+ src/optional/monocypher-ed25519.h
+ @mkdir -p $(@D)
+ $(CC) $(CFLAGS) $(MAIN_I) -fPIC -c -o $@ src/optional/monocypher-ed25519.c
+
+####################
+## Test libraries ##
+####################
+TEST_COMMON=tests/utils.h src/monocypher.h src/optional/monocypher-ed25519.h
+TEST_I=$(MAIN_I) -I tests
+
+lib/utils.o: tests/utils.c
+ @mkdir -p $(@D)
+ $(CC) $(CFLAGS) $(TEST_I) -fPIC -c -o $@ tests/utils.c
+
+lib/test.o: tests/test.c $(TEST_COMMON) tests/vectors.h
+ @mkdir -p $(@D)
+ $(CC) $(CFLAGS) $(TEST_I) -fPIC -c -o $@ tests/test.c
+
+lib/tis-ci.o: tests/tis-ci.c $(TEST_COMMON) tests/tis-ci-vectors.h
+ @mkdir -p $(@D)
+ $(CC) $(CFLAGS) $(TEST_I) -fPIC -c -o $@ tests/tis-ci.c
+
+lib/ctgrind.o: tests/ctgrind.c $(TEST_COMMON)
+ @mkdir -p $(@D)
+ $(CC) $(CFLAGS) $(TEST_I) -fPIC -c -o $@ tests/ctgrind.c
+
+######################
+## Test executables ##
+######################
+TEST_OBJ = lib/utils.o lib/monocypher.o lib/monocypher-ed25519.o
+
+test.out: lib/test.o $(TEST_OBJ)
+ $(CC) $(CFLAGS) -o $@ lib/test.o $(TEST_OBJ)
+
+tis-ci.out: lib/tis-ci.o $(TEST_OBJ)
+ $(CC) $(CFLAGS) -o $@ lib/tis-ci.o $(TEST_OBJ)
+
+ctgrind.out: lib/ctgrind.o $(TEST_OBJ)
+ $(CC) $(CFLAGS) -o $@ lib/ctgrind.o $(TEST_OBJ)
+# Remove lines below for the tarball
+
+tests/vectors.h:
+ @echo ""
+ @echo "======================================================"
+ @echo " I cannot perform the tests without the test vectors."
+ @echo " You must generate them. This requires Libsodium."
+ @echo " The following will generate the test vectors:"
+ @echo ""
+ @echo " $ cd tests/gen"
+ @echo " $ make"
+ @echo ""
+ @echo " Alternatively, you can grab an official release."
+ @echo " It will include the test vectors, so you won't"
+ @echo " need libsodium."
+ @echo "======================================================"
+ @echo ""
+ exit 1
+
+doc/man3/intro.3monocypher: \
+ doc/crypto_aead_lock.3monocypher doc/crypto_argon2.3monocypher \
+ doc/crypto_blake2b.3monocypher doc/crypto_chacha20_djb.3monocypher \
+ doc/crypto_ed25519_sign.3monocypher doc/crypto_eddsa_sign.3monocypher \
+ doc/crypto_elligator_map.3monocypher doc/crypto_poly1305.3monocypher \
+ doc/crypto_sha512.3monocypher doc/crypto_verify16.3monocypher \
+ doc/crypto_wipe.3monocypher doc/crypto_x25519.3monocypher \
+ doc/intro.3monocypher
+ doc/doc_gen.sh
+
+dist: tests/vectors.h
+ ./dist.sh
diff --git a/lib/Utils.Cryptography/monocypher/vendor/monocypher.pc b/lib/Utils.Cryptography/monocypher/vendor/monocypher.pc
new file mode 100644
index 0000000..0945104
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/monocypher.pc
@@ -0,0 +1,11 @@
+prefix=PREFIX
+exec_prefix=${prefix}
+libdir=${exec_prefix}/lib
+includedir=${prefix}/include
+
+Name: monocypher
+Version: __git__
+Description: Easy to use, easy to deploy crypto library
+
+Libs: -L${libdir} -lmonocypher
+Cflags: -I${includedir}
diff --git a/lib/Utils.Cryptography/monocypher/vendor/src/monocypher.c b/lib/Utils.Cryptography/monocypher/vendor/src/monocypher.c
new file mode 100644
index 0000000..0accae7
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/src/monocypher.c
@@ -0,0 +1,2956 @@
+// Monocypher version __git__
+//
+// This file is dual-licensed. Choose whichever licence you want from
+// the two licences listed below.
+//
+// The first licence is a regular 2-clause BSD licence. The second licence
+// is the CC-0 from Creative Commons. It is intended to release Monocypher
+// to the public domain. The BSD licence serves as a fallback option.
+//
+// SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+//
+// ------------------------------------------------------------------------
+//
+// Copyright (c) 2017-2020, Loup Vaillant
+// All rights reserved.
+//
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// ------------------------------------------------------------------------
+//
+// Written in 2017-2020 by Loup Vaillant
+//
+// To the extent possible under law, the author(s) have dedicated all copyright
+// and related neighboring rights to this software to the public domain
+// worldwide. This software is distributed without any warranty.
+//
+// You should have received a copy of the CC0 Public Domain Dedication along
+// with this software. If not, see
+// <https://creativecommons.org/publicdomain/zero/1.0/>
+
+#include "monocypher.h"
+
+#ifdef MONOCYPHER_CPP_NAMESPACE
+namespace MONOCYPHER_CPP_NAMESPACE {
+#endif
+
+/////////////////
+/// Utilities ///
+/////////////////
+#define FOR_T(type, i, start, end) for (type i = (start); i < (end); i++)
+#define FOR(i, start, end) FOR_T(size_t, i, start, end)
+#define COPY(dst, src, size) FOR(_i_, 0, size) (dst)[_i_] = (src)[_i_]
+#define ZERO(buf, size) FOR(_i_, 0, size) (buf)[_i_] = 0
+#define WIPE_CTX(ctx) crypto_wipe(ctx , sizeof(*(ctx)))
+#define WIPE_BUFFER(buffer) crypto_wipe(buffer, sizeof(buffer))
+#define MIN(a, b) ((a) <= (b) ? (a) : (b))
+#define MAX(a, b) ((a) >= (b) ? (a) : (b))
+
+typedef int8_t i8;
+typedef uint8_t u8;
+typedef int16_t i16;
+typedef uint32_t u32;
+typedef int32_t i32;
+typedef int64_t i64;
+typedef uint64_t u64;
+
+static const u8 zero[128] = {0};
+
+// returns the smallest positive integer y such that
+// (x + y) % pow_2 == 0
+// Basically, y is the "gap" missing to align x.
+// Only works when pow_2 is a power of 2.
+// Note: we use ~x+1 instead of -x to avoid compiler warnings
+static size_t gap(size_t x, size_t pow_2)
+{
+ return (~x + 1) & (pow_2 - 1);
+}
+
+static u32 load24_le(const u8 s[3])
+{
+ return
+ ((u32)s[0] << 0) |
+ ((u32)s[1] << 8) |
+ ((u32)s[2] << 16);
+}
+
+static u32 load32_le(const u8 s[4])
+{
+ return
+ ((u32)s[0] << 0) |
+ ((u32)s[1] << 8) |
+ ((u32)s[2] << 16) |
+ ((u32)s[3] << 24);
+}
+
+static u64 load64_le(const u8 s[8])
+{
+ return load32_le(s) | ((u64)load32_le(s+4) << 32);
+}
+
+static void store32_le(u8 out[4], u32 in)
+{
+ out[0] = in & 0xff;
+ out[1] = (in >> 8) & 0xff;
+ out[2] = (in >> 16) & 0xff;
+ out[3] = (in >> 24) & 0xff;
+}
+
+static void store64_le(u8 out[8], u64 in)
+{
+ store32_le(out , (u32)in );
+ store32_le(out + 4, in >> 32);
+}
+
+static void load32_le_buf (u32 *dst, const u8 *src, size_t size) {
+ FOR(i, 0, size) { dst[i] = load32_le(src + i*4); }
+}
+static void load64_le_buf (u64 *dst, const u8 *src, size_t size) {
+ FOR(i, 0, size) { dst[i] = load64_le(src + i*8); }
+}
+static void store32_le_buf(u8 *dst, const u32 *src, size_t size) {
+ FOR(i, 0, size) { store32_le(dst + i*4, src[i]); }
+}
+static void store64_le_buf(u8 *dst, const u64 *src, size_t size) {
+ FOR(i, 0, size) { store64_le(dst + i*8, src[i]); }
+}
+
+static u64 rotr64(u64 x, u64 n) { return (x >> n) ^ (x << (64 - n)); }
+static u32 rotl32(u32 x, u32 n) { return (x << n) ^ (x >> (32 - n)); }
+
+static int neq0(u64 diff)
+{
+ // constant time comparison to zero
+ // return diff != 0 ? -1 : 0
+ u64 half = (diff >> 32) | ((u32)diff);
+ return (1 & ((half - 1) >> 32)) - 1;
+}
+
+static u64 x16(const u8 a[16], const u8 b[16])
+{
+ return (load64_le(a + 0) ^ load64_le(b + 0))
+ | (load64_le(a + 8) ^ load64_le(b + 8));
+}
+static u64 x32(const u8 a[32],const u8 b[32]){return x16(a,b)| x16(a+16, b+16);}
+static u64 x64(const u8 a[64],const u8 b[64]){return x32(a,b)| x32(a+32, b+32);}
+int crypto_verify16(const u8 a[16], const u8 b[16]){ return neq0(x16(a, b)); }
+int crypto_verify32(const u8 a[32], const u8 b[32]){ return neq0(x32(a, b)); }
+int crypto_verify64(const u8 a[64], const u8 b[64]){ return neq0(x64(a, b)); }
+
+void crypto_wipe(void *secret, size_t size)
+{
+ volatile u8 *v_secret = (u8*)secret;
+ ZERO(v_secret, size);
+}
+
+/////////////////
+/// Chacha 20 ///
+/////////////////
+#define QUARTERROUND(a, b, c, d) \
+ a += b; d = rotl32(d ^ a, 16); \
+ c += d; b = rotl32(b ^ c, 12); \
+ a += b; d = rotl32(d ^ a, 8); \
+ c += d; b = rotl32(b ^ c, 7)
+
+static void chacha20_rounds(u32 out[16], const u32 in[16])
+{
+ // The temporary variables make Chacha20 10% faster.
+ u32 t0 = in[ 0]; u32 t1 = in[ 1]; u32 t2 = in[ 2]; u32 t3 = in[ 3];
+ u32 t4 = in[ 4]; u32 t5 = in[ 5]; u32 t6 = in[ 6]; u32 t7 = in[ 7];
+ u32 t8 = in[ 8]; u32 t9 = in[ 9]; u32 t10 = in[10]; u32 t11 = in[11];
+ u32 t12 = in[12]; u32 t13 = in[13]; u32 t14 = in[14]; u32 t15 = in[15];
+
+ FOR (i, 0, 10) { // 20 rounds, 2 rounds per loop.
+ QUARTERROUND(t0, t4, t8 , t12); // column 0
+ QUARTERROUND(t1, t5, t9 , t13); // column 1
+ QUARTERROUND(t2, t6, t10, t14); // column 2
+ QUARTERROUND(t3, t7, t11, t15); // column 3
+ QUARTERROUND(t0, t5, t10, t15); // diagonal 0
+ QUARTERROUND(t1, t6, t11, t12); // diagonal 1
+ QUARTERROUND(t2, t7, t8 , t13); // diagonal 2
+ QUARTERROUND(t3, t4, t9 , t14); // diagonal 3
+ }
+ out[ 0] = t0; out[ 1] = t1; out[ 2] = t2; out[ 3] = t3;
+ out[ 4] = t4; out[ 5] = t5; out[ 6] = t6; out[ 7] = t7;
+ out[ 8] = t8; out[ 9] = t9; out[10] = t10; out[11] = t11;
+ out[12] = t12; out[13] = t13; out[14] = t14; out[15] = t15;
+}
+
+static const u8 *chacha20_constant = (const u8*)"expand 32-byte k"; // 16 bytes
+
+void crypto_chacha20_h(u8 out[32], const u8 key[32], const u8 in [16])
+{
+ u32 block[16];
+ load32_le_buf(block , chacha20_constant, 4);
+ load32_le_buf(block + 4, key , 8);
+ load32_le_buf(block + 12, in , 4);
+
+ chacha20_rounds(block, block);
+
+ // prevent reversal of the rounds by revealing only half of the buffer.
+ store32_le_buf(out , block , 4); // constant
+ store32_le_buf(out+16, block+12, 4); // counter and nonce
+ WIPE_BUFFER(block);
+}
+
+u64 crypto_chacha20_djb(u8 *cipher_text, const u8 *plain_text,
+ size_t text_size, const u8 key[32], const u8 nonce[8],
+ u64 ctr)
+{
+ u32 input[16];
+ load32_le_buf(input , chacha20_constant, 4);
+ load32_le_buf(input + 4, key , 8);
+ load32_le_buf(input + 14, nonce , 2);
+ input[12] = (u32) ctr;
+ input[13] = (u32)(ctr >> 32);
+
+ // Whole blocks
+ u32 pool[16];
+ size_t nb_blocks = text_size >> 6;
+ FOR (i, 0, nb_blocks) {
+ chacha20_rounds(pool, input);
+ if (plain_text != NULL) {
+ FOR (j, 0, 16) {
+ u32 p = pool[j] + input[j];
+ store32_le(cipher_text, p ^ load32_le(plain_text));
+ cipher_text += 4;
+ plain_text += 4;
+ }
+ } else {
+ FOR (j, 0, 16) {
+ u32 p = pool[j] + input[j];
+ store32_le(cipher_text, p);
+ cipher_text += 4;
+ }
+ }
+ input[12]++;
+ if (input[12] == 0) {
+ input[13]++;
+ }
+ }
+ text_size &= 63;
+
+ // Last (incomplete) block
+ if (text_size > 0) {
+ if (plain_text == NULL) {
+ plain_text = zero;
+ }
+ chacha20_rounds(pool, input);
+ u8 tmp[64];
+ FOR (i, 0, 16) {
+ store32_le(tmp + i*4, pool[i] + input[i]);
+ }
+ FOR (i, 0, text_size) {
+ cipher_text[i] = tmp[i] ^ plain_text[i];
+ }
+ WIPE_BUFFER(tmp);
+ }
+ ctr = input[12] + ((u64)input[13] << 32) + (text_size > 0);
+
+ WIPE_BUFFER(pool);
+ WIPE_BUFFER(input);
+ return ctr;
+}
+
+u32 crypto_chacha20_ietf(u8 *cipher_text, const u8 *plain_text,
+ size_t text_size,
+ const u8 key[32], const u8 nonce[12], u32 ctr)
+{
+ u64 big_ctr = ctr + ((u64)load32_le(nonce) << 32);
+ return (u32)crypto_chacha20_djb(cipher_text, plain_text, text_size,
+ key, nonce + 4, big_ctr);
+}
+
+u64 crypto_chacha20_x(u8 *cipher_text, const u8 *plain_text,
+ size_t text_size,
+ const u8 key[32], const u8 nonce[24], u64 ctr)
+{
+ u8 sub_key[32];
+ crypto_chacha20_h(sub_key, key, nonce);
+ ctr = crypto_chacha20_djb(cipher_text, plain_text, text_size,
+ sub_key, nonce + 16, ctr);
+ WIPE_BUFFER(sub_key);
+ return ctr;
+}
+
+/////////////////
+/// Poly 1305 ///
+/////////////////
+
+// h = (h + c) * r
+// preconditions:
+// ctx->h <= 4_ffffffff_ffffffff_ffffffff_ffffffff
+// ctx->r <= 0ffffffc_0ffffffc_0ffffffc_0fffffff
+// end <= 1
+// Postcondition:
+// ctx->h <= 4_ffffffff_ffffffff_ffffffff_ffffffff
+static void poly_blocks(crypto_poly1305_ctx *ctx, const u8 *in,
+ size_t nb_blocks, unsigned end)
+{
+ // Local all the things!
+ const u32 r0 = ctx->r[0];
+ const u32 r1 = ctx->r[1];
+ const u32 r2 = ctx->r[2];
+ const u32 r3 = ctx->r[3];
+ const u32 rr0 = (r0 >> 2) * 5; // lose 2 bits...
+ const u32 rr1 = (r1 >> 2) + r1; // rr1 == (r1 >> 2) * 5
+ const u32 rr2 = (r2 >> 2) + r2; // rr1 == (r2 >> 2) * 5
+ const u32 rr3 = (r3 >> 2) + r3; // rr1 == (r3 >> 2) * 5
+ const u32 rr4 = r0 & 3; // ...recover 2 bits
+ u32 h0 = ctx->h[0];
+ u32 h1 = ctx->h[1];
+ u32 h2 = ctx->h[2];
+ u32 h3 = ctx->h[3];
+ u32 h4 = ctx->h[4];
+
+ FOR (i, 0, nb_blocks) {
+ // h + c, without carry propagation
+ const u64 s0 = (u64)h0 + load32_le(in); in += 4;
+ const u64 s1 = (u64)h1 + load32_le(in); in += 4;
+ const u64 s2 = (u64)h2 + load32_le(in); in += 4;
+ const u64 s3 = (u64)h3 + load32_le(in); in += 4;
+ const u32 s4 = h4 + end;
+
+ // (h + c) * r, without carry propagation
+ const u64 x0 = s0*r0+ s1*rr3+ s2*rr2+ s3*rr1+ s4*rr0;
+ const u64 x1 = s0*r1+ s1*r0 + s2*rr3+ s3*rr2+ s4*rr1;
+ const u64 x2 = s0*r2+ s1*r1 + s2*r0 + s3*rr3+ s4*rr2;
+ const u64 x3 = s0*r3+ s1*r2 + s2*r1 + s3*r0 + s4*rr3;
+ const u32 x4 = s4*rr4;
+
+ // partial reduction modulo 2^130 - 5
+ const u32 u5 = x4 + (x3 >> 32); // u5 <= 7ffffff5
+ const u64 u0 = (u5 >> 2) * 5 + (x0 & 0xffffffff);
+ const u64 u1 = (u0 >> 32) + (x1 & 0xffffffff) + (x0 >> 32);
+ const u64 u2 = (u1 >> 32) + (x2 & 0xffffffff) + (x1 >> 32);
+ const u64 u3 = (u2 >> 32) + (x3 & 0xffffffff) + (x2 >> 32);
+ const u32 u4 = (u3 >> 32) + (u5 & 3); // u4 <= 4
+
+ // Update the hash
+ h0 = u0 & 0xffffffff;
+ h1 = u1 & 0xffffffff;
+ h2 = u2 & 0xffffffff;
+ h3 = u3 & 0xffffffff;
+ h4 = u4;
+ }
+ ctx->h[0] = h0;
+ ctx->h[1] = h1;
+ ctx->h[2] = h2;
+ ctx->h[3] = h3;
+ ctx->h[4] = h4;
+}
+
+void crypto_poly1305_init(crypto_poly1305_ctx *ctx, const u8 key[32])
+{
+ ZERO(ctx->h, 5); // Initial hash is zero
+ ctx->c_idx = 0;
+ // load r and pad (r has some of its bits cleared)
+ load32_le_buf(ctx->r , key , 4);
+ load32_le_buf(ctx->pad, key+16, 4);
+ FOR (i, 0, 1) { ctx->r[i] &= 0x0fffffff; }
+ FOR (i, 1, 4) { ctx->r[i] &= 0x0ffffffc; }
+}
+
+void crypto_poly1305_update(crypto_poly1305_ctx *ctx,
+ const u8 *message, size_t message_size)
+{
+ // Avoid undefined NULL pointer increments with empty messages
+ if (message_size == 0) {
+ return;
+ }
+
+ // Align ourselves with block boundaries
+ size_t aligned = MIN(gap(ctx->c_idx, 16), message_size);
+ FOR (i, 0, aligned) {
+ ctx->c[ctx->c_idx] = *message;
+ ctx->c_idx++;
+ message++;
+ message_size--;
+ }
+
+ // If block is complete, process it
+ if (ctx->c_idx == 16) {
+ poly_blocks(ctx, ctx->c, 1, 1);
+ ctx->c_idx = 0;
+ }
+
+ // Process the message block by block
+ size_t nb_blocks = message_size >> 4;
+ poly_blocks(ctx, message, nb_blocks, 1);
+ message += nb_blocks << 4;
+ message_size &= 15;
+
+ // remaining bytes (we never complete a block here)
+ FOR (i, 0, message_size) {
+ ctx->c[ctx->c_idx] = message[i];
+ ctx->c_idx++;
+ }
+}
+
+void crypto_poly1305_final(crypto_poly1305_ctx *ctx, u8 mac[16])
+{
+ // Process the last block (if any)
+ // We move the final 1 according to remaining input length
+ // (this will add less than 2^130 to the last input block)
+ if (ctx->c_idx != 0) {
+ ZERO(ctx->c + ctx->c_idx, 16 - ctx->c_idx);
+ ctx->c[ctx->c_idx] = 1;
+ poly_blocks(ctx, ctx->c, 1, 0);
+ }
+
+ // check if we should subtract 2^130-5 by performing the
+ // corresponding carry propagation.
+ u64 c = 5;
+ FOR (i, 0, 4) {
+ c += ctx->h[i];
+ c >>= 32;
+ }
+ c += ctx->h[4];
+ c = (c >> 2) * 5; // shift the carry back to the beginning
+ // c now indicates how many times we should subtract 2^130-5 (0 or 1)
+ FOR (i, 0, 4) {
+ c += (u64)ctx->h[i] + ctx->pad[i];
+ store32_le(mac + i*4, (u32)c);
+ c = c >> 32;
+ }
+ WIPE_CTX(ctx);
+}
+
+void crypto_poly1305(u8 mac[16], const u8 *message,
+ size_t message_size, const u8 key[32])
+{
+ crypto_poly1305_ctx ctx;
+ crypto_poly1305_init (&ctx, key);
+ crypto_poly1305_update(&ctx, message, message_size);
+ crypto_poly1305_final (&ctx, mac);
+}
+
+////////////////
+/// BLAKE2 b ///
+////////////////
+static const u64 iv[8] = {
+ 0x6a09e667f3bcc908, 0xbb67ae8584caa73b,
+ 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1,
+ 0x510e527fade682d1, 0x9b05688c2b3e6c1f,
+ 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179,
+};
+
+static void blake2b_compress(crypto_blake2b_ctx *ctx, int is_last_block)
+{
+ static const u8 sigma[12][16] = {
+ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
+ { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 },
+ { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 },
+ { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 },
+ { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 },
+ { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 },
+ { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 },
+ { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 },
+ { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 },
+ { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 },
+ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
+ { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 },
+ };
+
+ // increment input offset
+ u64 *x = ctx->input_offset;
+ size_t y = ctx->input_idx;
+ x[0] += y;
+ if (x[0] < y) {
+ x[1]++;
+ }
+
+ // init work vector
+ u64 v0 = ctx->hash[0]; u64 v8 = iv[0];
+ u64 v1 = ctx->hash[1]; u64 v9 = iv[1];
+ u64 v2 = ctx->hash[2]; u64 v10 = iv[2];
+ u64 v3 = ctx->hash[3]; u64 v11 = iv[3];
+ u64 v4 = ctx->hash[4]; u64 v12 = iv[4] ^ ctx->input_offset[0];
+ u64 v5 = ctx->hash[5]; u64 v13 = iv[5] ^ ctx->input_offset[1];
+ u64 v6 = ctx->hash[6]; u64 v14 = iv[6] ^ (u64)~(is_last_block - 1);
+ u64 v7 = ctx->hash[7]; u64 v15 = iv[7];
+
+ // mangle work vector
+ u64 *input = ctx->input;
+#define BLAKE2_G(a, b, c, d, x, y) \
+ a += b + x; d = rotr64(d ^ a, 32); \
+ c += d; b = rotr64(b ^ c, 24); \
+ a += b + y; d = rotr64(d ^ a, 16); \
+ c += d; b = rotr64(b ^ c, 63)
+#define BLAKE2_ROUND(i) \
+ BLAKE2_G(v0, v4, v8 , v12, input[sigma[i][ 0]], input[sigma[i][ 1]]); \
+ BLAKE2_G(v1, v5, v9 , v13, input[sigma[i][ 2]], input[sigma[i][ 3]]); \
+ BLAKE2_G(v2, v6, v10, v14, input[sigma[i][ 4]], input[sigma[i][ 5]]); \
+ BLAKE2_G(v3, v7, v11, v15, input[sigma[i][ 6]], input[sigma[i][ 7]]); \
+ BLAKE2_G(v0, v5, v10, v15, input[sigma[i][ 8]], input[sigma[i][ 9]]); \
+ BLAKE2_G(v1, v6, v11, v12, input[sigma[i][10]], input[sigma[i][11]]); \
+ BLAKE2_G(v2, v7, v8 , v13, input[sigma[i][12]], input[sigma[i][13]]); \
+ BLAKE2_G(v3, v4, v9 , v14, input[sigma[i][14]], input[sigma[i][15]])
+
+#ifdef BLAKE2_NO_UNROLLING
+ FOR (i, 0, 12) {
+ BLAKE2_ROUND(i);
+ }
+#else
+ BLAKE2_ROUND(0); BLAKE2_ROUND(1); BLAKE2_ROUND(2); BLAKE2_ROUND(3);
+ BLAKE2_ROUND(4); BLAKE2_ROUND(5); BLAKE2_ROUND(6); BLAKE2_ROUND(7);
+ BLAKE2_ROUND(8); BLAKE2_ROUND(9); BLAKE2_ROUND(10); BLAKE2_ROUND(11);
+#endif
+
+ // update hash
+ ctx->hash[0] ^= v0 ^ v8; ctx->hash[1] ^= v1 ^ v9;
+ ctx->hash[2] ^= v2 ^ v10; ctx->hash[3] ^= v3 ^ v11;
+ ctx->hash[4] ^= v4 ^ v12; ctx->hash[5] ^= v5 ^ v13;
+ ctx->hash[6] ^= v6 ^ v14; ctx->hash[7] ^= v7 ^ v15;
+}
+
+void crypto_blake2b_keyed_init(crypto_blake2b_ctx *ctx, size_t hash_size,
+ const u8 *key, size_t key_size)
+{
+ // initial hash
+ COPY(ctx->hash, iv, 8);
+ ctx->hash[0] ^= 0x01010000 ^ (key_size << 8) ^ hash_size;
+
+ ctx->input_offset[0] = 0; // beginning of the input, no offset
+ ctx->input_offset[1] = 0; // beginning of the input, no offset
+ ctx->hash_size = hash_size;
+ ctx->input_idx = 0;
+ ZERO(ctx->input, 16);
+
+ // if there is a key, the first block is that key (padded with zeroes)
+ if (key_size > 0) {
+ u8 key_block[128] = {0};
+ COPY(key_block, key, key_size);
+ // same as calling crypto_blake2b_update(ctx, key_block , 128)
+ load64_le_buf(ctx->input, key_block, 16);
+ ctx->input_idx = 128;
+ }
+}
+
+void crypto_blake2b_init(crypto_blake2b_ctx *ctx, size_t hash_size)
+{
+ crypto_blake2b_keyed_init(ctx, hash_size, 0, 0);
+}
+
+void crypto_blake2b_update(crypto_blake2b_ctx *ctx,
+ const u8 *message, size_t message_size)
+{
+ // Avoid undefined NULL pointer increments with empty messages
+ if (message_size == 0) {
+ return;
+ }
+
+ // Align with word boundaries
+ if ((ctx->input_idx & 7) != 0) {
+ size_t nb_bytes = MIN(gap(ctx->input_idx, 8), message_size);
+ size_t word = ctx->input_idx >> 3;
+ size_t byte = ctx->input_idx & 7;
+ FOR (i, 0, nb_bytes) {
+ ctx->input[word] |= (u64)message[i] << ((byte + i) << 3);
+ }
+ ctx->input_idx += nb_bytes;
+ message += nb_bytes;
+ message_size -= nb_bytes;
+ }
+
+ // Align with block boundaries (faster than byte by byte)
+ if ((ctx->input_idx & 127) != 0) {
+ size_t nb_words = MIN(gap(ctx->input_idx, 128), message_size) >> 3;
+ load64_le_buf(ctx->input + (ctx->input_idx >> 3), message, nb_words);
+ ctx->input_idx += nb_words << 3;
+ message += nb_words << 3;
+ message_size -= nb_words << 3;
+ }
+
+ // Process block by block
+ size_t nb_blocks = message_size >> 7;
+ FOR (i, 0, nb_blocks) {
+ if (ctx->input_idx == 128) {
+ blake2b_compress(ctx, 0);
+ }
+ load64_le_buf(ctx->input, message, 16);
+ message += 128;
+ ctx->input_idx = 128;
+ }
+ message_size &= 127;
+
+ if (message_size != 0) {
+ // Compress block & flush input buffer as needed
+ if (ctx->input_idx == 128) {
+ blake2b_compress(ctx, 0);
+ ctx->input_idx = 0;
+ }
+ if (ctx->input_idx == 0) {
+ ZERO(ctx->input, 16);
+ }
+ // Fill remaining words (faster than byte by byte)
+ size_t nb_words = message_size >> 3;
+ load64_le_buf(ctx->input, message, nb_words);
+ ctx->input_idx += nb_words << 3;
+ message += nb_words << 3;
+ message_size -= nb_words << 3;
+
+ // Fill remaining bytes
+ FOR (i, 0, message_size) {
+ size_t word = ctx->input_idx >> 3;
+ size_t byte = ctx->input_idx & 7;
+ ctx->input[word] |= (u64)message[i] << (byte << 3);
+ ctx->input_idx++;
+ }
+ }
+}
+
+void crypto_blake2b_final(crypto_blake2b_ctx *ctx, u8 *hash)
+{
+ blake2b_compress(ctx, 1); // compress the last block
+ size_t hash_size = MIN(ctx->hash_size, 64);
+ size_t nb_words = hash_size >> 3;
+ store64_le_buf(hash, ctx->hash, nb_words);
+ FOR (i, nb_words << 3, hash_size) {
+ hash[i] = (ctx->hash[i >> 3] >> (8 * (i & 7))) & 0xff;
+ }
+ WIPE_CTX(ctx);
+}
+
+void crypto_blake2b_keyed(u8 *hash, size_t hash_size,
+ const u8 *key, size_t key_size,
+ const u8 *message, size_t message_size)
+{
+ crypto_blake2b_ctx ctx;
+ crypto_blake2b_keyed_init(&ctx, hash_size, key, key_size);
+ crypto_blake2b_update (&ctx, message, message_size);
+ crypto_blake2b_final (&ctx, hash);
+}
+
+void crypto_blake2b(u8 *hash, size_t hash_size, const u8 *msg, size_t msg_size)
+{
+ crypto_blake2b_keyed(hash, hash_size, 0, 0, msg, msg_size);
+}
+
+//////////////
+/// Argon2 ///
+//////////////
+// references to R, Z, Q etc. come from the spec
+
+// Argon2 operates on 1024 byte blocks.
+typedef struct { u64 a[128]; } blk;
+
+// updates a BLAKE2 hash with a 32 bit word, little endian.
+static void blake_update_32(crypto_blake2b_ctx *ctx, u32 input)
+{
+ u8 buf[4];
+ store32_le(buf, input);
+ crypto_blake2b_update(ctx, buf, 4);
+ WIPE_BUFFER(buf);
+}
+
+static void blake_update_32_buf(crypto_blake2b_ctx *ctx,
+ const u8 *buf, u32 size)
+{
+ blake_update_32(ctx, size);
+ crypto_blake2b_update(ctx, buf, size);
+}
+
+
+static void copy_block(blk *o,const blk*in){FOR(i, 0, 128) o->a[i] = in->a[i];}
+static void xor_block(blk *o,const blk*in){FOR(i, 0, 128) o->a[i] ^= in->a[i];}
+
+// Hash with a virtually unlimited digest size.
+// Doesn't extract more entropy than the base hash function.
+// Mainly used for filling a whole kilobyte block with pseudo-random bytes.
+// (One could use a stream cipher with a seed hash as the key, but
+// this would introduce another dependency —and point of failure.)
+static void extended_hash(u8 *digest, u32 digest_size,
+ const u8 *input , u32 input_size)
+{
+ crypto_blake2b_ctx ctx;
+ crypto_blake2b_init (&ctx, MIN(digest_size, 64));
+ blake_update_32 (&ctx, digest_size);
+ crypto_blake2b_update(&ctx, input, input_size);
+ crypto_blake2b_final (&ctx, digest);
+
+ if (digest_size > 64) {
+ // the conversion to u64 avoids integer overflow on
+ // ludicrously big hash sizes.
+ u32 r = (u32)(((u64)digest_size + 31) >> 5) - 2;
+ u32 i = 1;
+ u32 in = 0;
+ u32 out = 32;
+ while (i < r) {
+ // Input and output overlap. This is intentional
+ crypto_blake2b(digest + out, 64, digest + in, 64);
+ i += 1;
+ in += 32;
+ out += 32;
+ }
+ crypto_blake2b(digest + out, digest_size - (32 * r), digest + in , 64);
+ }
+}
+
+#define LSB(x) ((u64)(u32)x)
+#define G(a, b, c, d) \
+ a += b + ((LSB(a) * LSB(b)) << 1); d ^= a; d = rotr64(d, 32); \
+ c += d + ((LSB(c) * LSB(d)) << 1); b ^= c; b = rotr64(b, 24); \
+ a += b + ((LSB(a) * LSB(b)) << 1); d ^= a; d = rotr64(d, 16); \
+ c += d + ((LSB(c) * LSB(d)) << 1); b ^= c; b = rotr64(b, 63)
+#define ROUND(v0, v1, v2, v3, v4, v5, v6, v7, \
+ v8, v9, v10, v11, v12, v13, v14, v15) \
+ G(v0, v4, v8, v12); G(v1, v5, v9, v13); \
+ G(v2, v6, v10, v14); G(v3, v7, v11, v15); \
+ G(v0, v5, v10, v15); G(v1, v6, v11, v12); \
+ G(v2, v7, v8, v13); G(v3, v4, v9, v14)
+
+// Core of the compression function G. Computes Z from R in place.
+static void g_rounds(blk *b)
+{
+ // column rounds (work_block = Q)
+ for (int i = 0; i < 128; i += 16) {
+ ROUND(b->a[i ], b->a[i+ 1], b->a[i+ 2], b->a[i+ 3],
+ b->a[i+ 4], b->a[i+ 5], b->a[i+ 6], b->a[i+ 7],
+ b->a[i+ 8], b->a[i+ 9], b->a[i+10], b->a[i+11],
+ b->a[i+12], b->a[i+13], b->a[i+14], b->a[i+15]);
+ }
+ // row rounds (b = Z)
+ for (int i = 0; i < 16; i += 2) {
+ ROUND(b->a[i ], b->a[i+ 1], b->a[i+ 16], b->a[i+ 17],
+ b->a[i+32], b->a[i+33], b->a[i+ 48], b->a[i+ 49],
+ b->a[i+64], b->a[i+65], b->a[i+ 80], b->a[i+ 81],
+ b->a[i+96], b->a[i+97], b->a[i+112], b->a[i+113]);
+ }
+}
+
+const crypto_argon2_extras crypto_argon2_no_extras = { 0, 0, 0, 0 };
+
+void crypto_argon2(u8 *hash, u32 hash_size, void *work_area,
+ crypto_argon2_config config,
+ crypto_argon2_inputs inputs,
+ crypto_argon2_extras extras)
+{
+ const u32 segment_size = config.nb_blocks / config.nb_lanes / 4;
+ const u32 lane_size = segment_size * 4;
+ const u32 nb_blocks = lane_size * config.nb_lanes; // rounding down
+
+ // work area seen as blocks (must be suitably aligned)
+ blk *blocks = (blk*)work_area;
+ {
+ u8 initial_hash[72]; // 64 bytes plus 2 words for future hashes
+ crypto_blake2b_ctx ctx;
+ crypto_blake2b_init (&ctx, 64);
+ blake_update_32 (&ctx, config.nb_lanes ); // p: number of "threads"
+ blake_update_32 (&ctx, hash_size);
+ blake_update_32 (&ctx, config.nb_blocks);
+ blake_update_32 (&ctx, config.nb_passes);
+ blake_update_32 (&ctx, 0x13); // v: version number
+ blake_update_32 (&ctx, config.algorithm); // y: Argon2i, Argon2d...
+ blake_update_32_buf (&ctx, inputs.pass, inputs.pass_size);
+ blake_update_32_buf (&ctx, inputs.salt, inputs.salt_size);
+ blake_update_32_buf (&ctx, extras.key, extras.key_size);
+ blake_update_32_buf (&ctx, extras.ad, extras.ad_size);
+ crypto_blake2b_final(&ctx, initial_hash); // fill 64 first bytes only
+
+ // fill first 2 blocks of each lane
+ u8 hash_area[1024];
+ FOR_T(u32, l, 0, config.nb_lanes) {
+ FOR_T(u32, i, 0, 2) {
+ store32_le(initial_hash + 64, i); // first additional word
+ store32_le(initial_hash + 68, l); // second additional word
+ extended_hash(hash_area, 1024, initial_hash, 72);
+ load64_le_buf(blocks[l * lane_size + i].a, hash_area, 128);
+ }
+ }
+
+ WIPE_BUFFER(initial_hash);
+ WIPE_BUFFER(hash_area);
+ }
+
+ // Argon2i and Argon2id start with constant time indexing
+ int constant_time = config.algorithm != CRYPTO_ARGON2_D;
+
+ // Fill (and re-fill) the rest of the blocks
+ //
+ // Note: even though each segment within the same slice can be
+ // computed in parallel, (one thread per lane), we are computing
+ // them sequentially, because Monocypher doesn't support threads.
+ //
+ // Yet optimal performance (and therefore security) requires one
+ // thread per lane. The only reason Monocypher supports multiple
+ // lanes is compatibility.
+ blk tmp;
+ FOR_T(u32, pass, 0, config.nb_passes) {
+ FOR_T(u32, slice, 0, 4) {
+ // On the first slice of the first pass,
+ // blocks 0 and 1 are already filled, hence pass_offset.
+ u32 pass_offset = pass == 0 && slice == 0 ? 2 : 0;
+ u32 slice_offset = slice * segment_size;
+
+ // Argon2id switches back to non-constant time indexing
+ // after the first two slices of the first pass
+ if (slice == 2 && config.algorithm == CRYPTO_ARGON2_ID) {
+ constant_time = 0;
+ }
+
+ // Each iteration of the following loop may be performed in
+ // a separate thread. All segments must be fully completed
+ // before we start filling the next slice.
+ FOR_T(u32, segment, 0, config.nb_lanes) {
+ blk index_block;
+ u32 index_ctr = 1;
+ FOR_T (u32, block, pass_offset, segment_size) {
+ // Current and previous blocks
+ u32 lane_offset = segment * lane_size;
+ blk *segment_start = blocks + lane_offset + slice_offset;
+ blk *current = segment_start + block;
+ blk *previous =
+ block == 0 && slice_offset == 0
+ ? segment_start + lane_size - 1
+ : segment_start + block - 1;
+
+ u64 index_seed;
+ if (constant_time) {
+ if (block == pass_offset || (block % 128) == 0) {
+ // Fill or refresh deterministic indices block
+
+ // seed the beginning of the block...
+ ZERO(index_block.a, 128);
+ index_block.a[0] = pass;
+ index_block.a[1] = segment;
+ index_block.a[2] = slice;
+ index_block.a[3] = nb_blocks;
+ index_block.a[4] = config.nb_passes;
+ index_block.a[5] = config.algorithm;
+ index_block.a[6] = index_ctr;
+ index_ctr++;
+
+ // ... then shuffle it
+ copy_block(&tmp, &index_block);
+ g_rounds (&index_block);
+ xor_block (&index_block, &tmp);
+ copy_block(&tmp, &index_block);
+ g_rounds (&index_block);
+ xor_block (&index_block, &tmp);
+ }
+ index_seed = index_block.a[block % 128];
+ } else {
+ index_seed = previous->a[0];
+ }
+
+ // Establish the reference set. *Approximately* comprises:
+ // - The last 3 slices (if they exist yet)
+ // - The already constructed blocks in the current segment
+ u32 next_slice = ((slice + 1) % 4) * segment_size;
+ u32 window_start = pass == 0 ? 0 : next_slice;
+ u32 nb_segments = pass == 0 ? slice : 3;
+ u32 lane =
+ pass == 0 && slice == 0
+ ? segment
+ : (index_seed >> 32) % config.nb_lanes;
+ u32 window_size =
+ nb_segments * segment_size +
+ (lane == segment ? block-1 :
+ block == 0 ? (u32)-1 : 0);
+
+ // Find reference block
+ u64 j1 = index_seed & 0xffffffff; // block selector
+ u64 x = (j1 * j1) >> 32;
+ u64 y = (window_size * x) >> 32;
+ u64 z = (window_size - 1) - y;
+ u32 ref = (window_start + z) % lane_size;
+ u32 index = lane * lane_size + ref;
+ blk *reference = blocks + index;
+
+ // Shuffle the previous & reference block
+ // into the current block
+ copy_block(&tmp, previous);
+ xor_block (&tmp, reference);
+ if (pass == 0) { copy_block(current, &tmp); }
+ else { xor_block (current, &tmp); }
+ g_rounds (&tmp);
+ xor_block (current, &tmp);
+ }
+ }
+ }
+ }
+
+ // Wipe temporary block
+ volatile u64* p = tmp.a;
+ ZERO(p, 128);
+
+ // XOR last blocks of each lane
+ blk *last_block = blocks + lane_size - 1;
+ FOR_T (u32, lane, 1, config.nb_lanes) {
+ blk *next_block = last_block + lane_size;
+ xor_block(next_block, last_block);
+ last_block = next_block;
+ }
+
+ // Serialize last block
+ u8 final_block[1024];
+ store64_le_buf(final_block, last_block->a, 128);
+
+ // Wipe work area
+ p = (u64*)work_area;
+ ZERO(p, 128 * nb_blocks);
+
+ // Hash the very last block with H' into the output hash
+ extended_hash(hash, hash_size, final_block, 1024);
+ WIPE_BUFFER(final_block);
+}
+
+////////////////////////////////////
+/// Arithmetic modulo 2^255 - 19 ///
+////////////////////////////////////
+// Originally taken from SUPERCOP's ref10 implementation.
+// A bit bigger than TweetNaCl, over 4 times faster.
+
+// field element
+typedef i32 fe[10];
+
+// field constants
+//
+// fe_one : 1
+// sqrtm1 : sqrt(-1)
+// d : -121665 / 121666
+// D2 : 2 * -121665 / 121666
+// lop_x, lop_y: low order point in Edwards coordinates
+// ufactor : -sqrt(-1) * 2
+// A2 : 486662^2 (A squared)
+static const fe fe_one = {1};
+static const fe sqrtm1 = {
+ -32595792, -7943725, 9377950, 3500415, 12389472,
+ -272473, -25146209, -2005654, 326686, 11406482,
+};
+static const fe d = {
+ -10913610, 13857413, -15372611, 6949391, 114729,
+ -8787816, -6275908, -3247719, -18696448, -12055116,
+};
+static const fe D2 = {
+ -21827239, -5839606, -30745221, 13898782, 229458,
+ 15978800, -12551817, -6495438, 29715968, 9444199,
+};
+static const fe lop_x = {
+ 21352778, 5345713, 4660180, -8347857, 24143090,
+ 14568123, 30185756, -12247770, -33528939, 8345319,
+};
+static const fe lop_y = {
+ -6952922, -1265500, 6862341, -7057498, -4037696,
+ -5447722, 31680899, -15325402, -19365852, 1569102,
+};
+static const fe ufactor = {
+ -1917299, 15887451, -18755900, -7000830, -24778944,
+ 544946, -16816446, 4011309, -653372, 10741468,
+};
+static const fe A2 = {
+ 12721188, 3529, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+static void fe_0(fe h) { ZERO(h , 10); }
+static void fe_1(fe h) { h[0] = 1; ZERO(h+1, 9); }
+
+static void fe_copy(fe h,const fe f ){FOR(i,0,10) h[i] = f[i]; }
+static void fe_neg (fe h,const fe f ){FOR(i,0,10) h[i] = -f[i]; }
+static void fe_add (fe h,const fe f,const fe g){FOR(i,0,10) h[i] = f[i] + g[i];}
+static void fe_sub (fe h,const fe f,const fe g){FOR(i,0,10) h[i] = f[i] - g[i];}
+
+static void fe_cswap(fe f, fe g, int b)
+{
+ i32 mask = -b; // -1 = 0xffffffff
+ FOR (i, 0, 10) {
+ i32 x = (f[i] ^ g[i]) & mask;
+ f[i] = f[i] ^ x;
+ g[i] = g[i] ^ x;
+ }
+}
+
+static void fe_ccopy(fe f, const fe g, int b)
+{
+ i32 mask = -b; // -1 = 0xffffffff
+ FOR (i, 0, 10) {
+ i32 x = (f[i] ^ g[i]) & mask;
+ f[i] = f[i] ^ x;
+ }
+}
+
+
+// Signed carry propagation
+// ------------------------
+//
+// Let t be a number. It can be uniquely decomposed thus:
+//
+// t = h*2^26 + l
+// such that -2^25 <= l < 2^25
+//
+// Let c = (t + 2^25) / 2^26 (rounded down)
+// c = (h*2^26 + l + 2^25) / 2^26 (rounded down)
+// c = h + (l + 2^25) / 2^26 (rounded down)
+// c = h (exactly)
+// Because 0 <= l + 2^25 < 2^26
+//
+// Let u = t - c*2^26
+// u = h*2^26 + l - h*2^26
+// u = l
+// Therefore, -2^25 <= u < 2^25
+//
+// Additionally, if |t| < x, then |h| < x/2^26 (rounded down)
+//
+// Notations:
+// - In C, 1<<25 means 2^25.
+// - In C, x>>25 means floor(x / (2^25)).
+// - All of the above applies with 25 & 24 as well as 26 & 25.
+//
+//
+// Note on negative right shifts
+// -----------------------------
+//
+// In C, x >> n, where x is a negative integer, is implementation
+// defined. In practice, all platforms do arithmetic shift, which is
+// equivalent to division by 2^26, rounded down. Some compilers, like
+// GCC, even guarantee it.
+//
+// If we ever stumble upon a platform that does not propagate the sign
+// bit (we won't), visible failures will show at the slightest test, and
+// the signed shifts can be replaced by the following:
+//
+// typedef struct { i64 x:39; } s25;
+// typedef struct { i64 x:38; } s26;
+// i64 shift25(i64 x) { s25 s; s.x = ((u64)x)>>25; return s.x; }
+// i64 shift26(i64 x) { s26 s; s.x = ((u64)x)>>26; return s.x; }
+//
+// Current compilers cannot optimise this, causing a 30% drop in
+// performance. Fairly expensive for something that never happens.
+//
+//
+// Precondition
+// ------------
+//
+// |t0| < 2^63
+// |t1|..|t9| < 2^62
+//
+// Algorithm
+// ---------
+// c = t0 + 2^25 / 2^26 -- |c| <= 2^36
+// t0 -= c * 2^26 -- |t0| <= 2^25
+// t1 += c -- |t1| <= 2^63
+//
+// c = t4 + 2^25 / 2^26 -- |c| <= 2^36
+// t4 -= c * 2^26 -- |t4| <= 2^25
+// t5 += c -- |t5| <= 2^63
+//
+// c = t1 + 2^24 / 2^25 -- |c| <= 2^38
+// t1 -= c * 2^25 -- |t1| <= 2^24
+// t2 += c -- |t2| <= 2^63
+//
+// c = t5 + 2^24 / 2^25 -- |c| <= 2^38
+// t5 -= c * 2^25 -- |t5| <= 2^24
+// t6 += c -- |t6| <= 2^63
+//
+// c = t2 + 2^25 / 2^26 -- |c| <= 2^37
+// t2 -= c * 2^26 -- |t2| <= 2^25 < 1.1 * 2^25 (final t2)
+// t3 += c -- |t3| <= 2^63
+//
+// c = t6 + 2^25 / 2^26 -- |c| <= 2^37
+// t6 -= c * 2^26 -- |t6| <= 2^25 < 1.1 * 2^25 (final t6)
+// t7 += c -- |t7| <= 2^63
+//
+// c = t3 + 2^24 / 2^25 -- |c| <= 2^38
+// t3 -= c * 2^25 -- |t3| <= 2^24 < 1.1 * 2^24 (final t3)
+// t4 += c -- |t4| <= 2^25 + 2^38 < 2^39
+//
+// c = t7 + 2^24 / 2^25 -- |c| <= 2^38
+// t7 -= c * 2^25 -- |t7| <= 2^24 < 1.1 * 2^24 (final t7)
+// t8 += c -- |t8| <= 2^63
+//
+// c = t4 + 2^25 / 2^26 -- |c| <= 2^13
+// t4 -= c * 2^26 -- |t4| <= 2^25 < 1.1 * 2^25 (final t4)
+// t5 += c -- |t5| <= 2^24 + 2^13 < 1.1 * 2^24 (final t5)
+//
+// c = t8 + 2^25 / 2^26 -- |c| <= 2^37
+// t8 -= c * 2^26 -- |t8| <= 2^25 < 1.1 * 2^25 (final t8)
+// t9 += c -- |t9| <= 2^63
+//
+// c = t9 + 2^24 / 2^25 -- |c| <= 2^38
+// t9 -= c * 2^25 -- |t9| <= 2^24 < 1.1 * 2^24 (final t9)
+// t0 += c * 19 -- |t0| <= 2^25 + 2^38*19 < 2^44
+//
+// c = t0 + 2^25 / 2^26 -- |c| <= 2^18
+// t0 -= c * 2^26 -- |t0| <= 2^25 < 1.1 * 2^25 (final t0)
+// t1 += c -- |t1| <= 2^24 + 2^18 < 1.1 * 2^24 (final t1)
+//
+// Postcondition
+// -------------
+// |t0|, |t2|, |t4|, |t6|, |t8| < 1.1 * 2^25
+// |t1|, |t3|, |t5|, |t7|, |t9| < 1.1 * 2^24
+#define FE_CARRY \
+ i64 c; \
+ c = (t0 + ((i64)1<<25)) >> 26; t0 -= c * ((i64)1 << 26); t1 += c; \
+ c = (t4 + ((i64)1<<25)) >> 26; t4 -= c * ((i64)1 << 26); t5 += c; \
+ c = (t1 + ((i64)1<<24)) >> 25; t1 -= c * ((i64)1 << 25); t2 += c; \
+ c = (t5 + ((i64)1<<24)) >> 25; t5 -= c * ((i64)1 << 25); t6 += c; \
+ c = (t2 + ((i64)1<<25)) >> 26; t2 -= c * ((i64)1 << 26); t3 += c; \
+ c = (t6 + ((i64)1<<25)) >> 26; t6 -= c * ((i64)1 << 26); t7 += c; \
+ c = (t3 + ((i64)1<<24)) >> 25; t3 -= c * ((i64)1 << 25); t4 += c; \
+ c = (t7 + ((i64)1<<24)) >> 25; t7 -= c * ((i64)1 << 25); t8 += c; \
+ c = (t4 + ((i64)1<<25)) >> 26; t4 -= c * ((i64)1 << 26); t5 += c; \
+ c = (t8 + ((i64)1<<25)) >> 26; t8 -= c * ((i64)1 << 26); t9 += c; \
+ c = (t9 + ((i64)1<<24)) >> 25; t9 -= c * ((i64)1 << 25); t0 += c * 19; \
+ c = (t0 + ((i64)1<<25)) >> 26; t0 -= c * ((i64)1 << 26); t1 += c; \
+ h[0]=(i32)t0; h[1]=(i32)t1; h[2]=(i32)t2; h[3]=(i32)t3; h[4]=(i32)t4; \
+ h[5]=(i32)t5; h[6]=(i32)t6; h[7]=(i32)t7; h[8]=(i32)t8; h[9]=(i32)t9
+
+// Decodes a field element from a byte buffer.
+// mask specifies how many bits we ignore.
+// Traditionally we ignore 1. It's useful for EdDSA,
+// which uses that bit to denote the sign of x.
+// Elligator however uses positive representatives,
+// which means ignoring 2 bits instead.
+static void fe_frombytes_mask(fe h, const u8 s[32], unsigned nb_mask)
+{
+ u32 mask = 0xffffff >> nb_mask;
+ i64 t0 = load32_le(s); // t0 < 2^32
+ i64 t1 = load24_le(s + 4) << 6; // t1 < 2^30
+ i64 t2 = load24_le(s + 7) << 5; // t2 < 2^29
+ i64 t3 = load24_le(s + 10) << 3; // t3 < 2^27
+ i64 t4 = load24_le(s + 13) << 2; // t4 < 2^26
+ i64 t5 = load32_le(s + 16); // t5 < 2^32
+ i64 t6 = load24_le(s + 20) << 7; // t6 < 2^31
+ i64 t7 = load24_le(s + 23) << 5; // t7 < 2^29
+ i64 t8 = load24_le(s + 26) << 4; // t8 < 2^28
+ i64 t9 = (load24_le(s + 29) & mask) << 2; // t9 < 2^25
+ FE_CARRY; // Carry precondition OK
+}
+
+static void fe_frombytes(fe h, const u8 s[32])
+{
+ fe_frombytes_mask(h, s, 1);
+}
+
+
+// Precondition
+// |h[0]|, |h[2]|, |h[4]|, |h[6]|, |h[8]| < 1.1 * 2^25
+// |h[1]|, |h[3]|, |h[5]|, |h[7]|, |h[9]| < 1.1 * 2^24
+//
+// Therefore, |h| < 2^255-19
+// There are two possibilities:
+//
+// - If h is positive, all we need to do is reduce its individual
+// limbs down to their tight positive range.
+// - If h is negative, we also need to add 2^255-19 to it.
+// Or just remove 19 and chop off any excess bit.
+static void fe_tobytes(u8 s[32], const fe h)
+{
+ i32 t[10];
+ COPY(t, h, 10);
+ i32 q = (19 * t[9] + (((i32) 1) << 24)) >> 25;
+ // |t9| < 1.1 * 2^24
+ // -1.1 * 2^24 < t9 < 1.1 * 2^24
+ // -21 * 2^24 < 19 * t9 < 21 * 2^24
+ // -2^29 < 19 * t9 + 2^24 < 2^29
+ // -2^29 / 2^25 < (19 * t9 + 2^24) / 2^25 < 2^29 / 2^25
+ // -16 < (19 * t9 + 2^24) / 2^25 < 16
+ FOR (i, 0, 5) {
+ q += t[2*i ]; q >>= 26; // q = 0 or -1
+ q += t[2*i+1]; q >>= 25; // q = 0 or -1
+ }
+ // q = 0 iff h >= 0
+ // q = -1 iff h < 0
+ // Adding q * 19 to h reduces h to its proper range.
+ q *= 19; // Shift carry back to the beginning
+ FOR (i, 0, 5) {
+ t[i*2 ] += q; q = t[i*2 ] >> 26; t[i*2 ] -= q * ((i32)1 << 26);
+ t[i*2+1] += q; q = t[i*2+1] >> 25; t[i*2+1] -= q * ((i32)1 << 25);
+ }
+ // h is now fully reduced, and q represents the excess bit.
+
+ store32_le(s + 0, ((u32)t[0] >> 0) | ((u32)t[1] << 26));
+ store32_le(s + 4, ((u32)t[1] >> 6) | ((u32)t[2] << 19));
+ store32_le(s + 8, ((u32)t[2] >> 13) | ((u32)t[3] << 13));
+ store32_le(s + 12, ((u32)t[3] >> 19) | ((u32)t[4] << 6));
+ store32_le(s + 16, ((u32)t[5] >> 0) | ((u32)t[6] << 25));
+ store32_le(s + 20, ((u32)t[6] >> 7) | ((u32)t[7] << 19));
+ store32_le(s + 24, ((u32)t[7] >> 13) | ((u32)t[8] << 12));
+ store32_le(s + 28, ((u32)t[8] >> 20) | ((u32)t[9] << 6));
+
+ WIPE_BUFFER(t);
+}
+
+// Precondition
+// -------------
+// |f0|, |f2|, |f4|, |f6|, |f8| < 1.65 * 2^26
+// |f1|, |f3|, |f5|, |f7|, |f9| < 1.65 * 2^25
+//
+// |g0|, |g2|, |g4|, |g6|, |g8| < 1.65 * 2^26
+// |g1|, |g3|, |g5|, |g7|, |g9| < 1.65 * 2^25
+static void fe_mul_small(fe h, const fe f, i32 g)
+{
+ i64 t0 = f[0] * (i64) g; i64 t1 = f[1] * (i64) g;
+ i64 t2 = f[2] * (i64) g; i64 t3 = f[3] * (i64) g;
+ i64 t4 = f[4] * (i64) g; i64 t5 = f[5] * (i64) g;
+ i64 t6 = f[6] * (i64) g; i64 t7 = f[7] * (i64) g;
+ i64 t8 = f[8] * (i64) g; i64 t9 = f[9] * (i64) g;
+ // |t0|, |t2|, |t4|, |t6|, |t8| < 1.65 * 2^26 * 2^31 < 2^58
+ // |t1|, |t3|, |t5|, |t7|, |t9| < 1.65 * 2^25 * 2^31 < 2^57
+
+ FE_CARRY; // Carry precondition OK
+}
+
+// Precondition
+// -------------
+// |f0|, |f2|, |f4|, |f6|, |f8| < 1.65 * 2^26
+// |f1|, |f3|, |f5|, |f7|, |f9| < 1.65 * 2^25
+//
+// |g0|, |g2|, |g4|, |g6|, |g8| < 1.65 * 2^26
+// |g1|, |g3|, |g5|, |g7|, |g9| < 1.65 * 2^25
+static void fe_mul(fe h, const fe f, const fe g)
+{
+ // Everything is unrolled and put in temporary variables.
+ // We could roll the loop, but that would make curve25519 twice as slow.
+ i32 f0 = f[0]; i32 f1 = f[1]; i32 f2 = f[2]; i32 f3 = f[3]; i32 f4 = f[4];
+ i32 f5 = f[5]; i32 f6 = f[6]; i32 f7 = f[7]; i32 f8 = f[8]; i32 f9 = f[9];
+ i32 g0 = g[0]; i32 g1 = g[1]; i32 g2 = g[2]; i32 g3 = g[3]; i32 g4 = g[4];
+ i32 g5 = g[5]; i32 g6 = g[6]; i32 g7 = g[7]; i32 g8 = g[8]; i32 g9 = g[9];
+ i32 F1 = f1*2; i32 F3 = f3*2; i32 F5 = f5*2; i32 F7 = f7*2; i32 F9 = f9*2;
+ i32 G1 = g1*19; i32 G2 = g2*19; i32 G3 = g3*19;
+ i32 G4 = g4*19; i32 G5 = g5*19; i32 G6 = g6*19;
+ i32 G7 = g7*19; i32 G8 = g8*19; i32 G9 = g9*19;
+ // |F1|, |F3|, |F5|, |F7|, |F9| < 1.65 * 2^26
+ // |G0|, |G2|, |G4|, |G6|, |G8| < 2^31
+ // |G1|, |G3|, |G5|, |G7|, |G9| < 2^30
+
+ i64 t0 = f0*(i64)g0 + F1*(i64)G9 + f2*(i64)G8 + F3*(i64)G7 + f4*(i64)G6
+ + F5*(i64)G5 + f6*(i64)G4 + F7*(i64)G3 + f8*(i64)G2 + F9*(i64)G1;
+ i64 t1 = f0*(i64)g1 + f1*(i64)g0 + f2*(i64)G9 + f3*(i64)G8 + f4*(i64)G7
+ + f5*(i64)G6 + f6*(i64)G5 + f7*(i64)G4 + f8*(i64)G3 + f9*(i64)G2;
+ i64 t2 = f0*(i64)g2 + F1*(i64)g1 + f2*(i64)g0 + F3*(i64)G9 + f4*(i64)G8
+ + F5*(i64)G7 + f6*(i64)G6 + F7*(i64)G5 + f8*(i64)G4 + F9*(i64)G3;
+ i64 t3 = f0*(i64)g3 + f1*(i64)g2 + f2*(i64)g1 + f3*(i64)g0 + f4*(i64)G9
+ + f5*(i64)G8 + f6*(i64)G7 + f7*(i64)G6 + f8*(i64)G5 + f9*(i64)G4;
+ i64 t4 = f0*(i64)g4 + F1*(i64)g3 + f2*(i64)g2 + F3*(i64)g1 + f4*(i64)g0
+ + F5*(i64)G9 + f6*(i64)G8 + F7*(i64)G7 + f8*(i64)G6 + F9*(i64)G5;
+ i64 t5 = f0*(i64)g5 + f1*(i64)g4 + f2*(i64)g3 + f3*(i64)g2 + f4*(i64)g1
+ + f5*(i64)g0 + f6*(i64)G9 + f7*(i64)G8 + f8*(i64)G7 + f9*(i64)G6;
+ i64 t6 = f0*(i64)g6 + F1*(i64)g5 + f2*(i64)g4 + F3*(i64)g3 + f4*(i64)g2
+ + F5*(i64)g1 + f6*(i64)g0 + F7*(i64)G9 + f8*(i64)G8 + F9*(i64)G7;
+ i64 t7 = f0*(i64)g7 + f1*(i64)g6 + f2*(i64)g5 + f3*(i64)g4 + f4*(i64)g3
+ + f5*(i64)g2 + f6*(i64)g1 + f7*(i64)g0 + f8*(i64)G9 + f9*(i64)G8;
+ i64 t8 = f0*(i64)g8 + F1*(i64)g7 + f2*(i64)g6 + F3*(i64)g5 + f4*(i64)g4
+ + F5*(i64)g3 + f6*(i64)g2 + F7*(i64)g1 + f8*(i64)g0 + F9*(i64)G9;
+ i64 t9 = f0*(i64)g9 + f1*(i64)g8 + f2*(i64)g7 + f3*(i64)g6 + f4*(i64)g5
+ + f5*(i64)g4 + f6*(i64)g3 + f7*(i64)g2 + f8*(i64)g1 + f9*(i64)g0;
+ // t0 < 0.67 * 2^61
+ // t1 < 0.41 * 2^61
+ // t2 < 0.52 * 2^61
+ // t3 < 0.32 * 2^61
+ // t4 < 0.38 * 2^61
+ // t5 < 0.22 * 2^61
+ // t6 < 0.23 * 2^61
+ // t7 < 0.13 * 2^61
+ // t8 < 0.09 * 2^61
+ // t9 < 0.03 * 2^61
+
+ FE_CARRY; // Everything below 2^62, Carry precondition OK
+}
+
+// Precondition
+// -------------
+// |f0|, |f2|, |f4|, |f6|, |f8| < 1.65 * 2^26
+// |f1|, |f3|, |f5|, |f7|, |f9| < 1.65 * 2^25
+//
+// Note: we could use fe_mul() for this, but this is significantly faster
+static void fe_sq(fe h, const fe f)
+{
+ i32 f0 = f[0]; i32 f1 = f[1]; i32 f2 = f[2]; i32 f3 = f[3]; i32 f4 = f[4];
+ i32 f5 = f[5]; i32 f6 = f[6]; i32 f7 = f[7]; i32 f8 = f[8]; i32 f9 = f[9];
+ i32 f0_2 = f0*2; i32 f1_2 = f1*2; i32 f2_2 = f2*2; i32 f3_2 = f3*2;
+ i32 f4_2 = f4*2; i32 f5_2 = f5*2; i32 f6_2 = f6*2; i32 f7_2 = f7*2;
+ i32 f5_38 = f5*38; i32 f6_19 = f6*19; i32 f7_38 = f7*38;
+ i32 f8_19 = f8*19; i32 f9_38 = f9*38;
+ // |f0_2| , |f2_2| , |f4_2| , |f6_2| , |f8_2| < 1.65 * 2^27
+ // |f1_2| , |f3_2| , |f5_2| , |f7_2| , |f9_2| < 1.65 * 2^26
+ // |f5_38|, |f6_19|, |f7_38|, |f8_19|, |f9_38| < 2^31
+
+ i64 t0 = f0 *(i64)f0 + f1_2*(i64)f9_38 + f2_2*(i64)f8_19
+ + f3_2*(i64)f7_38 + f4_2*(i64)f6_19 + f5 *(i64)f5_38;
+ i64 t1 = f0_2*(i64)f1 + f2 *(i64)f9_38 + f3_2*(i64)f8_19
+ + f4 *(i64)f7_38 + f5_2*(i64)f6_19;
+ i64 t2 = f0_2*(i64)f2 + f1_2*(i64)f1 + f3_2*(i64)f9_38
+ + f4_2*(i64)f8_19 + f5_2*(i64)f7_38 + f6 *(i64)f6_19;
+ i64 t3 = f0_2*(i64)f3 + f1_2*(i64)f2 + f4 *(i64)f9_38
+ + f5_2*(i64)f8_19 + f6 *(i64)f7_38;
+ i64 t4 = f0_2*(i64)f4 + f1_2*(i64)f3_2 + f2 *(i64)f2
+ + f5_2*(i64)f9_38 + f6_2*(i64)f8_19 + f7 *(i64)f7_38;
+ i64 t5 = f0_2*(i64)f5 + f1_2*(i64)f4 + f2_2*(i64)f3
+ + f6 *(i64)f9_38 + f7_2*(i64)f8_19;
+ i64 t6 = f0_2*(i64)f6 + f1_2*(i64)f5_2 + f2_2*(i64)f4
+ + f3_2*(i64)f3 + f7_2*(i64)f9_38 + f8 *(i64)f8_19;
+ i64 t7 = f0_2*(i64)f7 + f1_2*(i64)f6 + f2_2*(i64)f5
+ + f3_2*(i64)f4 + f8 *(i64)f9_38;
+ i64 t8 = f0_2*(i64)f8 + f1_2*(i64)f7_2 + f2_2*(i64)f6
+ + f3_2*(i64)f5_2 + f4 *(i64)f4 + f9 *(i64)f9_38;
+ i64 t9 = f0_2*(i64)f9 + f1_2*(i64)f8 + f2_2*(i64)f7
+ + f3_2*(i64)f6 + f4 *(i64)f5_2;
+ // t0 < 0.67 * 2^61
+ // t1 < 0.41 * 2^61
+ // t2 < 0.52 * 2^61
+ // t3 < 0.32 * 2^61
+ // t4 < 0.38 * 2^61
+ // t5 < 0.22 * 2^61
+ // t6 < 0.23 * 2^61
+ // t7 < 0.13 * 2^61
+ // t8 < 0.09 * 2^61
+ // t9 < 0.03 * 2^61
+
+ FE_CARRY;
+}
+
+// Parity check. Returns 0 if even, 1 if odd
+static int fe_isodd(const fe f)
+{
+ u8 s[32];
+ fe_tobytes(s, f);
+ u8 isodd = s[0] & 1;
+ WIPE_BUFFER(s);
+ return isodd;
+}
+
+// Returns 1 if equal, 0 if not equal
+static int fe_isequal(const fe f, const fe g)
+{
+ u8 fs[32];
+ u8 gs[32];
+ fe_tobytes(fs, f);
+ fe_tobytes(gs, g);
+ int isdifferent = crypto_verify32(fs, gs);
+ WIPE_BUFFER(fs);
+ WIPE_BUFFER(gs);
+ return 1 + isdifferent;
+}
+
+// Inverse square root.
+// Returns true if x is a square, false otherwise.
+// After the call:
+// isr = sqrt(1/x) if x is a non-zero square.
+// isr = sqrt(sqrt(-1)/x) if x is not a square.
+// isr = 0 if x is zero.
+// We do not guarantee the sign of the square root.
+//
+// Notes:
+// Let quartic = x^((p-1)/4)
+//
+// x^((p-1)/2) = chi(x)
+// quartic^2 = chi(x)
+// quartic = sqrt(chi(x))
+// quartic = 1 or -1 or sqrt(-1) or -sqrt(-1)
+//
+// Note that x is a square if quartic is 1 or -1
+// There are 4 cases to consider:
+//
+// if quartic = 1 (x is a square)
+// then x^((p-1)/4) = 1
+// x^((p-5)/4) * x = 1
+// x^((p-5)/4) = 1/x
+// x^((p-5)/8) = sqrt(1/x) or -sqrt(1/x)
+//
+// if quartic = -1 (x is a square)
+// then x^((p-1)/4) = -1
+// x^((p-5)/4) * x = -1
+// x^((p-5)/4) = -1/x
+// x^((p-5)/8) = sqrt(-1) / sqrt(x)
+// x^((p-5)/8) * sqrt(-1) = sqrt(-1)^2 / sqrt(x)
+// x^((p-5)/8) * sqrt(-1) = -1/sqrt(x)
+// x^((p-5)/8) * sqrt(-1) = -sqrt(1/x) or sqrt(1/x)
+//
+// if quartic = sqrt(-1) (x is not a square)
+// then x^((p-1)/4) = sqrt(-1)
+// x^((p-5)/4) * x = sqrt(-1)
+// x^((p-5)/4) = sqrt(-1)/x
+// x^((p-5)/8) = sqrt(sqrt(-1)/x) or -sqrt(sqrt(-1)/x)
+//
+// Note that the product of two non-squares is always a square:
+// For any non-squares a and b, chi(a) = -1 and chi(b) = -1.
+// Since chi(x) = x^((p-1)/2), chi(a)*chi(b) = chi(a*b) = 1.
+// Therefore a*b is a square.
+//
+// Since sqrt(-1) and x are both non-squares, their product is a
+// square, and we can compute their square root.
+//
+// if quartic = -sqrt(-1) (x is not a square)
+// then x^((p-1)/4) = -sqrt(-1)
+// x^((p-5)/4) * x = -sqrt(-1)
+// x^((p-5)/4) = -sqrt(-1)/x
+// x^((p-5)/8) = sqrt(-sqrt(-1)/x)
+// x^((p-5)/8) = sqrt( sqrt(-1)/x) * sqrt(-1)
+// x^((p-5)/8) * sqrt(-1) = sqrt( sqrt(-1)/x) * sqrt(-1)^2
+// x^((p-5)/8) * sqrt(-1) = sqrt( sqrt(-1)/x) * -1
+// x^((p-5)/8) * sqrt(-1) = -sqrt(sqrt(-1)/x) or sqrt(sqrt(-1)/x)
+static int invsqrt(fe isr, const fe x)
+{
+ fe t0, t1, t2;
+
+ // t0 = x^((p-5)/8)
+ // Can be achieved with a simple double & add ladder,
+ // but it would be slower.
+ fe_sq(t0, x);
+ fe_sq(t1,t0); fe_sq(t1, t1); fe_mul(t1, x, t1);
+ fe_mul(t0, t0, t1);
+ fe_sq(t0, t0); fe_mul(t0, t1, t0);
+ fe_sq(t1, t0); FOR (i, 1, 5) { fe_sq(t1, t1); } fe_mul(t0, t1, t0);
+ fe_sq(t1, t0); FOR (i, 1, 10) { fe_sq(t1, t1); } fe_mul(t1, t1, t0);
+ fe_sq(t2, t1); FOR (i, 1, 20) { fe_sq(t2, t2); } fe_mul(t1, t2, t1);
+ fe_sq(t1, t1); FOR (i, 1, 10) { fe_sq(t1, t1); } fe_mul(t0, t1, t0);
+ fe_sq(t1, t0); FOR (i, 1, 50) { fe_sq(t1, t1); } fe_mul(t1, t1, t0);
+ fe_sq(t2, t1); FOR (i, 1, 100) { fe_sq(t2, t2); } fe_mul(t1, t2, t1);
+ fe_sq(t1, t1); FOR (i, 1, 50) { fe_sq(t1, t1); } fe_mul(t0, t1, t0);
+ fe_sq(t0, t0); FOR (i, 1, 2) { fe_sq(t0, t0); } fe_mul(t0, t0, x);
+
+ // quartic = x^((p-1)/4)
+ i32 *quartic = t1;
+ fe_sq (quartic, t0);
+ fe_mul(quartic, quartic, x);
+
+ i32 *check = t2;
+ fe_0 (check); int z0 = fe_isequal(x , check);
+ fe_1 (check); int p1 = fe_isequal(quartic, check);
+ fe_neg(check, check ); int m1 = fe_isequal(quartic, check);
+ fe_neg(check, sqrtm1); int ms = fe_isequal(quartic, check);
+
+ // if quartic == -1 or sqrt(-1)
+ // then isr = x^((p-1)/4) * sqrt(-1)
+ // else isr = x^((p-1)/4)
+ fe_mul(isr, t0, sqrtm1);
+ fe_ccopy(isr, t0, 1 - (m1 | ms));
+
+ WIPE_BUFFER(t0);
+ WIPE_BUFFER(t1);
+ WIPE_BUFFER(t2);
+ return p1 | m1 | z0;
+}
+
+// Inverse in terms of inverse square root.
+// Requires two additional squarings to get rid of the sign.
+//
+// 1/x = x * (+invsqrt(x^2))^2
+// = x * (-invsqrt(x^2))^2
+//
+// A fully optimised exponentiation by p-1 would save 6 field
+// multiplications, but it would require more code.
+static void fe_invert(fe out, const fe x)
+{
+ fe tmp;
+ fe_sq(tmp, x);
+ invsqrt(tmp, tmp);
+ fe_sq(tmp, tmp);
+ fe_mul(out, tmp, x);
+ WIPE_BUFFER(tmp);
+}
+
+// trim a scalar for scalar multiplication
+void crypto_eddsa_trim_scalar(u8 out[32], const u8 in[32])
+{
+ COPY(out, in, 32);
+ out[ 0] &= 248;
+ out[31] &= 127;
+ out[31] |= 64;
+}
+
+// get bit from scalar at position i
+static int scalar_bit(const u8 s[32], int i)
+{
+ if (i < 0) { return 0; } // handle -1 for sliding windows
+ return (s[i>>3] >> (i&7)) & 1;
+}
+
+///////////////
+/// X-25519 /// Taken from SUPERCOP's ref10 implementation.
+///////////////
+static void scalarmult(u8 q[32], const u8 scalar[32], const u8 p[32],
+ int nb_bits)
+{
+ // computes the scalar product
+ fe x1;
+ fe_frombytes(x1, p);
+
+ // computes the actual scalar product (the result is in x2 and z2)
+ fe x2, z2, x3, z3, t0, t1;
+ // Montgomery ladder
+ // In projective coordinates, to avoid divisions: x = X / Z
+ // We don't care about the y coordinate, it's only 1 bit of information
+ fe_1(x2); fe_0(z2); // "zero" point
+ fe_copy(x3, x1); fe_1(z3); // "one" point
+ int swap = 0;
+ for (int pos = nb_bits-1; pos >= 0; --pos) {
+ // constant time conditional swap before ladder step
+ int b = scalar_bit(scalar, pos);
+ swap ^= b; // xor trick avoids swapping at the end of the loop
+ fe_cswap(x2, x3, swap);
+ fe_cswap(z2, z3, swap);
+ swap = b; // anticipates one last swap after the loop
+
+ // Montgomery ladder step: replaces (P2, P3) by (P2*2, P2+P3)
+ // with differential addition
+ fe_sub(t0, x3, z3);
+ fe_sub(t1, x2, z2);
+ fe_add(x2, x2, z2);
+ fe_add(z2, x3, z3);
+ fe_mul(z3, t0, x2);
+ fe_mul(z2, z2, t1);
+ fe_sq (t0, t1 );
+ fe_sq (t1, x2 );
+ fe_add(x3, z3, z2);
+ fe_sub(z2, z3, z2);
+ fe_mul(x2, t1, t0);
+ fe_sub(t1, t1, t0);
+ fe_sq (z2, z2 );
+ fe_mul_small(z3, t1, 121666);
+ fe_sq (x3, x3 );
+ fe_add(t0, t0, z3);
+ fe_mul(z3, x1, z2);
+ fe_mul(z2, t1, t0);
+ }
+ // last swap is necessary to compensate for the xor trick
+ // Note: after this swap, P3 == P2 + P1.
+ fe_cswap(x2, x3, swap);
+ fe_cswap(z2, z3, swap);
+
+ // normalises the coordinates: x == X / Z
+ fe_invert(z2, z2);
+ fe_mul(x2, x2, z2);
+ fe_tobytes(q, x2);
+
+ WIPE_BUFFER(x1);
+ WIPE_BUFFER(x2); WIPE_BUFFER(z2); WIPE_BUFFER(t0);
+ WIPE_BUFFER(x3); WIPE_BUFFER(z3); WIPE_BUFFER(t1);
+}
+
+void crypto_x25519(u8 raw_shared_secret[32],
+ const u8 your_secret_key [32],
+ const u8 their_public_key [32])
+{
+ // restrict the possible scalar values
+ u8 e[32];
+ crypto_eddsa_trim_scalar(e, your_secret_key);
+ scalarmult(raw_shared_secret, e, their_public_key, 255);
+ WIPE_BUFFER(e);
+}
+
+void crypto_x25519_public_key(u8 public_key[32],
+ const u8 secret_key[32])
+{
+ static const u8 base_point[32] = {9};
+ crypto_x25519(public_key, secret_key, base_point);
+}
+
+///////////////////////////
+/// Arithmetic modulo L ///
+///////////////////////////
+static const u32 L[8] = {
+ 0x5cf5d3ed, 0x5812631a, 0xa2f79cd6, 0x14def9de,
+ 0x00000000, 0x00000000, 0x00000000, 0x10000000,
+};
+
+// p = a*b + p
+static void multiply(u32 p[16], const u32 a[8], const u32 b[8])
+{
+ FOR (i, 0, 8) {
+ u64 carry = 0;
+ FOR (j, 0, 8) {
+ carry += p[i+j] + (u64)a[i] * b[j];
+ p[i+j] = (u32)carry;
+ carry >>= 32;
+ }
+ p[i+8] = (u32)carry;
+ }
+}
+
+static int is_above_l(const u32 x[8])
+{
+ // We work with L directly, in a 2's complement encoding
+ // (-L == ~L + 1)
+ u64 carry = 1;
+ FOR (i, 0, 8) {
+ carry += (u64)x[i] + (~L[i] & 0xffffffff);
+ carry >>= 32;
+ }
+ return (int)carry; // carry is either 0 or 1
+}
+
+// Final reduction modulo L, by conditionally removing L.
+// if x < l , then r = x
+// if l <= x 2*l, then r = x-l
+// otherwise the result will be wrong
+static void remove_l(u32 r[8], const u32 x[8])
+{
+ u64 carry = (u64)is_above_l(x);
+ u32 mask = ~(u32)carry + 1; // carry == 0 or 1
+ FOR (i, 0, 8) {
+ carry += (u64)x[i] + (~L[i] & mask);
+ r[i] = (u32)carry;
+ carry >>= 32;
+ }
+}
+
+// Full reduction modulo L (Barrett reduction)
+static void mod_l(u8 reduced[32], const u32 x[16])
+{
+ static const u32 r[9] = {
+ 0x0a2c131b,0xed9ce5a3,0x086329a7,0x2106215d,
+ 0xffffffeb,0xffffffff,0xffffffff,0xffffffff,0xf,
+ };
+ // xr = x * r
+ u32 xr[25] = {0};
+ FOR (i, 0, 9) {
+ u64 carry = 0;
+ FOR (j, 0, 16) {
+ carry += xr[i+j] + (u64)r[i] * x[j];
+ xr[i+j] = (u32)carry;
+ carry >>= 32;
+ }
+ xr[i+16] = (u32)carry;
+ }
+ // xr = floor(xr / 2^512) * L
+ // Since the result is guaranteed to be below 2*L,
+ // it is enough to only compute the first 256 bits.
+ // The division is performed by saying xr[i+16]. (16 * 32 = 512)
+ ZERO(xr, 8);
+ FOR (i, 0, 8) {
+ u64 carry = 0;
+ FOR (j, 0, 8-i) {
+ carry += xr[i+j] + (u64)xr[i+16] * L[j];
+ xr[i+j] = (u32)carry;
+ carry >>= 32;
+ }
+ }
+ // xr = x - xr
+ u64 carry = 1;
+ FOR (i, 0, 8) {
+ carry += (u64)x[i] + (~xr[i] & 0xffffffff);
+ xr[i] = (u32)carry;
+ carry >>= 32;
+ }
+ // Final reduction modulo L (conditional subtraction)
+ remove_l(xr, xr);
+ store32_le_buf(reduced, xr, 8);
+
+ WIPE_BUFFER(xr);
+}
+
+void crypto_eddsa_reduce(u8 reduced[32], const u8 expanded[64])
+{
+ u32 x[16];
+ load32_le_buf(x, expanded, 16);
+ mod_l(reduced, x);
+ WIPE_BUFFER(x);
+}
+
+// r = (a * b) + c
+void crypto_eddsa_mul_add(u8 r[32],
+ const u8 a[32], const u8 b[32], const u8 c[32])
+{
+ u32 A[8]; load32_le_buf(A, a, 8);
+ u32 B[8]; load32_le_buf(B, b, 8);
+ u32 p[16]; load32_le_buf(p, c, 8); ZERO(p + 8, 8);
+ multiply(p, A, B);
+ mod_l(r, p);
+ WIPE_BUFFER(p);
+ WIPE_BUFFER(A);
+ WIPE_BUFFER(B);
+}
+
+///////////////
+/// Ed25519 ///
+///////////////
+
+// Point (group element, ge) in a twisted Edwards curve,
+// in extended projective coordinates.
+// ge : x = X/Z, y = Y/Z, T = XY/Z
+// ge_cached : Yp = X+Y, Ym = X-Y, T2 = T*D2
+// ge_precomp: Z = 1
+typedef struct { fe X; fe Y; fe Z; fe T; } ge;
+typedef struct { fe Yp; fe Ym; fe Z; fe T2; } ge_cached;
+typedef struct { fe Yp; fe Ym; fe T2; } ge_precomp;
+
+static void ge_zero(ge *p)
+{
+ fe_0(p->X);
+ fe_1(p->Y);
+ fe_1(p->Z);
+ fe_0(p->T);
+}
+
+static void ge_tobytes(u8 s[32], const ge *h)
+{
+ fe recip, x, y;
+ fe_invert(recip, h->Z);
+ fe_mul(x, h->X, recip);
+ fe_mul(y, h->Y, recip);
+ fe_tobytes(s, y);
+ s[31] ^= fe_isodd(x) << 7;
+
+ WIPE_BUFFER(recip);
+ WIPE_BUFFER(x);
+ WIPE_BUFFER(y);
+}
+
+// h = -s, where s is a point encoded in 32 bytes
+//
+// Variable time! Inputs must not be secret!
+// => Use only to *check* signatures.
+//
+// From the specifications:
+// The encoding of s contains y and the sign of x
+// x = sqrt((y^2 - 1) / (d*y^2 + 1))
+// In extended coordinates:
+// X = x, Y = y, Z = 1, T = x*y
+//
+// Note that num * den is a square iff num / den is a square
+// If num * den is not a square, the point was not on the curve.
+// From the above:
+// Let num = y^2 - 1
+// Let den = d*y^2 + 1
+// x = sqrt((y^2 - 1) / (d*y^2 + 1))
+// x = sqrt(num / den)
+// x = sqrt(num^2 / (num * den))
+// x = num * sqrt(1 / (num * den))
+//
+// Therefore, we can just compute:
+// num = y^2 - 1
+// den = d*y^2 + 1
+// isr = invsqrt(num * den) // abort if not square
+// x = num * isr
+// Finally, negate x if its sign is not as specified.
+static int ge_frombytes_neg_vartime(ge *h, const u8 s[32])
+{
+ fe_frombytes(h->Y, s);
+ fe_1(h->Z);
+ fe_sq (h->T, h->Y); // t = y^2
+ fe_mul(h->X, h->T, d ); // x = d*y^2
+ fe_sub(h->T, h->T, h->Z); // t = y^2 - 1
+ fe_add(h->X, h->X, h->Z); // x = d*y^2 + 1
+ fe_mul(h->X, h->T, h->X); // x = (y^2 - 1) * (d*y^2 + 1)
+ int is_square = invsqrt(h->X, h->X);
+ if (!is_square) {
+ return -1; // Not on the curve, abort
+ }
+ fe_mul(h->X, h->T, h->X); // x = sqrt((y^2 - 1) / (d*y^2 + 1))
+ if (fe_isodd(h->X) == (s[31] >> 7)) {
+ fe_neg(h->X, h->X);
+ }
+ fe_mul(h->T, h->X, h->Y);
+ return 0;
+}
+
+static void ge_cache(ge_cached *c, const ge *p)
+{
+ fe_add (c->Yp, p->Y, p->X);
+ fe_sub (c->Ym, p->Y, p->X);
+ fe_copy(c->Z , p->Z );
+ fe_mul (c->T2, p->T, D2 );
+}
+
+// Internal buffers are not wiped! Inputs must not be secret!
+// => Use only to *check* signatures.
+static void ge_add(ge *s, const ge *p, const ge_cached *q)
+{
+ fe a, b;
+ fe_add(a , p->Y, p->X );
+ fe_sub(b , p->Y, p->X );
+ fe_mul(a , a , q->Yp);
+ fe_mul(b , b , q->Ym);
+ fe_add(s->Y, a , b );
+ fe_sub(s->X, a , b );
+
+ fe_add(s->Z, p->Z, p->Z );
+ fe_mul(s->Z, s->Z, q->Z );
+ fe_mul(s->T, p->T, q->T2);
+ fe_add(a , s->Z, s->T );
+ fe_sub(b , s->Z, s->T );
+
+ fe_mul(s->T, s->X, s->Y);
+ fe_mul(s->X, s->X, b );
+ fe_mul(s->Y, s->Y, a );
+ fe_mul(s->Z, a , b );
+}
+
+// Internal buffers are not wiped! Inputs must not be secret!
+// => Use only to *check* signatures.
+static void ge_sub(ge *s, const ge *p, const ge_cached *q)
+{
+ ge_cached neg;
+ fe_copy(neg.Ym, q->Yp);
+ fe_copy(neg.Yp, q->Ym);
+ fe_copy(neg.Z , q->Z );
+ fe_neg (neg.T2, q->T2);
+ ge_add(s, p, &neg);
+}
+
+static void ge_madd(ge *s, const ge *p, const ge_precomp *q, fe a, fe b)
+{
+ fe_add(a , p->Y, p->X );
+ fe_sub(b , p->Y, p->X );
+ fe_mul(a , a , q->Yp);
+ fe_mul(b , b , q->Ym);
+ fe_add(s->Y, a , b );
+ fe_sub(s->X, a , b );
+
+ fe_add(s->Z, p->Z, p->Z );
+ fe_mul(s->T, p->T, q->T2);
+ fe_add(a , s->Z, s->T );
+ fe_sub(b , s->Z, s->T );
+
+ fe_mul(s->T, s->X, s->Y);
+ fe_mul(s->X, s->X, b );
+ fe_mul(s->Y, s->Y, a );
+ fe_mul(s->Z, a , b );
+}
+
+// Internal buffers are not wiped! Inputs must not be secret!
+// => Use only to *check* signatures.
+static void ge_msub(ge *s, const ge *p, const ge_precomp *q, fe a, fe b)
+{
+ ge_precomp neg;
+ fe_copy(neg.Ym, q->Yp);
+ fe_copy(neg.Yp, q->Ym);
+ fe_neg (neg.T2, q->T2);
+ ge_madd(s, p, &neg, a, b);
+}
+
+static void ge_double(ge *s, const ge *p, ge *q)
+{
+ fe_sq (q->X, p->X);
+ fe_sq (q->Y, p->Y);
+ fe_sq (q->Z, p->Z); // qZ = pZ^2
+ fe_mul_small(q->Z, q->Z, 2); // qZ = pZ^2 * 2
+ fe_add(q->T, p->X, p->Y);
+ fe_sq (s->T, q->T);
+ fe_add(q->T, q->Y, q->X);
+ fe_sub(q->Y, q->Y, q->X);
+ fe_sub(q->X, s->T, q->T);
+ fe_sub(q->Z, q->Z, q->Y);
+
+ fe_mul(s->X, q->X , q->Z);
+ fe_mul(s->Y, q->T , q->Y);
+ fe_mul(s->Z, q->Y , q->Z);
+ fe_mul(s->T, q->X , q->T);
+}
+
+// 5-bit signed window in cached format (Niels coordinates, Z=1)
+static const ge_precomp b_window[8] = {
+ {{25967493,-14356035,29566456,3660896,-12694345,
+ 4014787,27544626,-11754271,-6079156,2047605,},
+ {-12545711,934262,-2722910,3049990,-727428,
+ 9406986,12720692,5043384,19500929,-15469378,},
+ {-8738181,4489570,9688441,-14785194,10184609,
+ -12363380,29287919,11864899,-24514362,-4438546,},},
+ {{15636291,-9688557,24204773,-7912398,616977,
+ -16685262,27787600,-14772189,28944400,-1550024,},
+ {16568933,4717097,-11556148,-1102322,15682896,
+ -11807043,16354577,-11775962,7689662,11199574,},
+ {30464156,-5976125,-11779434,-15670865,23220365,
+ 15915852,7512774,10017326,-17749093,-9920357,},},
+ {{10861363,11473154,27284546,1981175,-30064349,
+ 12577861,32867885,14515107,-15438304,10819380,},
+ {4708026,6336745,20377586,9066809,-11272109,
+ 6594696,-25653668,12483688,-12668491,5581306,},
+ {19563160,16186464,-29386857,4097519,10237984,
+ -4348115,28542350,13850243,-23678021,-15815942,},},
+ {{5153746,9909285,1723747,-2777874,30523605,
+ 5516873,19480852,5230134,-23952439,-15175766,},
+ {-30269007,-3463509,7665486,10083793,28475525,
+ 1649722,20654025,16520125,30598449,7715701,},
+ {28881845,14381568,9657904,3680757,-20181635,
+ 7843316,-31400660,1370708,29794553,-1409300,},},
+ {{-22518993,-6692182,14201702,-8745502,-23510406,
+ 8844726,18474211,-1361450,-13062696,13821877,},
+ {-6455177,-7839871,3374702,-4740862,-27098617,
+ -10571707,31655028,-7212327,18853322,-14220951,},
+ {4566830,-12963868,-28974889,-12240689,-7602672,
+ -2830569,-8514358,-10431137,2207753,-3209784,},},
+ {{-25154831,-4185821,29681144,7868801,-6854661,
+ -9423865,-12437364,-663000,-31111463,-16132436,},
+ {25576264,-2703214,7349804,-11814844,16472782,
+ 9300885,3844789,15725684,171356,6466918,},
+ {23103977,13316479,9739013,-16149481,817875,
+ -15038942,8965339,-14088058,-30714912,16193877,},},
+ {{-33521811,3180713,-2394130,14003687,-16903474,
+ -16270840,17238398,4729455,-18074513,9256800,},
+ {-25182317,-4174131,32336398,5036987,-21236817,
+ 11360617,22616405,9761698,-19827198,630305,},
+ {-13720693,2639453,-24237460,-7406481,9494427,
+ -5774029,-6554551,-15960994,-2449256,-14291300,},},
+ {{-3151181,-5046075,9282714,6866145,-31907062,
+ -863023,-18940575,15033784,25105118,-7894876,},
+ {-24326370,15950226,-31801215,-14592823,-11662737,
+ -5090925,1573892,-2625887,2198790,-15804619,},
+ {-3099351,10324967,-2241613,7453183,-5446979,
+ -2735503,-13812022,-16236442,-32461234,-12290683,},},
+};
+
+// Incremental sliding windows (left to right)
+// Based on Roberto Maria Avanzi[2005]
+typedef struct {
+ i16 next_index; // position of the next signed digit
+ i8 next_digit; // next signed digit (odd number below 2^window_width)
+ u8 next_check; // point at which we must check for a new window
+} slide_ctx;
+
+static void slide_init(slide_ctx *ctx, const u8 scalar[32])
+{
+ // scalar is guaranteed to be below L, either because we checked (s),
+ // or because we reduced it modulo L (h_ram). L is under 2^253, so
+ // so bits 253 to 255 are guaranteed to be zero. No need to test them.
+ //
+ // Note however that L is very close to 2^252, so bit 252 is almost
+ // always zero. If we were to start at bit 251, the tests wouldn't
+ // catch the off-by-one error (constructing one that does would be
+ // prohibitively expensive).
+ //
+ // We should still check bit 252, though.
+ int i = 252;
+ while (i > 0 && scalar_bit(scalar, i) == 0) {
+ i--;
+ }
+ ctx->next_check = (u8)(i + 1);
+ ctx->next_index = -1;
+ ctx->next_digit = -1;
+}
+
+static int slide_step(slide_ctx *ctx, int width, int i, const u8 scalar[32])
+{
+ if (i == ctx->next_check) {
+ if (scalar_bit(scalar, i) == scalar_bit(scalar, i - 1)) {
+ ctx->next_check--;
+ } else {
+ // compute digit of next window
+ int w = MIN(width, i + 1);
+ int v = -(scalar_bit(scalar, i) << (w-1));
+ FOR_T (int, j, 0, w-1) {
+ v += scalar_bit(scalar, i-(w-1)+j) << j;
+ }
+ v += scalar_bit(scalar, i-w);
+ int lsb = v & (~v + 1); // smallest bit of v
+ int s = // log2(lsb)
+ (((lsb & 0xAA) != 0) << 0) |
+ (((lsb & 0xCC) != 0) << 1) |
+ (((lsb & 0xF0) != 0) << 2);
+ ctx->next_index = (i16)(i-(w-1)+s);
+ ctx->next_digit = (i8) (v >> s );
+ ctx->next_check -= (u8) w;
+ }
+ }
+ return i == ctx->next_index ? ctx->next_digit: 0;
+}
+
+#define P_W_WIDTH 3 // Affects the size of the stack
+#define B_W_WIDTH 5 // Affects the size of the binary
+#define P_W_SIZE (1<<(P_W_WIDTH-2))
+
+int crypto_eddsa_check_equation(const u8 signature[64], const u8 public_key[32],
+ const u8 h[32])
+{
+ ge minus_A; // -public_key
+ ge minus_R; // -first_half_of_signature
+ const u8 *s = signature + 32;
+
+ // Check that A and R are on the curve
+ // Check that 0 <= S < L (prevents malleability)
+ // *Allow* non-cannonical encoding for A and R
+ {
+ u32 s32[8];
+ load32_le_buf(s32, s, 8);
+ if (ge_frombytes_neg_vartime(&minus_A, public_key) ||
+ ge_frombytes_neg_vartime(&minus_R, signature) ||
+ is_above_l(s32)) {
+ return -1;
+ }
+ }
+
+ // look-up table for minus_A
+ ge_cached lutA[P_W_SIZE];
+ {
+ ge minus_A2, tmp;
+ ge_double(&minus_A2, &minus_A, &tmp);
+ ge_cache(&lutA[0], &minus_A);
+ FOR (i, 1, P_W_SIZE) {
+ ge_add(&tmp, &minus_A2, &lutA[i-1]);
+ ge_cache(&lutA[i], &tmp);
+ }
+ }
+
+ // sum = [s]B - [h]A
+ // Merged double and add ladder, fused with sliding
+ slide_ctx h_slide; slide_init(&h_slide, h);
+ slide_ctx s_slide; slide_init(&s_slide, s);
+ int i = MAX(h_slide.next_check, s_slide.next_check);
+ ge *sum = &minus_A; // reuse minus_A for the sum
+ ge_zero(sum);
+ while (i >= 0) {
+ ge tmp;
+ ge_double(sum, sum, &tmp);
+ int h_digit = slide_step(&h_slide, P_W_WIDTH, i, h);
+ int s_digit = slide_step(&s_slide, B_W_WIDTH, i, s);
+ if (h_digit > 0) { ge_add(sum, sum, &lutA[ h_digit / 2]); }
+ if (h_digit < 0) { ge_sub(sum, sum, &lutA[-h_digit / 2]); }
+ fe t1, t2;
+ if (s_digit > 0) { ge_madd(sum, sum, b_window + s_digit/2, t1, t2); }
+ if (s_digit < 0) { ge_msub(sum, sum, b_window + -s_digit/2, t1, t2); }
+ i--;
+ }
+
+ // Compare [8](sum-R) and the zero point
+ // The multiplication by 8 eliminates any low-order component
+ // and ensures consistency with batched verification.
+ ge_cached cached;
+ u8 check[32];
+ static const u8 zero_point[32] = {1}; // Point of order 1
+ ge_cache(&cached, &minus_R);
+ ge_add(sum, sum, &cached);
+ ge_double(sum, sum, &minus_R); // reuse minus_R as temporary
+ ge_double(sum, sum, &minus_R); // reuse minus_R as temporary
+ ge_double(sum, sum, &minus_R); // reuse minus_R as temporary
+ ge_tobytes(check, sum);
+ return crypto_verify32(check, zero_point);
+}
+
+// 5-bit signed comb in cached format (Niels coordinates, Z=1)
+static const ge_precomp b_comb_low[8] = {
+ {{-6816601,-2324159,-22559413,124364,18015490,
+ 8373481,19993724,1979872,-18549925,9085059,},
+ {10306321,403248,14839893,9633706,8463310,
+ -8354981,-14305673,14668847,26301366,2818560,},
+ {-22701500,-3210264,-13831292,-2927732,-16326337,
+ -14016360,12940910,177905,12165515,-2397893,},},
+ {{-12282262,-7022066,9920413,-3064358,-32147467,
+ 2927790,22392436,-14852487,2719975,16402117,},
+ {-7236961,-4729776,2685954,-6525055,-24242706,
+ -15940211,-6238521,14082855,10047669,12228189,},
+ {-30495588,-12893761,-11161261,3539405,-11502464,
+ 16491580,-27286798,-15030530,-7272871,-15934455,},},
+ {{17650926,582297,-860412,-187745,-12072900,
+ -10683391,-20352381,15557840,-31072141,-5019061,},
+ {-6283632,-2259834,-4674247,-4598977,-4089240,
+ 12435688,-31278303,1060251,6256175,10480726,},
+ {-13871026,2026300,-21928428,-2741605,-2406664,
+ -8034988,7355518,15733500,-23379862,7489131,},},
+ {{6883359,695140,23196907,9644202,-33430614,
+ 11354760,-20134606,6388313,-8263585,-8491918,},
+ {-7716174,-13605463,-13646110,14757414,-19430591,
+ -14967316,10359532,-11059670,-21935259,12082603,},
+ {-11253345,-15943946,10046784,5414629,24840771,
+ 8086951,-6694742,9868723,15842692,-16224787,},},
+ {{9639399,11810955,-24007778,-9320054,3912937,
+ -9856959,996125,-8727907,-8919186,-14097242,},
+ {7248867,14468564,25228636,-8795035,14346339,
+ 8224790,6388427,-7181107,6468218,-8720783,},
+ {15513115,15439095,7342322,-10157390,18005294,
+ -7265713,2186239,4884640,10826567,7135781,},},
+ {{-14204238,5297536,-5862318,-6004934,28095835,
+ 4236101,-14203318,1958636,-16816875,3837147,},
+ {-5511166,-13176782,-29588215,12339465,15325758,
+ -15945770,-8813185,11075932,-19608050,-3776283,},
+ {11728032,9603156,-4637821,-5304487,-7827751,
+ 2724948,31236191,-16760175,-7268616,14799772,},},
+ {{-28842672,4840636,-12047946,-9101456,-1445464,
+ 381905,-30977094,-16523389,1290540,12798615,},
+ {27246947,-10320914,14792098,-14518944,5302070,
+ -8746152,-3403974,-4149637,-27061213,10749585,},
+ {25572375,-6270368,-15353037,16037944,1146292,
+ 32198,23487090,9585613,24714571,-1418265,},},
+ {{19844825,282124,-17583147,11004019,-32004269,
+ -2716035,6105106,-1711007,-21010044,14338445,},
+ {8027505,8191102,-18504907,-12335737,25173494,
+ -5923905,15446145,7483684,-30440441,10009108,},
+ {-14134701,-4174411,10246585,-14677495,33553567,
+ -14012935,23366126,15080531,-7969992,7663473,},},
+};
+
+static const ge_precomp b_comb_high[8] = {
+ {{33055887,-4431773,-521787,6654165,951411,
+ -6266464,-5158124,6995613,-5397442,-6985227,},
+ {4014062,6967095,-11977872,3960002,8001989,
+ 5130302,-2154812,-1899602,-31954493,-16173976,},
+ {16271757,-9212948,23792794,731486,-25808309,
+ -3546396,6964344,-4767590,10976593,10050757,},},
+ {{2533007,-4288439,-24467768,-12387405,-13450051,
+ 14542280,12876301,13893535,15067764,8594792,},
+ {20073501,-11623621,3165391,-13119866,13188608,
+ -11540496,-10751437,-13482671,29588810,2197295,},
+ {-1084082,11831693,6031797,14062724,14748428,
+ -8159962,-20721760,11742548,31368706,13161200,},},
+ {{2050412,-6457589,15321215,5273360,25484180,
+ 124590,-18187548,-7097255,-6691621,-14604792,},
+ {9938196,2162889,-6158074,-1711248,4278932,
+ -2598531,-22865792,-7168500,-24323168,11746309,},
+ {-22691768,-14268164,5965485,9383325,20443693,
+ 5854192,28250679,-1381811,-10837134,13717818,},},
+ {{-8495530,16382250,9548884,-4971523,-4491811,
+ -3902147,6182256,-12832479,26628081,10395408,},
+ {27329048,-15853735,7715764,8717446,-9215518,
+ -14633480,28982250,-5668414,4227628,242148,},
+ {-13279943,-7986904,-7100016,8764468,-27276630,
+ 3096719,29678419,-9141299,3906709,11265498,},},
+ {{11918285,15686328,-17757323,-11217300,-27548967,
+ 4853165,-27168827,6807359,6871949,-1075745,},
+ {-29002610,13984323,-27111812,-2713442,28107359,
+ -13266203,6155126,15104658,3538727,-7513788,},
+ {14103158,11233913,-33165269,9279850,31014152,
+ 4335090,-1827936,4590951,13960841,12787712,},},
+ {{1469134,-16738009,33411928,13942824,8092558,
+ -8778224,-11165065,1437842,22521552,-2792954,},
+ {31352705,-4807352,-25327300,3962447,12541566,
+ -9399651,-27425693,7964818,-23829869,5541287,},
+ {-25732021,-6864887,23848984,3039395,-9147354,
+ 6022816,-27421653,10590137,25309915,-1584678,},},
+ {{-22951376,5048948,31139401,-190316,-19542447,
+ -626310,-17486305,-16511925,-18851313,-12985140,},
+ {-9684890,14681754,30487568,7717771,-10829709,
+ 9630497,30290549,-10531496,-27798994,-13812825,},
+ {5827835,16097107,-24501327,12094619,7413972,
+ 11447087,28057551,-1793987,-14056981,4359312,},},
+ {{26323183,2342588,-21887793,-1623758,-6062284,
+ 2107090,-28724907,9036464,-19618351,-13055189,},
+ {-29697200,14829398,-4596333,14220089,-30022969,
+ 2955645,12094100,-13693652,-5941445,7047569,},
+ {-3201977,14413268,-12058324,-16417589,-9035655,
+ -7224648,9258160,1399236,30397584,-5684634,},},
+};
+
+static void lookup_add(ge *p, ge_precomp *tmp_c, fe tmp_a, fe tmp_b,
+ const ge_precomp comb[8], const u8 scalar[32], int i)
+{
+ u8 teeth = (u8)((scalar_bit(scalar, i) ) +
+ (scalar_bit(scalar, i + 32) << 1) +
+ (scalar_bit(scalar, i + 64) << 2) +
+ (scalar_bit(scalar, i + 96) << 3));
+ u8 high = teeth >> 3;
+ u8 index = (teeth ^ (high - 1)) & 7;
+ FOR (j, 0, 8) {
+ i32 select = 1 & (((j ^ index) - 1) >> 8);
+ fe_ccopy(tmp_c->Yp, comb[j].Yp, select);
+ fe_ccopy(tmp_c->Ym, comb[j].Ym, select);
+ fe_ccopy(tmp_c->T2, comb[j].T2, select);
+ }
+ fe_neg(tmp_a, tmp_c->T2);
+ fe_cswap(tmp_c->T2, tmp_a , high ^ 1);
+ fe_cswap(tmp_c->Yp, tmp_c->Ym, high ^ 1);
+ ge_madd(p, p, tmp_c, tmp_a, tmp_b);
+}
+
+// p = [scalar]B, where B is the base point
+static void ge_scalarmult_base(ge *p, const u8 scalar[32])
+{
+ // twin 4-bits signed combs, from Mike Hamburg's
+ // Fast and compact elliptic-curve cryptography (2012)
+ // 1 / 2 modulo L
+ static const u8 half_mod_L[32] = {
+ 247,233,122,46,141,49,9,44,107,206,123,81,239,124,111,10,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,
+ };
+ // (2^256 - 1) / 2 modulo L
+ static const u8 half_ones[32] = {
+ 142,74,204,70,186,24,118,107,184,231,190,57,250,173,119,99,
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,7,
+ };
+
+ // All bits set form: 1 means 1, 0 means -1
+ u8 s_scalar[32];
+ crypto_eddsa_mul_add(s_scalar, scalar, half_mod_L, half_ones);
+
+ // Double and add ladder
+ fe tmp_a, tmp_b; // temporaries for addition
+ ge_precomp tmp_c; // temporary for comb lookup
+ ge tmp_d; // temporary for doubling
+ fe_1(tmp_c.Yp);
+ fe_1(tmp_c.Ym);
+ fe_0(tmp_c.T2);
+
+ // Save a double on the first iteration
+ ge_zero(p);
+ lookup_add(p, &tmp_c, tmp_a, tmp_b, b_comb_low , s_scalar, 31);
+ lookup_add(p, &tmp_c, tmp_a, tmp_b, b_comb_high, s_scalar, 31+128);
+ // Regular double & add for the rest
+ for (int i = 30; i >= 0; i--) {
+ ge_double(p, p, &tmp_d);
+ lookup_add(p, &tmp_c, tmp_a, tmp_b, b_comb_low , s_scalar, i);
+ lookup_add(p, &tmp_c, tmp_a, tmp_b, b_comb_high, s_scalar, i+128);
+ }
+ // Note: we could save one addition at the end if we assumed the
+ // scalar fit in 252 bits. Which it does in practice if it is
+ // selected at random. However, non-random, non-hashed scalars
+ // *can* overflow 252 bits in practice. Better account for that
+ // than leaving that kind of subtle corner case.
+
+ WIPE_BUFFER(tmp_a); WIPE_CTX(&tmp_d);
+ WIPE_BUFFER(tmp_b); WIPE_CTX(&tmp_c);
+ WIPE_BUFFER(s_scalar);
+}
+
+void crypto_eddsa_scalarbase(u8 point[32], const u8 scalar[32])
+{
+ ge P;
+ ge_scalarmult_base(&P, scalar);
+ ge_tobytes(point, &P);
+ WIPE_CTX(&P);
+}
+
+void crypto_eddsa_key_pair(u8 secret_key[64], u8 public_key[32], u8 seed[32])
+{
+ // To allow overlaps, observable writes happen in this order:
+ // 1. seed
+ // 2. secret_key
+ // 3. public_key
+ u8 a[64];
+ COPY(a, seed, 32);
+ crypto_wipe(seed, 32);
+ COPY(secret_key, a, 32);
+ crypto_blake2b(a, 64, a, 32);
+ crypto_eddsa_trim_scalar(a, a);
+ crypto_eddsa_scalarbase(secret_key + 32, a);
+ COPY(public_key, secret_key + 32, 32);
+ WIPE_BUFFER(a);
+}
+
+static void hash_reduce(u8 h[32],
+ const u8 *a, size_t a_size,
+ const u8 *b, size_t b_size,
+ const u8 *c, size_t c_size)
+{
+ u8 hash[64];
+ crypto_blake2b_ctx ctx;
+ crypto_blake2b_init (&ctx, 64);
+ crypto_blake2b_update(&ctx, a, a_size);
+ crypto_blake2b_update(&ctx, b, b_size);
+ crypto_blake2b_update(&ctx, c, c_size);
+ crypto_blake2b_final (&ctx, hash);
+ crypto_eddsa_reduce(h, hash);
+}
+
+// Digital signature of a message with from a secret key.
+//
+// The secret key comprises two parts:
+// - The seed that generates the key (secret_key[ 0..31])
+// - The public key (secret_key[32..63])
+//
+// The seed and the public key are bundled together to make sure users
+// don't use mismatched seeds and public keys, which would instantly
+// leak the secret scalar and allow forgeries (allowing this to happen
+// has resulted in critical vulnerabilities in the wild).
+//
+// The seed is hashed to derive the secret scalar and a secret prefix.
+// The sole purpose of the prefix is to generate a secret random nonce.
+// The properties of that nonce must be as follows:
+// - Unique: we need a different one for each message.
+// - Secret: third parties must not be able to predict it.
+// - Random: any detectable bias would break all security.
+//
+// There are two ways to achieve these properties. The obvious one is
+// to simply generate a random number. Here that would be a parameter
+// (Monocypher doesn't have an RNG). It works, but then users may reuse
+// the nonce by accident, which _also_ leaks the secret scalar and
+// allows forgeries. This has happened in the wild too.
+//
+// This is no good, so instead we generate that nonce deterministically
+// by reducing modulo L a hash of the secret prefix and the message.
+// The secret prefix makes the nonce unpredictable, the message makes it
+// unique, and the hash/reduce removes all bias.
+//
+// The cost of that safety is hashing the message twice. If that cost
+// is unacceptable, there are two alternatives:
+//
+// - Signing a hash of the message instead of the message itself. This
+// is fine as long as the hash is collision resistant. It is not
+// compatible with existing "pure" signatures, but at least it's safe.
+//
+// - Using a random nonce. Please exercise **EXTREME CAUTION** if you
+// ever do that. It is absolutely **critical** that the nonce is
+// really an unbiased random number between 0 and L-1, never reused,
+// and wiped immediately.
+//
+// To lower the likelihood of complete catastrophe if the RNG is
+// either flawed or misused, you can hash the RNG output together with
+// the secret prefix and the beginning of the message, and use the
+// reduction of that hash instead of the RNG output itself. It's not
+// foolproof (you'd need to hash the whole message) but it helps.
+//
+// Signing a message involves the following operations:
+//
+// scalar, prefix = HASH(secret_key)
+// r = HASH(prefix || message) % L
+// R = [r]B
+// h = HASH(R || public_key || message) % L
+// S = ((h * a) + r) % L
+// signature = R || S
+void crypto_eddsa_sign(u8 signature [64], const u8 secret_key[64],
+ const u8 *message, size_t message_size)
+{
+ u8 a[64]; // secret scalar and prefix
+ u8 r[32]; // secret deterministic "random" nonce
+ u8 h[32]; // publically verifiable hash of the message (not wiped)
+ u8 R[32]; // first half of the signature (allows overlapping inputs)
+
+ crypto_blake2b(a, 64, secret_key, 32);
+ crypto_eddsa_trim_scalar(a, a);
+ hash_reduce(r, a + 32, 32, message, message_size, 0, 0);
+ crypto_eddsa_scalarbase(R, r);
+ hash_reduce(h, R, 32, secret_key + 32, 32, message, message_size);
+ COPY(signature, R, 32);
+ crypto_eddsa_mul_add(signature + 32, h, a, r);
+
+ WIPE_BUFFER(a);
+ WIPE_BUFFER(r);
+}
+
+// To check the signature R, S of the message M with the public key A,
+// there are 3 steps:
+//
+// compute h = HASH(R || A || message) % L
+// check that A is on the curve.
+// check that R == [s]B - [h]A
+//
+// The last two steps are done in crypto_eddsa_check_equation()
+int crypto_eddsa_check(const u8 signature[64], const u8 public_key[32],
+ const u8 *message, size_t message_size)
+{
+ u8 h[32];
+ hash_reduce(h, signature, 32, public_key, 32, message, message_size);
+ return crypto_eddsa_check_equation(signature, public_key, h);
+}
+
+/////////////////////////
+/// EdDSA <--> X25519 ///
+/////////////////////////
+void crypto_eddsa_to_x25519(u8 x25519[32], const u8 eddsa[32])
+{
+ // (u, v) = ((1+y)/(1-y), sqrt(-486664)*u/x)
+ // Only converting y to u, the sign of x is ignored.
+ fe t1, t2;
+ fe_frombytes(t2, eddsa);
+ fe_add(t1, fe_one, t2);
+ fe_sub(t2, fe_one, t2);
+ fe_invert(t2, t2);
+ fe_mul(t1, t1, t2);
+ fe_tobytes(x25519, t1);
+ WIPE_BUFFER(t1);
+ WIPE_BUFFER(t2);
+}
+
+void crypto_x25519_to_eddsa(u8 eddsa[32], const u8 x25519[32])
+{
+ // (x, y) = (sqrt(-486664)*u/v, (u-1)/(u+1))
+ // Only converting u to y, x is assumed positive.
+ fe t1, t2;
+ fe_frombytes(t2, x25519);
+ fe_sub(t1, t2, fe_one);
+ fe_add(t2, t2, fe_one);
+ fe_invert(t2, t2);
+ fe_mul(t1, t1, t2);
+ fe_tobytes(eddsa, t1);
+ WIPE_BUFFER(t1);
+ WIPE_BUFFER(t2);
+}
+
+/////////////////////////////////////////////
+/// Dirty ephemeral public key generation ///
+/////////////////////////////////////////////
+
+// Those functions generates a public key, *without* clearing the
+// cofactor. Sending that key over the network leaks 3 bits of the
+// private key. Use only to generate ephemeral keys that will be hidden
+// with crypto_curve_to_hidden().
+//
+// The public key is otherwise compatible with crypto_x25519(), which
+// properly clears the cofactor.
+//
+// Note that the distribution of the resulting public keys is almost
+// uniform. Flipping the sign of the v coordinate (not provided by this
+// function), covers the entire key space almost perfectly, where
+// "almost" means a 2^-128 bias (undetectable). This uniformity is
+// needed to ensure the proper randomness of the resulting
+// representatives (once we apply crypto_curve_to_hidden()).
+//
+// Recall that Curve25519 has order C = 2^255 + e, with e < 2^128 (not
+// to be confused with the prime order of the main subgroup, L, which is
+// 8 times less than that).
+//
+// Generating all points would require us to multiply a point of order C
+// (the base point plus any point of order 8) by all scalars from 0 to
+// C-1. Clamping limits us to scalars between 2^254 and 2^255 - 1. But
+// by negating the resulting point at random, we also cover scalars from
+// -2^255 + 1 to -2^254 (which modulo C is congruent to e+1 to 2^254 + e).
+//
+// In practice:
+// - Scalars from 0 to e + 1 are never generated
+// - Scalars from 2^255 to 2^255 + e are never generated
+// - Scalars from 2^254 + 1 to 2^254 + e are generated twice
+//
+// Since e < 2^128, detecting this bias requires observing over 2^100
+// representatives from a given source (this will never happen), *and*
+// recovering enough of the private key to determine that they do, or do
+// not, belong to the biased set (this practically requires solving
+// discrete logarithm, which is conjecturally intractable).
+//
+// In practice, this means the bias is impossible to detect.
+
+// s + (x*L) % 8*L
+// Guaranteed to fit in 256 bits iff s fits in 255 bits.
+// L < 2^253
+// x%8 < 2^3
+// L * (x%8) < 2^255
+// s < 2^255
+// s + L * (x%8) < 2^256
+static void add_xl(u8 s[32], u8 x)
+{
+ u64 mod8 = x & 7;
+ u64 carry = 0;
+ FOR (i , 0, 8) {
+ carry = carry + load32_le(s + 4*i) + L[i] * mod8;
+ store32_le(s + 4*i, (u32)carry);
+ carry >>= 32;
+ }
+}
+
+// "Small" dirty ephemeral key.
+// Use if you need to shrink the size of the binary, and can afford to
+// slow down by a factor of two (compared to the fast version)
+//
+// This version works by decoupling the cofactor from the main factor.
+//
+// - The trimmed scalar determines the main factor
+// - The clamped bits of the scalar determine the cofactor.
+//
+// Cofactor and main factor are combined into a single scalar, which is
+// then multiplied by a point of order 8*L (unlike the base point, which
+// has prime order). That "dirty" base point is the addition of the
+// regular base point (9), and a point of order 8.
+void crypto_x25519_dirty_small(u8 public_key[32], const u8 secret_key[32])
+{
+ // Base point of order 8*L
+ // Raw scalar multiplication with it does not clear the cofactor,
+ // and the resulting public key will reveal 3 bits of the scalar.
+ //
+ // The low order component of this base point has been chosen
+ // to yield the same results as crypto_x25519_dirty_fast().
+ static const u8 dirty_base_point[32] = {
+ 0xd8, 0x86, 0x1a, 0xa2, 0x78, 0x7a, 0xd9, 0x26,
+ 0x8b, 0x74, 0x74, 0xb6, 0x82, 0xe3, 0xbe, 0xc3,
+ 0xce, 0x36, 0x9a, 0x1e, 0x5e, 0x31, 0x47, 0xa2,
+ 0x6d, 0x37, 0x7c, 0xfd, 0x20, 0xb5, 0xdf, 0x75,
+ };
+ // separate the main factor & the cofactor of the scalar
+ u8 scalar[32];
+ crypto_eddsa_trim_scalar(scalar, secret_key);
+
+ // Separate the main factor and the cofactor
+ //
+ // The scalar is trimmed, so its cofactor is cleared. The three
+ // least significant bits however still have a main factor. We must
+ // remove it for X25519 compatibility.
+ //
+ // cofactor = lsb * L (modulo 8*L)
+ // combined = scalar + cofactor (modulo 8*L)
+ add_xl(scalar, secret_key[0]);
+ scalarmult(public_key, scalar, dirty_base_point, 256);
+ WIPE_BUFFER(scalar);
+}
+
+// Select low order point
+// We're computing the [cofactor]lop scalar multiplication, where:
+//
+// cofactor = tweak & 7.
+// lop = (lop_x, lop_y)
+// lop_x = sqrt((sqrt(d + 1) + 1) / d)
+// lop_y = -lop_x * sqrtm1
+//
+// The low order point has order 8. There are 4 such points. We've
+// chosen the one whose both coordinates are positive (below p/2).
+// The 8 low order points are as follows:
+//
+// [0]lop = ( 0 , 1 )
+// [1]lop = ( lop_x , lop_y)
+// [2]lop = ( sqrt(-1), -0 )
+// [3]lop = ( lop_x , -lop_y)
+// [4]lop = (-0 , -1 )
+// [5]lop = (-lop_x , -lop_y)
+// [6]lop = (-sqrt(-1), 0 )
+// [7]lop = (-lop_x , lop_y)
+//
+// The x coordinate is either 0, sqrt(-1), lop_x, or their opposite.
+// The y coordinate is either 0, -1 , lop_y, or their opposite.
+// The pattern for both is the same, except for a rotation of 2 (modulo 8)
+//
+// This helper function captures the pattern, and we can use it thus:
+//
+// select_lop(x, lop_x, sqrtm1, cofactor);
+// select_lop(y, lop_y, fe_one, cofactor + 2);
+//
+// This is faster than an actual scalar multiplication,
+// and requires less code than naive constant time look up.
+static void select_lop(fe out, const fe x, const fe k, u8 cofactor)
+{
+ fe tmp;
+ fe_0(out);
+ fe_ccopy(out, k , (cofactor >> 1) & 1); // bit 1
+ fe_ccopy(out, x , (cofactor >> 0) & 1); // bit 0
+ fe_neg (tmp, out);
+ fe_ccopy(out, tmp, (cofactor >> 2) & 1); // bit 2
+ WIPE_BUFFER(tmp);
+}
+
+// "Fast" dirty ephemeral key
+// We use this one by default.
+//
+// This version works by performing a regular scalar multiplication,
+// then add a low order point. The scalar multiplication is done in
+// Edwards space for more speed (*2 compared to the "small" version).
+// The cost is a bigger binary for programs that don't also sign messages.
+void crypto_x25519_dirty_fast(u8 public_key[32], const u8 secret_key[32])
+{
+ // Compute clean scalar multiplication
+ u8 scalar[32];
+ ge pk;
+ crypto_eddsa_trim_scalar(scalar, secret_key);
+ ge_scalarmult_base(&pk, scalar);
+
+ // Compute low order point
+ fe t1, t2;
+ select_lop(t1, lop_x, sqrtm1, secret_key[0]);
+ select_lop(t2, lop_y, fe_one, secret_key[0] + 2);
+ ge_precomp low_order_point;
+ fe_add(low_order_point.Yp, t2, t1);
+ fe_sub(low_order_point.Ym, t2, t1);
+ fe_mul(low_order_point.T2, t2, t1);
+ fe_mul(low_order_point.T2, low_order_point.T2, D2);
+
+ // Add low order point to the public key
+ ge_madd(&pk, &pk, &low_order_point, t1, t2);
+
+ // Convert to Montgomery u coordinate (we ignore the sign)
+ fe_add(t1, pk.Z, pk.Y);
+ fe_sub(t2, pk.Z, pk.Y);
+ fe_invert(t2, t2);
+ fe_mul(t1, t1, t2);
+
+ fe_tobytes(public_key, t1);
+
+ WIPE_BUFFER(t1); WIPE_CTX(&pk);
+ WIPE_BUFFER(t2); WIPE_CTX(&low_order_point);
+ WIPE_BUFFER(scalar);
+}
+
+///////////////////
+/// Elligator 2 ///
+///////////////////
+static const fe A = {486662};
+
+// Elligator direct map
+//
+// Computes the point corresponding to a representative, encoded in 32
+// bytes (little Endian). Since positive representatives fits in 254
+// bits, The two most significant bits are ignored.
+//
+// From the paper:
+// w = -A / (fe(1) + non_square * r^2)
+// e = chi(w^3 + A*w^2 + w)
+// u = e*w - (fe(1)-e)*(A//2)
+// v = -e * sqrt(u^3 + A*u^2 + u)
+//
+// We ignore v because we don't need it for X25519 (the Montgomery
+// ladder only uses u).
+//
+// Note that e is either 0, 1 or -1
+// if e = 0 u = 0 and v = 0
+// if e = 1 u = w
+// if e = -1 u = -w - A = w * non_square * r^2
+//
+// Let r1 = non_square * r^2
+// Let r2 = 1 + r1
+// Note that r2 cannot be zero, -1/non_square is not a square.
+// We can (tediously) verify that:
+// w^3 + A*w^2 + w = (A^2*r1 - r2^2) * A / r2^3
+// Therefore:
+// chi(w^3 + A*w^2 + w) = chi((A^2*r1 - r2^2) * (A / r2^3))
+// chi(w^3 + A*w^2 + w) = chi((A^2*r1 - r2^2) * (A / r2^3)) * 1
+// chi(w^3 + A*w^2 + w) = chi((A^2*r1 - r2^2) * (A / r2^3)) * chi(r2^6)
+// chi(w^3 + A*w^2 + w) = chi((A^2*r1 - r2^2) * (A / r2^3) * r2^6)
+// chi(w^3 + A*w^2 + w) = chi((A^2*r1 - r2^2) * A * r2^3)
+// Corollary:
+// e = 1 if (A^2*r1 - r2^2) * A * r2^3) is a non-zero square
+// e = -1 if (A^2*r1 - r2^2) * A * r2^3) is not a square
+// Note that w^3 + A*w^2 + w (and therefore e) can never be zero:
+// w^3 + A*w^2 + w = w * (w^2 + A*w + 1)
+// w^3 + A*w^2 + w = w * (w^2 + A*w + A^2/4 - A^2/4 + 1)
+// w^3 + A*w^2 + w = w * (w + A/2)^2 - A^2/4 + 1)
+// which is zero only if:
+// w = 0 (impossible)
+// (w + A/2)^2 = A^2/4 - 1 (impossible, because A^2/4-1 is not a square)
+//
+// Let isr = invsqrt((A^2*r1 - r2^2) * A * r2^3)
+// isr = sqrt(1 / ((A^2*r1 - r2^2) * A * r2^3)) if e = 1
+// isr = sqrt(sqrt(-1) / ((A^2*r1 - r2^2) * A * r2^3)) if e = -1
+//
+// if e = 1
+// let u1 = -A * (A^2*r1 - r2^2) * A * r2^2 * isr^2
+// u1 = w
+// u1 = u
+//
+// if e = -1
+// let ufactor = -non_square * sqrt(-1) * r^2
+// let vfactor = sqrt(ufactor)
+// let u2 = -A * (A^2*r1 - r2^2) * A * r2^2 * isr^2 * ufactor
+// u2 = w * -1 * -non_square * r^2
+// u2 = w * non_square * r^2
+// u2 = u
+void crypto_elligator_map(u8 curve[32], const u8 hidden[32])
+{
+ fe r, u, t1, t2, t3;
+ fe_frombytes_mask(r, hidden, 2); // r is encoded in 254 bits.
+ fe_sq(r, r);
+ fe_add(t1, r, r);
+ fe_add(u, t1, fe_one);
+ fe_sq (t2, u);
+ fe_mul(t3, A2, t1);
+ fe_sub(t3, t3, t2);
+ fe_mul(t3, t3, A);
+ fe_mul(t1, t2, u);
+ fe_mul(t1, t3, t1);
+ int is_square = invsqrt(t1, t1);
+ fe_mul(u, r, ufactor);
+ fe_ccopy(u, fe_one, is_square);
+ fe_sq (t1, t1);
+ fe_mul(u, u, A);
+ fe_mul(u, u, t3);
+ fe_mul(u, u, t2);
+ fe_mul(u, u, t1);
+ fe_neg(u, u);
+ fe_tobytes(curve, u);
+
+ WIPE_BUFFER(t1); WIPE_BUFFER(r);
+ WIPE_BUFFER(t2); WIPE_BUFFER(u);
+ WIPE_BUFFER(t3);
+}
+
+// Elligator inverse map
+//
+// Computes the representative of a point, if possible. If not, it does
+// nothing and returns -1. Note that the success of the operation
+// depends only on the point (more precisely its u coordinate). The
+// tweak parameter is used only upon success
+//
+// The tweak should be a random byte. Beyond that, its contents are an
+// implementation detail. Currently, the tweak comprises:
+// - Bit 1 : sign of the v coordinate (0 if positive, 1 if negative)
+// - Bit 2-5: not used
+// - Bits 6-7: random padding
+//
+// From the paper:
+// Let sq = -non_square * u * (u+A)
+// if sq is not a square, or u = -A, there is no mapping
+// Assuming there is a mapping:
+// if v is positive: r = sqrt(-u / (non_square * (u+A)))
+// if v is negative: r = sqrt(-(u+A) / (non_square * u ))
+//
+// We compute isr = invsqrt(-non_square * u * (u+A))
+// if it wasn't a square, abort.
+// else, isr = sqrt(-1 / (non_square * u * (u+A))
+//
+// If v is positive, we return isr * u:
+// isr * u = sqrt(-1 / (non_square * u * (u+A)) * u
+// isr * u = sqrt(-u / (non_square * (u+A))
+//
+// If v is negative, we return isr * (u+A):
+// isr * (u+A) = sqrt(-1 / (non_square * u * (u+A)) * (u+A)
+// isr * (u+A) = sqrt(-(u+A) / (non_square * u)
+int crypto_elligator_rev(u8 hidden[32], const u8 public_key[32], u8 tweak)
+{
+ fe t1, t2, t3;
+ fe_frombytes(t1, public_key); // t1 = u
+
+ fe_add(t2, t1, A); // t2 = u + A
+ fe_mul(t3, t1, t2);
+ fe_mul_small(t3, t3, -2);
+ int is_square = invsqrt(t3, t3); // t3 = sqrt(-1 / non_square * u * (u+A))
+ if (is_square) {
+ // The only variable time bit. This ultimately reveals how many
+ // tries it took us to find a representable key.
+ // This does not affect security as long as we try keys at random.
+
+ fe_ccopy (t1, t2, tweak & 1); // multiply by u if v is positive,
+ fe_mul (t3, t1, t3); // multiply by u+A otherwise
+ fe_mul_small(t1, t3, 2);
+ fe_neg (t2, t3);
+ fe_ccopy (t3, t2, fe_isodd(t1));
+ fe_tobytes(hidden, t3);
+
+ // Pad with two random bits
+ hidden[31] |= tweak & 0xc0;
+ }
+
+ WIPE_BUFFER(t1);
+ WIPE_BUFFER(t2);
+ WIPE_BUFFER(t3);
+ return is_square - 1;
+}
+
+void crypto_elligator_key_pair(u8 hidden[32], u8 secret_key[32], u8 seed[32])
+{
+ u8 pk [32]; // public key
+ u8 buf[64]; // seed + representative
+ COPY(buf + 32, seed, 32);
+ do {
+ crypto_chacha20_djb(buf, 0, 64, buf+32, zero, 0);
+ crypto_x25519_dirty_fast(pk, buf); // or the "small" version
+ } while(crypto_elligator_rev(buf+32, pk, buf[32]));
+ // Note that the return value of crypto_elligator_rev() is
+ // independent from its tweak parameter.
+ // Therefore, buf[32] is not actually reused. Either we loop one
+ // more time and buf[32] is used for the new seed, or we succeeded,
+ // and buf[32] becomes the tweak parameter.
+
+ crypto_wipe(seed, 32);
+ COPY(hidden , buf + 32, 32);
+ COPY(secret_key, buf , 32);
+ WIPE_BUFFER(buf);
+ WIPE_BUFFER(pk);
+}
+
+///////////////////////
+/// Scalar division ///
+///////////////////////
+
+// Montgomery reduction.
+// Divides x by (2^256), and reduces the result modulo L
+//
+// Precondition:
+// x < L * 2^256
+// Constants:
+// r = 2^256 (makes division by r trivial)
+// k = (r * (1/r) - 1) // L (1/r is computed modulo L )
+// Algorithm:
+// s = (x * k) % r
+// t = x + s*L (t is always a multiple of r)
+// u = (t/r) % L (u is always below 2*L, conditional subtraction is enough)
+static void redc(u32 u[8], u32 x[16])
+{
+ static const u32 k[8] = {
+ 0x12547e1b, 0xd2b51da3, 0xfdba84ff, 0xb1a206f2,
+ 0xffa36bea, 0x14e75438, 0x6fe91836, 0x9db6c6f2,
+ };
+
+ // s = x * k (modulo 2^256)
+ // This is cheaper than the full multiplication.
+ u32 s[8] = {0};
+ FOR (i, 0, 8) {
+ u64 carry = 0;
+ FOR (j, 0, 8-i) {
+ carry += s[i+j] + (u64)x[i] * k[j];
+ s[i+j] = (u32)carry;
+ carry >>= 32;
+ }
+ }
+ u32 t[16] = {0};
+ multiply(t, s, L);
+
+ // t = t + x
+ u64 carry = 0;
+ FOR (i, 0, 16) {
+ carry += (u64)t[i] + x[i];
+ t[i] = (u32)carry;
+ carry >>= 32;
+ }
+
+ // u = (t / 2^256) % L
+ // Note that t / 2^256 is always below 2*L,
+ // So a constant time conditional subtraction is enough
+ remove_l(u, t+8);
+
+ WIPE_BUFFER(s);
+ WIPE_BUFFER(t);
+}
+
+void crypto_x25519_inverse(u8 blind_salt [32], const u8 private_key[32],
+ const u8 curve_point[32])
+{
+ static const u8 Lm2[32] = { // L - 2
+ 0xeb, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58,
+ 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+ };
+ // 1 in Montgomery form
+ u32 m_inv [8] = {
+ 0x8d98951d, 0xd6ec3174, 0x737dcf70, 0xc6ef5bf4,
+ 0xfffffffe, 0xffffffff, 0xffffffff, 0x0fffffff,
+ };
+
+ u8 scalar[32];
+ crypto_eddsa_trim_scalar(scalar, private_key);
+
+ // Convert the scalar in Montgomery form
+ // m_scl = scalar * 2^256 (modulo L)
+ u32 m_scl[8];
+ {
+ u32 tmp[16];
+ ZERO(tmp, 8);
+ load32_le_buf(tmp+8, scalar, 8);
+ mod_l(scalar, tmp);
+ load32_le_buf(m_scl, scalar, 8);
+ WIPE_BUFFER(tmp); // Wipe ASAP to save stack space
+ }
+
+ // Compute the inverse
+ u32 product[16];
+ for (int i = 252; i >= 0; i--) {
+ ZERO(product, 16);
+ multiply(product, m_inv, m_inv);
+ redc(m_inv, product);
+ if (scalar_bit(Lm2, i)) {
+ ZERO(product, 16);
+ multiply(product, m_inv, m_scl);
+ redc(m_inv, product);
+ }
+ }
+ // Convert the inverse *out* of Montgomery form
+ // scalar = m_inv / 2^256 (modulo L)
+ COPY(product, m_inv, 8);
+ ZERO(product + 8, 8);
+ redc(m_inv, product);
+ store32_le_buf(scalar, m_inv, 8); // the *inverse* of the scalar
+
+ // Clear the cofactor of scalar:
+ // cleared = scalar * (3*L + 1) (modulo 8*L)
+ // cleared = scalar + scalar * 3 * L (modulo 8*L)
+ // Note that (scalar * 3) is reduced modulo 8, so we only need the
+ // first byte.
+ add_xl(scalar, scalar[0] * 3);
+
+ // Recall that 8*L < 2^256. However it is also very close to
+ // 2^255. If we spanned the ladder over 255 bits, random tests
+ // wouldn't catch the off-by-one error.
+ scalarmult(blind_salt, scalar, curve_point, 256);
+
+ WIPE_BUFFER(scalar); WIPE_BUFFER(m_scl);
+ WIPE_BUFFER(product); WIPE_BUFFER(m_inv);
+}
+
+////////////////////////////////
+/// Authenticated encryption ///
+////////////////////////////////
+static void lock_auth(u8 mac[16], const u8 auth_key[32],
+ const u8 *ad , size_t ad_size,
+ const u8 *cipher_text, size_t text_size)
+{
+ u8 sizes[16]; // Not secret, not wiped
+ store64_le(sizes + 0, ad_size);
+ store64_le(sizes + 8, text_size);
+ crypto_poly1305_ctx poly_ctx; // auto wiped...
+ crypto_poly1305_init (&poly_ctx, auth_key);
+ crypto_poly1305_update(&poly_ctx, ad , ad_size);
+ crypto_poly1305_update(&poly_ctx, zero , gap(ad_size, 16));
+ crypto_poly1305_update(&poly_ctx, cipher_text, text_size);
+ crypto_poly1305_update(&poly_ctx, zero , gap(text_size, 16));
+ crypto_poly1305_update(&poly_ctx, sizes , 16);
+ crypto_poly1305_final (&poly_ctx, mac); // ...here
+}
+
+void crypto_aead_init_x(crypto_aead_ctx *ctx,
+ u8 const key[32], const u8 nonce[24])
+{
+ crypto_chacha20_h(ctx->key, key, nonce);
+ COPY(ctx->nonce, nonce + 16, 8);
+ ctx->counter = 0;
+}
+
+void crypto_aead_init_djb(crypto_aead_ctx *ctx,
+ const u8 key[32], const u8 nonce[8])
+{
+ COPY(ctx->key , key , 32);
+ COPY(ctx->nonce, nonce, 8);
+ ctx->counter = 0;
+}
+
+void crypto_aead_init_ietf(crypto_aead_ctx *ctx,
+ const u8 key[32], const u8 nonce[12])
+{
+ COPY(ctx->key , key , 32);
+ COPY(ctx->nonce, nonce + 4, 8);
+ ctx->counter = (u64)load32_le(nonce) << 32;
+}
+
+void crypto_aead_write(crypto_aead_ctx *ctx, u8 *cipher_text, u8 mac[16],
+ const u8 *ad, size_t ad_size,
+ const u8 *plain_text, size_t text_size)
+{
+ u8 auth_key[64]; // the last 32 bytes are used for rekeying.
+ crypto_chacha20_djb(auth_key, 0, 64, ctx->key, ctx->nonce, ctx->counter);
+ crypto_chacha20_djb(cipher_text, plain_text, text_size,
+ ctx->key, ctx->nonce, ctx->counter + 1);
+ lock_auth(mac, auth_key, ad, ad_size, cipher_text, text_size);
+ COPY(ctx->key, auth_key + 32, 32);
+ WIPE_BUFFER(auth_key);
+}
+
+int crypto_aead_read(crypto_aead_ctx *ctx, u8 *plain_text, const u8 mac[16],
+ const u8 *ad, size_t ad_size,
+ const u8 *cipher_text, size_t text_size)
+{
+ u8 auth_key[64]; // the last 32 bytes are used for rekeying.
+ u8 real_mac[16];
+ crypto_chacha20_djb(auth_key, 0, 64, ctx->key, ctx->nonce, ctx->counter);
+ lock_auth(real_mac, auth_key, ad, ad_size, cipher_text, text_size);
+ int mismatch = crypto_verify16(mac, real_mac);
+ if (!mismatch) {
+ crypto_chacha20_djb(plain_text, cipher_text, text_size,
+ ctx->key, ctx->nonce, ctx->counter + 1);
+ COPY(ctx->key, auth_key + 32, 32);
+ }
+ WIPE_BUFFER(auth_key);
+ WIPE_BUFFER(real_mac);
+ return mismatch;
+}
+
+void crypto_aead_lock(u8 *cipher_text, u8 mac[16], const u8 key[32],
+ const u8 nonce[24], const u8 *ad, size_t ad_size,
+ const u8 *plain_text, size_t text_size)
+{
+ crypto_aead_ctx ctx;
+ crypto_aead_init_x(&ctx, key, nonce);
+ crypto_aead_write(&ctx, cipher_text, mac, ad, ad_size,
+ plain_text, text_size);
+ crypto_wipe(&ctx, sizeof(ctx));
+}
+
+int crypto_aead_unlock(u8 *plain_text, const u8 mac[16], const u8 key[32],
+ const u8 nonce[24], const u8 *ad, size_t ad_size,
+ const u8 *cipher_text, size_t text_size)
+{
+ crypto_aead_ctx ctx;
+ crypto_aead_init_x(&ctx, key, nonce);
+ int mismatch = crypto_aead_read(&ctx, plain_text, mac, ad, ad_size,
+ cipher_text, text_size);
+ crypto_wipe(&ctx, sizeof(ctx));
+ return mismatch;
+}
+
+#ifdef MONOCYPHER_CPP_NAMESPACE
+}
+#endif
diff --git a/lib/Utils.Cryptography/monocypher/vendor/src/monocypher.h b/lib/Utils.Cryptography/monocypher/vendor/src/monocypher.h
new file mode 100644
index 0000000..cf635e8
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/src/monocypher.h
@@ -0,0 +1,321 @@
+// Monocypher version __git__
+//
+// This file is dual-licensed. Choose whichever licence you want from
+// the two licences listed below.
+//
+// The first licence is a regular 2-clause BSD licence. The second licence
+// is the CC-0 from Creative Commons. It is intended to release Monocypher
+// to the public domain. The BSD licence serves as a fallback option.
+//
+// SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+//
+// ------------------------------------------------------------------------
+//
+// Copyright (c) 2017-2019, Loup Vaillant
+// All rights reserved.
+//
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// ------------------------------------------------------------------------
+//
+// Written in 2017-2019 by Loup Vaillant
+//
+// To the extent possible under law, the author(s) have dedicated all copyright
+// and related neighboring rights to this software to the public domain
+// worldwide. This software is distributed without any warranty.
+//
+// You should have received a copy of the CC0 Public Domain Dedication along
+// with this software. If not, see
+// <https://creativecommons.org/publicdomain/zero/1.0/>
+
+#ifndef MONOCYPHER_H
+#define MONOCYPHER_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+#ifdef MONOCYPHER_CPP_NAMESPACE
+namespace MONOCYPHER_CPP_NAMESPACE {
+#elif defined(__cplusplus)
+extern "C" {
+#endif
+
+// Constant time comparisons
+// -------------------------
+
+// Return 0 if a and b are equal, -1 otherwise
+int crypto_verify16(const uint8_t a[16], const uint8_t b[16]);
+int crypto_verify32(const uint8_t a[32], const uint8_t b[32]);
+int crypto_verify64(const uint8_t a[64], const uint8_t b[64]);
+
+
+// Erase sensitive data
+// --------------------
+void crypto_wipe(void *secret, size_t size);
+
+
+// Authenticated encryption
+// ------------------------
+void crypto_aead_lock(uint8_t *cipher_text,
+ uint8_t mac [16],
+ const uint8_t key [32],
+ const uint8_t nonce[24],
+ const uint8_t *ad, size_t ad_size,
+ const uint8_t *plain_text, size_t text_size);
+int crypto_aead_unlock(uint8_t *plain_text,
+ const uint8_t mac [16],
+ const uint8_t key [32],
+ const uint8_t nonce[24],
+ const uint8_t *ad, size_t ad_size,
+ const uint8_t *cipher_text, size_t text_size);
+
+// Authenticated stream
+// --------------------
+typedef struct {
+ uint64_t counter;
+ uint8_t key[32];
+ uint8_t nonce[8];
+} crypto_aead_ctx;
+
+void crypto_aead_init_x(crypto_aead_ctx *ctx,
+ const uint8_t key[32], const uint8_t nonce[24]);
+void crypto_aead_init_djb(crypto_aead_ctx *ctx,
+ const uint8_t key[32], const uint8_t nonce[8]);
+void crypto_aead_init_ietf(crypto_aead_ctx *ctx,
+ const uint8_t key[32], const uint8_t nonce[12]);
+
+void crypto_aead_write(crypto_aead_ctx *ctx,
+ uint8_t *cipher_text,
+ uint8_t mac[16],
+ const uint8_t *ad , size_t ad_size,
+ const uint8_t *plain_text, size_t text_size);
+int crypto_aead_read(crypto_aead_ctx *ctx,
+ uint8_t *plain_text,
+ const uint8_t mac[16],
+ const uint8_t *ad , size_t ad_size,
+ const uint8_t *cipher_text, size_t text_size);
+
+
+// General purpose hash (BLAKE2b)
+// ------------------------------
+
+// Direct interface
+void crypto_blake2b(uint8_t *hash, size_t hash_size,
+ const uint8_t *message, size_t message_size);
+
+void crypto_blake2b_keyed(uint8_t *hash, size_t hash_size,
+ const uint8_t *key, size_t key_size,
+ const uint8_t *message, size_t message_size);
+
+// Incremental interface
+typedef struct {
+ // Do not rely on the size or contents of this type,
+ // for they may change without notice.
+ uint64_t hash[8];
+ uint64_t input_offset[2];
+ uint64_t input[16];
+ size_t input_idx;
+ size_t hash_size;
+} crypto_blake2b_ctx;
+
+void crypto_blake2b_init(crypto_blake2b_ctx *ctx, size_t hash_size);
+void crypto_blake2b_keyed_init(crypto_blake2b_ctx *ctx, size_t hash_size,
+ const uint8_t *key, size_t key_size);
+void crypto_blake2b_update(crypto_blake2b_ctx *ctx,
+ const uint8_t *message, size_t message_size);
+void crypto_blake2b_final(crypto_blake2b_ctx *ctx, uint8_t *hash);
+
+
+// Password key derivation (Argon2)
+// --------------------------------
+#define CRYPTO_ARGON2_D 0
+#define CRYPTO_ARGON2_I 1
+#define CRYPTO_ARGON2_ID 2
+
+typedef struct {
+ uint32_t algorithm; // Argon2d, Argon2i, Argon2id
+ uint32_t nb_blocks; // memory hardness, >= 8 * nb_lanes
+ uint32_t nb_passes; // CPU hardness, >= 1 (>= 3 recommended for Argon2i)
+ uint32_t nb_lanes; // parallelism level (single threaded anyway)
+} crypto_argon2_config;
+
+typedef struct {
+ const uint8_t *pass;
+ const uint8_t *salt;
+ uint32_t pass_size;
+ uint32_t salt_size; // 16 bytes recommended
+} crypto_argon2_inputs;
+
+typedef struct {
+ const uint8_t *key; // may be NULL if no key
+ const uint8_t *ad; // may be NULL if no additional data
+ uint32_t key_size; // 0 if no key (32 bytes recommended otherwise)
+ uint32_t ad_size; // 0 if no additional data
+} crypto_argon2_extras;
+
+extern const crypto_argon2_extras crypto_argon2_no_extras;
+
+void crypto_argon2(uint8_t *hash, uint32_t hash_size, void *work_area,
+ crypto_argon2_config config,
+ crypto_argon2_inputs inputs,
+ crypto_argon2_extras extras);
+
+
+// Key exchange (X-25519)
+// ----------------------
+
+// Shared secrets are not quite random.
+// Hash them to derive an actual shared key.
+void crypto_x25519_public_key(uint8_t public_key[32],
+ const uint8_t secret_key[32]);
+void crypto_x25519(uint8_t raw_shared_secret[32],
+ const uint8_t your_secret_key [32],
+ const uint8_t their_public_key [32]);
+
+// Conversion to EdDSA
+void crypto_x25519_to_eddsa(uint8_t eddsa[32], const uint8_t x25519[32]);
+
+// scalar "division"
+// Used for OPRF. Be aware that exponential blinding is less secure
+// than Diffie-Hellman key exchange.
+void crypto_x25519_inverse(uint8_t blind_salt [32],
+ const uint8_t private_key[32],
+ const uint8_t curve_point[32]);
+
+// "Dirty" versions of x25519_public_key().
+// Use with crypto_elligator_rev().
+// Leaks 3 bits of the private key.
+void crypto_x25519_dirty_small(uint8_t pk[32], const uint8_t sk[32]);
+void crypto_x25519_dirty_fast (uint8_t pk[32], const uint8_t sk[32]);
+
+
+// Signatures
+// ----------
+
+// EdDSA with curve25519 + BLAKE2b
+void crypto_eddsa_key_pair(uint8_t secret_key[64],
+ uint8_t public_key[32],
+ uint8_t seed[32]);
+void crypto_eddsa_sign(uint8_t signature [64],
+ const uint8_t secret_key[64],
+ const uint8_t *message, size_t message_size);
+int crypto_eddsa_check(const uint8_t signature [64],
+ const uint8_t public_key[32],
+ const uint8_t *message, size_t message_size);
+
+// Conversion to X25519
+void crypto_eddsa_to_x25519(uint8_t x25519[32], const uint8_t eddsa[32]);
+
+// EdDSA building blocks
+void crypto_eddsa_trim_scalar(uint8_t out[32], const uint8_t in[32]);
+void crypto_eddsa_reduce(uint8_t reduced[32], const uint8_t expanded[64]);
+void crypto_eddsa_mul_add(uint8_t r[32],
+ const uint8_t a[32],
+ const uint8_t b[32],
+ const uint8_t c[32]);
+void crypto_eddsa_scalarbase(uint8_t point[32], const uint8_t scalar[32]);
+int crypto_eddsa_check_equation(const uint8_t signature[64],
+ const uint8_t public_key[32],
+ const uint8_t h_ram[32]);
+
+
+// Chacha20
+// --------
+
+// Specialised hash.
+// Used to hash X25519 shared secrets.
+void crypto_chacha20_h(uint8_t out[32],
+ const uint8_t key[32],
+ const uint8_t in [16]);
+
+// Unauthenticated stream cipher.
+// Don't forget to add authentication.
+uint64_t crypto_chacha20_djb(uint8_t *cipher_text,
+ const uint8_t *plain_text,
+ size_t text_size,
+ const uint8_t key[32],
+ const uint8_t nonce[8],
+ uint64_t ctr);
+uint32_t crypto_chacha20_ietf(uint8_t *cipher_text,
+ const uint8_t *plain_text,
+ size_t text_size,
+ const uint8_t key[32],
+ const uint8_t nonce[12],
+ uint32_t ctr);
+uint64_t crypto_chacha20_x(uint8_t *cipher_text,
+ const uint8_t *plain_text,
+ size_t text_size,
+ const uint8_t key[32],
+ const uint8_t nonce[24],
+ uint64_t ctr);
+
+
+// Poly 1305
+// ---------
+
+// This is a *one time* authenticator.
+// Disclosing the mac reveals the key.
+// See crypto_lock() on how to use it properly.
+
+// Direct interface
+void crypto_poly1305(uint8_t mac[16],
+ const uint8_t *message, size_t message_size,
+ const uint8_t key[32]);
+
+// Incremental interface
+typedef struct {
+ // Do not rely on the size or contents of this type,
+ // for they may change without notice.
+ uint8_t c[16]; // chunk of the message
+ size_t c_idx; // How many bytes are there in the chunk.
+ uint32_t r [4]; // constant multiplier (from the secret key)
+ uint32_t pad[4]; // random number added at the end (from the secret key)
+ uint32_t h [5]; // accumulated hash
+} crypto_poly1305_ctx;
+
+void crypto_poly1305_init (crypto_poly1305_ctx *ctx, const uint8_t key[32]);
+void crypto_poly1305_update(crypto_poly1305_ctx *ctx,
+ const uint8_t *message, size_t message_size);
+void crypto_poly1305_final (crypto_poly1305_ctx *ctx, uint8_t mac[16]);
+
+
+// Elligator 2
+// -----------
+
+// Elligator mappings proper
+void crypto_elligator_map(uint8_t curve [32], const uint8_t hidden[32]);
+int crypto_elligator_rev(uint8_t hidden[32], const uint8_t curve [32],
+ uint8_t tweak);
+
+// Easy to use key pair generation
+void crypto_elligator_key_pair(uint8_t hidden[32], uint8_t secret_key[32],
+ uint8_t seed[32]);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // MONOCYPHER_H
diff --git a/lib/Utils.Cryptography/monocypher/vendor/src/optional/monocypher-ed25519.c b/lib/Utils.Cryptography/monocypher/vendor/src/optional/monocypher-ed25519.c
new file mode 100644
index 0000000..5e4dcdf
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/src/optional/monocypher-ed25519.c
@@ -0,0 +1,500 @@
+// Monocypher version __git__
+//
+// This file is dual-licensed. Choose whichever licence you want from
+// the two licences listed below.
+//
+// The first licence is a regular 2-clause BSD licence. The second licence
+// is the CC-0 from Creative Commons. It is intended to release Monocypher
+// to the public domain. The BSD licence serves as a fallback option.
+//
+// SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+//
+// ------------------------------------------------------------------------
+//
+// Copyright (c) 2017-2019, Loup Vaillant
+// All rights reserved.
+//
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// ------------------------------------------------------------------------
+//
+// Written in 2017-2019 by Loup Vaillant
+//
+// To the extent possible under law, the author(s) have dedicated all copyright
+// and related neighboring rights to this software to the public domain
+// worldwide. This software is distributed without any warranty.
+//
+// You should have received a copy of the CC0 Public Domain Dedication along
+// with this software. If not, see
+// <https://creativecommons.org/publicdomain/zero/1.0/>
+
+#include "monocypher-ed25519.h"
+
+#ifdef MONOCYPHER_CPP_NAMESPACE
+namespace MONOCYPHER_CPP_NAMESPACE {
+#endif
+
+/////////////////
+/// Utilities ///
+/////////////////
+#define FOR(i, min, max) for (size_t i = min; i < max; i++)
+#define COPY(dst, src, size) FOR(_i_, 0, size) (dst)[_i_] = (src)[_i_]
+#define ZERO(buf, size) FOR(_i_, 0, size) (buf)[_i_] = 0
+#define WIPE_CTX(ctx) crypto_wipe(ctx , sizeof(*(ctx)))
+#define WIPE_BUFFER(buffer) crypto_wipe(buffer, sizeof(buffer))
+#define MIN(a, b) ((a) <= (b) ? (a) : (b))
+typedef uint8_t u8;
+typedef uint64_t u64;
+
+// Returns the smallest positive integer y such that
+// (x + y) % pow_2 == 0
+// Basically, it's how many bytes we need to add to "align" x.
+// Only works when pow_2 is a power of 2.
+// Note: we use ~x+1 instead of -x to avoid compiler warnings
+static size_t align(size_t x, size_t pow_2)
+{
+ return (~x + 1) & (pow_2 - 1);
+}
+
+static u64 load64_be(const u8 s[8])
+{
+ return((u64)s[0] << 56)
+ | ((u64)s[1] << 48)
+ | ((u64)s[2] << 40)
+ | ((u64)s[3] << 32)
+ | ((u64)s[4] << 24)
+ | ((u64)s[5] << 16)
+ | ((u64)s[6] << 8)
+ | (u64)s[7];
+}
+
+static void store64_be(u8 out[8], u64 in)
+{
+ out[0] = (in >> 56) & 0xff;
+ out[1] = (in >> 48) & 0xff;
+ out[2] = (in >> 40) & 0xff;
+ out[3] = (in >> 32) & 0xff;
+ out[4] = (in >> 24) & 0xff;
+ out[5] = (in >> 16) & 0xff;
+ out[6] = (in >> 8) & 0xff;
+ out[7] = in & 0xff;
+}
+
+static void load64_be_buf (u64 *dst, const u8 *src, size_t size) {
+ FOR(i, 0, size) { dst[i] = load64_be(src + i*8); }
+}
+
+///////////////
+/// SHA 512 ///
+///////////////
+static u64 rot(u64 x, int c ) { return (x >> c) | (x << (64 - c)); }
+static u64 ch (u64 x, u64 y, u64 z) { return (x & y) ^ (~x & z); }
+static u64 maj(u64 x, u64 y, u64 z) { return (x & y) ^ ( x & z) ^ (y & z); }
+static u64 big_sigma0(u64 x) { return rot(x, 28) ^ rot(x, 34) ^ rot(x, 39); }
+static u64 big_sigma1(u64 x) { return rot(x, 14) ^ rot(x, 18) ^ rot(x, 41); }
+static u64 lit_sigma0(u64 x) { return rot(x, 1) ^ rot(x, 8) ^ (x >> 7); }
+static u64 lit_sigma1(u64 x) { return rot(x, 19) ^ rot(x, 61) ^ (x >> 6); }
+
+static const u64 K[80] = {
+ 0x428a2f98d728ae22,0x7137449123ef65cd,0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc,
+ 0x3956c25bf348b538,0x59f111f1b605d019,0x923f82a4af194f9b,0xab1c5ed5da6d8118,
+ 0xd807aa98a3030242,0x12835b0145706fbe,0x243185be4ee4b28c,0x550c7dc3d5ffb4e2,
+ 0x72be5d74f27b896f,0x80deb1fe3b1696b1,0x9bdc06a725c71235,0xc19bf174cf692694,
+ 0xe49b69c19ef14ad2,0xefbe4786384f25e3,0x0fc19dc68b8cd5b5,0x240ca1cc77ac9c65,
+ 0x2de92c6f592b0275,0x4a7484aa6ea6e483,0x5cb0a9dcbd41fbd4,0x76f988da831153b5,
+ 0x983e5152ee66dfab,0xa831c66d2db43210,0xb00327c898fb213f,0xbf597fc7beef0ee4,
+ 0xc6e00bf33da88fc2,0xd5a79147930aa725,0x06ca6351e003826f,0x142929670a0e6e70,
+ 0x27b70a8546d22ffc,0x2e1b21385c26c926,0x4d2c6dfc5ac42aed,0x53380d139d95b3df,
+ 0x650a73548baf63de,0x766a0abb3c77b2a8,0x81c2c92e47edaee6,0x92722c851482353b,
+ 0xa2bfe8a14cf10364,0xa81a664bbc423001,0xc24b8b70d0f89791,0xc76c51a30654be30,
+ 0xd192e819d6ef5218,0xd69906245565a910,0xf40e35855771202a,0x106aa07032bbd1b8,
+ 0x19a4c116b8d2d0c8,0x1e376c085141ab53,0x2748774cdf8eeb99,0x34b0bcb5e19b48a8,
+ 0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb,0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3,
+ 0x748f82ee5defb2fc,0x78a5636f43172f60,0x84c87814a1f0ab72,0x8cc702081a6439ec,
+ 0x90befffa23631e28,0xa4506cebde82bde9,0xbef9a3f7b2c67915,0xc67178f2e372532b,
+ 0xca273eceea26619c,0xd186b8c721c0c207,0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178,
+ 0x06f067aa72176fba,0x0a637dc5a2c898a6,0x113f9804bef90dae,0x1b710b35131c471b,
+ 0x28db77f523047d84,0x32caab7b40c72493,0x3c9ebe0a15c9bebc,0x431d67c49c100d4c,
+ 0x4cc5d4becb3e42b6,0x597f299cfc657e2a,0x5fcb6fab3ad6faec,0x6c44198c4a475817
+};
+
+static void sha512_compress(crypto_sha512_ctx *ctx)
+{
+ u64 a = ctx->hash[0]; u64 b = ctx->hash[1];
+ u64 c = ctx->hash[2]; u64 d = ctx->hash[3];
+ u64 e = ctx->hash[4]; u64 f = ctx->hash[5];
+ u64 g = ctx->hash[6]; u64 h = ctx->hash[7];
+
+ FOR (j, 0, 16) {
+ u64 in = K[j] + ctx->input[j];
+ u64 t1 = big_sigma1(e) + ch (e, f, g) + h + in;
+ u64 t2 = big_sigma0(a) + maj(a, b, c);
+ h = g; g = f; f = e; e = d + t1;
+ d = c; c = b; b = a; a = t1 + t2;
+ }
+ size_t i16 = 0;
+ FOR(i, 1, 5) {
+ i16 += 16;
+ FOR (j, 0, 16) {
+ ctx->input[j] += lit_sigma1(ctx->input[(j- 2) & 15]);
+ ctx->input[j] += lit_sigma0(ctx->input[(j-15) & 15]);
+ ctx->input[j] += ctx->input[(j- 7) & 15];
+ u64 in = K[i16 + j] + ctx->input[j];
+ u64 t1 = big_sigma1(e) + ch (e, f, g) + h + in;
+ u64 t2 = big_sigma0(a) + maj(a, b, c);
+ h = g; g = f; f = e; e = d + t1;
+ d = c; c = b; b = a; a = t1 + t2;
+ }
+ }
+
+ ctx->hash[0] += a; ctx->hash[1] += b;
+ ctx->hash[2] += c; ctx->hash[3] += d;
+ ctx->hash[4] += e; ctx->hash[5] += f;
+ ctx->hash[6] += g; ctx->hash[7] += h;
+}
+
+// Write 1 input byte
+static void sha512_set_input(crypto_sha512_ctx *ctx, u8 input)
+{
+ size_t word = ctx->input_idx >> 3;
+ size_t byte = ctx->input_idx & 7;
+ ctx->input[word] |= (u64)input << (8 * (7 - byte));
+}
+
+// Increment a 128-bit "word".
+static void sha512_incr(u64 x[2], u64 y)
+{
+ x[1] += y;
+ if (x[1] < y) {
+ x[0]++;
+ }
+}
+
+void crypto_sha512_init(crypto_sha512_ctx *ctx)
+{
+ ctx->hash[0] = 0x6a09e667f3bcc908;
+ ctx->hash[1] = 0xbb67ae8584caa73b;
+ ctx->hash[2] = 0x3c6ef372fe94f82b;
+ ctx->hash[3] = 0xa54ff53a5f1d36f1;
+ ctx->hash[4] = 0x510e527fade682d1;
+ ctx->hash[5] = 0x9b05688c2b3e6c1f;
+ ctx->hash[6] = 0x1f83d9abfb41bd6b;
+ ctx->hash[7] = 0x5be0cd19137e2179;
+ ctx->input_size[0] = 0;
+ ctx->input_size[1] = 0;
+ ctx->input_idx = 0;
+ ZERO(ctx->input, 16);
+}
+
+void crypto_sha512_update(crypto_sha512_ctx *ctx,
+ const u8 *message, size_t message_size)
+{
+ // Avoid undefined NULL pointer increments with empty messages
+ if (message_size == 0) {
+ return;
+ }
+
+ // Align ourselves with word boundaries
+ if ((ctx->input_idx & 7) != 0) {
+ size_t nb_bytes = MIN(align(ctx->input_idx, 8), message_size);
+ FOR (i, 0, nb_bytes) {
+ sha512_set_input(ctx, message[i]);
+ ctx->input_idx++;
+ }
+ message += nb_bytes;
+ message_size -= nb_bytes;
+ }
+
+ // Align ourselves with block boundaries
+ if ((ctx->input_idx & 127) != 0) {
+ size_t nb_words = MIN(align(ctx->input_idx, 128), message_size) >> 3;
+ load64_be_buf(ctx->input + (ctx->input_idx >> 3), message, nb_words);
+ ctx->input_idx += nb_words << 3;
+ message += nb_words << 3;
+ message_size -= nb_words << 3;
+ }
+
+ // Compress block if needed
+ if (ctx->input_idx == 128) {
+ sha512_incr(ctx->input_size, 1024); // size is in bits
+ sha512_compress(ctx);
+ ctx->input_idx = 0;
+ ZERO(ctx->input, 16);
+ }
+
+ // Process the message block by block
+ FOR (i, 0, message_size >> 7) { // number of blocks
+ load64_be_buf(ctx->input, message, 16);
+ sha512_incr(ctx->input_size, 1024); // size is in bits
+ sha512_compress(ctx);
+ ctx->input_idx = 0;
+ ZERO(ctx->input, 16);
+ message += 128;
+ }
+ message_size &= 127;
+
+ if (message_size != 0) {
+ // Remaining words
+ size_t nb_words = message_size >> 3;
+ load64_be_buf(ctx->input, message, nb_words);
+ ctx->input_idx += nb_words << 3;
+ message += nb_words << 3;
+ message_size -= nb_words << 3;
+
+ // Remaining bytes
+ FOR (i, 0, message_size) {
+ sha512_set_input(ctx, message[i]);
+ ctx->input_idx++;
+ }
+ }
+}
+
+void crypto_sha512_final(crypto_sha512_ctx *ctx, u8 hash[64])
+{
+ // Add padding bit
+ if (ctx->input_idx == 0) {
+ ZERO(ctx->input, 16);
+ }
+ sha512_set_input(ctx, 128);
+
+ // Update size
+ sha512_incr(ctx->input_size, ctx->input_idx * 8);
+
+ // Compress penultimate block (if any)
+ if (ctx->input_idx > 111) {
+ sha512_compress(ctx);
+ ZERO(ctx->input, 14);
+ }
+ // Compress last block
+ ctx->input[14] = ctx->input_size[0];
+ ctx->input[15] = ctx->input_size[1];
+ sha512_compress(ctx);
+
+ // Copy hash to output (big endian)
+ FOR (i, 0, 8) {
+ store64_be(hash + i*8, ctx->hash[i]);
+ }
+
+ WIPE_CTX(ctx);
+}
+
+void crypto_sha512(u8 hash[64], const u8 *message, size_t message_size)
+{
+ crypto_sha512_ctx ctx;
+ crypto_sha512_init (&ctx);
+ crypto_sha512_update(&ctx, message, message_size);
+ crypto_sha512_final (&ctx, hash);
+}
+
+////////////////////
+/// HMAC SHA 512 ///
+////////////////////
+void crypto_sha512_hmac_init(crypto_sha512_hmac_ctx *ctx,
+ const u8 *key, size_t key_size)
+{
+ // hash key if it is too long
+ if (key_size > 128) {
+ crypto_sha512(ctx->key, key, key_size);
+ key = ctx->key;
+ key_size = 64;
+ }
+ // Compute inner key: padded key XOR 0x36
+ FOR (i, 0, key_size) { ctx->key[i] = key[i] ^ 0x36; }
+ FOR (i, key_size, 128) { ctx->key[i] = 0x36; }
+ // Start computing inner hash
+ crypto_sha512_init (&ctx->ctx);
+ crypto_sha512_update(&ctx->ctx, ctx->key, 128);
+}
+
+void crypto_sha512_hmac_update(crypto_sha512_hmac_ctx *ctx,
+ const u8 *message, size_t message_size)
+{
+ crypto_sha512_update(&ctx->ctx, message, message_size);
+}
+
+void crypto_sha512_hmac_final(crypto_sha512_hmac_ctx *ctx, u8 hmac[64])
+{
+ // Finish computing inner hash
+ crypto_sha512_final(&ctx->ctx, hmac);
+ // Compute outer key: padded key XOR 0x5c
+ FOR (i, 0, 128) {
+ ctx->key[i] ^= 0x36 ^ 0x5c;
+ }
+ // Compute outer hash
+ crypto_sha512_init (&ctx->ctx);
+ crypto_sha512_update(&ctx->ctx, ctx->key , 128);
+ crypto_sha512_update(&ctx->ctx, hmac, 64);
+ crypto_sha512_final (&ctx->ctx, hmac); // outer hash
+ WIPE_CTX(ctx);
+}
+
+void crypto_sha512_hmac(u8 hmac[64], const u8 *key, size_t key_size,
+ const u8 *message, size_t message_size)
+{
+ crypto_sha512_hmac_ctx ctx;
+ crypto_sha512_hmac_init (&ctx, key, key_size);
+ crypto_sha512_hmac_update(&ctx, message, message_size);
+ crypto_sha512_hmac_final (&ctx, hmac);
+}
+
+////////////////////
+/// HKDF SHA 512 ///
+////////////////////
+void crypto_sha512_hkdf_expand(u8 *okm, size_t okm_size,
+ const u8 *prk, size_t prk_size,
+ const u8 *info, size_t info_size)
+{
+ int not_first = 0;
+ u8 ctr = 1;
+ u8 blk[64];
+
+ while (okm_size > 0) {
+ size_t out_size = MIN(okm_size, sizeof(blk));
+
+ crypto_sha512_hmac_ctx ctx;
+ crypto_sha512_hmac_init(&ctx, prk , prk_size);
+ if (not_first) {
+ // For some reason HKDF uses some kind of CBC mode.
+ // For some reason CTR mode alone wasn't enough.
+ // Like what, they didn't trust HMAC in 2010? Really??
+ crypto_sha512_hmac_update(&ctx, blk , sizeof(blk));
+ }
+ crypto_sha512_hmac_update(&ctx, info, info_size);
+ crypto_sha512_hmac_update(&ctx, &ctr, 1);
+ crypto_sha512_hmac_final(&ctx, blk);
+
+ COPY(okm, blk, out_size);
+
+ not_first = 1;
+ okm += out_size;
+ okm_size -= out_size;
+ ctr++;
+ }
+}
+
+void crypto_sha512_hkdf(u8 *okm , size_t okm_size,
+ const u8 *ikm , size_t ikm_size,
+ const u8 *salt, size_t salt_size,
+ const u8 *info, size_t info_size)
+{
+ // Extract
+ u8 prk[64];
+ crypto_sha512_hmac(prk, salt, salt_size, ikm, ikm_size);
+
+ // Expand
+ crypto_sha512_hkdf_expand(okm, okm_size, prk, sizeof(prk), info, info_size);
+}
+
+///////////////
+/// Ed25519 ///
+///////////////
+void crypto_ed25519_key_pair(u8 secret_key[64], u8 public_key[32], u8 seed[32])
+{
+ u8 a[64];
+ COPY(a, seed, 32); // a[ 0..31] = seed
+ crypto_wipe(seed, 32);
+ COPY(secret_key, a, 32); // secret key = seed
+ crypto_sha512(a, a, 32); // a[ 0..31] = scalar
+ crypto_eddsa_trim_scalar(a, a); // a[ 0..31] = trimmed scalar
+ crypto_eddsa_scalarbase(public_key, a); // public key = [trimmed scalar]B
+ COPY(secret_key + 32, public_key, 32); // secret key includes public half
+ WIPE_BUFFER(a);
+}
+
+static void hash_reduce(u8 h[32],
+ const u8 *a, size_t a_size,
+ const u8 *b, size_t b_size,
+ const u8 *c, size_t c_size,
+ const u8 *d, size_t d_size)
+{
+ u8 hash[64];
+ crypto_sha512_ctx ctx;
+ crypto_sha512_init (&ctx);
+ crypto_sha512_update(&ctx, a, a_size);
+ crypto_sha512_update(&ctx, b, b_size);
+ crypto_sha512_update(&ctx, c, c_size);
+ crypto_sha512_update(&ctx, d, d_size);
+ crypto_sha512_final (&ctx, hash);
+ crypto_eddsa_reduce(h, hash);
+}
+
+static void ed25519_dom_sign(u8 signature [64], const u8 secret_key[32],
+ const u8 *dom, size_t dom_size,
+ const u8 *message, size_t message_size)
+{
+ u8 a[64]; // secret scalar and prefix
+ u8 r[32]; // secret deterministic "random" nonce
+ u8 h[32]; // publically verifiable hash of the message (not wiped)
+ u8 R[32]; // first half of the signature (allows overlapping inputs)
+ const u8 *pk = secret_key + 32;
+
+ crypto_sha512(a, secret_key, 32);
+ crypto_eddsa_trim_scalar(a, a);
+ hash_reduce(r, dom, dom_size, a + 32, 32, message, message_size, 0, 0);
+ crypto_eddsa_scalarbase(R, r);
+ hash_reduce(h, dom, dom_size, R, 32, pk, 32, message, message_size);
+ COPY(signature, R, 32);
+ crypto_eddsa_mul_add(signature + 32, h, a, r);
+
+ WIPE_BUFFER(a);
+ WIPE_BUFFER(r);
+}
+
+void crypto_ed25519_sign(u8 signature [64], const u8 secret_key[64],
+ const u8 *message, size_t message_size)
+{
+ ed25519_dom_sign(signature, secret_key, 0, 0, message, message_size);
+}
+
+int crypto_ed25519_check(const u8 signature[64], const u8 public_key[32],
+ const u8 *msg, size_t msg_size)
+{
+ u8 h_ram[32];
+ hash_reduce(h_ram, signature, 32, public_key, 32, msg, msg_size, 0, 0);
+ return crypto_eddsa_check_equation(signature, public_key, h_ram);
+}
+
+static const u8 domain[34] = "SigEd25519 no Ed25519 collisions\1";
+
+void crypto_ed25519_ph_sign(uint8_t signature[64], const uint8_t secret_key[64],
+ const uint8_t message_hash[64])
+{
+ ed25519_dom_sign(signature, secret_key, domain, sizeof(domain),
+ message_hash, 64);
+}
+
+int crypto_ed25519_ph_check(const uint8_t sig[64], const uint8_t pk[32],
+ const uint8_t msg_hash[64])
+{
+ u8 h_ram[32];
+ hash_reduce(h_ram, domain, sizeof(domain), sig, 32, pk, 32, msg_hash, 64);
+ return crypto_eddsa_check_equation(sig, pk, h_ram);
+}
+
+
+#ifdef MONOCYPHER_CPP_NAMESPACE
+}
+#endif
diff --git a/lib/Utils.Cryptography/monocypher/vendor/src/optional/monocypher-ed25519.h b/lib/Utils.Cryptography/monocypher/vendor/src/optional/monocypher-ed25519.h
new file mode 100644
index 0000000..d7aa004
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/src/optional/monocypher-ed25519.h
@@ -0,0 +1,140 @@
+// Monocypher version __git__
+//
+// This file is dual-licensed. Choose whichever licence you want from
+// the two licences listed below.
+//
+// The first licence is a regular 2-clause BSD licence. The second licence
+// is the CC-0 from Creative Commons. It is intended to release Monocypher
+// to the public domain. The BSD licence serves as a fallback option.
+//
+// SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+//
+// ------------------------------------------------------------------------
+//
+// Copyright (c) 2017-2019, Loup Vaillant
+// All rights reserved.
+//
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// ------------------------------------------------------------------------
+//
+// Written in 2017-2019 by Loup Vaillant
+//
+// To the extent possible under law, the author(s) have dedicated all copyright
+// and related neighboring rights to this software to the public domain
+// worldwide. This software is distributed without any warranty.
+//
+// You should have received a copy of the CC0 Public Domain Dedication along
+// with this software. If not, see
+// <https://creativecommons.org/publicdomain/zero/1.0/>
+
+#ifndef ED25519_H
+#define ED25519_H
+
+#include "monocypher.h"
+
+#ifdef MONOCYPHER_CPP_NAMESPACE
+namespace MONOCYPHER_CPP_NAMESPACE {
+#elif defined(__cplusplus)
+extern "C" {
+#endif
+
+////////////////////////
+/// Type definitions ///
+////////////////////////
+
+// Do not rely on the size or content on any of those types,
+// they may change without notice.
+typedef struct {
+ uint64_t hash[8];
+ uint64_t input[16];
+ uint64_t input_size[2];
+ size_t input_idx;
+} crypto_sha512_ctx;
+
+typedef struct {
+ uint8_t key[128];
+ crypto_sha512_ctx ctx;
+} crypto_sha512_hmac_ctx;
+
+
+// SHA 512
+// -------
+void crypto_sha512_init (crypto_sha512_ctx *ctx);
+void crypto_sha512_update(crypto_sha512_ctx *ctx,
+ const uint8_t *message, size_t message_size);
+void crypto_sha512_final (crypto_sha512_ctx *ctx, uint8_t hash[64]);
+void crypto_sha512(uint8_t hash[64],
+ const uint8_t *message, size_t message_size);
+
+// SHA 512 HMAC
+// ------------
+void crypto_sha512_hmac_init(crypto_sha512_hmac_ctx *ctx,
+ const uint8_t *key, size_t key_size);
+void crypto_sha512_hmac_update(crypto_sha512_hmac_ctx *ctx,
+ const uint8_t *message, size_t message_size);
+void crypto_sha512_hmac_final(crypto_sha512_hmac_ctx *ctx, uint8_t hmac[64]);
+void crypto_sha512_hmac(uint8_t hmac[64],
+ const uint8_t *key , size_t key_size,
+ const uint8_t *message, size_t message_size);
+
+// SHA 512 HKDF
+// ------------
+void crypto_sha512_hkdf_expand(uint8_t *okm, size_t okm_size,
+ const uint8_t *prk, size_t prk_size,
+ const uint8_t *info, size_t info_size);
+void crypto_sha512_hkdf(uint8_t *okm , size_t okm_size,
+ const uint8_t *ikm , size_t ikm_size,
+ const uint8_t *salt, size_t salt_size,
+ const uint8_t *info, size_t info_size);
+
+// Ed25519
+// -------
+// Signatures (EdDSA with curve25519 + SHA-512)
+// --------------------------------------------
+void crypto_ed25519_key_pair(uint8_t secret_key[64],
+ uint8_t public_key[32],
+ uint8_t seed[32]);
+void crypto_ed25519_sign(uint8_t signature [64],
+ const uint8_t secret_key[64],
+ const uint8_t *message, size_t message_size);
+int crypto_ed25519_check(const uint8_t signature [64],
+ const uint8_t public_key[32],
+ const uint8_t *message, size_t message_size);
+
+// Pre-hash variants
+void crypto_ed25519_ph_sign(uint8_t signature [64],
+ const uint8_t secret_key [64],
+ const uint8_t message_hash[64]);
+int crypto_ed25519_ph_check(const uint8_t signature [64],
+ const uint8_t public_key [32],
+ const uint8_t message_hash[64]);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // ED25519_H
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/coverage.sh b/lib/Utils.Cryptography/monocypher/vendor/tests/coverage.sh
new file mode 100644
index 0000000..dd872a9
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/coverage.sh
@@ -0,0 +1,59 @@
+#! /bin/sh
+
+# This file is dual-licensed. Choose whichever licence you want from
+# the two licences listed below.
+#
+# The first licence is a regular 2-clause BSD licence. The second licence
+# is the CC-0 from Creative Commons. It is intended to release Monocypher
+# to the public domain. The BSD licence serves as a fallback option.
+#
+# SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+#
+# ------------------------------------------------------------------------
+#
+# Copyright (c) 2017-2019, Loup Vaillant
+# All rights reserved.
+#
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# ------------------------------------------------------------------------
+#
+# Written in 2017-2019 by Loup Vaillant
+#
+# To the extent possible under law, the author(s) have dedicated all copyright
+# and related neighboring rights to this software to the public domain
+# worldwide. This software is distributed without any warranty.
+#
+# You should have received a copy of the CC0 Public Domain Dedication along
+# with this software. If not, see
+# <https://creativecommons.org/publicdomain/zero/1.0/>
+
+set -e
+
+make clean
+make test CC="clang -std=c99" CFLAGS="-fprofile-instr-generate -fcoverage-mapping"
+llvm-profdata merge default.profraw -o all.profdata
+llvm-cov show -instr-profile=all.profdata "./test.out"
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/ctgrind.c b/lib/Utils.Cryptography/monocypher/vendor/tests/ctgrind.c
new file mode 100644
index 0000000..b928683
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/ctgrind.c
@@ -0,0 +1,330 @@
+// This file is dual-licensed. Choose whichever licence you want from
+// the two licences listed below.
+//
+// The first licence is a regular 2-clause BSD licence. The second licence
+// is the CC-0 from Creative Commons. It is intended to release Monocypher
+// to the public domain. The BSD licence serves as a fallback option.
+//
+// SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+//
+// ------------------------------------------------------------------------
+//
+// Copyright (c) 2020, 2023 Loup Vaillant
+// All rights reserved.
+//
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// ------------------------------------------------------------------------
+//
+// Written in 2020 and 2023 by Loup Vaillant
+//
+// To the extent possible under law, the author(s) have dedicated all copyright
+// and related neighboring rights to this software to the public domain
+// worldwide. This software is distributed without any warranty.
+//
+// You should have received a copy of the CC0 Public Domain Dedication along
+// with this software. If not, see
+// <https://creativecommons.org/publicdomain/zero/1.0/>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "monocypher.h"
+#include "monocypher-ed25519.h"
+#include "utils.h"
+
+static void verify16()
+{
+ u8 a[16];
+ u8 b[16];
+ crypto_verify16(a, b);
+}
+
+static void verify32()
+{
+ u8 a[32];
+ u8 b[32];
+ crypto_verify32(a, b);
+}
+
+static void verify64()
+{
+ u8 a[64];
+ u8 b[64];
+ crypto_verify64(a, b);
+}
+
+static void wipe()
+{
+ FOR (i, 0, 128) {
+ u8 secret[128];
+ crypto_wipe(secret, i);
+ }
+}
+
+static void lock_aead()
+{
+ FOR(i, 0, 128) {
+ u8 mac [ 16];
+ u8 cipher_text[128];
+ u8 key [ 32];
+ u8 nonce [ 24];
+ u8 ad [128];
+ u8 plain_text [128];
+ crypto_aead_lock(cipher_text, mac, key, nonce, ad, i, plain_text, i);
+ }
+}
+
+static void unlock_aead()
+{
+ FOR(i, 0, 128) {
+ u8 plain_text [128];
+ u8 key [ 32];
+ u8 nonce [ 24];
+ u8 mac [ 16];
+ u8 ad [128];
+ u8 cipher_text[128];
+ crypto_aead_unlock(plain_text, mac, key, nonce, ad, i, cipher_text, i);
+ }
+}
+
+static void blake2b()
+{
+ FOR (i, 0, 256) {
+ u8 hash [ 64];
+ u8 key [ 64];
+ u8 message[256];
+ crypto_blake2b_keyed(hash, 64, key, 0, message, i);
+ }
+ FOR (i, 0, 64) {
+ u8 hash [ 64];
+ u8 key [ 64];
+ u8 message[256];
+ crypto_blake2b_keyed(hash, 64, key, i, message, 128);
+ }
+ FOR (i, 0, 64) {
+ u8 hash [ 64];
+ u8 key [ 64];
+ u8 message[256];
+ crypto_blake2b_keyed(hash, i, key, 0, message, 0);
+ }
+}
+
+static void argon2()
+{
+ void *work_area = alloc(1024 * 600 * 4);
+ u8 hash[ 32];
+ u8 pass[ 16];
+ u8 salt[ 16];
+ u8 key [ 32];
+ u8 ad [128];
+
+ crypto_argon2_config config;
+ config.algorithm = CRYPTO_ARGON2_ID;
+ config.nb_blocks = 600 * 4;
+ config.nb_passes = 3;
+ config.nb_lanes = 4;
+
+ crypto_argon2_inputs inputs;
+ inputs.pass = pass;
+ inputs.salt = salt;
+ inputs.pass_size = sizeof(pass);
+ inputs.salt_size = sizeof(salt);
+
+ crypto_argon2_extras extras;
+ extras.key = key;
+ extras.ad = ad;
+ extras.key_size = sizeof(key);
+ extras.ad_size = sizeof(ad);
+
+ crypto_argon2(hash, 32, work_area, config, inputs, extras);
+ free(work_area);
+}
+
+static void x25519()
+{
+ u8 shared_key [32];
+ u8 your_secret_key [32];
+ u8 their_public_key[32];
+ crypto_x25519(shared_key, your_secret_key, their_public_key);
+}
+
+static void x25519_to_eddsa()
+{
+ u8 x25519[32];
+ u8 eddsa[32];
+ crypto_x25519_to_eddsa(eddsa, x25519);
+}
+
+static void eddsa_key_pair()
+{
+ u8 seed[32];
+ u8 secret_key[64];
+ u8 public_key[32];
+ crypto_eddsa_key_pair(secret_key, public_key, seed);
+}
+
+static void eddsa_sign()
+{
+ u8 signature [64];
+ u8 secret_key[64];
+ u8 message [64];
+ crypto_eddsa_sign(signature, secret_key, message, 64);
+}
+
+static void eddsa_to_x25519()
+{
+ u8 x25519[32];
+ u8 eddsa [32];
+ crypto_eddsa_to_x25519(x25519, eddsa);
+}
+
+static void elligator_map()
+{
+ u8 curve [32];
+ u8 hidden[32];
+ crypto_elligator_map(curve, hidden);
+}
+
+static void elligator_rev()
+{
+ u8 hidden[32];
+ u8 curve [32];
+ u8 tweak; // The compiler notices this one is used uninitialised
+ crypto_elligator_rev(hidden, curve, tweak);
+}
+
+static void elligator_key_pair()
+{
+ u8 hidden [32];
+ u8 secret_key[32];
+ u8 seed [32];
+ crypto_elligator_key_pair(hidden, secret_key,seed);
+}
+
+static void chacha20_h()
+{
+ u8 out[32], key[32], in[16];
+ crypto_chacha20_h(out, key, in);
+}
+
+static void chacha20_x()
+{
+ FOR (i, 0, 128) {
+ u8 cipher_text[128];
+ u8 plain_text [128];
+ u8 key [ 32];
+ u8 nonce [ 24];
+ crypto_chacha20_x(cipher_text, plain_text, i, key, nonce, 0);
+ }
+}
+
+static void chacha20_djb()
+{
+ FOR (i, 0, 128) {
+ u8 cipher_text[128];
+ u8 plain_text [128];
+ u8 key [ 32];
+ u8 nonce [ 8];
+ crypto_chacha20_djb(cipher_text, plain_text, i, key, nonce, 0);
+ }
+}
+
+static void chacha20_ietf()
+{
+ FOR (i, 0, 128) {
+ u8 cipher_text[128];
+ u8 plain_text [128];
+ u8 key [ 32];
+ u8 nonce [ 12];
+ crypto_chacha20_ietf(cipher_text, plain_text, i, key, nonce, 0);
+ }
+}
+
+static void poly1305()
+{
+ FOR (i, 0, 32) {
+ u8 mac [16];
+ u8 message [32];
+ u8 key [32];
+ crypto_poly1305(mac, message, i, key);
+ }
+}
+
+static void x25519_dirty_small()
+{
+ u8 pk[32];
+ u8 sk[32];
+ crypto_x25519_dirty_small(pk, sk);
+}
+static void x25519_dirty_fast()
+{
+ u8 pk[32];
+ u8 sk[32];
+ crypto_x25519_dirty_fast(pk, sk);
+}
+
+static void x25519_inverse()
+{
+ u8 blind_salt [32];
+ u8 private_key[32];
+ u8 curve_point[32];
+ crypto_x25519_inverse(blind_salt, private_key, curve_point);
+}
+
+
+#define RUN(f, s) printf("%s: crypto_"#f"\n", s); f()
+
+int main()
+{
+ RUN(verify16 , "constant time");
+ RUN(verify32 , "constant time");
+ RUN(verify64 , "constant time");
+ RUN(wipe , "constant time");
+ RUN(lock_aead , "constant time");
+ RUN(unlock_aead , "1 conditional");
+ RUN(blake2b , "constant time");
+ RUN(argon2 , "constant time"); // "use" of uninitialised value
+ RUN(x25519 , "constant time");
+ RUN(x25519_to_eddsa , "constant time");
+ RUN(eddsa_key_pair , "constant time");
+ RUN(eddsa_sign , "constant time");
+ printf( "skipped : crypto_check.\n");
+ RUN(eddsa_to_x25519 , "constant time");
+ RUN(elligator_map , "constant time");
+ RUN(elligator_rev , "1 conditional");
+ RUN(elligator_key_pair, "2 conditionals");
+ RUN(chacha20_h , "constant time");
+ RUN(chacha20_x , "constant time");
+ RUN(chacha20_djb , "constant time");
+ RUN(chacha20_ietf , "constant time");
+ RUN(poly1305 , "constant time");
+ RUN(x25519_dirty_small, "constant time");
+ RUN(x25519_dirty_fast , "constant time");
+ RUN(x25519_inverse , "constant time");
+
+ return 0;
+}
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/c25519/.gitignore b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/c25519/.gitignore
new file mode 100644
index 0000000..d74e014
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/c25519/.gitignore
@@ -0,0 +1,5 @@
+.*.swp
+*~
+*.o
+*.su
+*.test
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/c25519/AUTHORS.md b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/c25519/AUTHORS.md
new file mode 100644
index 0000000..d7c7bfb
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/c25519/AUTHORS.md
@@ -0,0 +1,5 @@
+The code of C25519 has been written by Daniel Beers <dlbeer@gmail.com>
+and dedicated to the public domain; refer to the file headers.
+
+C25519 has been obtained via <https://www.dlbeer.co.nz/oss/c25519.html>.
+
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/c25519/c25519.c b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/c25519/c25519.c
new file mode 100644
index 0000000..a9c9f08
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/c25519/c25519.c
@@ -0,0 +1,124 @@
+/* Curve25519 (Montgomery form)
+ * Daniel Beer <dlbeer@gmail.com>, 18 Apr 2014
+ *
+ * This file is in the public domain.
+ */
+
+#include "c25519.h"
+
+const uint8_t c25519_base_x[F25519_SIZE] = {9};
+
+/* Double an X-coordinate */
+static void xc_double(uint8_t *x3, uint8_t *z3,
+ const uint8_t *x1, const uint8_t *z1)
+{
+ /* Explicit formulas database: dbl-1987-m
+ *
+ * source 1987 Montgomery "Speeding the Pollard and elliptic
+ * curve methods of factorization", page 261, fourth display
+ * compute X3 = (X1^2-Z1^2)^2
+ * compute Z3 = 4 X1 Z1 (X1^2 + a X1 Z1 + Z1^2)
+ */
+ uint8_t x1sq[F25519_SIZE];
+ uint8_t z1sq[F25519_SIZE];
+ uint8_t x1z1[F25519_SIZE];
+ uint8_t a[F25519_SIZE];
+
+ f25519_mul__distinct(x1sq, x1, x1);
+ f25519_mul__distinct(z1sq, z1, z1);
+ f25519_mul__distinct(x1z1, x1, z1);
+
+ f25519_sub(a, x1sq, z1sq);
+ f25519_mul__distinct(x3, a, a);
+
+ f25519_mul_c(a, x1z1, 486662);
+ f25519_add(a, x1sq, a);
+ f25519_add(a, z1sq, a);
+ f25519_mul__distinct(x1sq, x1z1, a);
+ f25519_mul_c(z3, x1sq, 4);
+}
+
+/* Differential addition */
+static void xc_diffadd(uint8_t *x5, uint8_t *z5,
+ const uint8_t *x1, const uint8_t *z1,
+ const uint8_t *x2, const uint8_t *z2,
+ const uint8_t *x3, const uint8_t *z3)
+{
+ /* Explicit formulas database: dbl-1987-m3
+ *
+ * source 1987 Montgomery "Speeding the Pollard and elliptic curve
+ * methods of factorization", page 261, fifth display, plus
+ * common-subexpression elimination
+ * compute A = X2+Z2
+ * compute B = X2-Z2
+ * compute C = X3+Z3
+ * compute D = X3-Z3
+ * compute DA = D A
+ * compute CB = C B
+ * compute X5 = Z1(DA+CB)^2
+ * compute Z5 = X1(DA-CB)^2
+ */
+ uint8_t da[F25519_SIZE];
+ uint8_t cb[F25519_SIZE];
+ uint8_t a[F25519_SIZE];
+ uint8_t b[F25519_SIZE];
+
+ f25519_add(a, x2, z2);
+ f25519_sub(b, x3, z3); /* D */
+ f25519_mul__distinct(da, a, b);
+
+ f25519_sub(b, x2, z2);
+ f25519_add(a, x3, z3); /* C */
+ f25519_mul__distinct(cb, a, b);
+
+ f25519_add(a, da, cb);
+ f25519_mul__distinct(b, a, a);
+ f25519_mul__distinct(x5, z1, b);
+
+ f25519_sub(a, da, cb);
+ f25519_mul__distinct(b, a, a);
+ f25519_mul__distinct(z5, x1, b);
+}
+
+void c25519_smult(uint8_t *result, const uint8_t *q, const uint8_t *e)
+{
+ /* Current point: P_m */
+ uint8_t xm[F25519_SIZE];
+ uint8_t zm[F25519_SIZE] = {1};
+
+ /* Predecessor: P_(m-1) */
+ uint8_t xm1[F25519_SIZE] = {1};
+ uint8_t zm1[F25519_SIZE] = {0};
+
+ int i;
+
+ /* Note: bit 254 is assumed to be 1 */
+ f25519_copy(xm, q);
+
+ for (i = 253; i >= 0; i--) {
+ const int bit = (e[i >> 3] >> (i & 7)) & 1;
+ uint8_t xms[F25519_SIZE];
+ uint8_t zms[F25519_SIZE];
+
+ /* From P_m and P_(m-1), compute P_(2m) and P_(2m-1) */
+ xc_diffadd(xm1, zm1, q, f25519_one, xm, zm, xm1, zm1);
+ xc_double(xm, zm, xm, zm);
+
+ /* Compute P_(2m+1) */
+ xc_diffadd(xms, zms, xm1, zm1, xm, zm, q, f25519_one);
+
+ /* Select:
+ * bit = 1 --> (P_(2m+1), P_(2m))
+ * bit = 0 --> (P_(2m), P_(2m-1))
+ */
+ f25519_select(xm1, xm1, xm, bit);
+ f25519_select(zm1, zm1, zm, bit);
+ f25519_select(xm, xm, xms, bit);
+ f25519_select(zm, zm, zms, bit);
+ }
+
+ /* Freeze out of projective coordinates */
+ f25519_inv__distinct(zm1, zm);
+ f25519_mul__distinct(result, zm1, xm);
+ f25519_normalize(result);
+}
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/c25519/c25519.h b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/c25519/c25519.h
new file mode 100644
index 0000000..4596438
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/c25519/c25519.h
@@ -0,0 +1,48 @@
+/* Curve25519 (Montgomery form)
+ * Daniel Beer <dlbeer@gmail.com>, 18 Apr 2014
+ *
+ * This file is in the public domain.
+ */
+
+#ifndef C25519_H_
+#define C25519_H_
+
+#include <stdint.h>
+#include "f25519.h"
+
+/* Curve25519 has the equation over F(p = 2^255-19):
+ *
+ * y^2 = x^3 + 486662x^2 + x
+ *
+ * 486662 = 4A+2, where A = 121665. This is a Montgomery curve.
+ *
+ * For more information, see:
+ *
+ * Bernstein, D.J. (2006) "Curve25519: New Diffie-Hellman speed
+ * records". Document ID: 4230efdfa673480fc079449d90f322c0.
+ */
+
+/* This is the site of a Curve25519 exponent (private key) */
+#define C25519_EXPONENT_SIZE 32
+
+/* Having generated 32 random bytes, you should call this function to
+ * finalize the generated key.
+ */
+static inline void c25519_prepare(uint8_t *key)
+{
+ key[0] &= 0xf8;
+ key[31] &= 0x7f;
+ key[31] |= 0x40;
+}
+
+/* X-coordinate of the base point */
+extern const uint8_t c25519_base_x[F25519_SIZE];
+
+/* X-coordinate scalar multiply: given the X-coordinate of q, return the
+ * X-coordinate of e*q.
+ *
+ * result and q are field elements. e is an exponent.
+ */
+void c25519_smult(uint8_t *result, const uint8_t *q, const uint8_t *e);
+
+#endif
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/c25519/ed25519.c b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/c25519/ed25519.c
new file mode 100644
index 0000000..51ac462
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/c25519/ed25519.c
@@ -0,0 +1,320 @@
+/* Edwards curve operations
+ * Daniel Beer <dlbeer@gmail.com>, 9 Jan 2014
+ *
+ * This file is in the public domain.
+ */
+
+#include "ed25519.h"
+
+/* Base point is (numbers wrapped):
+ *
+ * x = 151122213495354007725011514095885315114
+ * 54012693041857206046113283949847762202
+ * y = 463168356949264781694283940034751631413
+ * 07993866256225615783033603165251855960
+ *
+ * y is derived by transforming the original Montgomery base (u=9). x
+ * is the corresponding positive coordinate for the new curve equation.
+ * t is x*y.
+ */
+const struct ed25519_pt ed25519_base = {
+ .x = {
+ 0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9,
+ 0xb2, 0xa7, 0x25, 0x95, 0x60, 0xc7, 0x2c, 0x69,
+ 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0,
+ 0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21
+ },
+ .y = {
+ 0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+ 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+ 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+ 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66
+ },
+ .t = {
+ 0xa3, 0xdd, 0xb7, 0xa5, 0xb3, 0x8a, 0xde, 0x6d,
+ 0xf5, 0x52, 0x51, 0x77, 0x80, 0x9f, 0xf0, 0x20,
+ 0x7d, 0xe3, 0xab, 0x64, 0x8e, 0x4e, 0xea, 0x66,
+ 0x65, 0x76, 0x8b, 0xd7, 0x0f, 0x5f, 0x87, 0x67
+ },
+ .z = {1, 0}
+};
+
+const struct ed25519_pt ed25519_neutral = {
+ .x = {0},
+ .y = {1, 0},
+ .t = {0},
+ .z = {1, 0}
+};
+
+/* Conversion to and from projective coordinates */
+void ed25519_project(struct ed25519_pt *p,
+ const uint8_t *x, const uint8_t *y)
+{
+ f25519_copy(p->x, x);
+ f25519_copy(p->y, y);
+ f25519_load(p->z, 1);
+ f25519_mul__distinct(p->t, x, y);
+}
+
+void ed25519_unproject(uint8_t *x, uint8_t *y,
+ const struct ed25519_pt *p)
+{
+ uint8_t z1[F25519_SIZE];
+
+ f25519_inv__distinct(z1, p->z);
+ f25519_mul__distinct(x, p->x, z1);
+ f25519_mul__distinct(y, p->y, z1);
+
+ f25519_normalize(x);
+ f25519_normalize(y);
+}
+
+/* Compress/uncompress points. We compress points by storing the x
+ * coordinate and the parity of the y coordinate.
+ *
+ * Rearranging the curve equation, we obtain explicit formulae for the
+ * coordinates:
+ *
+ * x = sqrt((y^2-1) / (1+dy^2))
+ * y = sqrt((x^2+1) / (1-dx^2))
+ *
+ * Where d = (-121665/121666), or:
+ *
+ * d = 370957059346694393431380835087545651895
+ * 42113879843219016388785533085940283555
+ */
+
+static const uint8_t ed25519_d[F25519_SIZE] = {
+ 0xa3, 0x78, 0x59, 0x13, 0xca, 0x4d, 0xeb, 0x75,
+ 0xab, 0xd8, 0x41, 0x41, 0x4d, 0x0a, 0x70, 0x00,
+ 0x98, 0xe8, 0x79, 0x77, 0x79, 0x40, 0xc7, 0x8c,
+ 0x73, 0xfe, 0x6f, 0x2b, 0xee, 0x6c, 0x03, 0x52
+};
+
+void ed25519_pack(uint8_t *c, const uint8_t *x, const uint8_t *y)
+{
+ uint8_t tmp[F25519_SIZE];
+ uint8_t parity;
+
+ f25519_copy(tmp, x);
+ f25519_normalize(tmp);
+ parity = (tmp[0] & 1) << 7;
+
+ f25519_copy(c, y);
+ f25519_normalize(c);
+ c[31] |= parity;
+}
+
+uint8_t ed25519_try_unpack(uint8_t *x, uint8_t *y, const uint8_t *comp)
+{
+ const int parity = comp[31] >> 7;
+ uint8_t a[F25519_SIZE];
+ uint8_t b[F25519_SIZE];
+ uint8_t c[F25519_SIZE];
+
+ /* Unpack y */
+ f25519_copy(y, comp);
+ y[31] &= 127;
+
+ /* Compute c = y^2 */
+ f25519_mul__distinct(c, y, y);
+
+ /* Compute b = (1+dy^2)^-1 */
+ f25519_mul__distinct(b, c, ed25519_d);
+ f25519_add(a, b, f25519_one);
+ f25519_inv__distinct(b, a);
+
+ /* Compute a = y^2-1 */
+ f25519_sub(a, c, f25519_one);
+
+ /* Compute c = a*b = (y^2-1)/(1-dy^2) */
+ f25519_mul__distinct(c, a, b);
+
+ /* Compute a, b = +/-sqrt(c), if c is square */
+ f25519_sqrt(a, c);
+ f25519_neg(b, a);
+
+ /* Select one of them, based on the compressed parity bit */
+ f25519_select(x, a, b, (a[0] ^ parity) & 1);
+
+ /* Verify that x^2 = c */
+ f25519_mul__distinct(a, x, x);
+ f25519_normalize(a);
+ f25519_normalize(c);
+
+ return f25519_eq(a, c);
+}
+
+/* k = 2d */
+static const uint8_t ed25519_k[F25519_SIZE] = {
+ 0x59, 0xf1, 0xb2, 0x26, 0x94, 0x9b, 0xd6, 0xeb,
+ 0x56, 0xb1, 0x83, 0x82, 0x9a, 0x14, 0xe0, 0x00,
+ 0x30, 0xd1, 0xf3, 0xee, 0xf2, 0x80, 0x8e, 0x19,
+ 0xe7, 0xfc, 0xdf, 0x56, 0xdc, 0xd9, 0x06, 0x24
+};
+
+void ed25519_add(struct ed25519_pt *r,
+ const struct ed25519_pt *p1, const struct ed25519_pt *p2)
+{
+ /* Explicit formulas database: add-2008-hwcd-3
+ *
+ * source 2008 Hisil--Wong--Carter--Dawson,
+ * http://eprint.iacr.org/2008/522, Section 3.1
+ * appliesto extended-1
+ * parameter k
+ * assume k = 2 d
+ * compute A = (Y1-X1)(Y2-X2)
+ * compute B = (Y1+X1)(Y2+X2)
+ * compute C = T1 k T2
+ * compute D = Z1 2 Z2
+ * compute E = B - A
+ * compute F = D - C
+ * compute G = D + C
+ * compute H = B + A
+ * compute X3 = E F
+ * compute Y3 = G H
+ * compute T3 = E H
+ * compute Z3 = F G
+ */
+ uint8_t a[F25519_SIZE];
+ uint8_t b[F25519_SIZE];
+ uint8_t c[F25519_SIZE];
+ uint8_t d[F25519_SIZE];
+ uint8_t e[F25519_SIZE];
+ uint8_t f[F25519_SIZE];
+ uint8_t g[F25519_SIZE];
+ uint8_t h[F25519_SIZE];
+
+ /* A = (Y1-X1)(Y2-X2) */
+ f25519_sub(c, p1->y, p1->x);
+ f25519_sub(d, p2->y, p2->x);
+ f25519_mul__distinct(a, c, d);
+
+ /* B = (Y1+X1)(Y2+X2) */
+ f25519_add(c, p1->y, p1->x);
+ f25519_add(d, p2->y, p2->x);
+ f25519_mul__distinct(b, c, d);
+
+ /* C = T1 k T2 */
+ f25519_mul__distinct(d, p1->t, p2->t);
+ f25519_mul__distinct(c, d, ed25519_k);
+
+ /* D = Z1 2 Z2 */
+ f25519_mul__distinct(d, p1->z, p2->z);
+ f25519_add(d, d, d);
+
+ /* E = B - A */
+ f25519_sub(e, b, a);
+
+ /* F = D - C */
+ f25519_sub(f, d, c);
+
+ /* G = D + C */
+ f25519_add(g, d, c);
+
+ /* H = B + A */
+ f25519_add(h, b, a);
+
+ /* X3 = E F */
+ f25519_mul__distinct(r->x, e, f);
+
+ /* Y3 = G H */
+ f25519_mul__distinct(r->y, g, h);
+
+ /* T3 = E H */
+ f25519_mul__distinct(r->t, e, h);
+
+ /* Z3 = F G */
+ f25519_mul__distinct(r->z, f, g);
+}
+
+void ed25519_double(struct ed25519_pt *r, const struct ed25519_pt *p)
+{
+ /* Explicit formulas database: dbl-2008-hwcd
+ *
+ * source 2008 Hisil--Wong--Carter--Dawson,
+ * http://eprint.iacr.org/2008/522, Section 3.3
+ * compute A = X1^2
+ * compute B = Y1^2
+ * compute C = 2 Z1^2
+ * compute D = a A
+ * compute E = (X1+Y1)^2-A-B
+ * compute G = D + B
+ * compute F = G - C
+ * compute H = D - B
+ * compute X3 = E F
+ * compute Y3 = G H
+ * compute T3 = E H
+ * compute Z3 = F G
+ */
+ uint8_t a[F25519_SIZE];
+ uint8_t b[F25519_SIZE];
+ uint8_t c[F25519_SIZE];
+ uint8_t e[F25519_SIZE];
+ uint8_t f[F25519_SIZE];
+ uint8_t g[F25519_SIZE];
+ uint8_t h[F25519_SIZE];
+
+ /* A = X1^2 */
+ f25519_mul__distinct(a, p->x, p->x);
+
+ /* B = Y1^2 */
+ f25519_mul__distinct(b, p->y, p->y);
+
+ /* C = 2 Z1^2 */
+ f25519_mul__distinct(c, p->z, p->z);
+ f25519_add(c, c, c);
+
+ /* D = a A (alter sign) */
+ /* E = (X1+Y1)^2-A-B */
+ f25519_add(f, p->x, p->y);
+ f25519_mul__distinct(e, f, f);
+ f25519_sub(e, e, a);
+ f25519_sub(e, e, b);
+
+ /* G = D + B */
+ f25519_sub(g, b, a);
+
+ /* F = G - C */
+ f25519_sub(f, g, c);
+
+ /* H = D - B */
+ f25519_neg(h, b);
+ f25519_sub(h, h, a);
+
+ /* X3 = E F */
+ f25519_mul__distinct(r->x, e, f);
+
+ /* Y3 = G H */
+ f25519_mul__distinct(r->y, g, h);
+
+ /* T3 = E H */
+ f25519_mul__distinct(r->t, e, h);
+
+ /* Z3 = F G */
+ f25519_mul__distinct(r->z, f, g);
+}
+
+void ed25519_smult(struct ed25519_pt *r_out, const struct ed25519_pt *p,
+ const uint8_t *e)
+{
+ struct ed25519_pt r;
+ int i;
+
+ ed25519_copy(&r, &ed25519_neutral);
+
+ for (i = 255; i >= 0; i--) {
+ const uint8_t bit = (e[i >> 3] >> (i & 7)) & 1;
+ struct ed25519_pt s;
+
+ ed25519_double(&r, &r);
+ ed25519_add(&s, &r, p);
+
+ f25519_select(r.x, r.x, s.x, bit);
+ f25519_select(r.y, r.y, s.y, bit);
+ f25519_select(r.z, r.z, s.z, bit);
+ f25519_select(r.t, r.t, s.t, bit);
+ }
+
+ ed25519_copy(r_out, &r);
+}
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/c25519/ed25519.h b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/c25519/ed25519.h
new file mode 100644
index 0000000..62f0120
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/c25519/ed25519.h
@@ -0,0 +1,82 @@
+/* Edwards curve operations
+ * Daniel Beer <dlbeer@gmail.com>, 9 Jan 2014
+ *
+ * This file is in the public domain.
+ */
+
+#ifndef ED25519_H_
+#define ED25519_H_
+
+#include "f25519.h"
+
+/* This is not the Ed25519 signature system. Rather, we're implementing
+ * basic operations on the twisted Edwards curve over (Z mod 2^255-19):
+ *
+ * -x^2 + y^2 = 1 - (121665/121666)x^2y^2
+ *
+ * With the positive-x base point y = 4/5.
+ *
+ * These functions will not leak secret data through timing.
+ *
+ * For more information, see:
+ *
+ * Bernstein, D.J. & Lange, T. (2007) "Faster addition and doubling on
+ * elliptic curves". Document ID: 95616567a6ba20f575c5f25e7cebaf83.
+ *
+ * Hisil, H. & Wong, K K. & Carter, G. & Dawson, E. (2008) "Twisted
+ * Edwards curves revisited". Advances in Cryptology, ASIACRYPT 2008,
+ * Vol. 5350, pp. 326-343.
+ */
+
+/* Projective coordinates */
+struct ed25519_pt {
+ uint8_t x[F25519_SIZE];
+ uint8_t y[F25519_SIZE];
+ uint8_t t[F25519_SIZE];
+ uint8_t z[F25519_SIZE];
+};
+
+extern const struct ed25519_pt ed25519_base;
+extern const struct ed25519_pt ed25519_neutral;
+
+/* Convert between projective and affine coordinates (x/y in F25519) */
+void ed25519_project(struct ed25519_pt *p,
+ const uint8_t *x, const uint8_t *y);
+
+void ed25519_unproject(uint8_t *x, uint8_t *y,
+ const struct ed25519_pt *p);
+
+/* Compress/uncompress points. try_unpack() will check that the
+ * compressed point is on the curve, returning 1 if the unpacked point
+ * is valid, and 0 otherwise.
+ */
+#define ED25519_PACK_SIZE F25519_SIZE
+
+void ed25519_pack(uint8_t *c, const uint8_t *x, const uint8_t *y);
+uint8_t ed25519_try_unpack(uint8_t *x, uint8_t *y, const uint8_t *c);
+
+/* Add, double and scalar multiply */
+#define ED25519_EXPONENT_SIZE 32
+
+/* Prepare an exponent by clamping appropriate bits */
+static inline void ed25519_prepare(uint8_t *e)
+{
+ e[0] &= 0xf8;
+ e[31] &= 0x7f;
+ e[31] |= 0x40;
+}
+
+/* Order of the group generated by the base point */
+static inline void ed25519_copy(struct ed25519_pt *dst,
+ const struct ed25519_pt *src)
+{
+ memcpy(dst, src, sizeof(*dst));
+}
+
+void ed25519_add(struct ed25519_pt *r,
+ const struct ed25519_pt *a, const struct ed25519_pt *b);
+void ed25519_double(struct ed25519_pt *r, const struct ed25519_pt *a);
+void ed25519_smult(struct ed25519_pt *r, const struct ed25519_pt *a,
+ const uint8_t *e);
+
+#endif
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/c25519/edsign.c b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/c25519/edsign.c
new file mode 100644
index 0000000..bf131a5
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/c25519/edsign.c
@@ -0,0 +1,168 @@
+/* Edwards curve signature system
+ * Daniel Beer <dlbeer@gmail.com>, 22 Apr 2014
+ *
+ * This file is in the public domain.
+ */
+
+#include "ed25519.h"
+#include "sha512.h"
+#include "fprime.h"
+#include "edsign.h"
+
+#define EXPANDED_SIZE 64
+
+static const uint8_t ed25519_order[FPRIME_SIZE] = {
+ 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58,
+ 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10
+};
+
+static void expand_key(uint8_t *expanded, const uint8_t *secret)
+{
+ struct sha512_state s;
+
+ sha512_init(&s);
+ sha512_final(&s, secret, EDSIGN_SECRET_KEY_SIZE);
+ sha512_get(&s, expanded, 0, EXPANDED_SIZE);
+ ed25519_prepare(expanded);
+}
+
+static uint8_t upp(struct ed25519_pt *p, const uint8_t *packed)
+{
+ uint8_t x[F25519_SIZE];
+ uint8_t y[F25519_SIZE];
+ uint8_t ok = ed25519_try_unpack(x, y, packed);
+
+ ed25519_project(p, x, y);
+ return ok;
+}
+
+static void pp(uint8_t *packed, const struct ed25519_pt *p)
+{
+ uint8_t x[F25519_SIZE];
+ uint8_t y[F25519_SIZE];
+
+ ed25519_unproject(x, y, p);
+ ed25519_pack(packed, x, y);
+}
+
+static void sm_pack(uint8_t *r, const uint8_t *k)
+{
+ struct ed25519_pt p;
+
+ ed25519_smult(&p, &ed25519_base, k);
+ pp(r, &p);
+}
+
+void edsign_sec_to_pub(uint8_t *pub, const uint8_t *secret)
+{
+ uint8_t expanded[EXPANDED_SIZE];
+
+ expand_key(expanded, secret);
+ sm_pack(pub, expanded);
+}
+
+static void hash_with_prefix(uint8_t *out_fp,
+ uint8_t *init_block, unsigned int prefix_size,
+ const uint8_t *message, size_t len)
+{
+ struct sha512_state s;
+
+ sha512_init(&s);
+
+ if (len < SHA512_BLOCK_SIZE && len + prefix_size < SHA512_BLOCK_SIZE) {
+ memcpy(init_block + prefix_size, message, len);
+ sha512_final(&s, init_block, len + prefix_size);
+ } else {
+ size_t i;
+
+ memcpy(init_block + prefix_size, message,
+ SHA512_BLOCK_SIZE - prefix_size);
+ sha512_block(&s, init_block);
+
+ for (i = SHA512_BLOCK_SIZE - prefix_size;
+ i + SHA512_BLOCK_SIZE <= len;
+ i += SHA512_BLOCK_SIZE)
+ sha512_block(&s, message + i);
+
+ sha512_final(&s, message + i, len + prefix_size);
+ }
+
+ sha512_get(&s, init_block, 0, SHA512_HASH_SIZE);
+ fprime_from_bytes(out_fp, init_block, SHA512_HASH_SIZE, ed25519_order);
+}
+
+static void generate_k(uint8_t *k, const uint8_t *kgen_key,
+ const uint8_t *message, size_t len)
+{
+ uint8_t block[SHA512_BLOCK_SIZE];
+
+ memcpy(block, kgen_key, 32);
+ hash_with_prefix(k, block, 32, message, len);
+}
+
+static void hash_message(uint8_t *z, const uint8_t *r, const uint8_t *a,
+ const uint8_t *m, size_t len)
+{
+ uint8_t block[SHA512_BLOCK_SIZE];
+
+ memcpy(block, r, 32);
+ memcpy(block + 32, a, 32);
+ hash_with_prefix(z, block, 64, m, len);
+}
+
+void edsign_sign(uint8_t *signature, const uint8_t *pub,
+ const uint8_t *secret,
+ const uint8_t *message, size_t len)
+{
+ uint8_t expanded[EXPANDED_SIZE];
+ uint8_t e[FPRIME_SIZE];
+ uint8_t s[FPRIME_SIZE];
+ uint8_t k[FPRIME_SIZE];
+ uint8_t z[FPRIME_SIZE];
+
+ expand_key(expanded, secret);
+
+ /* Generate k and R = kB */
+ generate_k(k, expanded + 32, message, len);
+ sm_pack(signature, k);
+
+ /* Compute z = H(R, A, M) */
+ hash_message(z, signature, pub, message, len);
+
+ /* Obtain e */
+ fprime_from_bytes(e, expanded, 32, ed25519_order);
+
+ /* Compute s = ze + k */
+ fprime_mul(s, z, e, ed25519_order);
+ fprime_add(s, k, ed25519_order);
+ memcpy(signature + 32, s, 32);
+}
+
+uint8_t edsign_verify(const uint8_t *signature, const uint8_t *pub,
+ const uint8_t *message, size_t len)
+{
+ struct ed25519_pt p;
+ struct ed25519_pt q;
+ uint8_t lhs[F25519_SIZE];
+ uint8_t rhs[F25519_SIZE];
+ uint8_t z[FPRIME_SIZE];
+ uint8_t ok = 1;
+
+ /* Compute z = H(R, A, M) */
+ hash_message(z, signature, pub, message, len);
+
+ /* sB = (ze + k)B = ... */
+ sm_pack(lhs, signature + 32);
+
+ /* ... = zA + R */
+ ok &= upp(&p, pub);
+ ed25519_smult(&p, &p, z);
+ ok &= upp(&q, signature);
+ ed25519_add(&p, &p, &q);
+ pp(rhs, &p);
+
+ /* Equal? */
+ return ok & f25519_eq(lhs, rhs);
+}
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/c25519/edsign.h b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/c25519/edsign.h
new file mode 100644
index 0000000..85e2208
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/c25519/edsign.h
@@ -0,0 +1,51 @@
+/* Edwards curve signature system
+ * Daniel Beer <dlbeer@gmail.com>, 22 Apr 2014
+ *
+ * This file is in the public domain.
+ */
+
+#ifndef EDSIGN_H_
+#define EDSIGN_H_
+
+#include <stdint.h>
+#include <stddef.h>
+
+/* This is the Ed25519 signature system, as described in:
+ *
+ * Daniel J. Bernstein, Niels Duif, Tanja Lange, Peter Schwabe, Bo-Yin
+ * Yang. High-speed high-security signatures. Journal of Cryptographic
+ * Engineering 2 (2012), 77-89. Document ID:
+ * a1a62a2f76d23f65d622484ddd09caf8. URL:
+ * http://cr.yp.to/papers.html#ed25519. Date: 2011.09.26.
+ *
+ * The format and calculation of signatures is compatible with the
+ * Ed25519 implementation in SUPERCOP. Note, however, that our secret
+ * keys are half the size: we don't store a copy of the public key in
+ * the secret key (we generate it on demand).
+ */
+
+/* Any string of 32 random bytes is a valid secret key. There is no
+ * clamping of bits, because we don't use the key directly as an
+ * exponent (the exponent is derived from part of a key expansion).
+ */
+#define EDSIGN_SECRET_KEY_SIZE 32
+
+/* Given a secret key, produce the public key (a packed Edwards-curve
+ * point).
+ */
+#define EDSIGN_PUBLIC_KEY_SIZE 32
+
+void edsign_sec_to_pub(uint8_t *pub, const uint8_t *secret);
+
+/* Produce a signature for a message. */
+#define EDSIGN_SIGNATURE_SIZE 64
+
+void edsign_sign(uint8_t *signature, const uint8_t *pub,
+ const uint8_t *secret,
+ const uint8_t *message, size_t len);
+
+/* Verify a message signature. Returns non-zero if ok. */
+uint8_t edsign_verify(const uint8_t *signature, const uint8_t *pub,
+ const uint8_t *message, size_t len);
+
+#endif
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/c25519/f25519.c b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/c25519/f25519.c
new file mode 100644
index 0000000..3b06fa6
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/c25519/f25519.c
@@ -0,0 +1,324 @@
+/* Arithmetic mod p = 2^255-19
+ * Daniel Beer <dlbeer@gmail.com>, 5 Jan 2014
+ *
+ * This file is in the public domain.
+ */
+
+#include "f25519.h"
+
+const uint8_t f25519_zero[F25519_SIZE] = {0};
+const uint8_t f25519_one[F25519_SIZE] = {1};
+
+void f25519_load(uint8_t *x, uint32_t c)
+{
+ unsigned int i;
+
+ for (i = 0; i < sizeof(c); i++) {
+ x[i] = c;
+ c >>= 8;
+ }
+
+ for (; i < F25519_SIZE; i++)
+ x[i] = 0;
+}
+
+void f25519_normalize(uint8_t *x)
+{
+ uint8_t minusp[F25519_SIZE];
+ uint16_t c;
+ int i;
+
+ /* Reduce using 2^255 = 19 mod p */
+ c = (x[31] >> 7) * 19;
+ x[31] &= 127;
+
+ for (i = 0; i < F25519_SIZE; i++) {
+ c += x[i];
+ x[i] = c;
+ c >>= 8;
+ }
+
+ /* The number is now less than 2^255 + 18, and therefore less than
+ * 2p. Try subtracting p, and conditionally load the subtracted
+ * value if underflow did not occur.
+ */
+ c = 19;
+
+ for (i = 0; i + 1 < F25519_SIZE; i++) {
+ c += x[i];
+ minusp[i] = c;
+ c >>= 8;
+ }
+
+ c += ((uint16_t)x[i]) - 128;
+ minusp[31] = c;
+
+ /* Load x-p if no underflow */
+ f25519_select(x, minusp, x, (c >> 15) & 1);
+}
+
+uint8_t f25519_eq(const uint8_t *x, const uint8_t *y)
+{
+ uint8_t sum = 0;
+ int i;
+
+ for (i = 0; i < F25519_SIZE; i++)
+ sum |= x[i] ^ y[i];
+
+ sum |= (sum >> 4);
+ sum |= (sum >> 2);
+ sum |= (sum >> 1);
+
+ return (sum ^ 1) & 1;
+}
+
+void f25519_select(uint8_t *dst,
+ const uint8_t *zero, const uint8_t *one,
+ uint8_t condition)
+{
+ const uint8_t mask = -condition;
+ int i;
+
+ for (i = 0; i < F25519_SIZE; i++)
+ dst[i] = zero[i] ^ (mask & (one[i] ^ zero[i]));
+}
+
+void f25519_add(uint8_t *r, const uint8_t *a, const uint8_t *b)
+{
+ uint16_t c = 0;
+ int i;
+
+ /* Add */
+ for (i = 0; i < F25519_SIZE; i++) {
+ c >>= 8;
+ c += ((uint16_t)a[i]) + ((uint16_t)b[i]);
+ r[i] = c;
+ }
+
+ /* Reduce with 2^255 = 19 mod p */
+ r[31] &= 127;
+ c = (c >> 7) * 19;
+
+ for (i = 0; i < F25519_SIZE; i++) {
+ c += r[i];
+ r[i] = c;
+ c >>= 8;
+ }
+}
+
+void f25519_sub(uint8_t *r, const uint8_t *a, const uint8_t *b)
+{
+ uint32_t c = 0;
+ int i;
+
+ /* Calculate a + 2p - b, to avoid underflow */
+ c = 218;
+ for (i = 0; i + 1 < F25519_SIZE; i++) {
+ c += 65280 + ((uint32_t)a[i]) - ((uint32_t)b[i]);
+ r[i] = c;
+ c >>= 8;
+ }
+
+ c += ((uint32_t)a[31]) - ((uint32_t)b[31]);
+ r[31] = c & 127;
+ c = (c >> 7) * 19;
+
+ for (i = 0; i < F25519_SIZE; i++) {
+ c += r[i];
+ r[i] = c;
+ c >>= 8;
+ }
+}
+
+void f25519_neg(uint8_t *r, const uint8_t *a)
+{
+ uint32_t c = 0;
+ int i;
+
+ /* Calculate 2p - a, to avoid underflow */
+ c = 218;
+ for (i = 0; i + 1 < F25519_SIZE; i++) {
+ c += 65280 - ((uint32_t)a[i]);
+ r[i] = c;
+ c >>= 8;
+ }
+
+ c -= ((uint32_t)a[31]);
+ r[31] = c & 127;
+ c = (c >> 7) * 19;
+
+ for (i = 0; i < F25519_SIZE; i++) {
+ c += r[i];
+ r[i] = c;
+ c >>= 8;
+ }
+}
+
+void f25519_mul__distinct(uint8_t *r, const uint8_t *a, const uint8_t *b)
+{
+ uint32_t c = 0;
+ int i;
+
+ for (i = 0; i < F25519_SIZE; i++) {
+ int j;
+
+ c >>= 8;
+ for (j = 0; j <= i; j++)
+ c += ((uint32_t)a[j]) * ((uint32_t)b[i - j]);
+
+ for (; j < F25519_SIZE; j++)
+ c += ((uint32_t)a[j]) *
+ ((uint32_t)b[i + F25519_SIZE - j]) * 38;
+
+ r[i] = c;
+ }
+
+ r[31] &= 127;
+ c = (c >> 7) * 19;
+
+ for (i = 0; i < F25519_SIZE; i++) {
+ c += r[i];
+ r[i] = c;
+ c >>= 8;
+ }
+}
+
+void f25519_mul(uint8_t *r, const uint8_t *a, const uint8_t *b)
+{
+ uint8_t tmp[F25519_SIZE];
+
+ f25519_mul__distinct(tmp, a, b);
+ f25519_copy(r, tmp);
+}
+
+void f25519_mul_c(uint8_t *r, const uint8_t *a, uint32_t b)
+{
+ uint32_t c = 0;
+ int i;
+
+ for (i = 0; i < F25519_SIZE; i++) {
+ c >>= 8;
+ c += b * ((uint32_t)a[i]);
+ r[i] = c;
+ }
+
+ r[31] &= 127;
+ c >>= 7;
+ c *= 19;
+
+ for (i = 0; i < F25519_SIZE; i++) {
+ c += r[i];
+ r[i] = c;
+ c >>= 8;
+ }
+}
+
+void f25519_inv__distinct(uint8_t *r, const uint8_t *x)
+{
+ uint8_t s[F25519_SIZE];
+ int i;
+
+ /* This is a prime field, so by Fermat's little theorem:
+ *
+ * x^(p-1) = 1 mod p
+ *
+ * Therefore, raise to (p-2) = 2^255-21 to get a multiplicative
+ * inverse.
+ *
+ * This is a 255-bit binary number with the digits:
+ *
+ * 11111111... 01011
+ *
+ * We compute the result by the usual binary chain, but
+ * alternate between keeping the accumulator in r and s, so as
+ * to avoid copying temporaries.
+ */
+
+ /* 1 1 */
+ f25519_mul__distinct(s, x, x);
+ f25519_mul__distinct(r, s, x);
+
+ /* 1 x 248 */
+ for (i = 0; i < 248; i++) {
+ f25519_mul__distinct(s, r, r);
+ f25519_mul__distinct(r, s, x);
+ }
+
+ /* 0 */
+ f25519_mul__distinct(s, r, r);
+
+ /* 1 */
+ f25519_mul__distinct(r, s, s);
+ f25519_mul__distinct(s, r, x);
+
+ /* 0 */
+ f25519_mul__distinct(r, s, s);
+
+ /* 1 */
+ f25519_mul__distinct(s, r, r);
+ f25519_mul__distinct(r, s, x);
+
+ /* 1 */
+ f25519_mul__distinct(s, r, r);
+ f25519_mul__distinct(r, s, x);
+}
+
+void f25519_inv(uint8_t *r, const uint8_t *x)
+{
+ uint8_t tmp[F25519_SIZE];
+
+ f25519_inv__distinct(tmp, x);
+ f25519_copy(r, tmp);
+}
+
+/* Raise x to the power of (p-5)/8 = 2^252-3, using s for temporary
+ * storage.
+ */
+static void exp2523(uint8_t *r, const uint8_t *x, uint8_t *s)
+{
+ int i;
+
+ /* This number is a 252-bit number with the binary expansion:
+ *
+ * 111111... 01
+ */
+
+ /* 1 1 */
+ f25519_mul__distinct(r, x, x);
+ f25519_mul__distinct(s, r, x);
+
+ /* 1 x 248 */
+ for (i = 0; i < 248; i++) {
+ f25519_mul__distinct(r, s, s);
+ f25519_mul__distinct(s, r, x);
+ }
+
+ /* 0 */
+ f25519_mul__distinct(r, s, s);
+
+ /* 1 */
+ f25519_mul__distinct(s, r, r);
+ f25519_mul__distinct(r, s, x);
+}
+
+void f25519_sqrt(uint8_t *r, const uint8_t *a)
+{
+ uint8_t v[F25519_SIZE];
+ uint8_t i[F25519_SIZE];
+ uint8_t x[F25519_SIZE];
+ uint8_t y[F25519_SIZE];
+
+ /* v = (2a)^((p-5)/8) [x = 2a] */
+ f25519_mul_c(x, a, 2);
+ exp2523(v, x, y);
+
+ /* i = 2av^2 - 1 */
+ f25519_mul__distinct(y, v, v);
+ f25519_mul__distinct(i, x, y);
+ f25519_load(y, 1);
+ f25519_sub(i, i, y);
+
+ /* r = avi */
+ f25519_mul__distinct(x, v, a);
+ f25519_mul__distinct(r, x, i);
+}
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/c25519/f25519.h b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/c25519/f25519.h
new file mode 100644
index 0000000..4cfa5ec
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/c25519/f25519.h
@@ -0,0 +1,92 @@
+/* Arithmetic mod p = 2^255-19
+ * Daniel Beer <dlbeer@gmail.com>, 8 Jan 2014
+ *
+ * This file is in the public domain.
+ */
+
+#ifndef F25519_H_
+#define F25519_H_
+
+#include <stdint.h>
+#include <string.h>
+
+/* Field elements are represented as little-endian byte strings. All
+ * operations have timings which are independent of input data, so they
+ * can be safely used for cryptography.
+ *
+ * Computation is performed on un-normalized elements. These are byte
+ * strings which fall into the range 0 <= x < 2p. Use f25519_normalize()
+ * to convert to a value 0 <= x < p.
+ *
+ * Elements received from the outside may greater even than 2p.
+ * f25519_normalize() will correctly deal with these numbers too.
+ */
+#define F25519_SIZE 32
+
+/* Identity constants */
+extern const uint8_t f25519_zero[F25519_SIZE];
+extern const uint8_t f25519_one[F25519_SIZE];
+
+/* Load a small constant */
+void f25519_load(uint8_t *x, uint32_t c);
+
+/* Copy two points */
+static inline void f25519_copy(uint8_t *x, const uint8_t *a)
+{
+ memcpy(x, a, F25519_SIZE);
+}
+
+/* Normalize a field point x < 2*p by subtracting p if necessary */
+void f25519_normalize(uint8_t *x);
+
+/* Compare two field points in constant time. Return one if equal, zero
+ * otherwise. This should be performed only on normalized values.
+ */
+uint8_t f25519_eq(const uint8_t *x, const uint8_t *y);
+
+/* Conditional copy. If condition == 0, then zero is copied to dst. If
+ * condition == 1, then one is copied to dst. Any other value results in
+ * undefined behaviour.
+ */
+void f25519_select(uint8_t *dst,
+ const uint8_t *zero, const uint8_t *one,
+ uint8_t condition);
+
+/* Add/subtract two field points. The three pointers are not required to
+ * be distinct.
+ */
+void f25519_add(uint8_t *r, const uint8_t *a, const uint8_t *b);
+void f25519_sub(uint8_t *r, const uint8_t *a, const uint8_t *b);
+
+/* Unary negation */
+void f25519_neg(uint8_t *r, const uint8_t *a);
+
+/* Multiply two field points. The __distinct variant is used when r is
+ * known to be in a different location to a and b.
+ */
+void f25519_mul(uint8_t *r, const uint8_t *a, const uint8_t *b);
+void f25519_mul__distinct(uint8_t *r, const uint8_t *a, const uint8_t *b);
+
+/* Multiply a point by a small constant. The two pointers are not
+ * required to be distinct.
+ *
+ * The constant must be less than 2^24.
+ */
+void f25519_mul_c(uint8_t *r, const uint8_t *a, uint32_t b);
+
+/* Take the reciprocal of a field point. The __distinct variant is used
+ * when r is known to be in a different location to x.
+ */
+void f25519_inv(uint8_t *r, const uint8_t *x);
+void f25519_inv__distinct(uint8_t *r, const uint8_t *x);
+
+/* Compute one of the square roots of the field element, if the element
+ * is square. The other square is -r.
+ *
+ * If the input is not square, the returned value is a valid field
+ * element, but not the correct answer. If you don't already know that
+ * your element is square, you should square the return value and test.
+ */
+void f25519_sqrt(uint8_t *r, const uint8_t *x);
+
+#endif
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/c25519/fprime.c b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/c25519/fprime.c
new file mode 100644
index 0000000..25f2197
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/c25519/fprime.c
@@ -0,0 +1,215 @@
+/* Arithmetic in prime fields
+ * Daniel Beer <dlbeer@gmail.com>, 10 Jan 2014
+ *
+ * This file is in the public domain.
+ */
+
+#include "fprime.h"
+
+const uint8_t fprime_zero[FPRIME_SIZE] = {0};
+const uint8_t fprime_one[FPRIME_SIZE] = {1};
+
+static void raw_add(uint8_t *x, const uint8_t *p)
+{
+ uint16_t c = 0;
+ int i;
+
+ for (i = 0; i < FPRIME_SIZE; i++) {
+ c += ((uint16_t)x[i]) + ((uint16_t)p[i]);
+ x[i] = c;
+ c >>= 8;
+ }
+}
+
+static void raw_try_sub(uint8_t *x, const uint8_t *p)
+{
+ uint8_t minusp[FPRIME_SIZE];
+ uint16_t c = 0;
+ int i;
+
+ for (i = 0; i < FPRIME_SIZE; i++) {
+ c = ((uint16_t)x[i]) - ((uint16_t)p[i]) - c;
+ minusp[i] = c;
+ c = (c >> 8) & 1;
+ }
+
+ fprime_select(x, minusp, x, c);
+}
+
+/* Warning: this function is variable-time */
+static int prime_msb(const uint8_t *p)
+{
+ int i;
+ uint8_t x;
+
+ for (i = FPRIME_SIZE - 1; i >= 0; i--)
+ if (p[i])
+ break;
+
+ x = p[i];
+ i <<= 3;
+
+ while (x) {
+ x >>= 1;
+ i++;
+ }
+
+ return i - 1;
+}
+
+/* Warning: this function may be variable-time in the argument n */
+static void shift_n_bits(uint8_t *x, int n)
+{
+ uint16_t c = 0;
+ int i;
+
+ for (i = 0; i < FPRIME_SIZE; i++) {
+ c |= ((uint16_t)x[i]) << n;
+ x[i] = c;
+ c >>= 8;
+ }
+}
+
+void fprime_load(uint8_t *x, uint32_t c)
+{
+ unsigned int i;
+
+ for (i = 0; i < sizeof(c); i++) {
+ x[i] = c;
+ c >>= 8;
+ }
+
+ for (; i < FPRIME_SIZE; i++)
+ x[i] = 0;
+}
+
+static inline int min_int(int a, int b)
+{
+ return a < b ? a : b;
+}
+
+void fprime_from_bytes(uint8_t *n,
+ const uint8_t *x, size_t len,
+ const uint8_t *modulus)
+{
+ const int preload_total = min_int(prime_msb(modulus) - 1, len << 3);
+ const int preload_bytes = preload_total >> 3;
+ const int preload_bits = preload_total & 7;
+ const int rbits = (len << 3) - preload_total;
+ int i;
+
+ memset(n, 0, FPRIME_SIZE);
+
+ for (i = 0; i < preload_bytes; i++)
+ n[i] = x[len - preload_bytes + i];
+
+ if (preload_bits) {
+ shift_n_bits(n, preload_bits);
+ n[0] |= x[len - preload_bytes - 1] >> (8 - preload_bits);
+ }
+
+ for (i = rbits - 1; i >= 0; i--) {
+ const uint8_t bit = (x[i >> 3] >> (i & 7)) & 1;
+
+ shift_n_bits(n, 1);
+ n[0] |= bit;
+ raw_try_sub(n, modulus);
+ }
+}
+
+void fprime_normalize(uint8_t *x, const uint8_t *modulus)
+{
+ uint8_t n[FPRIME_SIZE];
+
+ fprime_from_bytes(n, x, FPRIME_SIZE, modulus);
+ fprime_copy(x, n);
+}
+
+uint8_t fprime_eq(const uint8_t *x, const uint8_t *y)
+{
+ uint8_t sum = 0;
+ int i;
+
+ for (i = 0; i < FPRIME_SIZE; i++)
+ sum |= x[i] ^ y[i];
+
+ sum |= (sum >> 4);
+ sum |= (sum >> 2);
+ sum |= (sum >> 1);
+
+ return (sum ^ 1) & 1;
+}
+
+void fprime_select(uint8_t *dst,
+ const uint8_t *zero, const uint8_t *one,
+ uint8_t condition)
+{
+ const uint8_t mask = -condition;
+ int i;
+
+ for (i = 0; i < FPRIME_SIZE; i++)
+ dst[i] = zero[i] ^ (mask & (one[i] ^ zero[i]));
+}
+
+void fprime_add(uint8_t *r, const uint8_t *a, const uint8_t *modulus)
+{
+ raw_add(r, a);
+ raw_try_sub(r, modulus);
+}
+
+void fprime_sub(uint8_t *r, const uint8_t *a, const uint8_t *modulus)
+{
+ raw_add(r, modulus);
+ raw_try_sub(r, a);
+ raw_try_sub(r, modulus);
+}
+
+void fprime_mul(uint8_t *r, const uint8_t *a, const uint8_t *b,
+ const uint8_t *modulus)
+{
+ int i;
+
+ memset(r, 0, FPRIME_SIZE);
+
+ for (i = prime_msb(modulus); i >= 0; i--) {
+ const uint8_t bit = (b[i >> 3] >> (i & 7)) & 1;
+ uint8_t plusa[FPRIME_SIZE];
+
+ shift_n_bits(r, 1);
+ raw_try_sub(r, modulus);
+
+ fprime_copy(plusa, r);
+ fprime_add(plusa, a, modulus);
+
+ fprime_select(r, r, plusa, bit);
+ }
+}
+
+void fprime_inv(uint8_t *r, const uint8_t *a, const uint8_t *modulus)
+{
+ uint8_t pm2[FPRIME_SIZE];
+ uint16_t c = 2;
+ int i;
+
+ /* Compute (p-2) */
+ fprime_copy(pm2, modulus);
+ for (i = 0; i < FPRIME_SIZE; i++) {
+ c = modulus[i] - c;
+ pm2[i] = c;
+ c >>= 8;
+ }
+
+ /* Binary exponentiation */
+ fprime_load(r, 1);
+
+ for (i = prime_msb(modulus); i >= 0; i--) {
+ uint8_t r2[FPRIME_SIZE];
+
+ fprime_mul(r2, r, r, modulus);
+
+ if ((pm2[i >> 3] >> (i & 7)) & 1)
+ fprime_mul(r, r2, a, modulus);
+ else
+ fprime_copy(r, r2);
+ }
+}
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/c25519/fprime.h b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/c25519/fprime.h
new file mode 100644
index 0000000..4a5486c
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/c25519/fprime.h
@@ -0,0 +1,70 @@
+/* Arithmetic in prime fields
+ * Daniel Beer <dlbeer@gmail.com>, 10 Jan 2014
+ *
+ * This file is in the public domain.
+ */
+
+#ifndef FPRIME_H_
+#define FPRIME_H_
+
+#include <stdint.h>
+#include <string.h>
+
+/* Maximum size of a field element (or a prime). Field elements are
+ * always manipulated and stored in normalized form, with 0 <= x < p.
+ * You can use normalize() to convert a denormalized bitstring to normal
+ * form.
+ *
+ * Operations are constant with respect to the value of field elements,
+ * but not with respect to the modulus.
+ *
+ * The modulus is a number p, such that 2p-1 fits in FPRIME_SIZE bytes.
+ */
+#define FPRIME_SIZE 32
+
+/* Useful constants */
+extern const uint8_t fprime_zero[FPRIME_SIZE];
+extern const uint8_t fprime_one[FPRIME_SIZE];
+
+/* Load a small constant */
+void fprime_load(uint8_t *x, uint32_t c);
+
+/* Load a large constant */
+void fprime_from_bytes(uint8_t *x,
+ const uint8_t *in, size_t len,
+ const uint8_t *modulus);
+
+/* Copy an element */
+static inline void fprime_copy(uint8_t *x, const uint8_t *a)
+{
+ memcpy(x, a, FPRIME_SIZE);
+}
+
+/* Normalize a field element */
+void fprime_normalize(uint8_t *x, const uint8_t *modulus);
+
+/* Compare two field points in constant time. Return one if equal, zero
+ * otherwise. This should be performed only on normalized values.
+ */
+uint8_t fprime_eq(const uint8_t *x, const uint8_t *y);
+
+/* Conditional copy. If condition == 0, then zero is copied to dst. If
+ * condition == 1, then one is copied to dst. Any other value results in
+ * undefined behaviour.
+ */
+void fprime_select(uint8_t *dst,
+ const uint8_t *zero, const uint8_t *one,
+ uint8_t condition);
+
+/* Add one value to another. The two pointers must be distinct. */
+void fprime_add(uint8_t *r, const uint8_t *a, const uint8_t *modulus);
+void fprime_sub(uint8_t *r, const uint8_t *a, const uint8_t *modulus);
+
+/* Multiply two values to get a third. r must be distinct from a and b */
+void fprime_mul(uint8_t *r, const uint8_t *a, const uint8_t *b,
+ const uint8_t *modulus);
+
+/* Compute multiplicative inverse. r must be distinct from a */
+void fprime_inv(uint8_t *r, const uint8_t *a, const uint8_t *modulus);
+
+#endif
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/c25519/morph25519.c b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/c25519/morph25519.c
new file mode 100644
index 0000000..3d64022
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/c25519/morph25519.c
@@ -0,0 +1,87 @@
+/* Montgomery <-> Edwards isomorphism
+ * Daniel Beer <dlbeer@gmail.com>, 18 Jan 2014
+ *
+ * This file is in the public domain.
+ */
+
+#include "morph25519.h"
+#include "f25519.h"
+
+void morph25519_e2m(uint8_t *montgomery, const uint8_t *y)
+{
+ uint8_t yplus[F25519_SIZE];
+ uint8_t yminus[F25519_SIZE];
+
+ f25519_sub(yplus, f25519_one, y);
+ f25519_inv__distinct(yminus, yplus);
+ f25519_add(yplus, f25519_one, y);
+ f25519_mul__distinct(montgomery, yplus, yminus);
+ f25519_normalize(montgomery);
+}
+
+static void mx2ey(uint8_t *ey, const uint8_t *mx)
+{
+ uint8_t n[F25519_SIZE];
+ uint8_t d[F25519_SIZE];
+
+ f25519_add(n, mx, f25519_one);
+ f25519_inv__distinct(d, n);
+ f25519_sub(n, mx, f25519_one);
+ f25519_mul__distinct(ey, n, d);
+}
+
+static uint8_t ey2ex(uint8_t *x, const uint8_t *y, int parity)
+{
+ static const uint8_t d[F25519_SIZE] = {
+ 0xa3, 0x78, 0x59, 0x13, 0xca, 0x4d, 0xeb, 0x75,
+ 0xab, 0xd8, 0x41, 0x41, 0x4d, 0x0a, 0x70, 0x00,
+ 0x98, 0xe8, 0x79, 0x77, 0x79, 0x40, 0xc7, 0x8c,
+ 0x73, 0xfe, 0x6f, 0x2b, 0xee, 0x6c, 0x03, 0x52
+ };
+
+ uint8_t a[F25519_SIZE];
+ uint8_t b[F25519_SIZE];
+ uint8_t c[F25519_SIZE];
+
+ /* Compute c = y^2 */
+ f25519_mul__distinct(c, y, y);
+
+ /* Compute b = (1+dy^2)^-1 */
+ f25519_mul__distinct(b, c, d);
+ f25519_add(a, b, f25519_one);
+ f25519_inv__distinct(b, a);
+
+ /* Compute a = y^2-1 */
+ f25519_sub(a, c, f25519_one);
+
+ /* Compute c = a*b = (y^2+1)/(1-dy^2) */
+ f25519_mul__distinct(c, a, b);
+
+ /* Compute a, b = +/-sqrt(c), if c is square */
+ f25519_sqrt(a, c);
+ f25519_neg(b, a);
+
+ /* Select one of them, based on the parity bit */
+ f25519_select(x, a, b, (a[0] ^ parity) & 1);
+
+ /* Verify that x^2 = c */
+ f25519_mul__distinct(a, x, x);
+ f25519_normalize(a);
+ f25519_normalize(c);
+
+ return f25519_eq(a, c);
+}
+
+uint8_t morph25519_m2e(uint8_t *ex, uint8_t *ey,
+ const uint8_t *mx, int parity)
+{
+ uint8_t ok;
+
+ mx2ey(ey, mx);
+ ok = ey2ex(ex, ey, parity);
+
+ f25519_normalize(ex);
+ f25519_normalize(ey);
+
+ return ok;
+}
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/c25519/morph25519.h b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/c25519/morph25519.h
new file mode 100644
index 0000000..ead91f4
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/c25519/morph25519.h
@@ -0,0 +1,29 @@
+/* Montgomery <-> Edwards isomorphism
+ * Daniel Beer <dlbeer@gmail.com>, 18 Jan 2014
+ *
+ * This file is in the public domain.
+ */
+
+#ifndef MORPH25519_H_
+#define MORPH25519_H_
+
+#include <stdint.h>
+
+/* Convert an Edwards Y to a Montgomery X (Edwards X is not used).
+ * Resulting coordinate is normalized.
+ */
+void morph25519_e2m(uint8_t *montgomery_x, const uint8_t *edwards_y);
+
+/* Return a parity bit for the Edwards X coordinate */
+static inline int morph25519_eparity(const uint8_t *edwards_x)
+{
+ return edwards_x[0] & 1;
+}
+
+/* Convert a Montgomery X and a parity bit to an Edwards X/Y. Returns
+ * non-zero if successful.
+ */
+uint8_t morph25519_m2e(uint8_t *ex, uint8_t *ey,
+ const uint8_t *mx, int parity);
+
+#endif
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/c25519/sha512.c b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/c25519/sha512.c
new file mode 100644
index 0000000..d90d22d
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/c25519/sha512.c
@@ -0,0 +1,228 @@
+/* SHA512
+ * Daniel Beer <dlbeer@gmail.com>, 22 Apr 2014
+ *
+ * This file is in the public domain.
+ */
+
+#include "sha512.h"
+
+const struct sha512_state sha512_initial_state = { {
+ 0x6a09e667f3bcc908LL, 0xbb67ae8584caa73bLL,
+ 0x3c6ef372fe94f82bLL, 0xa54ff53a5f1d36f1LL,
+ 0x510e527fade682d1LL, 0x9b05688c2b3e6c1fLL,
+ 0x1f83d9abfb41bd6bLL, 0x5be0cd19137e2179LL,
+} };
+
+static const uint64_t round_k[80] = {
+ 0x428a2f98d728ae22LL, 0x7137449123ef65cdLL,
+ 0xb5c0fbcfec4d3b2fLL, 0xe9b5dba58189dbbcLL,
+ 0x3956c25bf348b538LL, 0x59f111f1b605d019LL,
+ 0x923f82a4af194f9bLL, 0xab1c5ed5da6d8118LL,
+ 0xd807aa98a3030242LL, 0x12835b0145706fbeLL,
+ 0x243185be4ee4b28cLL, 0x550c7dc3d5ffb4e2LL,
+ 0x72be5d74f27b896fLL, 0x80deb1fe3b1696b1LL,
+ 0x9bdc06a725c71235LL, 0xc19bf174cf692694LL,
+ 0xe49b69c19ef14ad2LL, 0xefbe4786384f25e3LL,
+ 0x0fc19dc68b8cd5b5LL, 0x240ca1cc77ac9c65LL,
+ 0x2de92c6f592b0275LL, 0x4a7484aa6ea6e483LL,
+ 0x5cb0a9dcbd41fbd4LL, 0x76f988da831153b5LL,
+ 0x983e5152ee66dfabLL, 0xa831c66d2db43210LL,
+ 0xb00327c898fb213fLL, 0xbf597fc7beef0ee4LL,
+ 0xc6e00bf33da88fc2LL, 0xd5a79147930aa725LL,
+ 0x06ca6351e003826fLL, 0x142929670a0e6e70LL,
+ 0x27b70a8546d22ffcLL, 0x2e1b21385c26c926LL,
+ 0x4d2c6dfc5ac42aedLL, 0x53380d139d95b3dfLL,
+ 0x650a73548baf63deLL, 0x766a0abb3c77b2a8LL,
+ 0x81c2c92e47edaee6LL, 0x92722c851482353bLL,
+ 0xa2bfe8a14cf10364LL, 0xa81a664bbc423001LL,
+ 0xc24b8b70d0f89791LL, 0xc76c51a30654be30LL,
+ 0xd192e819d6ef5218LL, 0xd69906245565a910LL,
+ 0xf40e35855771202aLL, 0x106aa07032bbd1b8LL,
+ 0x19a4c116b8d2d0c8LL, 0x1e376c085141ab53LL,
+ 0x2748774cdf8eeb99LL, 0x34b0bcb5e19b48a8LL,
+ 0x391c0cb3c5c95a63LL, 0x4ed8aa4ae3418acbLL,
+ 0x5b9cca4f7763e373LL, 0x682e6ff3d6b2b8a3LL,
+ 0x748f82ee5defb2fcLL, 0x78a5636f43172f60LL,
+ 0x84c87814a1f0ab72LL, 0x8cc702081a6439ecLL,
+ 0x90befffa23631e28LL, 0xa4506cebde82bde9LL,
+ 0xbef9a3f7b2c67915LL, 0xc67178f2e372532bLL,
+ 0xca273eceea26619cLL, 0xd186b8c721c0c207LL,
+ 0xeada7dd6cde0eb1eLL, 0xf57d4f7fee6ed178LL,
+ 0x06f067aa72176fbaLL, 0x0a637dc5a2c898a6LL,
+ 0x113f9804bef90daeLL, 0x1b710b35131c471bLL,
+ 0x28db77f523047d84LL, 0x32caab7b40c72493LL,
+ 0x3c9ebe0a15c9bebcLL, 0x431d67c49c100d4cLL,
+ 0x4cc5d4becb3e42b6LL, 0x597f299cfc657e2aLL,
+ 0x5fcb6fab3ad6faecLL, 0x6c44198c4a475817LL,
+};
+
+static inline uint64_t load64(const uint8_t *x)
+{
+ uint64_t r;
+
+ r = *(x++);
+ r = (r << 8) | *(x++);
+ r = (r << 8) | *(x++);
+ r = (r << 8) | *(x++);
+ r = (r << 8) | *(x++);
+ r = (r << 8) | *(x++);
+ r = (r << 8) | *(x++);
+ r = (r << 8) | *(x++);
+
+ return r;
+}
+
+static inline void store64(uint8_t *x, uint64_t v)
+{
+ x += 7;
+ *(x--) = v;
+ v >>= 8;
+ *(x--) = v;
+ v >>= 8;
+ *(x--) = v;
+ v >>= 8;
+ *(x--) = v;
+ v >>= 8;
+ *(x--) = v;
+ v >>= 8;
+ *(x--) = v;
+ v >>= 8;
+ *(x--) = v;
+ v >>= 8;
+ *(x--) = v;
+}
+
+static inline uint64_t rot64(uint64_t x, int bits)
+{
+ return (x >> bits) | (x << (64 - bits));
+}
+
+void sha512_block(struct sha512_state *s, const uint8_t *blk)
+{
+ uint64_t w[16];
+ uint64_t a, b, c, d, e, f, g, h;
+ int i;
+
+ for (i = 0; i < 16; i++) {
+ w[i] = load64(blk);
+ blk += 8;
+ }
+
+ /* Load state */
+ a = s->h[0];
+ b = s->h[1];
+ c = s->h[2];
+ d = s->h[3];
+ e = s->h[4];
+ f = s->h[5];
+ g = s->h[6];
+ h = s->h[7];
+
+ for (i = 0; i < 80; i++) {
+ /* Compute value of w[i + 16]. w[wrap(i)] is currently w[i] */
+ const uint64_t wi = w[i & 15];
+ const uint64_t wi15 = w[(i + 1) & 15];
+ const uint64_t wi2 = w[(i + 14) & 15];
+ const uint64_t wi7 = w[(i + 9) & 15];
+ const uint64_t s0 =
+ rot64(wi15, 1) ^ rot64(wi15, 8) ^ (wi15 >> 7);
+ const uint64_t s1 =
+ rot64(wi2, 19) ^ rot64(wi2, 61) ^ (wi2 >> 6);
+
+ /* Round calculations */
+ const uint64_t S0 = rot64(a, 28) ^ rot64(a, 34) ^ rot64(a, 39);
+ const uint64_t S1 = rot64(e, 14) ^ rot64(e, 18) ^ rot64(e, 41);
+ const uint64_t ch = (e & f) ^ ((~e) & g);
+ const uint64_t temp1 = h + S1 + ch + round_k[i] + wi;
+ const uint64_t maj = (a & b) ^ (a & c) ^ (b & c);
+ const uint64_t temp2 = S0 + maj;
+
+ /* Update round state */
+ h = g;
+ g = f;
+ f = e;
+ e = d + temp1;
+ d = c;
+ c = b;
+ b = a;
+ a = temp1 + temp2;
+
+ /* w[wrap(i)] becomes w[i + 16] */
+ w[i & 15] = wi + s0 + wi7 + s1;
+ }
+
+ /* Store state */
+ s->h[0] += a;
+ s->h[1] += b;
+ s->h[2] += c;
+ s->h[3] += d;
+ s->h[4] += e;
+ s->h[5] += f;
+ s->h[6] += g;
+ s->h[7] += h;
+}
+
+void sha512_final(struct sha512_state *s, const uint8_t *blk,
+ size_t total_size)
+{
+ uint8_t temp[SHA512_BLOCK_SIZE] = {0};
+ const size_t last_size = total_size & (SHA512_BLOCK_SIZE - 1);
+
+ if (last_size)
+ memcpy(temp, blk, last_size);
+ temp[last_size] = 0x80;
+
+ if (last_size > 111) {
+ sha512_block(s, temp);
+ memset(temp, 0, sizeof(temp));
+ }
+
+ /* Note: we assume total_size fits in 61 bits */
+ store64(temp + SHA512_BLOCK_SIZE - 8, total_size << 3);
+ sha512_block(s, temp);
+}
+
+void sha512_get(const struct sha512_state *s, uint8_t *hash,
+ unsigned int offset, unsigned int len)
+{
+ int i;
+
+ if (offset > SHA512_BLOCK_SIZE)
+ return;
+
+ if (len > SHA512_BLOCK_SIZE - offset)
+ len = SHA512_BLOCK_SIZE - offset;
+
+ /* Skip whole words */
+ i = offset >> 3;
+ offset &= 7;
+
+ /* Skip/read out bytes */
+ if (offset) {
+ uint8_t tmp[8];
+ unsigned int c = 8 - offset;
+
+ if (c > len)
+ c = len;
+
+ store64(tmp, s->h[i++]);
+ memcpy(hash, tmp + offset, c);
+ len -= c;
+ hash += c;
+ }
+
+ /* Read out whole words */
+ while (len >= 8) {
+ store64(hash, s->h[i++]);
+ hash += 8;
+ len -= 8;
+ }
+
+ /* Read out bytes */
+ if (len) {
+ uint8_t tmp[8];
+
+ store64(tmp, s->h[i]);
+ memcpy(hash, tmp, len);
+ }
+}
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/c25519/sha512.h b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/c25519/sha512.h
new file mode 100644
index 0000000..1391745
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/c25519/sha512.h
@@ -0,0 +1,52 @@
+/* SHA512
+ * Daniel Beer <dlbeer@gmail.com>, 22 Apr 2014
+ *
+ * This file is in the public domain.
+ */
+
+#ifndef SHA512_H_
+#define SHA512_H_
+
+#include <stdint.h>
+#include <stddef.h>
+#include <string.h>
+
+/* SHA512 state. State is updated as data is fed in, and then the final
+ * hash can be read out in slices.
+ *
+ * Data is fed in as a sequence of full blocks terminated by a single
+ * partial block.
+ */
+struct sha512_state {
+ uint64_t h[8];
+};
+
+/* Initial state */
+extern const struct sha512_state sha512_initial_state;
+
+/* Set up a new context */
+static inline void sha512_init(struct sha512_state *s)
+{
+ memcpy(s, &sha512_initial_state, sizeof(*s));
+}
+
+/* Feed a full block in */
+#define SHA512_BLOCK_SIZE 128
+
+void sha512_block(struct sha512_state *s, const uint8_t *blk);
+
+/* Feed the last partial block in. The total stream size must be
+ * specified. The size of the block given is assumed to be (total_size %
+ * SHA512_BLOCK_SIZE). This might be zero, but you still need to call
+ * this function to terminate the stream.
+ */
+void sha512_final(struct sha512_state *s, const uint8_t *blk,
+ size_t total_size);
+
+/* Fetch a slice of the hash result. */
+#define SHA512_HASH_SIZE 64
+
+void sha512_get(const struct sha512_state *s, uint8_t *hash,
+ unsigned int offset, unsigned int len);
+
+#endif
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/ed25519-donna/AUTHORS.md b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/ed25519-donna/AUTHORS.md
new file mode 100644
index 0000000..79cf545
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/ed25519-donna/AUTHORS.md
@@ -0,0 +1,42 @@
+The following files have been written by Andrew Moon and have been
+dedicated to the public domain:
+
+* curve25519-donna-32bit.h
+* curve25519-donna-helpers.h
+* ed25519.c
+* modm-donna-32bit.h
+
+The following files carry no copyright information:
+
+* ed25519-donna-32bit-tables.h
+* ed25519-donna-basepoint-table.h
+* ed25519-donna-batchverify.h
+* ed25519-donna-impl-base.h
+* ed25519-donna-portable-identify.h
+* ed25519-donna-portable.h
+* ed25519-hash-custom.h
+* ed25519-hash.h
+* ed25519-randombytes.h
+* ed25519.h
+
+However, their git history shows that they were written by Andrew Moon
+as well; the initial check-in has public domain headers for all files
+(git commit a98e950f). Newer files lack a similar header, but it seems
+the author didn't realise that that adding them would be required
+(see https://github.com/floodyberry/ed25519-donna/issues/24);
+issue comment 24#issuecomment-82552250 in particular seems to suggest as
+much. It is therefore assumed that they are intended to be placed in
+the public domain as well.
+
+curve25519-donna.h has been modified by Andrew Moon, based on the
+amd64-51-30k implementation by Daniel J. Bernstein, Niels Duif,
+Tanja Lange, Peter Schwabe, and Bo-Yin Yang. The amd64-51-30k
+implementation is contained in SUPERCOP
+(<https://bench.cr.yp.to/supercop.html>);
+the amd64-51-30k is part of the Ed25519 software, which has been
+dedicated to the public domain by its authors
+(<https://ed25519.cr.yp.to/software.html>).
+
+The code in this directory has been obtained via
+<https://www.github.com/floodyberry/ed25519-donna>.
+
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/ed25519-donna/curve25519-donna-32bit.h b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/ed25519-donna/curve25519-donna-32bit.h
new file mode 100644
index 0000000..b0861ac
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/ed25519-donna/curve25519-donna-32bit.h
@@ -0,0 +1,579 @@
+/*
+ Public domain by Andrew M. <liquidsun@gmail.com>
+ See: https://github.com/floodyberry/curve25519-donna
+
+ 32 bit integer curve25519 implementation
+*/
+
+typedef uint32_t bignum25519[10];
+typedef uint32_t bignum25519align16[12];
+
+static const uint32_t reduce_mask_25 = (1 << 25) - 1;
+static const uint32_t reduce_mask_26 = (1 << 26) - 1;
+
+
+/* out = in */
+DONNA_INLINE static void
+curve25519_copy(bignum25519 out, const bignum25519 in) {
+ out[0] = in[0];
+ out[1] = in[1];
+ out[2] = in[2];
+ out[3] = in[3];
+ out[4] = in[4];
+ out[5] = in[5];
+ out[6] = in[6];
+ out[7] = in[7];
+ out[8] = in[8];
+ out[9] = in[9];
+}
+
+/* out = a + b */
+DONNA_INLINE static void
+curve25519_add(bignum25519 out, const bignum25519 a, const bignum25519 b) {
+ out[0] = a[0] + b[0];
+ out[1] = a[1] + b[1];
+ out[2] = a[2] + b[2];
+ out[3] = a[3] + b[3];
+ out[4] = a[4] + b[4];
+ out[5] = a[5] + b[5];
+ out[6] = a[6] + b[6];
+ out[7] = a[7] + b[7];
+ out[8] = a[8] + b[8];
+ out[9] = a[9] + b[9];
+}
+
+DONNA_INLINE static void
+curve25519_add_after_basic(bignum25519 out, const bignum25519 a, const bignum25519 b) {
+ uint32_t c;
+ out[0] = a[0] + b[0] ; c = (out[0] >> 26); out[0] &= reduce_mask_26;
+ out[1] = a[1] + b[1] + c; c = (out[1] >> 25); out[1] &= reduce_mask_25;
+ out[2] = a[2] + b[2] + c; c = (out[2] >> 26); out[2] &= reduce_mask_26;
+ out[3] = a[3] + b[3] + c; c = (out[3] >> 25); out[3] &= reduce_mask_25;
+ out[4] = a[4] + b[4] + c; c = (out[4] >> 26); out[4] &= reduce_mask_26;
+ out[5] = a[5] + b[5] + c; c = (out[5] >> 25); out[5] &= reduce_mask_25;
+ out[6] = a[6] + b[6] + c; c = (out[6] >> 26); out[6] &= reduce_mask_26;
+ out[7] = a[7] + b[7] + c; c = (out[7] >> 25); out[7] &= reduce_mask_25;
+ out[8] = a[8] + b[8] + c; c = (out[8] >> 26); out[8] &= reduce_mask_26;
+ out[9] = a[9] + b[9] + c; c = (out[9] >> 25); out[9] &= reduce_mask_25;
+ out[0] += 19 * c;
+}
+
+DONNA_INLINE static void
+curve25519_add_reduce(bignum25519 out, const bignum25519 a, const bignum25519 b) {
+ uint32_t c;
+ out[0] = a[0] + b[0] ; c = (out[0] >> 26); out[0] &= reduce_mask_26;
+ out[1] = a[1] + b[1] + c; c = (out[1] >> 25); out[1] &= reduce_mask_25;
+ out[2] = a[2] + b[2] + c; c = (out[2] >> 26); out[2] &= reduce_mask_26;
+ out[3] = a[3] + b[3] + c; c = (out[3] >> 25); out[3] &= reduce_mask_25;
+ out[4] = a[4] + b[4] + c; c = (out[4] >> 26); out[4] &= reduce_mask_26;
+ out[5] = a[5] + b[5] + c; c = (out[5] >> 25); out[5] &= reduce_mask_25;
+ out[6] = a[6] + b[6] + c; c = (out[6] >> 26); out[6] &= reduce_mask_26;
+ out[7] = a[7] + b[7] + c; c = (out[7] >> 25); out[7] &= reduce_mask_25;
+ out[8] = a[8] + b[8] + c; c = (out[8] >> 26); out[8] &= reduce_mask_26;
+ out[9] = a[9] + b[9] + c; c = (out[9] >> 25); out[9] &= reduce_mask_25;
+ out[0] += 19 * c;
+}
+
+/* multiples of p */
+static const uint32_t twoP0 = 0x07ffffda;
+static const uint32_t twoP13579 = 0x03fffffe;
+static const uint32_t twoP2468 = 0x07fffffe;
+static const uint32_t fourP0 = 0x0fffffb4;
+static const uint32_t fourP13579 = 0x07fffffc;
+static const uint32_t fourP2468 = 0x0ffffffc;
+
+/* out = a - b */
+DONNA_INLINE static void
+curve25519_sub(bignum25519 out, const bignum25519 a, const bignum25519 b) {
+ uint32_t c;
+ out[0] = twoP0 + a[0] - b[0] ; c = (out[0] >> 26); out[0] &= reduce_mask_26;
+ out[1] = twoP13579 + a[1] - b[1] + c; c = (out[1] >> 25); out[1] &= reduce_mask_25;
+ out[2] = twoP2468 + a[2] - b[2] + c; c = (out[2] >> 26); out[2] &= reduce_mask_26;
+ out[3] = twoP13579 + a[3] - b[3] + c; c = (out[3] >> 25); out[3] &= reduce_mask_25;
+ out[4] = twoP2468 + a[4] - b[4] + c;
+ out[5] = twoP13579 + a[5] - b[5] ;
+ out[6] = twoP2468 + a[6] - b[6] ;
+ out[7] = twoP13579 + a[7] - b[7] ;
+ out[8] = twoP2468 + a[8] - b[8] ;
+ out[9] = twoP13579 + a[9] - b[9] ;
+}
+
+/* out = a - b, where a is the result of a basic op (add,sub) */
+DONNA_INLINE static void
+curve25519_sub_after_basic(bignum25519 out, const bignum25519 a, const bignum25519 b) {
+ uint32_t c;
+ out[0] = fourP0 + a[0] - b[0] ; c = (out[0] >> 26); out[0] &= reduce_mask_26;
+ out[1] = fourP13579 + a[1] - b[1] + c; c = (out[1] >> 25); out[1] &= reduce_mask_25;
+ out[2] = fourP2468 + a[2] - b[2] + c; c = (out[2] >> 26); out[2] &= reduce_mask_26;
+ out[3] = fourP13579 + a[3] - b[3] + c; c = (out[3] >> 25); out[3] &= reduce_mask_25;
+ out[4] = fourP2468 + a[4] - b[4] + c; c = (out[4] >> 26); out[4] &= reduce_mask_26;
+ out[5] = fourP13579 + a[5] - b[5] + c; c = (out[5] >> 25); out[5] &= reduce_mask_25;
+ out[6] = fourP2468 + a[6] - b[6] + c; c = (out[6] >> 26); out[6] &= reduce_mask_26;
+ out[7] = fourP13579 + a[7] - b[7] + c; c = (out[7] >> 25); out[7] &= reduce_mask_25;
+ out[8] = fourP2468 + a[8] - b[8] + c; c = (out[8] >> 26); out[8] &= reduce_mask_26;
+ out[9] = fourP13579 + a[9] - b[9] + c; c = (out[9] >> 25); out[9] &= reduce_mask_25;
+ out[0] += 19 * c;
+}
+
+DONNA_INLINE static void
+curve25519_sub_reduce(bignum25519 out, const bignum25519 a, const bignum25519 b) {
+ uint32_t c;
+ out[0] = fourP0 + a[0] - b[0] ; c = (out[0] >> 26); out[0] &= reduce_mask_26;
+ out[1] = fourP13579 + a[1] - b[1] + c; c = (out[1] >> 25); out[1] &= reduce_mask_25;
+ out[2] = fourP2468 + a[2] - b[2] + c; c = (out[2] >> 26); out[2] &= reduce_mask_26;
+ out[3] = fourP13579 + a[3] - b[3] + c; c = (out[3] >> 25); out[3] &= reduce_mask_25;
+ out[4] = fourP2468 + a[4] - b[4] + c; c = (out[4] >> 26); out[4] &= reduce_mask_26;
+ out[5] = fourP13579 + a[5] - b[5] + c; c = (out[5] >> 25); out[5] &= reduce_mask_25;
+ out[6] = fourP2468 + a[6] - b[6] + c; c = (out[6] >> 26); out[6] &= reduce_mask_26;
+ out[7] = fourP13579 + a[7] - b[7] + c; c = (out[7] >> 25); out[7] &= reduce_mask_25;
+ out[8] = fourP2468 + a[8] - b[8] + c; c = (out[8] >> 26); out[8] &= reduce_mask_26;
+ out[9] = fourP13579 + a[9] - b[9] + c; c = (out[9] >> 25); out[9] &= reduce_mask_25;
+ out[0] += 19 * c;
+}
+
+/* out = -a */
+DONNA_INLINE static void
+curve25519_neg(bignum25519 out, const bignum25519 a) {
+ uint32_t c;
+ out[0] = twoP0 - a[0] ; c = (out[0] >> 26); out[0] &= reduce_mask_26;
+ out[1] = twoP13579 - a[1] + c; c = (out[1] >> 25); out[1] &= reduce_mask_25;
+ out[2] = twoP2468 - a[2] + c; c = (out[2] >> 26); out[2] &= reduce_mask_26;
+ out[3] = twoP13579 - a[3] + c; c = (out[3] >> 25); out[3] &= reduce_mask_25;
+ out[4] = twoP2468 - a[4] + c; c = (out[4] >> 26); out[4] &= reduce_mask_26;
+ out[5] = twoP13579 - a[5] + c; c = (out[5] >> 25); out[5] &= reduce_mask_25;
+ out[6] = twoP2468 - a[6] + c; c = (out[6] >> 26); out[6] &= reduce_mask_26;
+ out[7] = twoP13579 - a[7] + c; c = (out[7] >> 25); out[7] &= reduce_mask_25;
+ out[8] = twoP2468 - a[8] + c; c = (out[8] >> 26); out[8] &= reduce_mask_26;
+ out[9] = twoP13579 - a[9] + c; c = (out[9] >> 25); out[9] &= reduce_mask_25;
+ out[0] += 19 * c;
+}
+
+/* out = a * b */
+#define curve25519_mul_noinline curve25519_mul
+static void
+curve25519_mul(bignum25519 out, const bignum25519 a, const bignum25519 b) {
+ uint32_t r0,r1,r2,r3,r4,r5,r6,r7,r8,r9;
+ uint32_t s0,s1,s2,s3,s4,s5,s6,s7,s8,s9;
+ uint64_t m0,m1,m2,m3,m4,m5,m6,m7,m8,m9,c;
+ uint32_t p;
+
+ r0 = b[0];
+ r1 = b[1];
+ r2 = b[2];
+ r3 = b[3];
+ r4 = b[4];
+ r5 = b[5];
+ r6 = b[6];
+ r7 = b[7];
+ r8 = b[8];
+ r9 = b[9];
+
+ s0 = a[0];
+ s1 = a[1];
+ s2 = a[2];
+ s3 = a[3];
+ s4 = a[4];
+ s5 = a[5];
+ s6 = a[6];
+ s7 = a[7];
+ s8 = a[8];
+ s9 = a[9];
+
+ m1 = mul32x32_64(r0, s1) + mul32x32_64(r1, s0);
+ m3 = mul32x32_64(r0, s3) + mul32x32_64(r1, s2) + mul32x32_64(r2, s1) + mul32x32_64(r3, s0);
+ m5 = mul32x32_64(r0, s5) + mul32x32_64(r1, s4) + mul32x32_64(r2, s3) + mul32x32_64(r3, s2) + mul32x32_64(r4, s1) + mul32x32_64(r5, s0);
+ m7 = mul32x32_64(r0, s7) + mul32x32_64(r1, s6) + mul32x32_64(r2, s5) + mul32x32_64(r3, s4) + mul32x32_64(r4, s3) + mul32x32_64(r5, s2) + mul32x32_64(r6, s1) + mul32x32_64(r7, s0);
+ m9 = mul32x32_64(r0, s9) + mul32x32_64(r1, s8) + mul32x32_64(r2, s7) + mul32x32_64(r3, s6) + mul32x32_64(r4, s5) + mul32x32_64(r5, s4) + mul32x32_64(r6, s3) + mul32x32_64(r7, s2) + mul32x32_64(r8, s1) + mul32x32_64(r9, s0);
+
+ r1 *= 2;
+ r3 *= 2;
+ r5 *= 2;
+ r7 *= 2;
+
+ m0 = mul32x32_64(r0, s0);
+ m2 = mul32x32_64(r0, s2) + mul32x32_64(r1, s1) + mul32x32_64(r2, s0);
+ m4 = mul32x32_64(r0, s4) + mul32x32_64(r1, s3) + mul32x32_64(r2, s2) + mul32x32_64(r3, s1) + mul32x32_64(r4, s0);
+ m6 = mul32x32_64(r0, s6) + mul32x32_64(r1, s5) + mul32x32_64(r2, s4) + mul32x32_64(r3, s3) + mul32x32_64(r4, s2) + mul32x32_64(r5, s1) + mul32x32_64(r6, s0);
+ m8 = mul32x32_64(r0, s8) + mul32x32_64(r1, s7) + mul32x32_64(r2, s6) + mul32x32_64(r3, s5) + mul32x32_64(r4, s4) + mul32x32_64(r5, s3) + mul32x32_64(r6, s2) + mul32x32_64(r7, s1) + mul32x32_64(r8, s0);
+
+ r1 *= 19;
+ r2 *= 19;
+ r3 = (r3 / 2) * 19;
+ r4 *= 19;
+ r5 = (r5 / 2) * 19;
+ r6 *= 19;
+ r7 = (r7 / 2) * 19;
+ r8 *= 19;
+ r9 *= 19;
+
+ m1 += (mul32x32_64(r9, s2) + mul32x32_64(r8, s3) + mul32x32_64(r7, s4) + mul32x32_64(r6, s5) + mul32x32_64(r5, s6) + mul32x32_64(r4, s7) + mul32x32_64(r3, s8) + mul32x32_64(r2, s9));
+ m3 += (mul32x32_64(r9, s4) + mul32x32_64(r8, s5) + mul32x32_64(r7, s6) + mul32x32_64(r6, s7) + mul32x32_64(r5, s8) + mul32x32_64(r4, s9));
+ m5 += (mul32x32_64(r9, s6) + mul32x32_64(r8, s7) + mul32x32_64(r7, s8) + mul32x32_64(r6, s9));
+ m7 += (mul32x32_64(r9, s8) + mul32x32_64(r8, s9));
+
+ r3 *= 2;
+ r5 *= 2;
+ r7 *= 2;
+ r9 *= 2;
+
+ m0 += (mul32x32_64(r9, s1) + mul32x32_64(r8, s2) + mul32x32_64(r7, s3) + mul32x32_64(r6, s4) + mul32x32_64(r5, s5) + mul32x32_64(r4, s6) + mul32x32_64(r3, s7) + mul32x32_64(r2, s8) + mul32x32_64(r1, s9));
+ m2 += (mul32x32_64(r9, s3) + mul32x32_64(r8, s4) + mul32x32_64(r7, s5) + mul32x32_64(r6, s6) + mul32x32_64(r5, s7) + mul32x32_64(r4, s8) + mul32x32_64(r3, s9));
+ m4 += (mul32x32_64(r9, s5) + mul32x32_64(r8, s6) + mul32x32_64(r7, s7) + mul32x32_64(r6, s8) + mul32x32_64(r5, s9));
+ m6 += (mul32x32_64(r9, s7) + mul32x32_64(r8, s8) + mul32x32_64(r7, s9));
+ m8 += (mul32x32_64(r9, s9));
+
+ r0 = (uint32_t)m0 & reduce_mask_26; c = (m0 >> 26);
+ m1 += c; r1 = (uint32_t)m1 & reduce_mask_25; c = (m1 >> 25);
+ m2 += c; r2 = (uint32_t)m2 & reduce_mask_26; c = (m2 >> 26);
+ m3 += c; r3 = (uint32_t)m3 & reduce_mask_25; c = (m3 >> 25);
+ m4 += c; r4 = (uint32_t)m4 & reduce_mask_26; c = (m4 >> 26);
+ m5 += c; r5 = (uint32_t)m5 & reduce_mask_25; c = (m5 >> 25);
+ m6 += c; r6 = (uint32_t)m6 & reduce_mask_26; c = (m6 >> 26);
+ m7 += c; r7 = (uint32_t)m7 & reduce_mask_25; c = (m7 >> 25);
+ m8 += c; r8 = (uint32_t)m8 & reduce_mask_26; c = (m8 >> 26);
+ m9 += c; r9 = (uint32_t)m9 & reduce_mask_25; p = (uint32_t)(m9 >> 25);
+ m0 = r0 + mul32x32_64(p,19); r0 = (uint32_t)m0 & reduce_mask_26; p = (uint32_t)(m0 >> 26);
+ r1 += p;
+
+ out[0] = r0;
+ out[1] = r1;
+ out[2] = r2;
+ out[3] = r3;
+ out[4] = r4;
+ out[5] = r5;
+ out[6] = r6;
+ out[7] = r7;
+ out[8] = r8;
+ out[9] = r9;
+}
+
+/* out = in*in */
+static void
+curve25519_square(bignum25519 out, const bignum25519 in) {
+ uint32_t r0,r1,r2,r3,r4,r5,r6,r7,r8,r9;
+ uint32_t d6,d7,d8,d9;
+ uint64_t m0,m1,m2,m3,m4,m5,m6,m7,m8,m9,c;
+ uint32_t p;
+
+ r0 = in[0];
+ r1 = in[1];
+ r2 = in[2];
+ r3 = in[3];
+ r4 = in[4];
+ r5 = in[5];
+ r6 = in[6];
+ r7 = in[7];
+ r8 = in[8];
+ r9 = in[9];
+
+ m0 = mul32x32_64(r0, r0);
+ r0 *= 2;
+ m1 = mul32x32_64(r0, r1);
+ m2 = mul32x32_64(r0, r2) + mul32x32_64(r1, r1 * 2);
+ r1 *= 2;
+ m3 = mul32x32_64(r0, r3) + mul32x32_64(r1, r2 );
+ m4 = mul32x32_64(r0, r4) + mul32x32_64(r1, r3 * 2) + mul32x32_64(r2, r2);
+ r2 *= 2;
+ m5 = mul32x32_64(r0, r5) + mul32x32_64(r1, r4 ) + mul32x32_64(r2, r3);
+ m6 = mul32x32_64(r0, r6) + mul32x32_64(r1, r5 * 2) + mul32x32_64(r2, r4) + mul32x32_64(r3, r3 * 2);
+ r3 *= 2;
+ m7 = mul32x32_64(r0, r7) + mul32x32_64(r1, r6 ) + mul32x32_64(r2, r5) + mul32x32_64(r3, r4 );
+ m8 = mul32x32_64(r0, r8) + mul32x32_64(r1, r7 * 2) + mul32x32_64(r2, r6) + mul32x32_64(r3, r5 * 2) + mul32x32_64(r4, r4 );
+ m9 = mul32x32_64(r0, r9) + mul32x32_64(r1, r8 ) + mul32x32_64(r2, r7) + mul32x32_64(r3, r6 ) + mul32x32_64(r4, r5 * 2);
+
+ d6 = r6 * 19;
+ d7 = r7 * 2 * 19;
+ d8 = r8 * 19;
+ d9 = r9 * 2 * 19;
+
+ m0 += (mul32x32_64(d9, r1 ) + mul32x32_64(d8, r2 ) + mul32x32_64(d7, r3 ) + mul32x32_64(d6, r4 * 2) + mul32x32_64(r5, r5 * 2 * 19));
+ m1 += (mul32x32_64(d9, r2 / 2) + mul32x32_64(d8, r3 ) + mul32x32_64(d7, r4 ) + mul32x32_64(d6, r5 * 2));
+ m2 += (mul32x32_64(d9, r3 ) + mul32x32_64(d8, r4 * 2) + mul32x32_64(d7, r5 * 2) + mul32x32_64(d6, r6 ));
+ m3 += (mul32x32_64(d9, r4 ) + mul32x32_64(d8, r5 * 2) + mul32x32_64(d7, r6 ));
+ m4 += (mul32x32_64(d9, r5 * 2) + mul32x32_64(d8, r6 * 2) + mul32x32_64(d7, r7 ));
+ m5 += (mul32x32_64(d9, r6 ) + mul32x32_64(d8, r7 * 2));
+ m6 += (mul32x32_64(d9, r7 * 2) + mul32x32_64(d8, r8 ));
+ m7 += (mul32x32_64(d9, r8 ));
+ m8 += (mul32x32_64(d9, r9 ));
+
+ r0 = (uint32_t)m0 & reduce_mask_26; c = (m0 >> 26);
+ m1 += c; r1 = (uint32_t)m1 & reduce_mask_25; c = (m1 >> 25);
+ m2 += c; r2 = (uint32_t)m2 & reduce_mask_26; c = (m2 >> 26);
+ m3 += c; r3 = (uint32_t)m3 & reduce_mask_25; c = (m3 >> 25);
+ m4 += c; r4 = (uint32_t)m4 & reduce_mask_26; c = (m4 >> 26);
+ m5 += c; r5 = (uint32_t)m5 & reduce_mask_25; c = (m5 >> 25);
+ m6 += c; r6 = (uint32_t)m6 & reduce_mask_26; c = (m6 >> 26);
+ m7 += c; r7 = (uint32_t)m7 & reduce_mask_25; c = (m7 >> 25);
+ m8 += c; r8 = (uint32_t)m8 & reduce_mask_26; c = (m8 >> 26);
+ m9 += c; r9 = (uint32_t)m9 & reduce_mask_25; p = (uint32_t)(m9 >> 25);
+ m0 = r0 + mul32x32_64(p,19); r0 = (uint32_t)m0 & reduce_mask_26; p = (uint32_t)(m0 >> 26);
+ r1 += p;
+
+ out[0] = r0;
+ out[1] = r1;
+ out[2] = r2;
+ out[3] = r3;
+ out[4] = r4;
+ out[5] = r5;
+ out[6] = r6;
+ out[7] = r7;
+ out[8] = r8;
+ out[9] = r9;
+}
+
+
+/* out = in ^ (2 * count) */
+static void
+curve25519_square_times(bignum25519 out, const bignum25519 in, int count) {
+ uint32_t r0,r1,r2,r3,r4,r5,r6,r7,r8,r9;
+ uint32_t d6,d7,d8,d9;
+ uint64_t m0,m1,m2,m3,m4,m5,m6,m7,m8,m9,c;
+ uint32_t p;
+
+ r0 = in[0];
+ r1 = in[1];
+ r2 = in[2];
+ r3 = in[3];
+ r4 = in[4];
+ r5 = in[5];
+ r6 = in[6];
+ r7 = in[7];
+ r8 = in[8];
+ r9 = in[9];
+
+ do {
+ m0 = mul32x32_64(r0, r0);
+ r0 *= 2;
+ m1 = mul32x32_64(r0, r1);
+ m2 = mul32x32_64(r0, r2) + mul32x32_64(r1, r1 * 2);
+ r1 *= 2;
+ m3 = mul32x32_64(r0, r3) + mul32x32_64(r1, r2 );
+ m4 = mul32x32_64(r0, r4) + mul32x32_64(r1, r3 * 2) + mul32x32_64(r2, r2);
+ r2 *= 2;
+ m5 = mul32x32_64(r0, r5) + mul32x32_64(r1, r4 ) + mul32x32_64(r2, r3);
+ m6 = mul32x32_64(r0, r6) + mul32x32_64(r1, r5 * 2) + mul32x32_64(r2, r4) + mul32x32_64(r3, r3 * 2);
+ r3 *= 2;
+ m7 = mul32x32_64(r0, r7) + mul32x32_64(r1, r6 ) + mul32x32_64(r2, r5) + mul32x32_64(r3, r4 );
+ m8 = mul32x32_64(r0, r8) + mul32x32_64(r1, r7 * 2) + mul32x32_64(r2, r6) + mul32x32_64(r3, r5 * 2) + mul32x32_64(r4, r4 );
+ m9 = mul32x32_64(r0, r9) + mul32x32_64(r1, r8 ) + mul32x32_64(r2, r7) + mul32x32_64(r3, r6 ) + mul32x32_64(r4, r5 * 2);
+
+ d6 = r6 * 19;
+ d7 = r7 * 2 * 19;
+ d8 = r8 * 19;
+ d9 = r9 * 2 * 19;
+
+ m0 += (mul32x32_64(d9, r1 ) + mul32x32_64(d8, r2 ) + mul32x32_64(d7, r3 ) + mul32x32_64(d6, r4 * 2) + mul32x32_64(r5, r5 * 2 * 19));
+ m1 += (mul32x32_64(d9, r2 / 2) + mul32x32_64(d8, r3 ) + mul32x32_64(d7, r4 ) + mul32x32_64(d6, r5 * 2));
+ m2 += (mul32x32_64(d9, r3 ) + mul32x32_64(d8, r4 * 2) + mul32x32_64(d7, r5 * 2) + mul32x32_64(d6, r6 ));
+ m3 += (mul32x32_64(d9, r4 ) + mul32x32_64(d8, r5 * 2) + mul32x32_64(d7, r6 ));
+ m4 += (mul32x32_64(d9, r5 * 2) + mul32x32_64(d8, r6 * 2) + mul32x32_64(d7, r7 ));
+ m5 += (mul32x32_64(d9, r6 ) + mul32x32_64(d8, r7 * 2));
+ m6 += (mul32x32_64(d9, r7 * 2) + mul32x32_64(d8, r8 ));
+ m7 += (mul32x32_64(d9, r8 ));
+ m8 += (mul32x32_64(d9, r9 ));
+
+ r0 = (uint32_t)m0 & reduce_mask_26; c = (m0 >> 26);
+ m1 += c; r1 = (uint32_t)m1 & reduce_mask_25; c = (m1 >> 25);
+ m2 += c; r2 = (uint32_t)m2 & reduce_mask_26; c = (m2 >> 26);
+ m3 += c; r3 = (uint32_t)m3 & reduce_mask_25; c = (m3 >> 25);
+ m4 += c; r4 = (uint32_t)m4 & reduce_mask_26; c = (m4 >> 26);
+ m5 += c; r5 = (uint32_t)m5 & reduce_mask_25; c = (m5 >> 25);
+ m6 += c; r6 = (uint32_t)m6 & reduce_mask_26; c = (m6 >> 26);
+ m7 += c; r7 = (uint32_t)m7 & reduce_mask_25; c = (m7 >> 25);
+ m8 += c; r8 = (uint32_t)m8 & reduce_mask_26; c = (m8 >> 26);
+ m9 += c; r9 = (uint32_t)m9 & reduce_mask_25; p = (uint32_t)(m9 >> 25);
+ m0 = r0 + mul32x32_64(p,19); r0 = (uint32_t)m0 & reduce_mask_26; p = (uint32_t)(m0 >> 26);
+ r1 += p;
+ } while (--count);
+
+ out[0] = r0;
+ out[1] = r1;
+ out[2] = r2;
+ out[3] = r3;
+ out[4] = r4;
+ out[5] = r5;
+ out[6] = r6;
+ out[7] = r7;
+ out[8] = r8;
+ out[9] = r9;
+}
+
+/* Take a little-endian, 32-byte number and expand it into polynomial form */
+static void
+curve25519_expand(bignum25519 out, const unsigned char in[32]) {
+ static const union { uint8_t b[2]; uint16_t s; } endian_check = {{1,0}};
+ uint32_t x0,x1,x2,x3,x4,x5,x6,x7;
+
+ if (endian_check.s == 1) {
+ x0 = *(uint32_t *)(in + 0);
+ x1 = *(uint32_t *)(in + 4);
+ x2 = *(uint32_t *)(in + 8);
+ x3 = *(uint32_t *)(in + 12);
+ x4 = *(uint32_t *)(in + 16);
+ x5 = *(uint32_t *)(in + 20);
+ x6 = *(uint32_t *)(in + 24);
+ x7 = *(uint32_t *)(in + 28);
+ } else {
+ #define F(s) \
+ ((((uint32_t)in[s + 0]) ) | \
+ (((uint32_t)in[s + 1]) << 8) | \
+ (((uint32_t)in[s + 2]) << 16) | \
+ (((uint32_t)in[s + 3]) << 24))
+ x0 = F(0);
+ x1 = F(4);
+ x2 = F(8);
+ x3 = F(12);
+ x4 = F(16);
+ x5 = F(20);
+ x6 = F(24);
+ x7 = F(28);
+ #undef F
+ }
+
+ out[0] = ( x0 ) & 0x3ffffff;
+ out[1] = ((((uint64_t)x1 << 32) | x0) >> 26) & 0x1ffffff;
+ out[2] = ((((uint64_t)x2 << 32) | x1) >> 19) & 0x3ffffff;
+ out[3] = ((((uint64_t)x3 << 32) | x2) >> 13) & 0x1ffffff;
+ out[4] = (( x3) >> 6) & 0x3ffffff;
+ out[5] = ( x4 ) & 0x1ffffff;
+ out[6] = ((((uint64_t)x5 << 32) | x4) >> 25) & 0x3ffffff;
+ out[7] = ((((uint64_t)x6 << 32) | x5) >> 19) & 0x1ffffff;
+ out[8] = ((((uint64_t)x7 << 32) | x6) >> 12) & 0x3ffffff;
+ out[9] = (( x7) >> 6) & 0x1ffffff;
+}
+
+/* Take a fully reduced polynomial form number and contract it into a
+ * little-endian, 32-byte array
+ */
+static void
+curve25519_contract(unsigned char out[32], const bignum25519 in) {
+ bignum25519 f;
+ curve25519_copy(f, in);
+
+ #define carry_pass() \
+ f[1] += f[0] >> 26; f[0] &= reduce_mask_26; \
+ f[2] += f[1] >> 25; f[1] &= reduce_mask_25; \
+ f[3] += f[2] >> 26; f[2] &= reduce_mask_26; \
+ f[4] += f[3] >> 25; f[3] &= reduce_mask_25; \
+ f[5] += f[4] >> 26; f[4] &= reduce_mask_26; \
+ f[6] += f[5] >> 25; f[5] &= reduce_mask_25; \
+ f[7] += f[6] >> 26; f[6] &= reduce_mask_26; \
+ f[8] += f[7] >> 25; f[7] &= reduce_mask_25; \
+ f[9] += f[8] >> 26; f[8] &= reduce_mask_26;
+
+ #define carry_pass_full() \
+ carry_pass() \
+ f[0] += 19 * (f[9] >> 25); f[9] &= reduce_mask_25;
+
+ #define carry_pass_final() \
+ carry_pass() \
+ f[9] &= reduce_mask_25;
+
+ carry_pass_full()
+ carry_pass_full()
+
+ /* now t is between 0 and 2^255-1, properly carried. */
+ /* case 1: between 0 and 2^255-20. case 2: between 2^255-19 and 2^255-1. */
+ f[0] += 19;
+ carry_pass_full()
+
+ /* now between 19 and 2^255-1 in both cases, and offset by 19. */
+ f[0] += (reduce_mask_26 + 1) - 19;
+ f[1] += (reduce_mask_25 + 1) - 1;
+ f[2] += (reduce_mask_26 + 1) - 1;
+ f[3] += (reduce_mask_25 + 1) - 1;
+ f[4] += (reduce_mask_26 + 1) - 1;
+ f[5] += (reduce_mask_25 + 1) - 1;
+ f[6] += (reduce_mask_26 + 1) - 1;
+ f[7] += (reduce_mask_25 + 1) - 1;
+ f[8] += (reduce_mask_26 + 1) - 1;
+ f[9] += (reduce_mask_25 + 1) - 1;
+
+ /* now between 2^255 and 2^256-20, and offset by 2^255. */
+ carry_pass_final()
+
+ #undef carry_pass
+ #undef carry_full
+ #undef carry_final
+
+ f[1] <<= 2;
+ f[2] <<= 3;
+ f[3] <<= 5;
+ f[4] <<= 6;
+ f[6] <<= 1;
+ f[7] <<= 3;
+ f[8] <<= 4;
+ f[9] <<= 6;
+
+ #define F(i, s) \
+ out[s+0] |= (unsigned char )(f[i] & 0xff); \
+ out[s+1] = (unsigned char )((f[i] >> 8) & 0xff); \
+ out[s+2] = (unsigned char )((f[i] >> 16) & 0xff); \
+ out[s+3] = (unsigned char )((f[i] >> 24) & 0xff);
+
+ out[0] = 0;
+ out[16] = 0;
+ F(0,0);
+ F(1,3);
+ F(2,6);
+ F(3,9);
+ F(4,12);
+ F(5,16);
+ F(6,19);
+ F(7,22);
+ F(8,25);
+ F(9,28);
+ #undef F
+}
+
+
+/* out = (flag) ? in : out */
+DONNA_INLINE static void
+curve25519_move_conditional_bytes(uint8_t out[96], const uint8_t in[96], uint32_t flag) {
+ const uint32_t nb = flag - 1, b = ~nb;
+ const uint32_t *inl = (const uint32_t *)in;
+ uint32_t *outl = (uint32_t *)out;
+ outl[0] = (outl[0] & nb) | (inl[0] & b);
+ outl[1] = (outl[1] & nb) | (inl[1] & b);
+ outl[2] = (outl[2] & nb) | (inl[2] & b);
+ outl[3] = (outl[3] & nb) | (inl[3] & b);
+ outl[4] = (outl[4] & nb) | (inl[4] & b);
+ outl[5] = (outl[5] & nb) | (inl[5] & b);
+ outl[6] = (outl[6] & nb) | (inl[6] & b);
+ outl[7] = (outl[7] & nb) | (inl[7] & b);
+ outl[8] = (outl[8] & nb) | (inl[8] & b);
+ outl[9] = (outl[9] & nb) | (inl[9] & b);
+ outl[10] = (outl[10] & nb) | (inl[10] & b);
+ outl[11] = (outl[11] & nb) | (inl[11] & b);
+ outl[12] = (outl[12] & nb) | (inl[12] & b);
+ outl[13] = (outl[13] & nb) | (inl[13] & b);
+ outl[14] = (outl[14] & nb) | (inl[14] & b);
+ outl[15] = (outl[15] & nb) | (inl[15] & b);
+ outl[16] = (outl[16] & nb) | (inl[16] & b);
+ outl[17] = (outl[17] & nb) | (inl[17] & b);
+ outl[18] = (outl[18] & nb) | (inl[18] & b);
+ outl[19] = (outl[19] & nb) | (inl[19] & b);
+ outl[20] = (outl[20] & nb) | (inl[20] & b);
+ outl[21] = (outl[21] & nb) | (inl[21] & b);
+ outl[22] = (outl[22] & nb) | (inl[22] & b);
+ outl[23] = (outl[23] & nb) | (inl[23] & b);
+
+}
+
+/* if (iswap) swap(a, b) */
+DONNA_INLINE static void
+curve25519_swap_conditional(bignum25519 a, bignum25519 b, uint32_t iswap) {
+ const uint32_t swap = (uint32_t)(-(int32_t)iswap);
+ uint32_t x0,x1,x2,x3,x4,x5,x6,x7,x8,x9;
+
+ x0 = swap & (a[0] ^ b[0]); a[0] ^= x0; b[0] ^= x0;
+ x1 = swap & (a[1] ^ b[1]); a[1] ^= x1; b[1] ^= x1;
+ x2 = swap & (a[2] ^ b[2]); a[2] ^= x2; b[2] ^= x2;
+ x3 = swap & (a[3] ^ b[3]); a[3] ^= x3; b[3] ^= x3;
+ x4 = swap & (a[4] ^ b[4]); a[4] ^= x4; b[4] ^= x4;
+ x5 = swap & (a[5] ^ b[5]); a[5] ^= x5; b[5] ^= x5;
+ x6 = swap & (a[6] ^ b[6]); a[6] ^= x6; b[6] ^= x6;
+ x7 = swap & (a[7] ^ b[7]); a[7] ^= x7; b[7] ^= x7;
+ x8 = swap & (a[8] ^ b[8]); a[8] ^= x8; b[8] ^= x8;
+ x9 = swap & (a[9] ^ b[9]); a[9] ^= x9; b[9] ^= x9;
+}
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/ed25519-donna/curve25519-donna-helpers.h b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/ed25519-donna/curve25519-donna-helpers.h
new file mode 100644
index 0000000..e4058ff
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/ed25519-donna/curve25519-donna-helpers.h
@@ -0,0 +1,67 @@
+/*
+ Public domain by Andrew M. <liquidsun@gmail.com>
+ See: https://github.com/floodyberry/curve25519-donna
+
+ Curve25519 implementation agnostic helpers
+*/
+
+/*
+ * In: b = 2^5 - 2^0
+ * Out: b = 2^250 - 2^0
+ */
+static void
+curve25519_pow_two5mtwo0_two250mtwo0(bignum25519 b) {
+ bignum25519 ALIGN(16) t0,c;
+
+ /* 2^5 - 2^0 */ /* b */
+ /* 2^10 - 2^5 */ curve25519_square_times(t0, b, 5);
+ /* 2^10 - 2^0 */ curve25519_mul_noinline(b, t0, b);
+ /* 2^20 - 2^10 */ curve25519_square_times(t0, b, 10);
+ /* 2^20 - 2^0 */ curve25519_mul_noinline(c, t0, b);
+ /* 2^40 - 2^20 */ curve25519_square_times(t0, c, 20);
+ /* 2^40 - 2^0 */ curve25519_mul_noinline(t0, t0, c);
+ /* 2^50 - 2^10 */ curve25519_square_times(t0, t0, 10);
+ /* 2^50 - 2^0 */ curve25519_mul_noinline(b, t0, b);
+ /* 2^100 - 2^50 */ curve25519_square_times(t0, b, 50);
+ /* 2^100 - 2^0 */ curve25519_mul_noinline(c, t0, b);
+ /* 2^200 - 2^100 */ curve25519_square_times(t0, c, 100);
+ /* 2^200 - 2^0 */ curve25519_mul_noinline(t0, t0, c);
+ /* 2^250 - 2^50 */ curve25519_square_times(t0, t0, 50);
+ /* 2^250 - 2^0 */ curve25519_mul_noinline(b, t0, b);
+}
+
+/*
+ * z^(p - 2) = z(2^255 - 21)
+ */
+static void
+curve25519_recip(bignum25519 out, const bignum25519 z) {
+ bignum25519 ALIGN(16) a,t0,b;
+
+ /* 2 */ curve25519_square_times(a, z, 1); /* a = 2 */
+ /* 8 */ curve25519_square_times(t0, a, 2);
+ /* 9 */ curve25519_mul_noinline(b, t0, z); /* b = 9 */
+ /* 11 */ curve25519_mul_noinline(a, b, a); /* a = 11 */
+ /* 22 */ curve25519_square_times(t0, a, 1);
+ /* 2^5 - 2^0 = 31 */ curve25519_mul_noinline(b, t0, b);
+ /* 2^250 - 2^0 */ curve25519_pow_two5mtwo0_two250mtwo0(b);
+ /* 2^255 - 2^5 */ curve25519_square_times(b, b, 5);
+ /* 2^255 - 21 */ curve25519_mul_noinline(out, b, a);
+}
+
+/*
+ * z^((p-5)/8) = z^(2^252 - 3)
+ */
+static void
+curve25519_pow_two252m3(bignum25519 two252m3, const bignum25519 z) {
+ bignum25519 ALIGN(16) b,c,t0;
+
+ /* 2 */ curve25519_square_times(c, z, 1); /* c = 2 */
+ /* 8 */ curve25519_square_times(t0, c, 2); /* t0 = 8 */
+ /* 9 */ curve25519_mul_noinline(b, t0, z); /* b = 9 */
+ /* 11 */ curve25519_mul_noinline(c, b, c); /* c = 11 */
+ /* 22 */ curve25519_square_times(t0, c, 1);
+ /* 2^5 - 2^0 = 31 */ curve25519_mul_noinline(b, t0, b);
+ /* 2^250 - 2^0 */ curve25519_pow_two5mtwo0_two250mtwo0(b);
+ /* 2^252 - 2^2 */ curve25519_square_times(b, b, 2);
+ /* 2^252 - 3 */ curve25519_mul_noinline(two252m3, b, z);
+}
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/ed25519-donna/ed25519-donna-32bit-tables.h b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/ed25519-donna/ed25519-donna-32bit-tables.h
new file mode 100644
index 0000000..c977c26
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/ed25519-donna/ed25519-donna-32bit-tables.h
@@ -0,0 +1,61 @@
+static const ge25519 ALIGN(16) ge25519_basepoint = {
+ {0x0325d51a,0x018b5823,0x00f6592a,0x0104a92d,0x01a4b31d,0x01d6dc5c,0x027118fe,0x007fd814,0x013cd6e5,0x0085a4db},
+ {0x02666658,0x01999999,0x00cccccc,0x01333333,0x01999999,0x00666666,0x03333333,0x00cccccc,0x02666666,0x01999999},
+ {0x00000001,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000},
+ {0x01b7dda3,0x01a2ace9,0x025eadbb,0x0003ba8a,0x0083c27e,0x00abe37d,0x01274732,0x00ccacdd,0x00fd78b7,0x019e1d7c}
+};
+
+/*
+ d
+*/
+
+static const bignum25519 ALIGN(16) ge25519_ecd = {
+ 0x035978a3,0x00d37284,0x03156ebd,0x006a0a0e,0x0001c029,0x0179e898,0x03a03cbb,0x01ce7198,0x02e2b6ff,0x01480db3
+};
+
+static const bignum25519 ALIGN(16) ge25519_ec2d = {
+ 0x02b2f159,0x01a6e509,0x022add7a,0x00d4141d,0x00038052,0x00f3d130,0x03407977,0x019ce331,0x01c56dff,0x00901b67
+};
+
+/*
+ sqrt(-1)
+*/
+
+static const bignum25519 ALIGN(16) ge25519_sqrtneg1 = {
+ 0x020ea0b0,0x0186c9d2,0x008f189d,0x0035697f,0x00bd0c60,0x01fbd7a7,0x02804c9e,0x01e16569,0x0004fc1d,0x00ae0c92
+};
+
+static const ge25519_niels ALIGN(16) ge25519_niels_sliding_multiples[32] = {
+ {{0x0340913e,0x000e4175,0x03d673a2,0x002e8a05,0x03f4e67c,0x008f8a09,0x00c21a34,0x004cf4b8,0x01298f81,0x0113f4be},{0x018c3b85,0x0124f1bd,0x01c325f7,0x0037dc60,0x033e4cb7,0x003d42c2,0x01a44c32,0x014ca4e1,0x03a33d4b,0x001f3e74},{0x037aaa68,0x00448161,0x0093d579,0x011e6556,0x009b67a0,0x0143598c,0x01bee5ee,0x00b50b43,0x0289f0c6,0x01bc45ed}},
+ {{0x00fcd265,0x0047fa29,0x034faacc,0x01ef2e0d,0x00ef4d4f,0x014bd6bd,0x00f98d10,0x014c5026,0x007555bd,0x00aae456},{0x00ee9730,0x016c2a13,0x017155e4,0x01874432,0x00096a10,0x01016732,0x01a8014f,0x011e9823,0x01b9a80f,0x01e85938},{0x01d0d889,0x01a4cfc3,0x034c4295,0x0110e1ae,0x0162508c,0x00f2db4c,0x0072a2c6,0x0098da2e,0x02f12b9b,0x0168a09a}},
+ {{0x0047d6ba,0x0060b0e9,0x0136eff2,0x008a5939,0x03540053,0x0064a087,0x02788e5c,0x00be7c67,0x033eb1b5,0x005529f9},{0x00a5bb33,0x00af1102,0x01a05442,0x001e3af7,0x02354123,0x00bfec44,0x01f5862d,0x00dd7ba3,0x03146e20,0x00a51733},{0x012a8285,0x00f6fc60,0x023f9797,0x003e85ee,0x009c3820,0x01bda72d,0x01b3858d,0x00d35683,0x0296b3bb,0x010eaaf9}},
+ {{0x023221b1,0x01cb26aa,0x0074f74d,0x0099ddd1,0x01b28085,0x00192c3a,0x013b27c9,0x00fc13bd,0x01d2e531,0x0075bb75},{0x004ea3bf,0x00973425,0x001a4d63,0x01d59cee,0x01d1c0d4,0x00542e49,0x01294114,0x004fce36,0x029283c9,0x01186fa9},{0x01b8b3a2,0x00db7200,0x00935e30,0x003829f5,0x02cc0d7d,0x0077adf3,0x0220dd2c,0x0014ea53,0x01c6a0f9,0x01ea7eec}},
+ {{0x039d8064,0x01885f80,0x00337e6d,0x01b7a902,0x02628206,0x015eb044,0x01e30473,0x0191f2d9,0x011fadc9,0x01270169},{0x02a8632f,0x0199e2a9,0x00d8b365,0x017a8de2,0x02994279,0x0086f5b5,0x0119e4e3,0x01eb39d6,0x0338add7,0x00d2e7b4},{0x0045af1b,0x013a2fe4,0x0245e0d6,0x014538ce,0x038bfe0f,0x01d4cf16,0x037e14c9,0x0160d55e,0x0021b008,0x01cf05c8}},
+ {{0x01864348,0x01d6c092,0x0070262b,0x014bb844,0x00fb5acd,0x008deb95,0x003aaab5,0x00eff474,0x00029d5c,0x0062ad66},{0x02802ade,0x01c02122,0x01c4e5f7,0x00781181,0x039767fb,0x01703406,0x0342388b,0x01f5e227,0x022546d8,0x0109d6ab},{0x016089e9,0x00cb317f,0x00949b05,0x01099417,0x000c7ad2,0x011a8622,0x0088ccda,0x01290886,0x022b53df,0x00f71954}},
+ {{0x027fbf93,0x01c04ecc,0x01ed6a0d,0x004cdbbb,0x02bbf3af,0x00ad5968,0x01591955,0x0094f3a2,0x02d17602,0x00099e20},{0x02007f6d,0x003088a8,0x03db77ee,0x00d5ade6,0x02fe12ce,0x0107ba07,0x0107097d,0x00482a6f,0x02ec346f,0x008d3f5f},{0x032ea378,0x0028465c,0x028e2a6c,0x018efc6e,0x0090df9a,0x01a7e533,0x039bfc48,0x010c745d,0x03daa097,0x0125ee9b}},
+ {{0x028ccf0b,0x00f36191,0x021ac081,0x012154c8,0x034e0a6e,0x01b25192,0x00180403,0x01d7eea1,0x00218d05,0x010ed735},{0x03cfeaa0,0x01b300c4,0x008da499,0x0068c4e1,0x0219230a,0x01f2d4d0,0x02defd60,0x00e565b7,0x017f12de,0x018788a4},{0x03d0b516,0x009d8be6,0x03ddcbb3,0x0071b9fe,0x03ace2bd,0x01d64270,0x032d3ec9,0x01084065,0x0210ae4d,0x01447584}},
+ {{0x0020de87,0x00e19211,0x01b68102,0x00b5ac97,0x022873c0,0x01942d25,0x01271394,0x0102073f,0x02fe2482,0x01c69ff9},{0x010e9d81,0x019dbbe5,0x0089f258,0x006e06b8,0x02951883,0x018f1248,0x019b3237,0x00bc7553,0x024ddb85,0x01b4c964},{0x01c8c854,0x0060ae29,0x01406d8e,0x01cff2f9,0x00cff451,0x01778d0c,0x03ac8c41,0x01552e59,0x036559ee,0x011d1b12}},
+ {{0x00741147,0x0151b219,0x01092690,0x00e877e6,0x01f4d6bb,0x0072a332,0x01cd3b03,0x00dadff2,0x0097db5e,0x0086598d},{0x01c69a2b,0x01decf1b,0x02c2fa6e,0x013b7c4f,0x037beac8,0x013a16b5,0x028e7bda,0x01f6e8ac,0x01e34fe9,0x01726947},{0x01f10e67,0x003c73de,0x022b7ea2,0x010f32c2,0x03ff776a,0x00142277,0x01d38b88,0x00776138,0x03c60822,0x01201140}},
+ {{0x0236d175,0x0008748e,0x03c6476d,0x013f4cdc,0x02eed02a,0x00838a47,0x032e7210,0x018bcbb3,0x00858de4,0x01dc7826},{0x00a37fc7,0x0127b40b,0x01957884,0x011d30ad,0x02816683,0x016e0e23,0x00b76be4,0x012db115,0x02516506,0x0154ce62},{0x00451edf,0x00bd749e,0x03997342,0x01cc2c4c,0x00eb6975,0x01a59508,0x03a516cf,0x00c228ef,0x0168ff5a,0x01697b47}},
+ {{0x00527359,0x01783156,0x03afd75c,0x00ce56dc,0x00e4b970,0x001cabe9,0x029e0f6d,0x0188850c,0x0135fefd,0x00066d80},{0x02150e83,0x01448abf,0x02bb0232,0x012bf259,0x033c8268,0x00711e20,0x03fc148f,0x005e0e70,0x017d8bf9,0x0112b2e2},{0x02134b83,0x001a0517,0x0182c3cc,0x00792182,0x0313d799,0x001a3ed7,0x0344547e,0x01f24a0d,0x03de6ad2,0x00543127}},
+ {{0x00dca868,0x00618f27,0x015a1709,0x00ddc38a,0x0320fd13,0x0036168d,0x0371ab06,0x01783fc7,0x0391e05f,0x01e29b5d},{0x01471138,0x00fca542,0x00ca31cf,0x01ca7bad,0x0175bfbc,0x01a708ad,0x03bce212,0x01244215,0x0075bb99,0x01acad68},{0x03a0b976,0x01dc12d1,0x011aab17,0x00aba0ba,0x029806cd,0x0142f590,0x018fd8ea,0x01a01545,0x03c4ad55,0x01c971ff}},
+ {{0x00d098c0,0x000afdc7,0x006cd230,0x01276af3,0x03f905b2,0x0102994c,0x002eb8a4,0x015cfbeb,0x025f855f,0x01335518},{0x01cf99b2,0x0099c574,0x01a69c88,0x00881510,0x01cd4b54,0x0112109f,0x008abdc5,0x0074647a,0x0277cb1f,0x01e53324},{0x02ac5053,0x01b109b0,0x024b095e,0x016997b3,0x02f26bb6,0x00311021,0x00197885,0x01d0a55a,0x03b6fcc8,0x01c020d5}},
+ {{0x02584a34,0x00e7eee0,0x03257a03,0x011e95a3,0x011ead91,0x00536202,0x00b1ce24,0x008516c6,0x03669d6d,0x004ea4a8},{0x00773f01,0x0019c9ce,0x019f6171,0x01d4afde,0x02e33323,0x01ad29b6,0x02ead1dc,0x01ed51a5,0x01851ad0,0x001bbdfa},{0x00577de5,0x00ddc730,0x038b9952,0x00f281ae,0x01d50390,0x0002e071,0x000780ec,0x010d448d,0x01f8a2af,0x00f0a5b7}},
+ {{0x031f2541,0x00d34bae,0x0323ff9d,0x003a056d,0x02e25443,0x00a1ad05,0x00d1bee8,0x002f7f8e,0x03007477,0x002a24b1},{0x0114a713,0x01457e76,0x032255d5,0x01cc647f,0x02a4bdef,0x0153d730,0x00118bcf,0x00f755ff,0x013490c7,0x01ea674e},{0x02bda3e8,0x00bb490d,0x00f291ea,0x000abf40,0x01dea321,0x002f9ce0,0x00b2b193,0x00fa54b5,0x0128302f,0x00a19d8b}},
+ {{0x022ef5bd,0x01638af3,0x038c6f8a,0x01a33a3d,0x039261b2,0x01bb89b8,0x010bcf9d,0x00cf42a9,0x023d6f17,0x01da1bca},{0x00e35b25,0x000d824f,0x0152e9cf,0x00ed935d,0x020b8460,0x01c7b83f,0x00c969e5,0x01a74198,0x0046a9d9,0x00cbc768},{0x01597c6a,0x0144a99b,0x00a57551,0x0018269c,0x023c464c,0x0009b022,0x00ee39e1,0x0114c7f2,0x038a9ad2,0x01584c17}},
+ {{0x03b0c0d5,0x00b30a39,0x038a6ce4,0x01ded83a,0x01c277a6,0x01010a61,0x0346d3eb,0x018d995e,0x02f2c57c,0x000c286b},{0x0092aed1,0x0125e37b,0x027ca201,0x001a6b6b,0x03290f55,0x0047ba48,0x018d916c,0x01a59062,0x013e35d4,0x0002abb1},{0x003ad2aa,0x007ddcc0,0x00c10f76,0x0001590b,0x002cfca6,0x000ed23e,0x00ee4329,0x00900f04,0x01c24065,0x0082fa70}},
+ {{0x02025e60,0x003912b8,0x0327041c,0x017e5ee5,0x02c0ecec,0x015a0d1c,0x02b1ce7c,0x0062220b,0x0145067e,0x01a5d931},{0x009673a6,0x00e1f609,0x00927c2a,0x016faa37,0x01650ef0,0x016f63b5,0x03cd40e1,0x003bc38f,0x0361f0ac,0x01d42acc},{0x02f81037,0x008ca0e8,0x017e23d1,0x011debfe,0x01bcbb68,0x002e2563,0x03e8add6,0x000816e5,0x03fb7075,0x0153e5ac}},
+ {{0x02b11ecd,0x016bf185,0x008f22ef,0x00e7d2bb,0x0225d92e,0x00ece785,0x00508873,0x017e16f5,0x01fbe85d,0x01e39a0e},{0x01669279,0x017c810a,0x024941f5,0x0023ebeb,0x00eb7688,0x005760f1,0x02ca4146,0x0073cde7,0x0052bb75,0x00f5ffa7},{0x03b8856b,0x00cb7dcd,0x02f14e06,0x001820d0,0x01d74175,0x00e59e22,0x03fba550,0x00484641,0x03350088,0x01c3c9a3}},
+ {{0x00dcf355,0x0104481c,0x0022e464,0x01f73fe7,0x00e03325,0x0152b698,0x02ef769a,0x00973663,0x00039b8c,0x0101395b},{0x01805f47,0x019160ec,0x03832cd0,0x008b06eb,0x03d4d717,0x004cb006,0x03a75b8f,0x013b3d30,0x01cfad88,0x01f034d1},{0x0078338a,0x01c7d2e3,0x02bc2b23,0x018b3f05,0x0280d9aa,0x005f3d44,0x0220a95a,0x00eeeb97,0x0362aaec,0x00835d51}},
+ {{0x01b9f543,0x013fac4d,0x02ad93ae,0x018ef464,0x0212cdf7,0x01138ba9,0x011583ab,0x019c3d26,0x028790b4,0x00e2e2b6},{0x033bb758,0x01f0dbf1,0x03734bd1,0x0129b1e5,0x02b3950e,0x003bc922,0x01a53ec8,0x018c5532,0x006f3cee,0x00ae3c79},{0x0351f95d,0x0012a737,0x03d596b8,0x017658fe,0x00ace54a,0x008b66da,0x0036c599,0x012a63a2,0x032ceba1,0x00126bac}},
+ {{0x03dcfe7e,0x019f4f18,0x01c81aee,0x0044bc2b,0x00827165,0x014f7c13,0x03b430f0,0x00bf96cc,0x020c8d62,0x01471997},{0x01fc7931,0x001f42dd,0x00ba754a,0x005bd339,0x003fbe49,0x016b3930,0x012a159c,0x009f83b0,0x03530f67,0x01e57b85},{0x02ecbd81,0x0096c294,0x01fce4a9,0x017701a5,0x0175047d,0x00ee4a31,0x012686e5,0x008efcd4,0x0349dc54,0x01b3466f}},
+ {{0x02179ca3,0x01d86414,0x03f0afd0,0x00305964,0x015c7428,0x0099711e,0x015d5442,0x00c71014,0x01b40b2e,0x01d483cf},{0x01afc386,0x01984859,0x036203ff,0x0045c6a8,0x0020a8aa,0x00990baa,0x03313f10,0x007ceede,0x027429e4,0x017806ce},{0x039357a1,0x0142f8f4,0x0294a7b6,0x00eaccf4,0x0259edb3,0x01311e6e,0x004d326f,0x0130c346,0x01ccef3c,0x01c424b2}},
+ {{0x0364918c,0x00148fc0,0x01638a7b,0x01a1fd5b,0x028ad013,0x0081e5a4,0x01a54f33,0x0174e101,0x003d0257,0x003a856c},{0x00051dcf,0x00f62b1d,0x0143d0ad,0x0042adbd,0x000fda90,0x01743ceb,0x0173e5e4,0x017bc749,0x03b7137a,0x0105ce96},{0x00f9218a,0x015b8c7c,0x00e102f8,0x0158d7e2,0x0169a5b8,0x00b2f176,0x018b347a,0x014cfef2,0x0214a4e3,0x017f1595}},
+ {{0x006d7ae5,0x0195c371,0x0391e26d,0x0062a7c6,0x003f42ab,0x010dad86,0x024f8198,0x01542b2a,0x0014c454,0x0189c471},{0x0390988e,0x00b8799d,0x02e44912,0x0078e2e6,0x00075654,0x01923eed,0x0040cd72,0x00a37c76,0x0009d466,0x00c8531d},{0x02651770,0x00609d01,0x0286c265,0x0134513c,0x00ee9281,0x005d223c,0x035c760c,0x00679b36,0x0073ecb8,0x016faa50}},
+ {{0x02c89be4,0x016fc244,0x02f38c83,0x018beb72,0x02b3ce2c,0x0097b065,0x034f017b,0x01dd957f,0x00148f61,0x00eab357},{0x0343d2f8,0x003398fc,0x011e368e,0x00782a1f,0x00019eea,0x00117b6f,0x0128d0d1,0x01a5e6bb,0x01944f1b,0x012b41e1},{0x03318301,0x018ecd30,0x0104d0b1,0x0038398b,0x03726701,0x019da88c,0x002d9769,0x00a7a681,0x031d9028,0x00ebfc32}},
+ {{0x0220405e,0x0171face,0x02d930f8,0x017f6d6a,0x023b8c47,0x0129d5f9,0x02972456,0x00a3a524,0x006f4cd2,0x004439fa},{0x00c53505,0x0190c2fd,0x00507244,0x009930f9,0x01a39270,0x01d327c6,0x0399bc47,0x01cfe13d,0x0332bd99,0x00b33e7d},{0x0203f5e4,0x003627b5,0x00018af8,0x01478581,0x004a2218,0x002e3bb7,0x039384d0,0x0146ea62,0x020b9693,0x0017155f}},
+ {{0x03c97e6f,0x00738c47,0x03b5db1f,0x01808fcf,0x01e8fc98,0x01ed25dd,0x01bf5045,0x00eb5c2b,0x0178fe98,0x01b85530},{0x01c20eb0,0x01aeec22,0x030b9eee,0x01b7d07e,0x0187e16f,0x014421fb,0x009fa731,0x0040b6d7,0x00841861,0x00a27fbc},{0x02d69abf,0x0058cdbf,0x0129f9ec,0x013c19ae,0x026c5b93,0x013a7fe7,0x004bb2ba,0x0063226f,0x002a95ca,0x01abefd9}},
+ {{0x02f5d2c1,0x00378318,0x03734fb5,0x01258073,0x0263f0f6,0x01ad70e0,0x01b56d06,0x01188fbd,0x011b9503,0x0036d2e1},{0x0113a8cc,0x01541c3e,0x02ac2bbc,0x01d95867,0x01f47459,0x00ead489,0x00ab5b48,0x01db3b45,0x00edb801,0x004b024f},{0x00b8190f,0x011fe4c2,0x00621f82,0x010508d7,0x001a5a76,0x00c7d7fd,0x03aab96d,0x019cd9dc,0x019c6635,0x00ceaa1e}},
+ {{0x01085cf2,0x01fd47af,0x03e3f5e1,0x004b3e99,0x01e3d46a,0x0060033c,0x015ff0a8,0x0150cdd8,0x029e8e21,0x008cf1bc},{0x00156cb1,0x003d623f,0x01a4f069,0x00d8d053,0x01b68aea,0x01ca5ab6,0x0316ae43,0x0134dc44,0x001c8d58,0x0084b343},{0x0318c781,0x0135441f,0x03a51a5e,0x019293f4,0x0048bb37,0x013d3341,0x0143151e,0x019c74e1,0x00911914,0x0076ddde}},
+ {{0x006bc26f,0x00d48e5f,0x00227bbe,0x00629ea8,0x01ea5f8b,0x0179a330,0x027a1d5f,0x01bf8f8e,0x02d26e2a,0x00c6b65e},{0x01701ab6,0x0051da77,0x01b4b667,0x00a0ce7c,0x038ae37b,0x012ac852,0x03a0b0fe,0x0097c2bb,0x00a017d2,0x01eb8b2a},{0x0120b962,0x0005fb42,0x0353b6fd,0x0061f8ce,0x007a1463,0x01560a64,0x00e0a792,0x01907c92,0x013a6622,0x007b47f1}}
+};
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/ed25519-donna/ed25519-donna-basepoint-table.h b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/ed25519-donna/ed25519-donna-basepoint-table.h
new file mode 100644
index 0000000..41dcd52
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/ed25519-donna/ed25519-donna-basepoint-table.h
@@ -0,0 +1,259 @@
+/* multiples of the base point in packed {ysubx, xaddy, t2d} form */
+static const uint8_t ALIGN(16) ge25519_niels_base_multiples[256][96] = {
+ {0x3e,0x91,0x40,0xd7,0x05,0x39,0x10,0x9d,0xb3,0xbe,0x40,0xd1,0x05,0x9f,0x39,0xfd,0x09,0x8a,0x8f,0x68,0x34,0x84,0xc1,0xa5,0x67,0x12,0xf8,0x98,0x92,0x2f,0xfd,0x44,0x85,0x3b,0x8c,0xf5,0xc6,0x93,0xbc,0x2f,0x19,0x0e,0x8c,0xfb,0xc6,0x2d,0x93,0xcf,0xc2,0x42,0x3d,0x64,0x98,0x48,0x0b,0x27,0x65,0xba,0xd4,0x33,0x3a,0x9d,0xcf,0x07,0x59,0xbb,0x6f,0x4b,0x67,0x15,0xbd,0xdb,0xea,0xa5,0xa2,0xee,0x00,0x3f,0xe1,0x41,0xfa,0xc6,0x57,0xc9,0x1c,0x9d,0xd4,0xcd,0xca,0xec,0x16,0xaf,0x1f,0xbe,0x0e,0x4f},
+ {0xa8,0xd5,0xb4,0x42,0x60,0xa5,0x99,0x8a,0xf6,0xac,0x60,0x4e,0x0c,0x81,0x2b,0x8f,0xaa,0x37,0x6e,0xb1,0x6b,0x23,0x9e,0xe0,0x55,0x25,0xc9,0x69,0xa6,0x95,0xb5,0x6b,0xd7,0x71,0x3c,0x93,0xfc,0xe7,0x24,0x92,0xb5,0xf5,0x0f,0x7a,0x96,0x9d,0x46,0x9f,0x02,0x07,0xd6,0xe1,0x65,0x9a,0xa6,0x5a,0x2e,0x2e,0x7d,0xa8,0x3f,0x06,0x0c,0x59,0x02,0x68,0xd3,0xda,0xaa,0x7e,0x34,0x6e,0x05,0x48,0xee,0x83,0x93,0x59,0xf3,0xba,0x26,0x68,0x07,0xe6,0x10,0xbe,0xca,0x3b,0xb8,0xd1,0x5e,0x16,0x0a,0x4f,0x31,0x49},
+ {0x65,0xd2,0xfc,0xa4,0xe8,0x1f,0x61,0x56,0x7d,0xba,0xc1,0xe5,0xfd,0x53,0xd3,0x3b,0xbd,0xd6,0x4b,0x21,0x1a,0xf3,0x31,0x81,0x62,0xda,0x5b,0x55,0x87,0x15,0xb9,0x2a,0x30,0x97,0xee,0x4c,0xa8,0xb0,0x25,0xaf,0x8a,0x4b,0x86,0xe8,0x30,0x84,0x5a,0x02,0x32,0x67,0x01,0x9f,0x02,0x50,0x1b,0xc1,0xf4,0xf8,0x80,0x9a,0x1b,0x4e,0x16,0x7a,0x34,0x48,0x67,0xf1,0xf4,0x11,0xf2,0x9b,0x95,0xf8,0x2d,0xf6,0x17,0x6b,0x4e,0xb8,0x4e,0x2a,0x72,0x5b,0x07,0x6f,0xde,0xd7,0x21,0x2a,0xbb,0x63,0xb9,0x04,0x9a,0x54},
+ {0xbf,0x18,0x68,0x05,0x0a,0x05,0xfe,0x95,0xa9,0xfa,0x60,0x56,0x71,0x89,0x7e,0x32,0x73,0x50,0xa0,0x06,0xcd,0xe3,0xe8,0xc3,0x9a,0xa4,0x45,0x74,0x4c,0x3f,0x93,0x27,0x9f,0x09,0xfc,0x8e,0xb9,0x51,0x73,0x28,0x38,0x25,0xfd,0x7d,0xf4,0xc6,0x65,0x67,0x65,0x92,0x0a,0xfb,0x3d,0x8d,0x34,0xca,0x27,0x87,0xe5,0x21,0x03,0x91,0x0e,0x68,0xb0,0x26,0x14,0xe5,0xec,0x45,0x1e,0xbf,0x94,0x0f,0xba,0x6d,0x3d,0xc6,0x2b,0xe3,0xc0,0x52,0xf8,0x8c,0xd5,0x74,0x29,0xe4,0x18,0x4c,0xe6,0xb0,0xb1,0x79,0xf0,0x44},
+ {0xba,0xd6,0x47,0xa4,0xc3,0x82,0x91,0x7f,0xb7,0x29,0x27,0x4b,0xd1,0x14,0x00,0xd5,0x87,0xa0,0x64,0xb8,0x1c,0xf1,0x3c,0xe3,0xf3,0x55,0x1b,0xeb,0x73,0x7e,0x4a,0x15,0x33,0xbb,0xa5,0x08,0x44,0xbc,0x12,0xa2,0x02,0xed,0x5e,0xc7,0xc3,0x48,0x50,0x8d,0x44,0xec,0xbf,0x5a,0x0c,0xeb,0x1b,0xdd,0xeb,0x06,0xe2,0x46,0xf1,0xcc,0x45,0x29,0xb3,0x03,0xd0,0xe7,0x79,0xa1,0x32,0xc8,0x7e,0x4d,0x12,0x00,0x0a,0x9d,0x72,0x5f,0xf3,0x8f,0x6d,0x0e,0xa1,0xd4,0xc1,0x62,0x98,0x7a,0xb2,0x38,0x59,0xac,0xb8,0x68},
+ {0xa4,0x8c,0x7d,0x7b,0xb6,0x06,0x98,0x49,0x39,0x27,0xd2,0x27,0x84,0xe2,0x5b,0x57,0xb9,0x53,0x45,0x20,0xe7,0x5c,0x08,0xbb,0x84,0x78,0x41,0xae,0x41,0x4c,0xb6,0x38,0x31,0x71,0x15,0x77,0xeb,0xee,0x0c,0x3a,0x88,0xaf,0xc8,0x00,0x89,0x15,0x27,0x9b,0x36,0xa7,0x59,0xda,0x68,0xb6,0x65,0x80,0xbd,0x38,0xcc,0xa2,0xb6,0x7b,0xe5,0x51,0xa4,0xe3,0x9d,0x68,0x91,0xad,0x9d,0x8f,0x37,0x91,0xfb,0xf8,0x28,0x24,0x5f,0x17,0x88,0xb9,0xcf,0x9f,0x32,0xb5,0x0a,0x05,0x9f,0xc0,0x54,0x13,0xa2,0xdf,0x65,0x78},
+ {0xb1,0x21,0x32,0xaa,0x9a,0x2c,0x6f,0xba,0xa7,0x23,0xba,0x3b,0x53,0x21,0xa0,0x6c,0x3a,0x2c,0x19,0x92,0x4f,0x76,0xea,0x9d,0xe0,0x17,0x53,0x2e,0x5d,0xdd,0x6e,0x1d,0xbf,0xa3,0x4e,0x94,0xd0,0x5c,0x1a,0x6b,0xd2,0xc0,0x9d,0xb3,0x3a,0x35,0x70,0x74,0x49,0x2e,0x54,0x28,0x82,0x52,0xb2,0x71,0x7e,0x92,0x3c,0x28,0x69,0xea,0x1b,0x46,0x36,0xda,0x0f,0xab,0xac,0x8a,0x7a,0x21,0xc8,0x49,0x35,0x3d,0x54,0xc6,0x28,0xa5,0x68,0x75,0xab,0x13,0x8b,0x5b,0xd0,0x37,0x37,0xbc,0x2c,0x3a,0x62,0xef,0x3c,0x23},
+ {0xd9,0x34,0x92,0xf3,0xed,0x5d,0xa7,0xe2,0xf9,0x58,0xb5,0xe1,0x80,0x76,0x3d,0x96,0xfb,0x23,0x3c,0x6e,0xac,0x41,0x27,0x2c,0xc3,0x01,0x0e,0x32,0xa1,0x24,0x90,0x3a,0x8f,0x3e,0xdd,0x04,0x66,0x59,0xb7,0x59,0x2c,0x70,0x88,0xe2,0x77,0x03,0xb3,0x6c,0x23,0xc3,0xd9,0x5e,0x66,0x9c,0x33,0xb1,0x2f,0xe5,0xbc,0x61,0x60,0xe7,0x15,0x09,0x7e,0xa3,0x34,0xa8,0x35,0xe8,0x7d,0xdf,0xea,0x57,0x98,0x68,0xda,0x9c,0xe1,0x8b,0x26,0xb3,0x67,0x71,0x36,0x85,0x11,0x2c,0xc2,0xd5,0xef,0xdb,0xd9,0xb3,0x9e,0x58},
+ {0x5e,0x51,0xaa,0x49,0x54,0x63,0x5b,0xed,0x3a,0x82,0xc6,0x0b,0x9f,0xc4,0x65,0xa8,0xc4,0xd1,0x42,0x5b,0xe9,0x1f,0x0c,0x85,0xb9,0x15,0xd3,0x03,0x6f,0x6d,0xd7,0x30,0x1d,0x9c,0x2f,0x63,0x0e,0xdd,0xcc,0x2e,0x15,0x31,0x89,0x76,0x96,0xb6,0xd0,0x51,0x58,0x7a,0x63,0xa8,0x6b,0xb7,0xdf,0x52,0x39,0xef,0x0e,0xa0,0x49,0x7d,0xd3,0x6d,0xc7,0xe4,0x06,0x21,0x17,0x44,0x44,0x6c,0x69,0x7f,0x8d,0x92,0x80,0xd6,0x53,0xfb,0x26,0x3f,0x4d,0x69,0xa4,0x9e,0x73,0xb4,0xb0,0x4b,0x86,0x2e,0x11,0x97,0xc6,0x10},
+ {0xde,0x5f,0xbe,0x7d,0x27,0xc4,0x93,0x64,0xa2,0x7e,0xad,0x19,0xad,0x4f,0x5d,0x26,0x90,0x45,0x30,0x46,0xc8,0xdf,0x00,0x0e,0x09,0xfe,0x66,0xed,0xab,0x1c,0xe6,0x25,0x05,0xc8,0x58,0x83,0xa0,0x2a,0xa6,0x0c,0x47,0x42,0x20,0x7a,0xe3,0x4a,0x3d,0x6a,0xdc,0xed,0x11,0x3b,0xa6,0xd3,0x64,0x74,0xef,0x06,0x08,0x55,0xaf,0x9b,0xbf,0x03,0x04,0x66,0x58,0xcc,0x28,0xe1,0x13,0x3f,0x7e,0x74,0x59,0xb4,0xec,0x73,0x58,0x6f,0xf5,0x68,0x12,0xcc,0xed,0x3d,0xb6,0xa0,0x2c,0xe2,0x86,0x45,0x63,0x78,0x6d,0x56},
+ {0x34,0x08,0xc1,0x9c,0x9f,0xa4,0x37,0x16,0x51,0xc4,0x9b,0xa8,0xd5,0x56,0x8e,0xbc,0xdb,0xd2,0x7f,0x7f,0x0f,0xec,0xb5,0x1c,0xd9,0x35,0xcc,0x5e,0xca,0x5b,0x97,0x33,0xd0,0x2f,0x5a,0xc6,0x85,0x42,0x05,0xa1,0xc3,0x67,0x16,0xf3,0x2a,0x11,0x64,0x6c,0x58,0xee,0x1a,0x73,0x40,0xe2,0x0a,0x68,0x2a,0xb2,0x93,0x47,0xf3,0xa5,0xfb,0x14,0xd4,0xf7,0x85,0x69,0x16,0x46,0xd7,0x3c,0x57,0x00,0xc8,0xc9,0x84,0x5e,0x3e,0x59,0x1e,0x13,0x61,0x7b,0xb6,0xf2,0xc3,0x2f,0x6c,0x52,0xfc,0x83,0xea,0x9c,0x82,0x14},
+ {0xc2,0x95,0xdd,0x97,0x84,0x7b,0x43,0xff,0xa7,0xb5,0x4e,0xaa,0x30,0x4e,0x74,0x6c,0x8b,0xe8,0x85,0x3c,0x61,0x5d,0x0c,0x9e,0x73,0x81,0x75,0x5f,0x1e,0xc7,0xd9,0x2f,0xb8,0xec,0x71,0x4e,0x2f,0x0b,0xe7,0x21,0xe3,0x77,0xa4,0x40,0xb9,0xdd,0x56,0xe6,0x80,0x4f,0x1d,0xce,0xce,0x56,0x65,0xbf,0x7e,0x7b,0x5d,0x53,0xc4,0x3b,0xfc,0x05,0xdd,0xde,0xaf,0x52,0xae,0xb3,0xb8,0x24,0xcf,0x30,0x3b,0xed,0x8c,0x63,0x95,0x34,0x95,0x81,0xbe,0xa9,0x83,0xbc,0xa4,0x33,0x04,0x1f,0x65,0x5c,0x47,0x67,0x37,0x37},
+ {0xd9,0xad,0xd1,0x40,0xfd,0x99,0xba,0x2f,0x27,0xd0,0xf4,0x96,0x6f,0x16,0x07,0xb3,0xae,0x3b,0xf0,0x15,0x52,0xf0,0x63,0x43,0x99,0xf9,0x18,0x3b,0x6c,0xa5,0xbe,0x1f,0x90,0x65,0x24,0x14,0xcb,0x95,0x40,0x63,0x35,0x55,0xc1,0x16,0x40,0x14,0x12,0xef,0x60,0xbc,0x10,0x89,0x0c,0x14,0x38,0x9e,0x8c,0x7c,0x90,0x30,0x57,0x90,0xf5,0x6b,0x8a,0x5b,0x41,0xe1,0xf1,0x78,0xa7,0x0f,0x7e,0xa7,0xc3,0xba,0xf7,0x9f,0x40,0x06,0x50,0x9a,0xa2,0x9a,0xb8,0xd7,0x52,0x6f,0x56,0x5a,0x63,0x7a,0xf6,0x1c,0x52,0x02},
+ {0x94,0x52,0x9d,0x0a,0x0b,0xee,0x3f,0x51,0x66,0x5a,0xdf,0x0f,0x5c,0xe7,0x98,0x8f,0xce,0x07,0xe1,0xbf,0x88,0x86,0x61,0xd4,0xed,0x2c,0x38,0x71,0x7e,0x0a,0xa0,0x3f,0xe4,0x5e,0x2f,0x77,0x20,0x67,0x14,0xb1,0xce,0x9a,0x07,0x96,0xb1,0x94,0xf8,0xe8,0x4a,0x82,0xac,0x00,0x4d,0x22,0xf8,0x4a,0xc4,0x6c,0xcd,0xf7,0xd9,0x53,0x17,0x00,0x34,0xdb,0x3d,0x96,0x2d,0x23,0x69,0x3c,0x58,0x38,0x97,0xb4,0xda,0x87,0xde,0x1d,0x85,0xf2,0x91,0xa0,0xf9,0xd1,0xd7,0xaa,0xb6,0xed,0x48,0xa0,0x2f,0xfe,0xb5,0x12},
+ {0x4d,0xe3,0xfc,0x96,0xc4,0xfb,0xf0,0x71,0xed,0x5b,0xf3,0xad,0x6b,0x82,0xb9,0x73,0x61,0xc5,0x28,0xff,0x61,0x72,0x04,0xd2,0x6f,0x20,0xb1,0x6f,0xf9,0x76,0x9b,0x74,0x92,0x1e,0x6f,0xad,0x26,0x7c,0x2b,0xdf,0x13,0x89,0x4b,0x50,0x23,0xd3,0x66,0x4b,0xc3,0x8b,0x1c,0x75,0xc0,0x9d,0x40,0x8c,0xb8,0xc7,0x96,0x07,0xc2,0x93,0x7e,0x6f,0x05,0xae,0xa6,0xae,0x04,0xf6,0x5a,0x1f,0x99,0x9c,0xe4,0xbe,0xf1,0x51,0x23,0xc1,0x66,0x6b,0xff,0xee,0xb5,0x08,0xa8,0x61,0x51,0x21,0xe0,0x01,0x0f,0xc1,0xce,0x0f},
+ {0x44,0x1e,0xfe,0x49,0xa6,0x58,0x4d,0x64,0x7e,0x77,0xad,0x31,0xa2,0xae,0xfc,0x21,0xd2,0xd0,0x7f,0x88,0x5a,0x1c,0x44,0x02,0xf3,0x11,0xc5,0x83,0x71,0xaa,0x01,0x49,0x45,0x4e,0x24,0xc4,0x9d,0xd2,0xf2,0x3d,0x0a,0xde,0xd8,0x93,0x74,0x0e,0x02,0x2b,0x4d,0x21,0x0c,0x82,0x7e,0x06,0xc8,0x6c,0x0a,0xb9,0xea,0x6f,0x16,0x79,0x37,0x41,0xf0,0xf8,0x1a,0x8c,0x54,0xb7,0xb1,0x08,0xb4,0x99,0x62,0x24,0x7c,0x7a,0x0f,0xce,0x39,0xd9,0x06,0x1e,0xf9,0xb0,0x60,0xf7,0x13,0x12,0x6d,0x72,0x7b,0x88,0xbb,0x41},
+ {0xbe,0x46,0x43,0x74,0x44,0x7d,0xe8,0x40,0x25,0x2b,0xb5,0x15,0xd4,0xda,0x48,0x1d,0x3e,0x60,0x3b,0xa1,0x18,0x8a,0x3a,0x7c,0xf7,0xbd,0xcd,0x2f,0xc1,0x28,0xb7,0x4e,0xae,0x91,0x66,0x7c,0x59,0x4c,0x23,0x7e,0xc8,0xb4,0x85,0x0a,0x3d,0x9d,0x88,0x64,0xe7,0xfa,0x4a,0x35,0x0c,0xc9,0xe2,0xda,0x1d,0x9e,0x6a,0x0c,0x07,0x1e,0x87,0x0a,0x89,0x89,0xbc,0x4b,0x99,0xb5,0x01,0x33,0x60,0x42,0xdd,0x5b,0x3a,0xae,0x6b,0x73,0x3c,0x9e,0xd5,0x19,0xe2,0xad,0x61,0x0d,0x64,0xd4,0x85,0x26,0x0f,0x30,0xe7,0x3e},
+ {0xb7,0xd6,0x7d,0x9e,0xe4,0x55,0xd2,0xf5,0xac,0x1e,0x0b,0x61,0x5c,0x11,0x16,0x80,0xca,0x87,0xe1,0x92,0x5d,0x97,0x99,0x3c,0xc2,0x25,0x91,0x97,0x62,0x57,0x81,0x13,0x18,0x75,0x1e,0x84,0x47,0x79,0xfa,0x43,0xd7,0x46,0x9c,0x63,0x59,0xfa,0xc6,0xe5,0x74,0x2b,0x05,0xe3,0x1d,0x5e,0x06,0xa1,0x30,0x90,0xb8,0xcf,0xa2,0xc6,0x47,0x7d,0xe0,0xd6,0xf0,0x8e,0x14,0xd0,0xda,0x3f,0x3c,0x6f,0x54,0x91,0x9a,0x74,0x3e,0x9d,0x57,0x81,0xbb,0x26,0x10,0x62,0xec,0x71,0x80,0xec,0xc9,0x34,0x8d,0xf5,0x8c,0x14},
+ {0x27,0xf0,0x34,0x79,0xf6,0x92,0xa4,0x46,0xa9,0x0a,0x84,0xf6,0xbe,0x84,0x99,0x46,0x54,0x18,0x61,0x89,0x2a,0xbc,0xa1,0x5c,0xd4,0xbb,0x5d,0xbd,0x1e,0xfa,0xf2,0x3f,0x6d,0x75,0xe4,0x9a,0x7d,0x2f,0x57,0xe2,0x7f,0x48,0xf3,0x88,0xbb,0x45,0xc3,0x56,0x8d,0xa8,0x60,0x69,0x6d,0x0b,0xd1,0x9f,0xb9,0xa1,0xae,0x4e,0xad,0xeb,0x8f,0x27,0x66,0x39,0x93,0x8c,0x1f,0x68,0xaa,0xb1,0x98,0x0c,0x29,0x20,0x9c,0x94,0x21,0x8c,0x52,0x3c,0x9d,0x21,0x91,0x52,0x11,0x39,0x7b,0x67,0x9c,0xfe,0x02,0xdd,0x04,0x41},
+ {0x2a,0x42,0x24,0x11,0x5e,0xbf,0xb2,0x72,0xb5,0x3a,0xa3,0x98,0x33,0x0c,0xfa,0xa1,0x66,0xb6,0x52,0xfa,0x01,0x61,0xcb,0x94,0xd5,0x53,0xaf,0xaf,0x00,0x3b,0x86,0x2c,0xb8,0x6a,0x09,0xdb,0x06,0x4e,0x21,0x81,0x35,0x4f,0xe4,0x0c,0xc9,0xb6,0xa8,0x21,0xf5,0x2a,0x9e,0x40,0x2a,0xc1,0x24,0x65,0x81,0xa4,0xfc,0x8e,0xa4,0xb5,0x65,0x01,0x76,0x6a,0x84,0xa0,0x74,0xa4,0x90,0xf1,0xc0,0x7c,0x2f,0xcd,0x84,0xf9,0xef,0x12,0x8f,0x2b,0xaa,0x58,0x06,0x29,0x5e,0x69,0xb8,0xc8,0xfe,0xbf,0xd9,0x67,0x1b,0x59},
+ {0xfa,0x9b,0xb4,0x80,0x1c,0x0d,0x2f,0x31,0x8a,0xec,0xf3,0xab,0x5e,0x51,0x79,0x59,0x88,0x1c,0xf0,0x9e,0xc0,0x33,0x70,0x72,0xcb,0x7b,0x8f,0xca,0xc7,0x2e,0xe0,0x3d,0x5d,0xb5,0x18,0x9f,0x71,0xb3,0xb9,0x99,0x1e,0x64,0x8c,0xa1,0xfa,0xe5,0x65,0xe4,0xed,0x05,0x9f,0xc2,0x36,0x11,0x08,0x61,0x8b,0x12,0x30,0x70,0x86,0x4f,0x9b,0x48,0xef,0x92,0xeb,0x3a,0x2d,0x10,0x32,0xd2,0x61,0xa8,0x16,0x61,0xb4,0x53,0x62,0xe1,0x24,0xaa,0x0b,0x19,0xe7,0xab,0x7e,0x3d,0xbf,0xbe,0x6c,0x49,0xba,0xfb,0xf5,0x49},
+ {0xd4,0xcf,0x5b,0x8a,0x10,0x9a,0x94,0x30,0xeb,0x73,0x64,0xbc,0x70,0xdd,0x40,0xdc,0x1c,0x0d,0x7c,0x30,0xc1,0x94,0xc2,0x92,0x74,0x6e,0xfa,0xcb,0x6d,0xa8,0x04,0x56,0x2e,0x57,0x9c,0x1e,0x8c,0x62,0x5d,0x15,0x41,0x47,0x88,0xc5,0xac,0x86,0x4d,0x8a,0xeb,0x63,0x57,0x51,0xf6,0x52,0xa3,0x91,0x5b,0x51,0x67,0x88,0xc2,0xa6,0xa1,0x06,0xb6,0x64,0x17,0x7c,0xd4,0xd1,0x88,0x72,0x51,0x8b,0x41,0xe0,0x40,0x11,0x54,0x72,0xd1,0xf6,0xac,0x18,0x60,0x1a,0x03,0x9f,0xc6,0x42,0x27,0xfe,0x89,0x9e,0x98,0x20},
+ {0x7f,0xcc,0x2d,0x3a,0xfd,0x77,0x97,0x49,0x92,0xd8,0x4f,0xa5,0x2c,0x7c,0x85,0x32,0xa0,0xe3,0x07,0xd2,0x64,0xd8,0x79,0xa2,0x29,0x7e,0xa6,0x0c,0x1d,0xed,0x03,0x04,0x2e,0xec,0xea,0x85,0x8b,0x27,0x74,0x16,0xdf,0x2b,0xcb,0x7a,0x07,0xdc,0x21,0x56,0x5a,0xf4,0xcb,0x61,0x16,0x4c,0x0a,0x64,0xd3,0x95,0x05,0xf7,0x50,0x99,0x0b,0x73,0x52,0xc5,0x4e,0x87,0x35,0x2d,0x4b,0xc9,0x8d,0x6f,0x24,0x98,0xcf,0xc8,0xe6,0xc5,0xce,0x35,0xc0,0x16,0xfa,0x46,0xcb,0xf7,0xcc,0x3d,0x30,0x08,0x43,0x45,0xd7,0x5b},
+ {0xc2,0x4c,0xb2,0x28,0x95,0xd1,0x9a,0x7f,0x81,0xc1,0x35,0x63,0x65,0x54,0x6b,0x7f,0x36,0x72,0xc0,0x4f,0x6e,0xb6,0xb8,0x66,0x83,0xad,0x80,0x73,0x00,0x78,0x3a,0x13,0x2a,0x79,0xe7,0x15,0x21,0x93,0xc4,0x85,0xc9,0xdd,0xcd,0xbd,0xa2,0x89,0x4c,0xc6,0x62,0xd7,0xa3,0xad,0xa8,0x3d,0x1e,0x9d,0x2c,0xf8,0x67,0x30,0x12,0xdb,0xb7,0x5b,0xbe,0x62,0xca,0xc6,0x67,0xf4,0x61,0x09,0xee,0x52,0x19,0x21,0xd6,0x21,0xec,0x04,0x70,0x47,0xd5,0x9b,0x77,0x60,0x23,0x18,0xd2,0xe0,0xf0,0x58,0x6d,0xca,0x0d,0x74},
+ {0x4e,0xce,0xcf,0x52,0x07,0xee,0x48,0xdf,0xb7,0x08,0xec,0x06,0xf3,0xfa,0xff,0xc3,0xc4,0x59,0x54,0xb9,0x2a,0x0b,0x71,0x05,0x8d,0xa3,0x3e,0x96,0xfa,0x25,0x1d,0x16,0x3c,0x43,0x78,0x04,0x57,0x8c,0x1a,0x23,0x9d,0x43,0x81,0xc2,0x0e,0x27,0xb5,0xb7,0x9f,0x07,0xd9,0xe3,0xea,0x99,0xaa,0xdb,0xd9,0x03,0x2b,0x6c,0x25,0xf5,0x03,0x2c,0x7d,0xa4,0x53,0x7b,0x75,0x18,0x0f,0x79,0x79,0x58,0x0c,0xcf,0x30,0x01,0x7b,0x30,0xf9,0xf7,0x7e,0x25,0x77,0x3d,0x90,0x31,0xaf,0xbb,0x96,0xbd,0xbd,0x68,0x94,0x69},
+ {0xcf,0xfe,0xda,0xf4,0x46,0x2f,0x1f,0xbd,0xf7,0xd6,0x7f,0xa4,0x14,0x01,0xef,0x7c,0x7f,0xb3,0x47,0x4a,0xda,0xfd,0x1f,0xd3,0x85,0x57,0x90,0x73,0xa4,0x19,0x52,0x52,0x48,0x19,0xa9,0x6a,0xe6,0x3d,0xdd,0xd8,0xcc,0xd2,0xc0,0x2f,0xc2,0x64,0x50,0x48,0x2f,0xea,0xfd,0x34,0x66,0x24,0x48,0x9b,0x3a,0x2e,0x4a,0x6c,0x4e,0x1c,0x3e,0x29,0xe1,0x12,0x51,0x92,0x4b,0x13,0x6e,0x37,0xa0,0x5d,0xa1,0xdc,0xb5,0x78,0x37,0x70,0x11,0x31,0x1c,0x46,0xaf,0x89,0x45,0xb0,0x23,0x28,0x03,0x7f,0x44,0x5c,0x60,0x5b},
+ {0x89,0x7c,0xc4,0x20,0x59,0x80,0x65,0xb9,0xcc,0x8f,0x3b,0x92,0x0c,0x10,0xf0,0xe7,0x77,0xef,0xe2,0x02,0x65,0x25,0x01,0x00,0xee,0xb3,0xae,0xa8,0xce,0x6d,0xa7,0x24,0x4c,0xf0,0xe7,0xf0,0xc6,0xfe,0xe9,0x3b,0x62,0x49,0xe3,0x75,0x9e,0x57,0x6a,0x86,0x1a,0xe6,0x1d,0x1e,0x16,0xef,0x42,0x55,0xd5,0xbd,0x5a,0xcc,0xf4,0xfe,0x12,0x2f,0x40,0xc7,0xc0,0xdf,0xb2,0x22,0x45,0x0a,0x07,0xa4,0xc9,0x40,0x7f,0x6e,0xd0,0x10,0x68,0xf6,0xcf,0x78,0x41,0x14,0xcf,0xc6,0x90,0x37,0xa4,0x18,0x25,0x7b,0x60,0x5e},
+ {0x18,0x18,0xdf,0x6c,0x8f,0x1d,0xb3,0x58,0xa2,0x58,0x62,0xc3,0x4f,0xa7,0xcf,0x35,0x6e,0x1d,0xe6,0x66,0x4f,0xff,0xb3,0xe1,0xf7,0xd5,0xcd,0x6c,0xab,0xac,0x67,0x50,0x14,0xcf,0x96,0xa5,0x1c,0x43,0x2c,0xa0,0x00,0xe4,0xd3,0xae,0x40,0x2d,0xc4,0xe3,0xdb,0x26,0x0f,0x2e,0x80,0x26,0x45,0xd2,0x68,0x70,0x45,0x9e,0x13,0x33,0x1f,0x20,0x51,0x9d,0x03,0x08,0x6b,0x7f,0x52,0xfd,0x06,0x00,0x7c,0x01,0x64,0x49,0xb1,0x18,0xa8,0xa4,0x25,0x2e,0xb0,0x0e,0x22,0xd5,0x75,0x03,0x46,0x62,0x88,0xba,0x7c,0x39},
+ {0xb2,0x59,0x59,0xf0,0x93,0x30,0xc1,0x30,0x76,0x79,0xa9,0xe9,0x8d,0xa1,0x3a,0xe2,0x26,0x5e,0x1d,0x72,0x91,0xd4,0x2f,0x22,0x3a,0x6c,0x6e,0x76,0x20,0xd3,0x39,0x23,0xe7,0x79,0x13,0xc8,0xfb,0xc3,0x15,0x78,0xf1,0x2a,0xe1,0xdd,0x20,0x94,0x61,0xa6,0xd5,0xfd,0xa8,0x85,0xf8,0xc0,0xa9,0xff,0x52,0xc2,0xe1,0xc1,0x22,0x40,0x1b,0x77,0xa7,0x2f,0x3a,0x51,0x86,0xd9,0x7d,0xd8,0x08,0xcf,0xd4,0xf9,0x71,0x9b,0xac,0xf5,0xb3,0x83,0xa2,0x1e,0x1b,0xc3,0x6b,0xd0,0x76,0x1a,0x97,0x19,0x92,0x18,0x1a,0x33},
+ {0xc6,0x80,0x4f,0xfb,0x45,0x6f,0x16,0xf5,0xcf,0x75,0xc7,0x61,0xde,0xc7,0x36,0x9c,0x1c,0xd9,0x41,0x90,0x1b,0xe8,0xd4,0xe3,0x21,0xfe,0xbd,0x83,0x6b,0x7c,0x16,0x31,0xaf,0x72,0x75,0x9d,0x3a,0x2f,0x51,0x26,0x9e,0x4a,0x07,0x68,0x88,0xe2,0xcb,0x5b,0xc4,0xf7,0x80,0x11,0xc1,0xc1,0xed,0x84,0x7b,0xa6,0x49,0xf6,0x9f,0x61,0xc9,0x1a,0x68,0x10,0x4b,0x52,0x42,0x38,0x2b,0xf2,0x87,0xe9,0x9c,0xee,0x3b,0x34,0x68,0x50,0xc8,0x50,0x62,0x4a,0x84,0x71,0x9d,0xfc,0x11,0xb1,0x08,0x1f,0x34,0x36,0x24,0x61},
+ {0x8d,0x89,0x4e,0x87,0xdb,0x41,0x9d,0xd9,0x20,0xdc,0x07,0x6c,0xf1,0xa5,0xfe,0x09,0xbc,0x9b,0x0f,0xd0,0x67,0x2c,0x3d,0x79,0x40,0xff,0x5e,0x9e,0x30,0xe2,0xeb,0x46,0x38,0x26,0x2d,0x1a,0xe3,0x49,0x63,0x8b,0x35,0xfd,0xd3,0x9b,0x00,0xb7,0xdf,0x9d,0xa4,0x6b,0xa0,0xa3,0xb8,0xf1,0x8b,0x7f,0x45,0x04,0xd9,0x78,0x31,0xaa,0x22,0x15,0x38,0x49,0x61,0x69,0x53,0x2f,0x38,0x2c,0x10,0x6d,0x2d,0xb7,0x9a,0x40,0xfe,0xda,0x27,0xf2,0x46,0xb6,0x91,0x33,0xc8,0xe8,0x6c,0x30,0x24,0x05,0xf5,0x70,0xfe,0x45},
+ {0x8c,0x0b,0x0c,0x96,0xa6,0x75,0x48,0xda,0x20,0x2f,0x0e,0xef,0x76,0xd0,0x68,0x5b,0xd4,0x8f,0x0b,0x3d,0xcf,0x51,0xfb,0x07,0xd4,0x92,0xe3,0xa0,0x23,0x16,0x8d,0x42,0x91,0x14,0x95,0xc8,0x20,0x49,0xf2,0x62,0xa2,0x0c,0x63,0x3f,0xc8,0x07,0xf0,0x05,0xb8,0xd4,0xc9,0xf5,0xd2,0x45,0xbb,0x6f,0x45,0x22,0x7a,0xb5,0x6d,0x9f,0x61,0x16,0xfd,0x08,0xa3,0x01,0x44,0x4a,0x4f,0x08,0xac,0xca,0xa5,0x76,0xc3,0x19,0x22,0xa8,0x7d,0xbc,0xd1,0x43,0x46,0xde,0xb8,0xde,0xc6,0x38,0xbd,0x60,0x2d,0x59,0x81,0x1d},
+ {0x5f,0xac,0x0d,0xa6,0x56,0x87,0x36,0x61,0x57,0xdc,0xab,0xeb,0x6a,0x2f,0xe0,0x17,0x7d,0x0f,0xce,0x4c,0x2d,0x3f,0x19,0x7f,0xf0,0xdc,0xec,0x89,0x77,0x4a,0x23,0x20,0xe8,0xc5,0x85,0x7b,0x9f,0xb6,0x65,0x87,0xb2,0xba,0x68,0xd1,0x8b,0x67,0xf0,0x6f,0x9b,0x0f,0x33,0x1d,0x7c,0xe7,0x70,0x3a,0x7c,0x8e,0xaf,0xb0,0x51,0x6d,0x5f,0x3a,0x52,0xb2,0x78,0x71,0xb6,0x0d,0xd2,0x76,0x60,0xd1,0x1e,0xd5,0xf9,0x34,0x1c,0x07,0x70,0x11,0xe4,0xb3,0x20,0x4a,0x2a,0xf6,0x66,0xe3,0xff,0x3c,0x35,0x82,0xd6,0x7c},
+ {0xb6,0xfa,0x87,0xd8,0x5b,0xa4,0xe1,0x0b,0x6e,0x3b,0x40,0xba,0x32,0x6a,0x84,0x2a,0x00,0x60,0x6e,0xe9,0x12,0x10,0x92,0xd9,0x43,0x09,0xdc,0x3b,0x86,0xc8,0x38,0x28,0xf3,0xf4,0xac,0x68,0x60,0xcd,0x65,0xa6,0xd3,0xe3,0xd7,0x3c,0x18,0x2d,0xd9,0x42,0xd9,0x25,0x60,0x33,0x9d,0x38,0x59,0x57,0xff,0xd8,0x2c,0x2b,0x3b,0x25,0xf0,0x3e,0x30,0x50,0x46,0x4a,0xcf,0xb0,0x6b,0xd1,0xab,0x77,0xc5,0x15,0x41,0x6b,0x49,0xfa,0x9d,0x41,0xab,0xf4,0x8a,0xae,0xcf,0x82,0x12,0x28,0xa8,0x06,0xa6,0xb8,0xdc,0x21},
+ {0xc8,0x9f,0x9d,0x8c,0x46,0x04,0x60,0x5c,0xcb,0xa3,0x2a,0xd4,0x6e,0x09,0x40,0x25,0x9c,0x2f,0xee,0x12,0x4c,0x4d,0x5b,0x12,0xab,0x1d,0xa3,0x94,0x81,0xd0,0xc3,0x0b,0xba,0x31,0x77,0xbe,0xfa,0x00,0x8d,0x9a,0x89,0x18,0x9e,0x62,0x7e,0x60,0x03,0x82,0x7f,0xd9,0xf3,0x43,0x37,0x02,0xcc,0xb2,0x8b,0x67,0x6f,0x6c,0xbf,0x0d,0x84,0x5d,0x8b,0xe1,0x9f,0x30,0x0d,0x38,0x6e,0x70,0xc7,0x65,0xe1,0xb9,0xa6,0x2d,0xb0,0x6e,0xab,0x20,0xae,0x7d,0x99,0xba,0xbb,0x57,0xdd,0x96,0xc1,0x2a,0x23,0x76,0x42,0x3a},
+ {0xfa,0x84,0x70,0x8a,0x2c,0x43,0x42,0x4b,0x45,0xe5,0xb9,0xdf,0xe3,0x19,0x8a,0x89,0x5d,0xe4,0x58,0x9c,0x21,0x00,0x9f,0xbe,0xd1,0xeb,0x6d,0xa1,0xce,0x77,0xf1,0x1f,0xcb,0x7e,0x44,0xdb,0x72,0xc1,0xf8,0x3b,0xbd,0x2d,0x28,0xc6,0x1f,0xc4,0xcf,0x5f,0xfe,0x15,0xaa,0x75,0xc0,0xff,0xac,0x80,0xf9,0xa9,0xe1,0x24,0xe8,0xc9,0x70,0x07,0xfd,0xb5,0xb5,0x45,0x9a,0xd9,0x61,0xcf,0x24,0x79,0x3a,0x1b,0xe9,0x84,0x09,0x86,0x89,0x3e,0x3e,0x30,0x19,0x09,0x30,0xe7,0x1e,0x0b,0x50,0x41,0xfd,0x64,0xf2,0x39},
+ {0x9c,0xe2,0xe7,0xdb,0x17,0x34,0xad,0xa7,0x9c,0x13,0x9c,0x2b,0x6a,0x37,0x94,0xbd,0xa9,0x7b,0x59,0x93,0x8e,0x1b,0xe9,0xa0,0x40,0x98,0x88,0x68,0x34,0xd7,0x12,0x17,0xe1,0x7b,0x09,0xfe,0xab,0x4a,0x9b,0xd1,0x29,0x19,0xe0,0xdf,0xe1,0xfc,0x6d,0xa4,0xff,0xf1,0xa6,0x2c,0x94,0x08,0xc9,0xc3,0x4e,0xf1,0x35,0x2c,0x27,0x21,0xc6,0x65,0xdd,0x93,0x31,0xce,0xf8,0x89,0x2b,0xe7,0xbb,0xc0,0x25,0xa1,0x56,0x33,0x10,0x4d,0x83,0xfe,0x1c,0x2e,0x3d,0xa9,0x19,0x04,0x72,0xe2,0x9c,0xb1,0x0a,0x80,0xf9,0x22},
+ {0xcb,0xf8,0x9e,0x3e,0x8a,0x36,0x5a,0x60,0x15,0x47,0x50,0xa5,0x22,0xc0,0xe9,0xe3,0x8f,0x24,0x24,0x5f,0xb0,0x48,0x3d,0x55,0xe5,0x26,0x76,0x64,0xcd,0x16,0xf4,0x13,0xac,0xfd,0x6e,0x9a,0xdd,0x9f,0x02,0x42,0x41,0x49,0xa5,0x34,0xbe,0xce,0x12,0xb9,0x7b,0xf3,0xbd,0x87,0xb9,0x64,0x0f,0x64,0xb4,0xca,0x98,0x85,0xd3,0xa4,0x71,0x41,0x8c,0x4c,0xc9,0x99,0xaa,0x58,0x27,0xfa,0x07,0xb8,0x00,0xb0,0x6f,0x6f,0x00,0x23,0x92,0x53,0xda,0xad,0xdd,0x91,0xd2,0xfb,0xab,0xd1,0x4b,0x57,0xfa,0x14,0x82,0x50},
+ {0x4b,0xfe,0xd6,0x3e,0x15,0x69,0x02,0xc2,0xc4,0x77,0x1d,0x51,0x39,0x67,0x5a,0xa6,0x94,0xaf,0x14,0x2c,0x46,0x26,0xde,0xcb,0x4b,0xa7,0xab,0x6f,0xec,0x60,0xf9,0x22,0xd6,0x03,0xd0,0x53,0xbb,0x15,0x1a,0x46,0x65,0xc9,0xf3,0xbc,0x88,0x28,0x10,0xb2,0x5a,0x3a,0x68,0x6c,0x75,0x76,0xc5,0x27,0x47,0xb4,0x6c,0xc8,0xa4,0x58,0x77,0x3a,0x76,0x50,0xae,0x93,0xf6,0x11,0x81,0x54,0xa6,0x54,0xfd,0x1d,0xdf,0x21,0xae,0x1d,0x65,0x5e,0x11,0xf3,0x90,0x8c,0x24,0x12,0x94,0xf4,0xe7,0x8d,0x5f,0xd1,0x9f,0x5d},
+ {0x7f,0x72,0x63,0x6d,0xd3,0x08,0x14,0x03,0x33,0xb5,0xc7,0xd7,0xef,0x9a,0x37,0x6a,0x4b,0xe2,0xae,0xcc,0xc5,0x8f,0xe1,0xa9,0xd3,0xbe,0x8f,0x4f,0x91,0x35,0x2f,0x33,0x1e,0x52,0xd7,0xee,0x2a,0x4d,0x24,0x3f,0x15,0x96,0x2e,0x43,0x28,0x90,0x3a,0x8e,0xd4,0x16,0x9c,0x2e,0x77,0xba,0x64,0xe1,0xd8,0x98,0xeb,0x47,0xfa,0x87,0xc1,0x3b,0x0c,0xc2,0x86,0xea,0x15,0x01,0x47,0x6d,0x25,0xd1,0x46,0x6c,0xcb,0xb7,0x8a,0x99,0x88,0x01,0x66,0x3a,0xb5,0x32,0x78,0xd7,0x03,0xba,0x6f,0x90,0xce,0x81,0x0d,0x45},
+ {0x75,0x52,0x20,0xa6,0xa1,0xb6,0x7b,0x6e,0x83,0x8e,0x3c,0x41,0xd7,0x21,0x4f,0xaa,0xb2,0x5c,0x8f,0xe8,0x55,0xd1,0x56,0x6f,0xe1,0x5b,0x34,0xa6,0x4b,0x5d,0xe2,0x2d,0x3f,0x74,0xae,0x1c,0x96,0xd8,0x74,0xd0,0xed,0x63,0x1c,0xee,0xf5,0x18,0x6d,0xf8,0x29,0xed,0xf4,0xe7,0x5b,0xc5,0xbd,0x97,0x08,0xb1,0x3a,0x66,0x79,0xd2,0xba,0x4c,0xcd,0x1f,0xd7,0xa0,0x24,0x90,0xd1,0x80,0xf8,0x8a,0x28,0xfb,0x0a,0xc2,0x25,0xc5,0x19,0x64,0x3a,0x5f,0x4b,0x97,0xa3,0xb1,0x33,0x72,0x00,0xe2,0xef,0xbc,0x7f,0x7d},
+ {0x01,0x28,0x6b,0x26,0x6a,0x1e,0xef,0xfa,0x16,0x9f,0x73,0xd5,0xc4,0x68,0x6c,0x86,0x2c,0x76,0x03,0x1b,0xbc,0x2f,0x8a,0xf6,0x8d,0x5a,0xb7,0x87,0x5e,0x43,0x75,0x59,0x94,0x90,0xc2,0xf3,0xc5,0x5d,0x7c,0xcd,0xab,0x05,0x91,0x2a,0x9a,0xa2,0x81,0xc7,0x58,0x30,0x1c,0x42,0x36,0x1d,0xc6,0x80,0xd7,0xd4,0xd8,0xdc,0x96,0xd1,0x9c,0x4f,0x68,0x37,0x7b,0x6a,0xd8,0x97,0x92,0x19,0x63,0x7a,0xd1,0x1a,0x24,0x58,0xd0,0xd0,0x17,0x0c,0x1c,0x5c,0xad,0x9c,0x02,0xba,0x07,0x03,0x7a,0x38,0x84,0xd0,0xcd,0x7c},
+ {0x17,0x04,0x26,0x6d,0x2c,0x42,0xa6,0xdc,0xbd,0x40,0x82,0x94,0x50,0x3d,0x15,0xae,0x77,0xc6,0x68,0xfb,0xb4,0xc1,0xc0,0xa9,0x53,0xcf,0xd0,0x61,0xed,0xd0,0x8b,0x42,0x93,0xcc,0x60,0x67,0x18,0x84,0x0c,0x9b,0x99,0x2a,0xb3,0x1a,0x7a,0x00,0xae,0xcd,0x18,0xda,0x0b,0x62,0x86,0xec,0x8d,0xa8,0x44,0xca,0x90,0x81,0x84,0xca,0x93,0x35,0xa7,0x9a,0x84,0x5e,0x9a,0x18,0x13,0x92,0xcd,0xfa,0xd8,0x65,0x35,0xc3,0xd8,0xd4,0xd1,0xbb,0xfd,0x53,0x5b,0x54,0x52,0x8c,0xe6,0x63,0x2d,0xda,0x08,0x83,0x39,0x27},
+ {0x13,0xd4,0x5e,0x43,0x28,0x8d,0xc3,0x42,0xc9,0xcc,0x78,0x32,0x60,0xf3,0x50,0xbd,0xef,0x03,0xda,0x79,0x1a,0xab,0x07,0xbb,0x55,0x33,0x8c,0xbe,0xae,0x97,0x95,0x26,0x53,0x24,0x70,0x0a,0x4c,0x0e,0xa1,0xb9,0xde,0x1b,0x7d,0xd5,0x66,0x58,0xa2,0x0f,0xf7,0xda,0x27,0xcd,0xb5,0xd9,0xb9,0xff,0xfd,0x33,0x2c,0x49,0x45,0x29,0x2c,0x57,0xbe,0x30,0xcd,0xd6,0x45,0xc7,0x7f,0xc7,0xfb,0xae,0xba,0xe3,0xd3,0xe8,0xdf,0xe4,0x0c,0xda,0x5d,0xaa,0x30,0x88,0x2c,0xa2,0x80,0xca,0x5b,0xc0,0x98,0x54,0x98,0x7f},
+ {0x17,0xe1,0x0b,0x9f,0x88,0xce,0x49,0x38,0x88,0xa2,0x54,0x7b,0x1b,0xad,0x05,0x80,0x1c,0x92,0xfc,0x23,0x9f,0xc3,0xa3,0x3d,0x04,0xf3,0x31,0x0a,0x47,0xec,0xc2,0x76,0x63,0x63,0xbf,0x0f,0x52,0x15,0x56,0xd3,0xa6,0xfb,0x4d,0xcf,0x45,0x5a,0x04,0x08,0xc2,0xa0,0x3f,0x87,0xbc,0x4f,0xc2,0xee,0xe7,0x12,0x9b,0xd6,0x3c,0x65,0xf2,0x30,0x85,0x0c,0xc1,0xaa,0x38,0xc9,0x08,0x8a,0xcb,0x6b,0x27,0xdb,0x60,0x9b,0x17,0x46,0x70,0xac,0x6f,0x0e,0x1e,0xc0,0x20,0xa9,0xda,0x73,0x64,0x59,0xf1,0x73,0x12,0x2f},
+ {0x11,0x1e,0xe0,0x8a,0x7c,0xfc,0x39,0x47,0x9f,0xab,0x6a,0x4a,0x90,0x74,0x52,0xfd,0x2e,0x8f,0x72,0x87,0x82,0x8a,0xd9,0x41,0xf2,0x69,0x5b,0xd8,0x2a,0x57,0x9e,0x5d,0xc0,0x0b,0xa7,0x55,0xd7,0x8b,0x48,0x30,0xe7,0x42,0xd4,0xf1,0xa4,0xb5,0xd6,0x06,0x62,0x61,0x59,0xbc,0x9e,0xa6,0xd1,0xea,0x84,0xf7,0xc5,0xed,0x97,0x19,0xac,0x38,0x3b,0xb1,0x51,0xa7,0x17,0xb5,0x66,0x06,0x8c,0x85,0x9b,0x7e,0x86,0x06,0x7d,0x74,0x49,0xde,0x4d,0x45,0x11,0xc0,0xac,0xac,0x9c,0xe6,0xe9,0xbf,0x9c,0xcd,0xdf,0x22},
+ {0xd9,0x0c,0x0d,0xc3,0xe0,0xd2,0xdb,0x8d,0x33,0x43,0xbb,0xac,0x5f,0x66,0x8e,0xad,0x1f,0x96,0x2a,0x32,0x8c,0x25,0x6b,0x8f,0xc7,0xc1,0x48,0x54,0xc0,0x16,0x29,0x6b,0xa1,0xe0,0x3b,0x10,0xb4,0x59,0xec,0x56,0x69,0xf9,0x59,0xd2,0xec,0xba,0xe3,0x2e,0x32,0xcd,0xf5,0x13,0x94,0xb2,0x7c,0x79,0x72,0xe4,0xcd,0x24,0x78,0x87,0xe9,0x0f,0x3b,0x91,0xba,0x0a,0xd1,0x34,0xdb,0x7e,0x0e,0xac,0x6d,0x2e,0x82,0xcd,0xa3,0x4e,0x15,0xf8,0x78,0x65,0xff,0x3d,0x08,0x66,0x17,0x0a,0xf0,0x7f,0x30,0x3f,0x30,0x4c},
+ {0x85,0x8c,0xb2,0x17,0xd6,0x3b,0x0a,0xd3,0xea,0x3b,0x77,0x39,0xb7,0x77,0xd3,0xc5,0xbf,0x5c,0x6a,0x1e,0x8c,0xe7,0xc6,0xc6,0xc4,0xb7,0x2a,0x8b,0xf7,0xb8,0x61,0x0d,0x00,0x45,0xd9,0x0d,0x58,0x03,0xfc,0x29,0x93,0xec,0xbb,0x6f,0xa4,0x7a,0xd2,0xec,0xf8,0xa7,0xe2,0xc2,0x5f,0x15,0x0a,0x13,0xd5,0xa1,0x06,0xb7,0x1a,0x15,0x6b,0x41,0xb0,0x36,0xc1,0xe9,0xef,0xd7,0xa8,0x56,0x20,0x4b,0xe4,0x58,0xcd,0xe5,0x07,0xbd,0xab,0xe0,0x57,0x1b,0xda,0x2f,0xe6,0xaf,0xd2,0xe8,0x77,0x42,0xf7,0x2a,0x1a,0x19},
+ {0x31,0x14,0x3c,0xc5,0x4b,0xf7,0x16,0xce,0xde,0xed,0x72,0x20,0xce,0x25,0x97,0x2b,0xe7,0x3e,0xb2,0xb5,0x6f,0xc3,0xb9,0xb8,0x08,0xc9,0x5c,0x0b,0x45,0x0e,0x2e,0x7e,0xfb,0x0e,0x46,0x4f,0x43,0x2b,0xe6,0x9f,0xd6,0x07,0x36,0xa6,0xd4,0x03,0xd3,0xde,0x24,0xda,0xa0,0xb7,0x0e,0x21,0x52,0xf0,0x93,0x5b,0x54,0x00,0xbe,0x7d,0x7e,0x23,0x30,0xb4,0x01,0x67,0xed,0x75,0x35,0x01,0x10,0xfd,0x0b,0x9f,0xe6,0x94,0x10,0x23,0x22,0x7f,0xe4,0x83,0x15,0x0f,0x32,0x75,0xe3,0x55,0x11,0xb1,0x99,0xa6,0xaf,0x71},
+ {0x1d,0xb6,0x53,0x39,0x9b,0x6f,0xce,0x65,0xe6,0x41,0xa1,0xaf,0xea,0x39,0x58,0xc6,0xfe,0x59,0xf7,0xa9,0xfd,0x5f,0x43,0x0f,0x8e,0xc2,0xb1,0xc2,0xe9,0x42,0x11,0x02,0xd6,0x50,0x3b,0x47,0x1c,0x3c,0x42,0xea,0x10,0xef,0x38,0x3b,0x1f,0x7a,0xe8,0x51,0x95,0xbe,0xc9,0xb2,0x5f,0xbf,0x84,0x9b,0x1c,0x9a,0xf8,0x78,0xbc,0x1f,0x73,0x00,0x80,0x18,0xf8,0x48,0x18,0xc7,0x30,0xe4,0x19,0xc1,0xce,0x5e,0x22,0x0c,0x96,0xbf,0xe3,0x15,0xba,0x6b,0x83,0xe0,0xda,0xb6,0x08,0x58,0xe1,0x47,0x33,0x6f,0x4d,0x4c},
+ {0xc9,0x1f,0x7d,0xc1,0xcf,0xec,0xf7,0x18,0x14,0x3c,0x40,0x51,0xa6,0xf5,0x75,0x6c,0xdf,0x0c,0xee,0xf7,0x2b,0x71,0xde,0xdb,0x22,0x7a,0xe4,0xa7,0xaa,0xdd,0x3f,0x19,0x70,0x19,0x8f,0x98,0xfc,0xdd,0x0c,0x2f,0x1b,0xf5,0xb9,0xb0,0x27,0x62,0x91,0x6b,0xbe,0x76,0x91,0x77,0xc4,0xb6,0xc7,0x6e,0xa8,0x9f,0x8f,0xa8,0x00,0x95,0xbf,0x38,0x6f,0x87,0xe8,0x37,0x3c,0xc9,0xd2,0x1f,0x2c,0x46,0xd1,0x18,0x5a,0x1e,0xf6,0xa2,0x76,0x12,0x24,0x39,0x82,0xf5,0x80,0x50,0x69,0x49,0x0d,0xbf,0x9e,0xb9,0x6f,0x6a},
+ {0xeb,0x55,0x08,0x56,0xbb,0xc1,0x46,0x6a,0x9d,0xf0,0x93,0xf8,0x38,0xbb,0x16,0x24,0xc1,0xac,0x71,0x8f,0x37,0x11,0x1d,0xd7,0xea,0x96,0x18,0xa3,0x14,0x69,0xf7,0x75,0xc6,0x23,0xe4,0xb6,0xb5,0x22,0xb1,0xee,0x8e,0xff,0x86,0xf2,0x10,0x70,0x9d,0x93,0x8c,0x5d,0xcf,0x1d,0x83,0x2a,0xa9,0x90,0x10,0xeb,0xc5,0x42,0x9f,0xda,0x6f,0x13,0xd1,0xbd,0x05,0xa3,0xb1,0xdf,0x4c,0xf9,0x08,0x2c,0xf8,0x9f,0x9d,0x4b,0x36,0x0f,0x8a,0x58,0xbb,0xc3,0xa5,0xd8,0x87,0x2a,0xba,0xdc,0xe8,0x0b,0x51,0x83,0x21,0x02},
+ {0x14,0x2d,0xad,0x5e,0x38,0x66,0xf7,0x4a,0x30,0x58,0x7c,0xca,0x80,0xd8,0x8e,0xa0,0x3d,0x1e,0x21,0x10,0xe6,0xa6,0x13,0x0d,0x03,0x6c,0x80,0x7b,0xe1,0x1c,0x07,0x6a,0x7f,0x7a,0x30,0x43,0x01,0x71,0x5a,0x9d,0x5f,0xa4,0x7d,0xc4,0x9e,0xde,0x63,0xb0,0xd3,0x7a,0x92,0xbe,0x52,0xfe,0xbb,0x22,0x6c,0x42,0x40,0xfd,0x41,0xc4,0x87,0x13,0xf8,0x8a,0x97,0x87,0xd1,0xc3,0xd3,0xb5,0x13,0x44,0x0e,0x7f,0x3d,0x5a,0x2b,0x72,0xa0,0x7c,0x47,0xbb,0x48,0x48,0x7b,0x0d,0x92,0xdc,0x1e,0xaf,0x6a,0xb2,0x71,0x31},
+ {0xa8,0x4c,0x56,0x97,0x90,0x31,0x2f,0xa9,0x19,0xe1,0x75,0x22,0x4c,0xb8,0x7b,0xff,0x50,0x51,0x87,0xa4,0x37,0xfe,0x55,0x4f,0x5a,0x83,0xf0,0x3c,0x87,0xd4,0x1f,0x22,0xd1,0x47,0x8a,0xb2,0xd8,0xb7,0x0d,0xa6,0xf1,0xa4,0x70,0x17,0xd6,0x14,0xbf,0xa6,0x58,0xbd,0xdd,0x53,0x93,0xf8,0xa1,0xd4,0xe9,0x43,0x42,0x34,0x63,0x4a,0x51,0x6c,0x41,0x63,0x15,0x3a,0x4f,0x20,0x22,0x23,0x2d,0x03,0x0a,0xba,0xe9,0xe0,0x73,0xfb,0x0e,0x03,0x0f,0x41,0x4c,0xdd,0xe0,0xfc,0xaa,0x4a,0x92,0xfb,0x96,0xa5,0xda,0x48},
+ {0xc7,0x9c,0xa5,0x5c,0x66,0x8e,0xca,0x6e,0xa0,0xac,0x38,0x2e,0x4b,0x25,0x47,0xa8,0xce,0x17,0x1e,0xd2,0x08,0xc7,0xaf,0x31,0xf7,0x4a,0xd8,0xca,0xfc,0xd6,0x6d,0x67,0x93,0x97,0x4c,0xc8,0x5d,0x1d,0xf6,0x14,0x06,0x82,0x41,0xef,0xe3,0xf9,0x41,0x99,0xac,0x77,0x62,0x34,0x8f,0xb8,0xf5,0xcd,0xa9,0x79,0x8a,0x0e,0xfa,0x37,0xc8,0x58,0x58,0x90,0xfc,0x96,0x85,0x68,0xf9,0x0c,0x1b,0xa0,0x56,0x7b,0xf3,0xbb,0xdc,0x1d,0x6a,0xd6,0x35,0x49,0x7d,0xe7,0xc2,0xdc,0x0a,0x7f,0xa5,0xc6,0xf2,0x73,0x4f,0x1c},
+ {0xbb,0xa0,0x5f,0x30,0xbd,0x4f,0x7a,0x0e,0xad,0x63,0xc6,0x54,0xe0,0x4c,0x9d,0x82,0x48,0x38,0xe3,0x2f,0x83,0xc3,0x21,0xf4,0x42,0x4c,0xf6,0x1b,0x0d,0xc8,0x5a,0x79,0x84,0x34,0x7c,0xfc,0x6e,0x70,0x6e,0xb3,0x61,0xcf,0xc1,0xc3,0xb4,0xc9,0xdf,0x73,0xe5,0xc7,0x1c,0x78,0xc9,0x79,0x1d,0xeb,0x5c,0x67,0xaf,0x7d,0xdb,0x9a,0x45,0x70,0xb3,0x2b,0xb4,0x91,0x49,0xdb,0x91,0x1b,0xca,0xdc,0x02,0x4b,0x23,0x96,0x26,0x57,0xdc,0x78,0x8c,0x1f,0xe5,0x9e,0xdf,0x9f,0xd3,0x1f,0xe2,0x8c,0x84,0x62,0xe1,0x5f},
+ {0x1a,0x96,0x94,0xe1,0x4f,0x21,0x59,0x4e,0x4f,0xcd,0x71,0x0d,0xc7,0x7d,0xbe,0x49,0x2d,0xf2,0x50,0x3b,0xd2,0xcf,0x00,0x93,0x32,0x72,0x91,0xfc,0x46,0xd4,0x89,0x47,0x08,0xb2,0x7c,0x5d,0x2d,0x85,0x79,0x28,0xe7,0xf2,0x7d,0x68,0x70,0xdd,0xde,0xb8,0x91,0x78,0x68,0x21,0xab,0xff,0x0b,0xdc,0x35,0xaa,0x7d,0x67,0x43,0xc0,0x44,0x2b,0x8e,0xb7,0x4e,0x07,0xab,0x87,0x1c,0x1a,0x67,0xf4,0xda,0x99,0x8e,0xd1,0xc6,0xfa,0x67,0x90,0x4f,0x48,0xcd,0xbb,0xac,0x3e,0xe4,0xa4,0xb9,0x2b,0xef,0x2e,0xc5,0x60},
+ {0xf1,0x8b,0xfd,0x3b,0xbc,0x89,0x5d,0x0b,0x1a,0x55,0xf3,0xc9,0x37,0x92,0x6b,0xb0,0xf5,0x28,0x30,0xd5,0xb0,0x16,0x4c,0x0e,0xab,0xca,0xcf,0x2c,0x31,0x9c,0xbc,0x10,0x11,0x6d,0xae,0x7c,0xc2,0xc5,0x2b,0x70,0xab,0x8c,0xa4,0x54,0x9b,0x69,0xc7,0x44,0xb2,0x2e,0x49,0xba,0x56,0x40,0xbc,0xef,0x6d,0x67,0xb6,0xd9,0x48,0x72,0xd7,0x70,0x5b,0xa0,0xc2,0x3e,0x4b,0xe8,0x8a,0xaa,0xe0,0x81,0x17,0xed,0xf4,0x9e,0x69,0x98,0xd1,0x85,0x8e,0x70,0xe4,0x13,0x45,0x79,0x13,0xf4,0x76,0xa9,0xd3,0x5b,0x75,0x63},
+ {0x53,0x08,0xd1,0x2a,0x3e,0xa0,0x5f,0xb5,0x69,0x35,0xe6,0x9e,0x90,0x75,0x6f,0x35,0x90,0xb8,0x69,0xbe,0xfd,0xf1,0xf9,0x9f,0x84,0x6f,0xc1,0x8b,0xc4,0xc1,0x8c,0x0d,0xb7,0xac,0xf1,0x97,0x18,0x10,0xc7,0x3d,0xd8,0xbb,0x65,0xc1,0x5e,0x7d,0xda,0x5d,0x0f,0x02,0xa1,0x0f,0x9c,0x5b,0x8e,0x50,0x56,0x2a,0xc5,0x37,0x17,0x75,0x63,0x27,0xa9,0x19,0xb4,0x6e,0xd3,0x02,0x94,0x02,0xa5,0x60,0xb4,0x77,0x7e,0x4e,0xb4,0xf0,0x56,0x49,0x3c,0xd4,0x30,0x62,0xa8,0xcf,0xe7,0x66,0xd1,0x7a,0x8a,0xdd,0xc2,0x70},
+ {0x0e,0xec,0x6f,0x9f,0x50,0x94,0x61,0x65,0x8d,0x51,0xc6,0x46,0xa9,0x7e,0x2e,0xee,0x5c,0x9b,0xe0,0x67,0xf3,0xc1,0x33,0x97,0x95,0x84,0x94,0x63,0x63,0xac,0x0f,0x2e,0x13,0x7e,0xed,0xb8,0x7d,0x96,0xd4,0x91,0x7a,0x81,0x76,0xd7,0x0a,0x2f,0x25,0x74,0x64,0x25,0x85,0x0d,0xe0,0x82,0x09,0xe4,0xe5,0x3c,0xa5,0x16,0x38,0x61,0xb8,0x32,0x64,0xcd,0x48,0xe4,0xbe,0xf7,0xe7,0x79,0xd0,0x86,0x78,0x08,0x67,0x3a,0xc8,0x6a,0x2e,0xdb,0xe4,0xa0,0xd9,0xd4,0x9f,0xf8,0x41,0x4f,0x5a,0x73,0x5c,0x21,0x79,0x41},
+ {0x2a,0xed,0xdc,0xd7,0xe7,0x94,0x70,0x8c,0x70,0x9c,0xd3,0x47,0xc3,0x8a,0xfb,0x97,0x02,0xd9,0x06,0xa9,0x33,0xe0,0x3b,0xe1,0x76,0x9d,0xd9,0x0c,0xa3,0x44,0x03,0x70,0x34,0xcd,0x6b,0x28,0xb9,0x33,0xae,0xe4,0xdc,0xd6,0x9d,0x55,0xb6,0x7e,0xef,0xb7,0x1f,0x8e,0xd3,0xb3,0x1f,0x14,0x8b,0x27,0x86,0xc2,0x41,0x22,0x66,0x85,0xfa,0x31,0xf4,0x22,0x36,0x2e,0x42,0x6c,0x82,0xaf,0x2d,0x50,0x33,0x98,0x87,0x29,0x20,0xc1,0x23,0x91,0x38,0x2b,0xe1,0xb7,0xc1,0x9b,0x89,0x24,0x95,0xa9,0x12,0x23,0xbb,0x24},
+ {0xc3,0x67,0xde,0x32,0x17,0xed,0xa8,0xb1,0x48,0x49,0x1b,0x46,0x18,0x94,0xb4,0x3c,0xd2,0xbc,0xcf,0x76,0x43,0x43,0xbd,0x8e,0x08,0x80,0x18,0x1e,0x87,0x3e,0xee,0x0f,0x6b,0x5c,0xf8,0xf5,0x2a,0x0c,0xf8,0x41,0x94,0x67,0xfa,0x04,0xc3,0x84,0x72,0x68,0xad,0x1b,0xba,0xa3,0x99,0xdf,0x45,0x89,0x16,0x5d,0xeb,0xff,0xf9,0x2a,0x1d,0x0d,0xdf,0x1e,0x62,0x32,0xa1,0x8a,0xda,0xa9,0x79,0x65,0x22,0x59,0xa1,0x22,0xb8,0x30,0x93,0xc1,0x9a,0xa7,0x7b,0x19,0x04,0x40,0x76,0x1d,0x53,0x18,0x97,0xd7,0xac,0x16},
+ {0x3d,0x1d,0x9b,0x2d,0xaf,0x72,0xdf,0x72,0x5a,0x24,0x32,0xa4,0x36,0x2a,0x46,0x63,0x37,0x96,0xb3,0x16,0x79,0xa0,0xce,0x3e,0x09,0x23,0x30,0xb9,0xf6,0x0e,0x3e,0x12,0xad,0xb6,0x87,0x78,0xc5,0xc6,0x59,0xc9,0xba,0xfe,0x90,0x5f,0xad,0x9e,0xe1,0x94,0x04,0xf5,0x42,0xa3,0x62,0x4e,0xe2,0x16,0x00,0x17,0x16,0x18,0x4b,0xd3,0x4e,0x16,0x9a,0xe6,0x2f,0x19,0x4c,0xd9,0x7e,0x48,0x13,0x15,0x91,0x3a,0xea,0x2c,0xae,0x61,0x27,0xde,0xa4,0xb9,0xd3,0xf6,0x7b,0x87,0xeb,0xf3,0x73,0x10,0xc6,0x0f,0xda,0x78},
+ {0x6a,0xc6,0x2b,0xe5,0x28,0x5d,0xf1,0x5b,0x8e,0x1a,0xf0,0x70,0x18,0xe3,0x47,0x2c,0xdd,0x8b,0xc2,0x06,0xbc,0xaf,0x19,0x24,0x3a,0x17,0x6b,0x25,0xeb,0xde,0x25,0x2d,0x94,0x3a,0x0c,0x68,0xf1,0x80,0x9f,0xa2,0xe6,0xe7,0xe9,0x1a,0x15,0x7e,0xf7,0x71,0x73,0x79,0x01,0x48,0x58,0xf1,0x00,0x11,0xdd,0x8d,0xb3,0x16,0xb3,0xa4,0x4a,0x05,0xb8,0x7c,0x26,0x19,0x8d,0x46,0xc8,0xdf,0xaf,0x4d,0xe5,0x66,0x9c,0x78,0x28,0x0b,0x17,0xec,0x6e,0x66,0x2a,0x1d,0xeb,0x2a,0x60,0xa7,0x7d,0xab,0xa6,0x10,0x46,0x13},
+ {0xfe,0xb0,0xf6,0x8d,0xc7,0x8e,0x13,0x51,0x1b,0xf5,0x75,0xe5,0x89,0xda,0x97,0x53,0xb9,0xf1,0x7a,0x71,0x1d,0x7a,0x20,0x09,0x50,0xd6,0x20,0x2b,0xba,0xfd,0x02,0x21,0x15,0xf5,0xd1,0x77,0xe7,0x65,0x2a,0xcd,0xf1,0x60,0xaa,0x8f,0x87,0x91,0x89,0x54,0xe5,0x06,0xbc,0xda,0xbc,0x3b,0xb7,0xb1,0xfb,0xc9,0x7c,0xa9,0xcb,0x78,0x48,0x65,0xa1,0xe6,0x5c,0x05,0x05,0xe4,0x9e,0x96,0x29,0xad,0x51,0x12,0x68,0xa7,0xbc,0x36,0x15,0xa4,0x7d,0xaa,0x17,0xf5,0x1a,0x3a,0xba,0xb2,0xec,0x29,0xdb,0x25,0xd7,0x0a},
+ {0x57,0x24,0x4e,0x83,0xb1,0x67,0x42,0xdc,0xc5,0x1b,0xce,0x70,0xb5,0x44,0x75,0xb6,0xd7,0x5e,0xd1,0xf7,0x0b,0x7a,0xf0,0x1a,0x50,0x36,0xa0,0x71,0xfb,0xcf,0xef,0x4a,0x85,0x6f,0x05,0x9b,0x0c,0xbc,0xc7,0xfe,0xd7,0xff,0xf5,0xe7,0x68,0x52,0x7d,0x53,0xfa,0xae,0x12,0x43,0x62,0xc6,0xaf,0x77,0xd9,0x9f,0x39,0x02,0x53,0x5f,0x67,0x4f,0x1e,0x17,0x15,0x04,0x36,0x36,0x2d,0xc3,0x3b,0x48,0x98,0x89,0x11,0xef,0x2b,0xcd,0x10,0x51,0x94,0xd0,0xad,0x6e,0x0a,0x87,0x61,0x65,0xa8,0xa2,0x72,0xbb,0xcc,0x0b},
+ {0xc8,0xa9,0xb1,0xea,0x2f,0x96,0x5e,0x18,0xcd,0x7d,0x14,0x65,0x35,0xe6,0xe7,0x86,0xf2,0x6d,0x5b,0xbb,0x31,0xe0,0x92,0xb0,0x3e,0xb7,0xd6,0x59,0xab,0xf0,0x24,0x40,0x96,0x12,0xfe,0x50,0x4c,0x5e,0x6d,0x18,0x7e,0x9f,0xe8,0xfe,0x82,0x7b,0x39,0xe0,0xb0,0x31,0x70,0x50,0xc5,0xf6,0xc7,0x3b,0xc2,0x37,0x8f,0x10,0x69,0xfd,0x78,0x66,0xc2,0x63,0x68,0x63,0x31,0xfa,0x86,0x15,0xf2,0x33,0x2d,0x57,0x48,0x8c,0xf6,0x07,0xfc,0xae,0x9e,0x78,0x9f,0xcc,0x73,0x4f,0x01,0x47,0xad,0x8e,0x10,0xe2,0x42,0x2d},
+ {0x9b,0xd2,0xdf,0x94,0x15,0x13,0xf5,0x97,0x6a,0x4c,0x3f,0x31,0x5d,0x98,0x55,0x61,0x10,0x50,0x45,0x08,0x07,0x3f,0xa1,0xeb,0x22,0xd3,0xd2,0xb8,0x08,0x26,0x6b,0x67,0x93,0x75,0x53,0x0f,0x0d,0x7b,0x71,0x21,0x4c,0x06,0x1e,0x13,0x0b,0x69,0x4e,0x91,0x9f,0xe0,0x2a,0x75,0xae,0x87,0xb6,0x1b,0x6e,0x3c,0x42,0x9b,0xa7,0xf3,0x0b,0x42,0x47,0x2b,0x5b,0x1c,0x65,0xba,0x38,0x81,0x80,0x1b,0x1b,0x31,0xec,0xb6,0x71,0x86,0xb0,0x35,0x31,0xbc,0xb1,0x0c,0xff,0x7b,0xe0,0xf1,0x0c,0x9c,0xfa,0x2f,0x5d,0x74},
+ {0xbd,0xc8,0xc9,0x2b,0x1e,0x5a,0x52,0xbf,0x81,0x9d,0x47,0x26,0x08,0x26,0x5b,0xea,0xdb,0x55,0x01,0xdf,0x0e,0xc7,0x11,0xd5,0xd0,0xf5,0x0c,0x96,0xeb,0x3c,0xe2,0x1a,0x6a,0x4e,0xd3,0x21,0x57,0xdf,0x36,0x60,0xd0,0xb3,0x7b,0x99,0x27,0x88,0xdb,0xb1,0xfa,0x6a,0x75,0xc8,0xc3,0x09,0xc2,0xd3,0x39,0xc8,0x1d,0x4c,0xe5,0x5b,0xe1,0x06,0x4a,0x99,0x32,0x19,0x87,0x5d,0x72,0x5b,0xb0,0xda,0xb1,0xce,0xb5,0x1c,0x35,0x32,0x05,0xca,0xb7,0xda,0x49,0x15,0xc4,0x7d,0xf7,0xc1,0x8e,0x27,0x61,0xd8,0xde,0x58},
+ {0x5c,0xc5,0x66,0xf2,0x93,0x37,0x17,0xd8,0x49,0x4e,0x45,0xcc,0xc5,0x76,0xc9,0xc8,0xa8,0xc3,0x26,0xbc,0xf8,0x82,0xe3,0x5c,0xf9,0xf6,0x85,0x54,0xe8,0x9d,0xf3,0x2f,0xa8,0xc9,0xc2,0xb6,0xa8,0x5b,0xfb,0x2d,0x8c,0x59,0x2c,0xf5,0x8e,0xef,0xee,0x48,0x73,0x15,0x2d,0xf1,0x07,0x91,0x80,0x33,0xd8,0x5b,0x1d,0x53,0x6b,0x69,0xba,0x08,0x7a,0xc5,0xef,0xc3,0xee,0x3e,0xed,0x77,0x11,0x48,0xff,0xd4,0x17,0x55,0xe0,0x04,0xcb,0x71,0xa6,0xf1,0x3f,0x7a,0x3d,0xea,0x54,0xfe,0x7c,0x94,0xb4,0x33,0x06,0x12},
+ {0x42,0x00,0x61,0x91,0x78,0x98,0x94,0x0b,0xe8,0xfa,0xeb,0xec,0x3c,0xb1,0xe7,0x4e,0xc0,0xa4,0xf0,0x94,0x95,0x73,0xbe,0x70,0x85,0x91,0xd5,0xb4,0x99,0x0a,0xd3,0x35,0x0a,0x10,0x12,0x49,0x47,0x31,0xbd,0x82,0x06,0xbe,0x6f,0x7e,0x6d,0x7b,0x23,0xde,0xc6,0x79,0xea,0x11,0x19,0x76,0x1e,0xe1,0xde,0x3b,0x39,0xcb,0xe3,0x3b,0x43,0x07,0xf4,0x97,0xe9,0x5c,0xc0,0x44,0x79,0xff,0xa3,0x51,0x5c,0xb0,0xe4,0x3d,0x5d,0x57,0x7c,0x84,0x76,0x5a,0xfd,0x81,0x33,0x58,0x9f,0xda,0xf6,0x7a,0xde,0x3e,0x87,0x2d},
+ {0x09,0x34,0x37,0x43,0x64,0x31,0x7a,0x15,0xd9,0x81,0xaa,0xf4,0xee,0xb7,0xb8,0xfa,0x06,0x48,0xa6,0xf5,0xe6,0xfe,0x93,0xb0,0xb6,0xa7,0x7f,0x70,0x54,0x36,0x77,0x2e,0x81,0xf9,0x5d,0x4e,0xe1,0x02,0x62,0xaa,0xf5,0xe1,0x15,0x50,0x17,0x59,0x0d,0xa2,0x6c,0x1d,0xe2,0xba,0xd3,0x75,0xa2,0x18,0x53,0x02,0x60,0x01,0x8a,0x61,0x43,0x05,0xc1,0x23,0x4c,0x97,0xf4,0xbd,0xea,0x0d,0x93,0x46,0xce,0x9d,0x25,0x0a,0x6f,0xaa,0x2c,0xba,0x9a,0xa2,0xb8,0x2c,0x20,0x04,0x0d,0x96,0x07,0x2d,0x36,0x43,0x14,0x4b},
+ {0x7a,0x1f,0x6e,0xb6,0xc7,0xb7,0xc4,0xcc,0x7e,0x2f,0x0c,0xf5,0x25,0x7e,0x15,0x44,0x1c,0xaf,0x3e,0x71,0xfc,0x6d,0xf0,0x3e,0xf7,0x63,0xda,0x52,0x67,0x44,0x2f,0x58,0xcb,0x9c,0x52,0x1c,0xe9,0x54,0x7c,0x96,0xfb,0x35,0xc6,0x64,0x92,0x26,0xf6,0x30,0x65,0x19,0x12,0x78,0xf4,0xaf,0x47,0x27,0x5c,0x6f,0xf6,0xea,0x18,0x84,0x03,0x17,0xe4,0x4c,0x32,0x20,0xd3,0x7b,0x31,0xc6,0xc4,0x8b,0x48,0xa4,0xe8,0x42,0x10,0xa8,0x64,0x13,0x5a,0x4e,0x8b,0xf1,0x1e,0xb2,0xc9,0x8d,0xa2,0xcd,0x4b,0x1c,0x2a,0x0c},
+ {0x47,0x04,0x1f,0x6f,0xd0,0xc7,0x4d,0xd2,0x59,0xc0,0x87,0xdb,0x3e,0x9e,0x26,0xb2,0x8f,0xd2,0xb2,0xfb,0x72,0x02,0x5b,0xd1,0x77,0x48,0xf6,0xc6,0xd1,0x8b,0x55,0x7c,0x45,0x69,0xbd,0x69,0x48,0x81,0xc4,0xed,0x22,0x8d,0x1c,0xbe,0x7d,0x90,0x6d,0x0d,0xab,0xc5,0x5c,0xd5,0x12,0xd2,0x3b,0xc6,0x83,0xdc,0x14,0xa3,0x30,0x9b,0x6a,0x5a,0x3d,0x46,0x96,0xd3,0x24,0x15,0xec,0xd0,0xf0,0x24,0x5a,0xc3,0x8a,0x62,0xbb,0x12,0xa4,0x5f,0xbc,0x1c,0x79,0x3a,0x0c,0xa5,0xc3,0xaf,0xfb,0x0a,0xca,0xa5,0x04,0x04},
+ {0xd6,0x43,0xa7,0x0a,0x07,0x40,0x1f,0x8c,0xe8,0x5e,0x26,0x5b,0xcb,0xd0,0xba,0xcc,0xde,0xd2,0x8f,0x66,0x6b,0x04,0x4b,0x57,0x33,0x96,0xdd,0xca,0xfd,0x5b,0x39,0x46,0xd1,0x6f,0x41,0x2a,0x1b,0x9e,0xbc,0x62,0x8b,0x59,0x50,0xe3,0x28,0xf7,0xc6,0xb5,0x67,0x69,0x5d,0x3d,0xd8,0x3f,0x34,0x04,0x98,0xee,0xf8,0xe7,0x16,0x75,0x52,0x39,0x9c,0x9a,0x5d,0x1a,0x2d,0xdb,0x7f,0x11,0x2a,0x5c,0x00,0xd1,0xbc,0x45,0x77,0x9c,0xea,0x6f,0xd5,0x54,0xf1,0xbe,0xd4,0xef,0x16,0xd0,0x22,0xe8,0x29,0x9a,0x57,0x76},
+ {0x17,0x2a,0xc0,0x49,0x7e,0x8e,0xb6,0x45,0x7f,0xa3,0xa9,0xbc,0xa2,0x51,0xcd,0x23,0x1b,0x4c,0x22,0xec,0x11,0x5f,0xd6,0x3e,0xb1,0xbd,0x05,0x9e,0xdc,0x84,0xa3,0x43,0xf2,0x34,0xb4,0x52,0x13,0xb5,0x3c,0x33,0xe1,0x80,0xde,0x93,0x49,0x28,0x32,0xd8,0xce,0x35,0x0d,0x75,0x87,0x28,0x51,0xb5,0xc1,0x77,0x27,0x2a,0xbb,0x14,0xc5,0x02,0x45,0xb6,0xf1,0x8b,0xda,0xd5,0x4b,0x68,0x53,0x4b,0xb5,0xf6,0x7e,0xd3,0x8b,0xfb,0x53,0xd2,0xb0,0xa9,0xd7,0x16,0x39,0x31,0x59,0x80,0x54,0x61,0x09,0x92,0x60,0x11},
+ {0xaa,0xcf,0xda,0x29,0x69,0x16,0x4d,0xb4,0x8f,0x59,0x13,0x84,0x4c,0x9f,0x52,0xda,0x59,0x55,0x3d,0x45,0xca,0x63,0xef,0xe9,0x0b,0x8e,0x69,0xc5,0x5b,0x12,0x1e,0x35,0xcd,0x4d,0x9b,0x36,0x16,0x56,0x38,0x7a,0x63,0x35,0x5c,0x65,0xa7,0x2c,0xc0,0x75,0x21,0x80,0xf1,0xd4,0xf9,0x1b,0xc2,0x7d,0x42,0xe0,0xe6,0x91,0x74,0x7d,0x63,0x2f,0xbe,0x7b,0xf6,0x1a,0x46,0x9b,0xb4,0xd4,0x61,0x89,0xab,0xc8,0x7a,0x03,0x03,0xd6,0xfb,0x99,0xa6,0xf9,0x9f,0xe1,0xde,0x71,0x9a,0x2a,0xce,0xe7,0x06,0x2d,0x18,0x7f},
+ {0xec,0x68,0x01,0xab,0x64,0x8e,0x7c,0x7a,0x43,0xc5,0xed,0x15,0x55,0x4a,0x5a,0xcb,0xda,0x0e,0xcd,0x47,0xd3,0x19,0x55,0x09,0xb0,0x93,0x3e,0x34,0x8c,0xac,0xd4,0x67,0x22,0x75,0x21,0x8e,0x72,0x4b,0x45,0x09,0xd8,0xb8,0x84,0xd4,0xf4,0xe8,0x58,0xaa,0x3c,0x90,0x46,0x7f,0x4d,0x25,0x58,0xd3,0x17,0x52,0x1c,0x24,0x43,0xc0,0xac,0x44,0x77,0x57,0x7a,0x4f,0xbb,0x6b,0x7d,0x1c,0xe1,0x13,0x83,0x91,0xd4,0xfe,0x35,0x8b,0x84,0x46,0x6b,0xc9,0xc6,0xa1,0xdc,0x4a,0xbd,0x71,0xad,0x12,0x83,0x1c,0x6d,0x55},
+ {0x82,0x39,0x8d,0x0c,0xe3,0x40,0xef,0x17,0x34,0xfa,0xa3,0x15,0x3e,0x07,0xf7,0x31,0x6e,0x64,0x73,0x07,0xcb,0xf3,0x21,0x4f,0xff,0x4e,0x82,0x1d,0x6d,0x6c,0x6c,0x74,0x21,0xe8,0x1b,0xb1,0x56,0x67,0xf0,0x81,0xdd,0xf3,0xa3,0x10,0x23,0xf8,0xaf,0x0f,0x5d,0x46,0x99,0x6a,0x55,0xd0,0xb2,0xf8,0x05,0x7f,0x8c,0xcc,0x38,0xbe,0x7a,0x09,0xa4,0x2d,0xa5,0x7e,0x87,0xc9,0x49,0x0c,0x43,0x1d,0xdc,0x9b,0x55,0x69,0x43,0x4c,0xd2,0xeb,0xcc,0xf7,0x09,0x38,0x2c,0x02,0xbd,0x84,0xee,0x4b,0xa3,0x14,0x7e,0x57},
+ {0x0a,0x3b,0xa7,0x61,0xac,0x68,0xe2,0xf0,0xf5,0xa5,0x91,0x37,0x10,0xfa,0xfa,0xf2,0xe9,0x00,0x6d,0x6b,0x82,0x3e,0xe1,0xc1,0x42,0x8f,0xd7,0x6f,0xe9,0x7e,0xfa,0x60,0x2b,0xd7,0x4d,0xbd,0xbe,0xce,0xfe,0x94,0x11,0x22,0x0f,0x06,0xda,0x4f,0x6a,0xf4,0xff,0xd1,0xc8,0xc0,0x77,0x59,0x4a,0x12,0x95,0x92,0x00,0xfb,0xb8,0x04,0x53,0x70,0xc6,0x6e,0x29,0x4d,0x35,0x1d,0x3d,0xb6,0xd8,0x31,0xad,0x5f,0x3e,0x05,0xc3,0xf3,0xec,0x42,0xbd,0xb4,0x8c,0x95,0x0b,0x67,0xfd,0x53,0x63,0xa1,0x0c,0x8e,0x39,0x21},
+ {0xf3,0x33,0x2b,0x38,0x8a,0x05,0xf5,0x89,0xb4,0xc0,0x48,0xad,0x0b,0xba,0xe2,0x5a,0x6e,0xb3,0x3d,0xa5,0x03,0xb5,0x93,0x8f,0xe6,0x32,0xa2,0x95,0x9d,0xed,0xa3,0x5a,0x01,0x56,0xb7,0xb4,0xf9,0xaa,0x98,0x27,0x72,0xad,0x8d,0x5c,0x13,0x72,0xac,0x5e,0x23,0xa0,0xb7,0x61,0x61,0xaa,0xce,0xd2,0x4e,0x7d,0x8f,0xe9,0x84,0xb2,0xbf,0x1b,0x61,0x65,0xd9,0xc7,0xe9,0x77,0x67,0x65,0x36,0x80,0xc7,0x72,0x54,0x12,0x2b,0xcb,0xee,0x6e,0x50,0xd9,0x99,0x32,0x05,0x65,0xcc,0x57,0x89,0x5e,0x4e,0xe1,0x07,0x4a},
+ {0x99,0xf9,0x0d,0x98,0xcb,0x12,0xe4,0x4e,0x71,0xc7,0x6e,0x3c,0x6f,0xd7,0x15,0xa3,0xfd,0x77,0x5c,0x92,0xde,0xed,0xa5,0xbb,0x02,0x34,0x31,0x1d,0x39,0xac,0x0b,0x3f,0x9b,0xa4,0x77,0xc4,0xcd,0x58,0x0b,0x24,0x17,0xf0,0x47,0x64,0xde,0xda,0x38,0xfd,0xad,0x6a,0xc8,0xa7,0x32,0x8d,0x92,0x19,0x81,0xa0,0xaf,0x84,0xed,0x7a,0xaf,0x50,0xe5,0x5b,0xf6,0x15,0x01,0xde,0x4f,0x6e,0xb2,0x09,0x61,0x21,0x21,0x26,0x98,0x29,0xd9,0xd6,0xad,0x0b,0x81,0x05,0x02,0x78,0x06,0xd0,0xeb,0xba,0x16,0xa3,0x21,0x19},
+ {0xfc,0x70,0xb8,0xdf,0x7e,0x2f,0x42,0x89,0xbd,0xb3,0x76,0x4f,0xeb,0x6b,0x29,0x2c,0xf7,0x4d,0xc2,0x36,0xd4,0xf1,0x38,0x07,0xb0,0xae,0x73,0xe2,0x41,0xdf,0x58,0x64,0x8b,0xc1,0xf3,0xd9,0x9a,0xad,0x5a,0xd7,0x9c,0xc1,0xb1,0x60,0xef,0x0e,0x6a,0x56,0xd9,0x0e,0x5c,0x25,0xac,0x0b,0x9a,0x3e,0xf5,0xc7,0x62,0xa0,0xec,0x9d,0x04,0x7b,0x83,0x44,0x44,0x35,0x7a,0xe3,0xcb,0xdc,0x93,0xbe,0xed,0x0f,0x33,0x79,0x88,0x75,0x87,0xdd,0xc5,0x12,0xc3,0x04,0x60,0x78,0x64,0x0e,0x95,0xc2,0xcb,0xdc,0x93,0x60},
+ {0x6d,0x70,0xe0,0x85,0x85,0x9a,0xf3,0x1f,0x33,0x39,0xe7,0xb3,0xd8,0xa5,0xd0,0x36,0x3b,0x45,0x8f,0x71,0xe1,0xf2,0xb9,0x43,0x7c,0xa9,0x27,0x48,0x08,0xea,0xd1,0x57,0x4b,0x03,0x84,0x60,0xbe,0xee,0xde,0x6b,0x54,0xb8,0x0f,0x78,0xb6,0xc2,0x99,0x31,0x95,0x06,0x2d,0xb6,0xab,0x76,0x33,0x97,0x90,0x7d,0x64,0x8b,0xc9,0x80,0x31,0x6e,0x71,0xb0,0x28,0xa1,0xe7,0xb6,0x7a,0xee,0xaa,0x8b,0xa8,0x93,0x6d,0x59,0xc1,0xa4,0x30,0x61,0x21,0xb2,0x82,0xde,0xb4,0xf7,0x18,0xbd,0x97,0xdd,0x9d,0x99,0x3e,0x36},
+ {0xc4,0x1f,0xee,0x35,0xc1,0x43,0xa8,0x96,0xcf,0xc8,0xe4,0x08,0x55,0xb3,0x6e,0x97,0x30,0xd3,0x8c,0xb5,0x01,0x68,0x2f,0xb4,0x2b,0x05,0x3a,0x69,0x78,0x9b,0xee,0x48,0xc6,0xae,0x4b,0xe2,0xdc,0x48,0x18,0x2f,0x60,0xaf,0xbc,0xba,0x55,0x72,0x9b,0x76,0x31,0xe9,0xef,0x3c,0x6e,0x3c,0xcb,0x90,0x55,0xb3,0xf9,0xc6,0x9b,0x97,0x1f,0x23,0xc6,0xf3,0x2a,0xcc,0x4b,0xde,0x31,0x5c,0x1f,0x8d,0x20,0xfe,0x30,0xb0,0x4b,0xb0,0x66,0xb4,0x4f,0xc1,0x09,0x70,0x8d,0xb7,0x13,0x24,0x79,0x08,0x9b,0xfa,0x9b,0x07},
+ {0xf4,0x0d,0x30,0xda,0x51,0x3a,0x90,0xe3,0xb0,0x5a,0xa9,0x3d,0x23,0x64,0x39,0x84,0x80,0x64,0x35,0x0b,0x2d,0xf1,0x3c,0xed,0x94,0x71,0x81,0x84,0xf6,0x77,0x8c,0x03,0x45,0x42,0xd5,0xa2,0x80,0xed,0xc9,0xf3,0x52,0x39,0xf6,0x77,0x78,0x8b,0xa0,0x0a,0x75,0x54,0x08,0xd1,0x63,0xac,0x6d,0xd7,0x6b,0x63,0x70,0x94,0x15,0xfb,0xf4,0x1e,0xec,0x7b,0x16,0x5b,0xe6,0x5e,0x4e,0x85,0xc2,0xcd,0xd0,0x96,0x42,0x0a,0x59,0x59,0x99,0x21,0x10,0x98,0x34,0xdf,0xb2,0x72,0x56,0xff,0x0b,0x4a,0x2a,0xe9,0x5e,0x57},
+ {0xcf,0x2f,0x18,0x8a,0x90,0x80,0xc0,0xd4,0xbd,0x9d,0x48,0x99,0xc2,0x70,0xe1,0x30,0xde,0x33,0xf7,0x52,0x57,0xbd,0xba,0x05,0x00,0xfd,0xd3,0x2c,0x11,0xe7,0xd4,0x43,0x01,0xd8,0xa4,0x0a,0x45,0xbc,0x46,0x5d,0xd8,0xb9,0x33,0xa5,0x27,0x12,0xaf,0xc3,0xc2,0x06,0x89,0x2b,0x26,0x3b,0x9e,0x38,0x1b,0x58,0x2f,0x38,0x7e,0x1e,0x0a,0x20,0xc5,0x3a,0xf9,0xea,0x67,0xb9,0x8d,0x51,0xc0,0x52,0x66,0x05,0x9b,0x98,0xbc,0x71,0xf5,0x97,0x71,0x56,0xd9,0x85,0x2b,0xfe,0x38,0x4e,0x1e,0x65,0x52,0xca,0x0e,0x05},
+ {0x9c,0x0c,0x3f,0x45,0xde,0x1a,0x43,0xc3,0x9b,0x3b,0x70,0xff,0x5e,0x04,0xf5,0xe9,0x3d,0x7b,0x84,0xed,0xc9,0x7a,0xd9,0xfc,0xc6,0xf4,0x58,0x1c,0xc2,0xe6,0x0e,0x4b,0xea,0x68,0xe6,0x60,0x76,0x39,0xac,0x97,0x97,0xb4,0x3a,0x15,0xfe,0xbb,0x19,0x9b,0x9f,0xa7,0xec,0x34,0xb5,0x79,0xb1,0x4c,0x57,0xae,0x31,0xa1,0x9f,0xc0,0x51,0x61,0x96,0x5d,0xf0,0xfd,0x0d,0x5c,0xf5,0x3a,0x7a,0xee,0xb4,0x2a,0xe0,0x2e,0x26,0xdd,0x09,0x17,0x17,0x12,0x87,0xbb,0xb2,0x11,0x0b,0x03,0x0f,0x80,0xfa,0x24,0xef,0x1f},
+ {0x96,0x31,0xa7,0x1a,0xfb,0x53,0xd6,0x37,0x18,0x64,0xd7,0x3f,0x30,0x95,0x94,0x0f,0xb2,0x17,0x3a,0xfb,0x09,0x0b,0x20,0xad,0x3e,0x61,0xc8,0x2f,0x29,0x49,0x4d,0x54,0x86,0x6b,0x97,0x30,0xf5,0xaf,0xd2,0x22,0x04,0x46,0xd2,0xc2,0x06,0xb8,0x90,0x8d,0xe5,0xba,0xe5,0x4d,0x6c,0x89,0xa1,0xdc,0x17,0x0c,0x34,0xc8,0xe6,0x5f,0x00,0x28,0x88,0x86,0x52,0x34,0x9f,0xba,0xef,0x6a,0xa1,0x7d,0x10,0x25,0x94,0xff,0x1b,0x5c,0x36,0x4b,0xd9,0x66,0xcd,0xbb,0x5b,0xf7,0xfa,0x6d,0x31,0x0f,0x93,0x72,0xe4,0x72},
+ {0x4f,0x08,0x81,0x97,0x8c,0x20,0x95,0x26,0xe1,0x0e,0x45,0x23,0x0b,0x2a,0x50,0xb1,0x02,0xde,0xef,0x03,0xa6,0xae,0x9d,0xfd,0x4c,0xa3,0x33,0x27,0x8c,0x2e,0x9d,0x5a,0x27,0x76,0x2a,0xd3,0x35,0xf6,0xf3,0x07,0xf0,0x66,0x65,0x5f,0x86,0x4d,0xaa,0x7a,0x50,0x44,0xd0,0x28,0x97,0xe7,0x85,0x3c,0x38,0x64,0xe0,0x0f,0x00,0x7f,0xee,0x1f,0xe5,0xf7,0xdb,0x03,0xda,0x05,0x53,0x76,0xbd,0xcd,0x34,0x14,0x49,0xf2,0xda,0xa4,0xec,0x88,0x4a,0xd2,0xcd,0xd5,0x4a,0x7b,0x43,0x05,0x04,0xee,0x51,0x40,0xf9,0x00},
+ {0xb2,0x30,0xd3,0xc3,0x23,0x6b,0x35,0x8d,0x06,0x1b,0x47,0xb0,0x9b,0x8b,0x1c,0xf2,0x3c,0xb8,0x42,0x6e,0x6c,0x31,0x6c,0xb3,0x0d,0xb1,0xea,0x8b,0x7e,0x9c,0xd7,0x07,0x53,0x97,0xaf,0x07,0xbb,0x93,0xef,0xd7,0xa7,0x66,0xb7,0x3d,0xcf,0xd0,0x3e,0x58,0xc5,0x1e,0x0b,0x6e,0xbf,0x98,0x69,0xce,0x52,0x04,0xd4,0x5d,0xd2,0xff,0xb7,0x47,0x12,0xdd,0x08,0xbc,0x9c,0xfb,0xfb,0x87,0x9b,0xc2,0xee,0xe1,0x3a,0x6b,0x06,0x8a,0xbf,0xc1,0x1f,0xdb,0x2b,0x24,0x57,0x0d,0xb6,0x4b,0xa6,0x5e,0xa3,0x20,0x35,0x1c},
+ {0x4a,0xa3,0xcb,0xbc,0xa6,0x53,0xd2,0x80,0x9b,0x21,0x38,0x38,0xa1,0xc3,0x61,0x3e,0x96,0xe3,0x82,0x98,0x01,0xb6,0xc3,0x90,0x6f,0xe6,0x0e,0x5d,0x77,0x05,0x3d,0x1c,0x59,0xc0,0x6b,0x21,0x40,0x6f,0xa8,0xcd,0x7e,0xd8,0xbc,0x12,0x1d,0x23,0xbb,0x1f,0x90,0x09,0xc7,0x17,0x9e,0x6a,0x95,0xb4,0x55,0x2e,0xd1,0x66,0x3b,0x0c,0x75,0x38,0x1a,0xe5,0x22,0x94,0x40,0xf1,0x2e,0x69,0x71,0xf6,0x5d,0x2b,0x3c,0xc7,0xc0,0xcb,0x29,0xe0,0x4c,0x74,0xe7,0x4f,0x01,0x21,0x7c,0x48,0x30,0xd3,0xc7,0xe2,0x21,0x06},
+ {0x8d,0x83,0x59,0x82,0xcc,0x60,0x98,0xaf,0xdc,0x9a,0x9f,0xc6,0xc1,0x48,0xea,0x90,0x30,0x1e,0x58,0x65,0x37,0x48,0x26,0x65,0xbc,0xa5,0xd3,0x7b,0x09,0xd6,0x07,0x00,0xf3,0xf0,0xdb,0xb0,0x96,0x17,0xae,0xb7,0x96,0xe1,0x7c,0xe1,0xb9,0xaf,0xdf,0x54,0xb4,0xa3,0xaa,0xe9,0x71,0x30,0x92,0x25,0x9d,0x2e,0x00,0xa1,0x9c,0x58,0x8e,0x5d,0x4b,0xa9,0x42,0x08,0x95,0x1d,0xbf,0xc0,0x3e,0x2e,0x8f,0x58,0x63,0xc3,0xd3,0xb2,0xef,0xe2,0x51,0xbb,0x38,0x14,0x96,0x0a,0x86,0xbf,0x1c,0x3c,0x78,0xd7,0x83,0x15},
+ {0xe1,0x7a,0xa2,0x5d,0xef,0xa2,0xee,0xec,0x74,0x01,0x67,0x55,0x14,0x3a,0x7c,0x59,0x7a,0x16,0x09,0x66,0x12,0x2a,0xa6,0xc9,0x70,0x8f,0xed,0x81,0x2e,0x5f,0x2a,0x25,0xc7,0x28,0x9d,0xcc,0x04,0x47,0x03,0x90,0x8f,0xc5,0x2c,0xf7,0x9e,0x67,0x1b,0x1d,0x26,0x87,0x5b,0xbe,0x5f,0x2b,0xe1,0x16,0x0a,0x58,0xc5,0x83,0x4e,0x06,0x58,0x49,0x0d,0xe8,0x66,0x50,0x26,0x94,0x28,0x0d,0x6b,0x8c,0x7c,0x30,0x85,0xf7,0xc3,0xfc,0xfd,0x12,0x11,0x0c,0x78,0xda,0x53,0x1b,0x88,0xb3,0x43,0xd8,0x0b,0x17,0x9c,0x07},
+ {0xff,0x6f,0xfa,0x64,0xe4,0xec,0x06,0x05,0x23,0xe5,0x05,0x62,0x1e,0x43,0xe3,0xbe,0x42,0xea,0xb8,0x51,0x24,0x42,0x79,0x35,0x00,0xfb,0xc9,0x4a,0xe3,0x05,0xec,0x6d,0x56,0xd0,0xd5,0xc0,0x50,0xcd,0xd6,0xcd,0x3b,0x57,0x03,0xbb,0x6d,0x68,0xf7,0x9a,0x48,0xef,0xc3,0xf3,0x3f,0x72,0xa6,0x3c,0xcc,0x8a,0x7b,0x31,0xd7,0xc0,0x68,0x67,0xb3,0xc1,0x55,0xf1,0xe5,0x25,0xb6,0x94,0x91,0x7b,0x7b,0x99,0xa7,0xf3,0x7b,0x41,0x00,0x26,0x6b,0x6d,0xdc,0xbd,0x2c,0xc2,0xf4,0x52,0xcd,0xdd,0x14,0x5e,0x44,0x51},
+ {0x51,0x49,0x14,0x3b,0x4b,0x2b,0x50,0x57,0xb3,0xbc,0x4b,0x44,0x6b,0xff,0x67,0x8e,0xdb,0x85,0x63,0x16,0x27,0x69,0xbd,0xb8,0xc8,0x95,0x92,0xe3,0x31,0x6f,0x18,0x13,0x55,0xa4,0xbe,0x2b,0xab,0x47,0x31,0x89,0x29,0x91,0x07,0x92,0x4f,0xa2,0x53,0x8c,0xa7,0xf7,0x30,0xbe,0x48,0xf9,0x49,0x4b,0x3d,0xd4,0x4f,0x6e,0x08,0x90,0xe9,0x12,0x2e,0xbb,0xdf,0x7f,0xb3,0x96,0x0c,0xf1,0xf9,0xea,0x1c,0x12,0x5e,0x93,0x9a,0x9f,0x3f,0x98,0x5b,0x3a,0xc4,0x36,0x11,0xdf,0xaf,0x99,0x3e,0x5d,0xf0,0xe3,0xb2,0x77},
+ {0xde,0xc4,0x2e,0x9c,0xc5,0xa9,0x6f,0x29,0xcb,0xf3,0x84,0x4f,0xbf,0x61,0x8b,0xbc,0x08,0xf9,0xa8,0x17,0xd9,0x06,0x77,0x1c,0x5d,0x25,0xd3,0x7a,0xfc,0x95,0xb7,0x63,0xa4,0xb0,0xdd,0x12,0x9c,0x63,0x98,0xd5,0x6b,0x86,0x24,0xc0,0x30,0x9f,0xd1,0xa5,0x60,0xe4,0xfc,0x58,0x03,0x2f,0x7c,0xd1,0x8a,0x5e,0x09,0x2e,0x15,0x95,0xa1,0x07,0xc8,0x5f,0x9e,0x38,0x02,0x8f,0x36,0xa8,0x3b,0xe4,0x8d,0xcf,0x02,0x3b,0x43,0x90,0x43,0x26,0x41,0xc5,0x5d,0xfd,0xa1,0xaf,0x37,0x01,0x2f,0x03,0x3d,0xe8,0x8f,0x3e},
+ {0x94,0xa2,0x70,0x05,0xb9,0x15,0x8b,0x2f,0x49,0x45,0x08,0x67,0x70,0x42,0xf2,0x94,0x84,0xfd,0xbb,0x61,0xe1,0x5a,0x1c,0xde,0x07,0x40,0xac,0x7f,0x79,0x3b,0xba,0x75,0x3c,0xd1,0xef,0xe8,0x8d,0x4c,0x70,0x08,0x31,0x37,0xe0,0x33,0x8e,0x1a,0xc5,0xdf,0xe3,0xcd,0x60,0x12,0xa5,0x5d,0x9d,0xa5,0x86,0x8c,0x25,0xa6,0x99,0x08,0xd6,0x22,0x96,0xd1,0xcd,0x70,0xc0,0xdb,0x39,0x62,0x9a,0x8a,0x7d,0x6c,0x8b,0x8a,0xfe,0x60,0x60,0x12,0x40,0xeb,0xbc,0x47,0x88,0xb3,0x5e,0x9e,0x77,0x87,0x7b,0xd0,0x04,0x09},
+ {0x9c,0x91,0xba,0xdd,0xd4,0x1f,0xce,0xb4,0xaa,0x8d,0x4c,0xc7,0x3e,0xdb,0x31,0xcf,0x51,0xcc,0x86,0xad,0x63,0xcc,0x63,0x2c,0x07,0xde,0x1d,0xbc,0x3f,0x14,0xe2,0x43,0xb9,0x40,0xf9,0x48,0x66,0x2d,0x32,0xf4,0x39,0x0c,0x2d,0xbd,0x0c,0x2f,0x95,0x06,0x31,0xf9,0x81,0xa0,0xad,0x97,0x76,0x16,0x6c,0x2a,0xf7,0xba,0xce,0xaa,0x40,0x62,0xa0,0x95,0xa2,0x5b,0x9c,0x74,0x34,0xf8,0x5a,0xd2,0x37,0xca,0x5b,0x7c,0x94,0xd6,0x6a,0x31,0xc9,0xe7,0xa7,0x3b,0xf1,0x66,0xac,0x0c,0xb4,0x8d,0x23,0xaf,0xbd,0x56},
+ {0xeb,0x33,0x35,0xf5,0xe3,0xb9,0x2a,0x36,0x40,0x3d,0xb9,0x6e,0xd5,0x68,0x85,0x33,0x72,0x55,0x5a,0x1d,0x52,0x14,0x0e,0x9e,0x18,0x13,0x74,0x83,0x6d,0xa8,0x24,0x1d,0xb2,0x3b,0x9d,0xc1,0x6c,0xd3,0x10,0x13,0xb9,0x86,0x23,0x62,0xb7,0x6b,0x2a,0x06,0x5c,0x4f,0xa1,0xd7,0x91,0x85,0x9b,0x7c,0x54,0x57,0x1e,0x7e,0x50,0x31,0xaa,0x03,0x1f,0xce,0xd4,0xff,0x48,0x76,0xec,0xf4,0x1c,0x8c,0xac,0x54,0xf0,0xea,0x45,0xe0,0x7c,0x35,0x09,0x1d,0x82,0x25,0xd2,0x88,0x59,0x48,0xeb,0x9a,0xdc,0x61,0xb2,0x43},
+ {0xbb,0x79,0xbb,0x88,0x19,0x1e,0x5b,0xe5,0x9d,0x35,0x7a,0xc1,0x7d,0xd0,0x9e,0xa0,0x33,0xea,0x3d,0x60,0xe2,0x2e,0x2c,0xb0,0xc2,0x6b,0x27,0x5b,0xcf,0x55,0x60,0x32,0x64,0x13,0x95,0x6c,0x8b,0x3d,0x51,0x19,0x7b,0xf4,0x0b,0x00,0x26,0x71,0xfe,0x94,0x67,0x95,0x4f,0xd5,0xdd,0x10,0x8d,0x02,0x64,0x09,0x94,0x42,0xe2,0xd5,0xb4,0x02,0xf2,0x8d,0xd1,0x28,0xcb,0x55,0xa1,0xb4,0x08,0xe5,0x6c,0x18,0x46,0x46,0xcc,0xea,0x89,0x43,0x82,0x6c,0x93,0xf4,0x9c,0xc4,0x10,0x34,0x5d,0xae,0x09,0xc8,0xa6,0x27},
+ {0x88,0xb1,0x0d,0x1f,0xcd,0xeb,0xa6,0x8b,0xe8,0x5b,0x5a,0x67,0x3a,0xd7,0xd3,0x37,0x5a,0x58,0xf5,0x15,0xa3,0xdf,0x2e,0xf2,0x7e,0xa1,0x60,0xff,0x74,0x71,0xb6,0x2c,0x54,0x69,0x3d,0xc4,0x0a,0x27,0x2c,0xcd,0xb2,0xca,0x66,0x6a,0x57,0x3e,0x4a,0xdd,0x6c,0x03,0xd7,0x69,0x24,0x59,0xfa,0x79,0x99,0x25,0x8c,0x3d,0x60,0x03,0x15,0x22,0xd0,0xe1,0x0b,0x39,0xf9,0xcd,0xee,0x59,0xf1,0xe3,0x8c,0x72,0x44,0x20,0x42,0xa9,0xf4,0xf0,0x94,0x7a,0x66,0x1c,0x89,0x82,0x36,0xf4,0x90,0x38,0xb7,0xf4,0x1d,0x7b},
+ {0x24,0xa2,0xb2,0xb3,0xe0,0xf2,0x92,0xe4,0x60,0x11,0x55,0x2b,0x06,0x9e,0x6c,0x7c,0x0e,0x7b,0x7f,0x0d,0xe2,0x8f,0xeb,0x15,0x92,0x59,0xfc,0x58,0x26,0xef,0xfc,0x61,0x8c,0xf5,0xf8,0x07,0x18,0x22,0x2e,0x5f,0xd4,0x09,0x94,0xd4,0x9f,0x5c,0x55,0xe3,0x30,0xa6,0xb6,0x1f,0x8d,0xa8,0xaa,0xb2,0x3d,0xe0,0x52,0xd3,0x45,0x82,0x69,0x68,0x7a,0x18,0x18,0x2a,0x85,0x5d,0xb1,0xdb,0xd7,0xac,0xdd,0x86,0xd3,0xaa,0xe4,0xf3,0x82,0xc4,0xf6,0x0f,0x81,0xe2,0xba,0x44,0xcf,0x01,0xaf,0x3d,0x47,0x4c,0xcf,0x46},
+ {0xf9,0xe5,0xc4,0x9e,0xed,0x25,0x65,0x42,0x03,0x33,0x90,0x16,0x01,0xda,0x5e,0x0e,0xdc,0xca,0xe5,0xcb,0xf2,0xa7,0xb1,0x72,0x40,0x5f,0xeb,0x14,0xcd,0x7b,0x38,0x29,0x40,0x81,0x49,0xf1,0xa7,0x6e,0x3c,0x21,0x54,0x48,0x2b,0x39,0xf8,0x7e,0x1e,0x7c,0xba,0xce,0x29,0x56,0x8c,0xc3,0x88,0x24,0xbb,0xc5,0x8c,0x0d,0xe5,0xaa,0x65,0x10,0x57,0x0d,0x20,0xdf,0x25,0x45,0x2c,0x1c,0x4a,0x67,0xca,0xbf,0xd6,0x2d,0x3b,0x5c,0x30,0x40,0x83,0xe1,0xb1,0xe7,0x07,0x0a,0x16,0xe7,0x1c,0x4f,0xe6,0x98,0xa1,0x69},
+ {0xbc,0x78,0x1a,0xd9,0xe0,0xb2,0x62,0x90,0x67,0x96,0x50,0xc8,0x9c,0x88,0xc9,0x47,0xb8,0x70,0x50,0x40,0x66,0x4a,0xf5,0x9d,0xbf,0xa1,0x93,0x24,0xa9,0xe6,0x69,0x73,0xed,0xca,0xc5,0xdc,0x34,0x44,0x01,0xe1,0x33,0xfb,0x84,0x3c,0x96,0x5d,0xed,0x47,0xe7,0xa0,0x86,0xed,0x76,0x95,0x01,0x70,0xe4,0xf9,0x67,0xd2,0x7b,0x69,0xb2,0x25,0x64,0x68,0x98,0x13,0xfb,0x3f,0x67,0x9d,0xb8,0xc7,0x5d,0x41,0xd9,0xfb,0xa5,0x3c,0x5e,0x3b,0x27,0xdf,0x3b,0xcc,0x4e,0xe0,0xd2,0x4c,0x4e,0xb5,0x3d,0x68,0x20,0x14},
+ {0x97,0xd1,0x9d,0x24,0x1e,0xbd,0x78,0xb4,0x02,0xc1,0x58,0x5e,0x00,0x35,0x0c,0x62,0x5c,0xac,0xba,0xcc,0x2f,0xd3,0x02,0xfb,0x2d,0xa7,0x08,0xf5,0xeb,0x3b,0xb6,0x60,0xd0,0x5a,0xcc,0xc1,0x6f,0xbb,0xee,0x34,0x8b,0xac,0x46,0x96,0xe9,0x0c,0x1b,0x6a,0x53,0xde,0x6b,0xa6,0x49,0xda,0xb0,0xd3,0xc1,0x81,0xd0,0x61,0x41,0x3b,0xe8,0x31,0x4f,0x2b,0x06,0x9e,0x12,0xc7,0xe8,0x97,0xd8,0x0a,0x32,0x29,0x4f,0x8f,0xe4,0x49,0x3f,0x68,0x18,0x6f,0x4b,0xe1,0xec,0x5b,0x17,0x03,0x55,0x2d,0xb6,0x1e,0xcf,0x55},
+ {0x58,0x3d,0xc2,0x65,0x10,0x10,0x79,0x58,0x9c,0x81,0x94,0x50,0x6d,0x08,0x9d,0x8b,0xa7,0x5f,0xc5,0x12,0xa9,0x2f,0x40,0xe2,0xd4,0x91,0x08,0x57,0x64,0x65,0x9a,0x66,0x52,0x8c,0xf5,0x7d,0xe3,0xb5,0x76,0x30,0x36,0xcc,0x99,0xe7,0xdd,0xb9,0x3a,0xd7,0x20,0xee,0x13,0x49,0xe3,0x1c,0x83,0xbd,0x33,0x01,0xba,0x62,0xaa,0xfb,0x56,0x1a,0xec,0xc9,0x9d,0x5c,0x50,0x6b,0x3e,0x94,0x1a,0x37,0x7c,0xa7,0xbb,0x57,0x25,0x30,0x51,0x76,0x34,0x41,0x56,0xae,0x73,0x98,0x5c,0x8a,0xc5,0x99,0x67,0x83,0xc4,0x13},
+ {0xb9,0xe1,0xb3,0x5a,0x46,0x5d,0x3a,0x42,0x61,0x3f,0xf1,0xc7,0x87,0xc1,0x13,0xfc,0xb6,0xb9,0xb5,0xec,0x64,0x36,0xf8,0x19,0x07,0xb6,0x37,0xa6,0x93,0x0c,0xf8,0x66,0x80,0xd0,0x8b,0x5d,0x6a,0xfb,0xdc,0xc4,0x42,0x48,0x1a,0x57,0xec,0xc4,0xeb,0xde,0x65,0x53,0xe5,0xb8,0x83,0xe8,0xb2,0xd4,0x27,0xb8,0xe5,0xc8,0x7d,0xc8,0xbd,0x50,0x11,0xe1,0xdf,0x6e,0x83,0x37,0x6d,0x60,0xd9,0xab,0x11,0xf0,0x15,0x3e,0x35,0x32,0x96,0x3b,0xb7,0x25,0xc3,0x3a,0xb0,0x64,0xae,0xd5,0x5f,0x72,0x44,0x64,0xd5,0x1d},
+ {0x7d,0x12,0x62,0x33,0xf8,0x7f,0xa4,0x8f,0x15,0x7c,0xcd,0x71,0xc4,0x6a,0x9f,0xbc,0x8b,0x0c,0x22,0x49,0x43,0x45,0x71,0x6e,0x2e,0x73,0x9f,0x21,0x12,0x59,0x64,0x0e,0x9a,0xc8,0xba,0x08,0x00,0xe6,0x97,0xc2,0xe0,0xc3,0xe1,0xea,0x11,0xea,0x4c,0x7d,0x7c,0x97,0xe7,0x9f,0xe1,0x8b,0xe3,0xf3,0xcd,0x05,0xa3,0x63,0x0f,0x45,0x3a,0x3a,0x27,0x46,0x39,0xd8,0x31,0x2f,0x8f,0x07,0x10,0xa5,0x94,0xde,0x83,0x31,0x9d,0x38,0x80,0x6f,0x99,0x17,0x6d,0x6c,0xe3,0xd1,0x7b,0xa8,0xa9,0x93,0x93,0x8d,0x8c,0x31},
+ {0x19,0xfe,0xff,0x2a,0x03,0x5d,0x74,0xf2,0x66,0xdb,0x24,0x7f,0x49,0x3c,0x9f,0x0c,0xef,0x98,0x85,0xba,0xe3,0xd3,0x98,0xbc,0x14,0x53,0x1d,0x9a,0x67,0x7c,0x4c,0x22,0x98,0xd3,0x1d,0xab,0x29,0x9e,0x66,0x5d,0x3b,0x9e,0x2d,0x34,0x58,0x16,0x92,0xfc,0xcd,0x73,0x59,0xf3,0xfd,0x1d,0x85,0x55,0xf6,0x0a,0x95,0x25,0xc3,0x41,0x9a,0x50,0xe9,0x25,0xf9,0xa6,0xdc,0x6e,0xc0,0xbd,0x33,0x1f,0x1b,0x64,0xf4,0xf3,0x3e,0x79,0x89,0x3e,0x83,0x9d,0x80,0x12,0xec,0x82,0x89,0x13,0xa1,0x28,0x23,0xf0,0xbf,0x05},
+ {0x0b,0xe0,0xca,0x23,0x70,0x13,0x32,0x36,0x59,0xcf,0xac,0xd1,0x0a,0xcf,0x4a,0x54,0x88,0x1c,0x1a,0xd2,0x49,0x10,0x74,0x96,0xa7,0x44,0x2a,0xfa,0xc3,0x8c,0x0b,0x78,0xe4,0x12,0xc5,0x0d,0xdd,0xa0,0x81,0x68,0xfe,0xfa,0xa5,0x44,0xc8,0x0d,0xe7,0x4f,0x40,0x52,0x4a,0x8f,0x6b,0x8e,0x74,0x1f,0xea,0xa3,0x01,0xee,0xcd,0x77,0x62,0x57,0x5f,0x30,0x4f,0x23,0xbc,0x8a,0xf3,0x1e,0x08,0xde,0x05,0x14,0xbd,0x7f,0x57,0x9a,0x0d,0x2a,0xe6,0x34,0x14,0xa5,0x82,0x5e,0xa1,0xb7,0x71,0x62,0x72,0x18,0xf4,0x5f},
+ {0x9d,0xdb,0x89,0x17,0x0c,0x08,0x8e,0x39,0xf5,0x78,0xe7,0xf3,0x25,0x20,0x60,0xa7,0x5d,0x03,0xbd,0x06,0x4c,0x89,0x98,0xfa,0xbe,0x66,0xa9,0x25,0xdc,0x03,0x6a,0x10,0x40,0x95,0xb6,0x13,0xe8,0x47,0xdb,0xe5,0xe1,0x10,0x26,0x43,0x3b,0x2a,0x5d,0xf3,0x76,0x12,0x78,0x38,0xe9,0x26,0x1f,0xac,0x69,0xcb,0xa0,0xa0,0x8c,0xdb,0xd4,0x29,0xd0,0x53,0x33,0x33,0xaf,0x0a,0xad,0xd9,0xe5,0x09,0xd3,0xac,0xa5,0x9d,0x66,0x38,0xf0,0xf7,0x88,0xc8,0x8a,0x65,0x57,0x3c,0xfa,0xbe,0x2c,0x05,0x51,0x8a,0xb3,0x4a},
+ {0x93,0xd5,0x68,0x67,0x25,0x2b,0x7c,0xda,0x13,0xca,0x22,0x44,0x57,0xc0,0xc1,0x98,0x1d,0xce,0x0a,0xca,0xd5,0x0b,0xa8,0xf1,0x90,0xa6,0x88,0xc0,0xad,0xd1,0xcd,0x29,0x9c,0xc0,0xdd,0x5f,0xef,0xd1,0xcf,0xd6,0xce,0x5d,0x57,0xf7,0xfd,0x3e,0x2b,0xe8,0xc2,0x34,0x16,0x20,0x5d,0x6b,0xd5,0x25,0x9b,0x2b,0xed,0x04,0xbb,0xc6,0x41,0x30,0x48,0xe1,0x56,0xd9,0xf9,0xf2,0xf2,0x0f,0x2e,0x6b,0x35,0x9f,0x75,0x97,0xe7,0xad,0x5c,0x02,0x6c,0x5f,0xbb,0x98,0x46,0x1a,0x7b,0x9a,0x04,0x14,0x68,0xbd,0x4b,0x10},
+ {0x67,0xed,0xf1,0x68,0x31,0xfd,0xf0,0x51,0xc2,0x3b,0x6f,0xd8,0xcd,0x1d,0x81,0x2c,0xde,0xf2,0xd2,0x04,0x43,0x5c,0xdc,0x44,0x49,0x71,0x2a,0x09,0x57,0xcc,0xe8,0x5b,0x63,0xf1,0x7f,0xd6,0x5f,0x9a,0x5d,0xa9,0x81,0x56,0xc7,0x4c,0x9d,0xe6,0x2b,0xe9,0x57,0xf2,0x20,0xde,0x4c,0x02,0xf8,0xb7,0xf5,0x2d,0x07,0xfb,0x20,0x2a,0x4f,0x20,0x79,0xb0,0xeb,0x30,0x3d,0x3b,0x14,0xc8,0x30,0x2e,0x65,0xbd,0x5a,0x15,0x89,0x75,0x31,0x5c,0x6d,0x8f,0x31,0x3c,0x3c,0x65,0x1f,0x16,0x79,0xc2,0x17,0xfb,0x70,0x25},
+ {0x75,0x15,0xb6,0x2c,0x7f,0x36,0xfa,0x3e,0x6c,0x02,0xd6,0x1c,0x76,0x6f,0xf9,0xf5,0x62,0x25,0xb5,0x65,0x2a,0x14,0xc7,0xe8,0xcd,0x0a,0x03,0x53,0xea,0x65,0xcb,0x3d,0x5a,0x24,0xb8,0x0b,0x55,0xa9,0x2e,0x19,0xd1,0x50,0x90,0x8f,0xa8,0xfb,0xe6,0xc8,0x35,0xc9,0xa4,0x88,0x2d,0xea,0x86,0x79,0x68,0x86,0x01,0xde,0x91,0x5f,0x1c,0x24,0xaa,0x6c,0xde,0x40,0x29,0x17,0xd8,0x28,0x3a,0x73,0xd9,0x22,0xf0,0x2c,0xbf,0x8f,0xd1,0x01,0x5b,0x23,0xdd,0xfc,0xd7,0x16,0xe5,0xf0,0xcd,0x5f,0xdd,0x0e,0x42,0x08},
+ {0x4a,0xfa,0x62,0x83,0xab,0x20,0xff,0xcd,0x6e,0x3e,0x1a,0xe2,0xd4,0x18,0xe1,0x57,0x2b,0xe6,0x39,0xfc,0x17,0x96,0x17,0xe3,0xfd,0x69,0x17,0xbc,0xef,0x53,0x9a,0x0d,0xce,0x10,0xf4,0x04,0x4e,0xc3,0x58,0x03,0x85,0x06,0x6e,0x27,0x5a,0x5b,0x13,0xb6,0x21,0x15,0xb9,0xeb,0xc7,0x70,0x96,0x5d,0x9c,0x88,0xdb,0x21,0xf3,0x54,0xd6,0x04,0xd5,0xb5,0xbd,0xdd,0x16,0xc1,0x7d,0x5e,0x2d,0xdd,0xa5,0x8d,0xb6,0xde,0x54,0x29,0x92,0xa2,0x34,0x33,0x17,0x08,0xb6,0x1c,0xd7,0x1a,0x99,0x18,0x26,0x4f,0x7a,0x4a},
+ {0x95,0x5f,0xb1,0x5f,0x02,0x18,0xa7,0xf4,0x8f,0x1b,0x5c,0x6b,0x34,0x5f,0xf6,0x3d,0x12,0x11,0xe0,0x00,0x85,0xf0,0xfc,0xcd,0x48,0x18,0xd3,0xdd,0x4c,0x0c,0xb5,0x11,0x4b,0x2a,0x37,0xaf,0x91,0xb2,0xc3,0x24,0xf2,0x47,0x81,0x71,0x70,0x82,0xda,0x93,0xf2,0x9e,0x89,0x86,0x64,0x85,0x84,0xdd,0x33,0xee,0xe0,0x23,0x42,0x31,0x96,0x4a,0xd6,0xff,0xa4,0x08,0x44,0x27,0xe8,0xa6,0xd9,0x76,0x15,0x9c,0x7e,0x17,0x8e,0x73,0xf2,0xb3,0x02,0x3d,0xb6,0x48,0x33,0x77,0x51,0xcc,0x6b,0xce,0x4d,0xce,0x4b,0x4f},
+ {0x84,0x25,0x24,0xe2,0x5a,0xce,0x1f,0xa7,0x9e,0x8a,0xf5,0x92,0x56,0x72,0xea,0x26,0xf4,0x3c,0xea,0x1c,0xd7,0x09,0x1a,0xd2,0xe6,0x01,0x1c,0xb7,0x14,0xdd,0xfc,0x73,0x6f,0x0b,0x9d,0xc4,0x6e,0x61,0xe2,0x30,0x17,0x23,0xec,0xca,0x8f,0x71,0x56,0xe4,0xa6,0x4f,0x6b,0xf2,0x9b,0x40,0xeb,0x48,0x37,0x5f,0x59,0x61,0xe5,0xce,0x42,0x30,0x41,0xac,0x9b,0x44,0x79,0x70,0x7e,0x42,0x0a,0x31,0xe2,0xbc,0x6d,0xe3,0x5a,0x85,0x7c,0x1a,0x84,0x5f,0x21,0x76,0xae,0x4c,0xd6,0xe1,0x9c,0x9a,0x0c,0x74,0x9e,0x38},
+ {0xce,0xb9,0xdc,0x34,0xae,0xb3,0xfc,0x64,0xad,0xd0,0x48,0xe3,0x23,0x03,0x50,0x97,0x1b,0x38,0xc6,0x62,0x7d,0xf0,0xb3,0x45,0x88,0x67,0x5a,0x46,0x79,0x53,0x54,0x61,0x28,0xac,0x0e,0x57,0xf6,0x78,0xbd,0xc9,0xe1,0x9c,0x91,0x27,0x32,0x0b,0x5b,0xe5,0xed,0x91,0x9b,0xa1,0xab,0x3e,0xfc,0x65,0x90,0x36,0x26,0xd6,0xe5,0x25,0xc4,0x25,0x6e,0xde,0xd7,0xf1,0xa6,0x06,0x3e,0x3f,0x08,0x23,0x06,0x8e,0x27,0x76,0xf9,0x3e,0x77,0x6c,0x8a,0x4e,0x26,0xf6,0x14,0x8c,0x59,0x47,0x48,0x15,0x89,0xa0,0x39,0x65},
+ {0x73,0xf7,0xd2,0xc3,0x74,0x1f,0xd2,0xe9,0x45,0x68,0xc4,0x25,0x41,0x54,0x50,0xc1,0x33,0x9e,0xb9,0xf9,0xe8,0x5c,0x4e,0x62,0x6c,0x18,0xcd,0xc5,0xaa,0xe4,0xc5,0x11,0x19,0x4a,0xbb,0x14,0xd4,0xdb,0xc4,0xdd,0x8e,0x4f,0x42,0x98,0x3c,0xbc,0xb2,0x19,0x69,0x71,0xca,0x36,0xd7,0x9f,0xa8,0x48,0x90,0xbd,0x19,0xf0,0x0e,0x32,0x65,0x0f,0xc6,0xe0,0xfd,0xca,0xb1,0xd1,0x86,0xd4,0x81,0x51,0x3b,0x16,0xe3,0xe6,0x3f,0x4f,0x9a,0x93,0xf2,0xfa,0x0d,0xaf,0xa8,0x59,0x2a,0x07,0x33,0xec,0xbd,0xc7,0xab,0x4c},
+ {0x2e,0x0a,0x9c,0x08,0x24,0x96,0x9e,0x23,0x38,0x47,0xfe,0x3a,0xc0,0xc4,0x48,0xc7,0x2a,0xa1,0x4f,0x76,0x2a,0xed,0xdb,0x17,0x82,0x85,0x1c,0x32,0xf0,0x93,0x9b,0x63,0x89,0xd2,0x78,0x3f,0x8f,0x78,0x8f,0xc0,0x9f,0x4d,0x40,0xa1,0x2c,0xa7,0x30,0xfe,0x9d,0xcc,0x65,0xcf,0xfc,0x8b,0x77,0xf2,0x21,0x20,0xcb,0x5a,0x16,0x98,0xe4,0x7e,0xc3,0xa1,0x11,0x91,0xe3,0x08,0xd5,0x7b,0x89,0x74,0x90,0x80,0xd4,0x90,0x2b,0x2b,0x19,0xfd,0x72,0xae,0xc2,0xae,0xd2,0xe7,0xa6,0x02,0xb6,0x85,0x3c,0x49,0xdf,0x0e},
+ {0x68,0x5a,0x9b,0x59,0x58,0x81,0xcc,0xae,0x0e,0xe2,0xad,0xeb,0x0f,0x4f,0x57,0xea,0x07,0x7f,0xb6,0x22,0x74,0x1d,0xe4,0x4f,0xb4,0x4f,0x9d,0x01,0xe3,0x92,0x3b,0x40,0x13,0x41,0x76,0x84,0xd2,0xc4,0x67,0x67,0x35,0xf8,0xf5,0xf7,0x3f,0x40,0x90,0xa0,0xde,0xbe,0xe6,0xca,0xfa,0xcf,0x8f,0x1c,0x69,0xa3,0xdf,0xd1,0x54,0x0c,0xc0,0x04,0xf8,0x5c,0x46,0x8b,0x81,0x2f,0xc2,0x4d,0xf8,0xef,0x80,0x14,0x5a,0xf3,0xa0,0x71,0x57,0xd6,0xc7,0x04,0xad,0xbf,0xe8,0xae,0xf4,0x76,0x61,0xb2,0x2a,0xb1,0x5b,0x35},
+ {0xf4,0xbb,0x93,0x74,0xcc,0x64,0x1e,0xa7,0xc3,0xb0,0xa3,0xec,0xd9,0x84,0xbd,0xe5,0x85,0xe7,0x05,0xfa,0x0c,0xc5,0x6b,0x0a,0x12,0xc3,0x2e,0x18,0x32,0x81,0x9b,0x0f,0x18,0x73,0x8c,0x5a,0xc7,0xda,0x01,0xa3,0x11,0xaa,0xce,0xb3,0x9d,0x03,0x90,0xed,0x2d,0x3f,0xae,0x3b,0xbf,0x7c,0x07,0x6f,0x8e,0xad,0x52,0xe0,0xf8,0xea,0x18,0x75,0x32,0x6c,0x7f,0x1b,0xc4,0x59,0x88,0xa4,0x98,0x32,0x38,0xf4,0xbc,0x60,0x2d,0x0f,0xd9,0xd1,0xb1,0xc9,0x29,0xa9,0x15,0x18,0xc4,0x55,0x17,0xbb,0x1b,0x87,0xc3,0x47},
+ {0x48,0x4f,0xec,0x71,0x97,0x53,0x44,0x51,0x6e,0x5d,0x8c,0xc9,0x7d,0xb1,0x05,0xf8,0x6b,0xc6,0xc3,0x47,0x1a,0xc1,0x62,0xf7,0xdc,0x99,0x46,0x76,0x85,0x9b,0xb8,0x00,0xb0,0x66,0x50,0xc8,0x50,0x5d,0xe6,0xfb,0xb0,0x99,0xa2,0xb3,0xb0,0xc4,0xec,0x62,0xe0,0xe8,0x1a,0x44,0xea,0x54,0x37,0xe5,0x5f,0x8d,0xd4,0xe8,0x2c,0xa0,0xfe,0x08,0xd0,0xea,0xde,0x68,0x76,0xdd,0x4d,0x82,0x23,0x5d,0x68,0x4b,0x20,0x45,0x64,0xc8,0x65,0xd6,0x89,0x5d,0xcd,0xcf,0x14,0xb5,0x37,0xd5,0x75,0x4f,0xa7,0x29,0x38,0x47},
+ {0x18,0xc4,0x79,0x46,0x75,0xda,0xd2,0x82,0xf0,0x8d,0x61,0xb2,0xd8,0xd7,0x3b,0xe6,0x0a,0xeb,0x47,0xac,0x24,0xef,0x5e,0x35,0xb4,0xc6,0x33,0x48,0x4c,0x68,0x78,0x20,0xc9,0x02,0x39,0xad,0x3a,0x53,0xd9,0x23,0x8f,0x58,0x03,0xef,0xce,0xdd,0xc2,0x64,0xb4,0x2f,0xe1,0xcf,0x90,0x73,0x25,0x15,0x90,0xd3,0xe4,0x44,0x4d,0x8b,0x66,0x6c,0x0c,0x82,0x78,0x7a,0x21,0xcf,0x48,0x3b,0x97,0x3e,0x27,0x81,0xb2,0x0a,0x6a,0xf7,0x7b,0xed,0x8e,0x8c,0xa7,0x65,0x6c,0xa9,0x3f,0x43,0x8a,0x4f,0x05,0xa6,0x11,0x74},
+ {0x6d,0xc8,0x9d,0xb9,0x32,0x9d,0x65,0x4d,0x15,0xf1,0x3a,0x60,0x75,0xdc,0x4c,0x04,0x88,0xe4,0xc2,0xdc,0x2c,0x71,0x4c,0xb3,0xff,0x34,0x81,0xfb,0x74,0x65,0x13,0x7c,0xb4,0x75,0xb1,0x18,0x3d,0xe5,0x9a,0x57,0x02,0xa1,0x92,0xf3,0x59,0x31,0x71,0x68,0xf5,0x35,0xef,0x1e,0xba,0xec,0x55,0x84,0x8f,0x39,0x8c,0x45,0x72,0xa8,0xc9,0x1e,0x9b,0x50,0xa2,0x00,0xd4,0xa4,0xe6,0xb8,0xb4,0x82,0xc8,0x0b,0x02,0xd7,0x81,0x9b,0x61,0x75,0x95,0xf1,0x9b,0xcc,0xe7,0x57,0x60,0x64,0xcd,0xc7,0xa5,0x88,0xdd,0x3a},
+ {0xf2,0xdc,0x35,0xb6,0x70,0x57,0x89,0xab,0xbc,0x1f,0x6c,0xf6,0x6c,0xef,0xdf,0x02,0x87,0xd1,0xb6,0xbe,0x68,0x02,0x53,0x85,0x74,0x9e,0x87,0xcc,0xfc,0x29,0x99,0x24,0x46,0x30,0x39,0x59,0xd4,0x98,0xc2,0x85,0xec,0x59,0xf6,0x5f,0x98,0x35,0x7e,0x8f,0x3a,0x6e,0xf6,0xf2,0x2a,0xa2,0x2c,0x1d,0x20,0xa7,0x06,0xa4,0x31,0x11,0xba,0x61,0x29,0x90,0x95,0x16,0xf1,0xa0,0xd0,0xa3,0x89,0xbd,0x7e,0xba,0x6c,0x6b,0x3b,0x02,0x07,0x33,0x78,0x26,0x3e,0x5a,0xf1,0x7b,0xe7,0xec,0xd8,0xbb,0x0c,0x31,0x20,0x56},
+ {0x43,0xd6,0x34,0x49,0x43,0x93,0x89,0x52,0xf5,0x22,0x12,0xa5,0x06,0xf8,0xdb,0xb9,0x22,0x1c,0xf4,0xc3,0x8f,0x87,0x6d,0x8f,0x30,0x97,0x9d,0x4d,0x2a,0x6a,0x67,0x37,0xd6,0x85,0xe2,0x77,0xf4,0xb5,0x46,0x66,0x93,0x61,0x8f,0x6c,0x67,0xff,0xe8,0x40,0xdd,0x94,0xb5,0xab,0x11,0x73,0xec,0xa6,0x4d,0xec,0x8c,0x65,0xf3,0x46,0xc8,0x7e,0xc7,0x2e,0xa2,0x1d,0x3f,0x8f,0x5e,0x9b,0x13,0xcd,0x01,0x6c,0x77,0x1d,0x0f,0x13,0xb8,0x9f,0x98,0xa2,0xcf,0x8f,0x4c,0x21,0xd5,0x9d,0x9b,0x39,0x23,0xf7,0xaa,0x6d},
+ {0x47,0xbe,0x3d,0xeb,0x62,0x75,0x3a,0x5f,0xb8,0xa0,0xbd,0x8e,0x54,0x38,0xea,0xf7,0x99,0x72,0x74,0x45,0x31,0xe5,0xc3,0x00,0x51,0xd5,0x27,0x16,0xe7,0xe9,0x04,0x13,0xa2,0x8e,0xad,0xac,0xbf,0x04,0x3b,0x58,0x84,0xe8,0x8b,0x14,0xe8,0x43,0xb7,0x29,0xdb,0xc5,0x10,0x08,0x3b,0x58,0x1e,0x2b,0xaa,0xbb,0xb3,0x8e,0xe5,0x49,0x54,0x2b,0xfe,0x9c,0xdc,0x6a,0xd2,0x14,0x98,0x78,0x0b,0xdd,0x48,0x8b,0x3f,0xab,0x1b,0x3c,0x0a,0xc6,0x79,0xf9,0xff,0xe1,0x0f,0xda,0x93,0xd6,0x2d,0x7c,0x2d,0xde,0x68,0x44},
+ {0x9e,0x46,0x19,0x94,0x5e,0x35,0xbb,0x51,0x54,0xc7,0xdd,0x23,0x4c,0xdc,0xe6,0x33,0x62,0x99,0x7f,0x44,0xd6,0xb6,0xa5,0x93,0x63,0xbd,0x44,0xfb,0x6f,0x7c,0xce,0x6c,0xce,0x07,0x63,0xf8,0xc6,0xd8,0x9a,0x4b,0x28,0x0c,0x5d,0x43,0x31,0x35,0x11,0x21,0x2c,0x77,0x7a,0x65,0xc5,0x66,0xa8,0xd4,0x52,0x73,0x24,0x63,0x7e,0x42,0xa6,0x5d,0xca,0x22,0xac,0xde,0x88,0xc6,0x94,0x1a,0xf8,0x1f,0xae,0xbb,0xf7,0x6e,0x06,0xb9,0x0f,0x58,0x59,0x8d,0x38,0x8c,0xad,0x88,0xa8,0x2c,0x9f,0xe7,0xbf,0x9a,0xf2,0x58},
+ {0x68,0x3e,0xe7,0x8d,0xab,0xcf,0x0e,0xe9,0xa5,0x76,0x7e,0x37,0x9f,0x6f,0x03,0x54,0x82,0x59,0x01,0xbe,0x0b,0x5b,0x49,0xf0,0x36,0x1e,0xf4,0xa7,0xc4,0x29,0x76,0x57,0xf6,0xcd,0x0e,0x71,0xbf,0x64,0x5a,0x4b,0x3c,0x29,0x2c,0x46,0x38,0xe5,0x4c,0xb1,0xb9,0x3a,0x0b,0xd5,0x56,0xd0,0x43,0x36,0x70,0x48,0x5b,0x18,0x24,0x37,0xf9,0x6a,0x88,0xa8,0xc6,0x09,0x45,0x02,0x20,0x32,0x73,0x89,0x55,0x4b,0x13,0x36,0xe0,0xd2,0x9f,0x28,0x33,0x3c,0x23,0x36,0xe2,0x83,0x8f,0xc1,0xae,0x0c,0xbb,0x25,0x1f,0x70},
+ {0xed,0x6c,0x61,0xe4,0xf8,0xb0,0xa8,0xc3,0x7d,0xa8,0x25,0x9e,0x0e,0x66,0x00,0xf7,0x9c,0xa5,0xbc,0xf4,0x1f,0x06,0xe3,0x61,0xe9,0x0b,0xc4,0xbd,0xbf,0x92,0x0c,0x2e,0x13,0xc1,0xbe,0x7c,0xd9,0xf6,0x18,0x9d,0xe4,0xdb,0xbf,0x74,0xe6,0x06,0x4a,0x84,0xd6,0x60,0x4e,0xac,0x22,0xb5,0xf5,0x20,0x51,0x5e,0x95,0x50,0xc0,0x5b,0x0a,0x72,0x35,0x5a,0x80,0x9b,0x43,0x09,0x3f,0x0c,0xfc,0xab,0x42,0x62,0x37,0x8b,0x4e,0xe8,0x46,0x93,0x22,0x5c,0xf3,0x17,0x14,0x69,0xec,0xf0,0x4e,0x14,0xbb,0x9c,0x9b,0x0e},
+ {0xad,0x20,0x57,0xfb,0x8f,0xd4,0xba,0xfb,0x0e,0x0d,0xf9,0xdb,0x6b,0x91,0x81,0xee,0xbf,0x43,0x55,0x63,0x52,0x31,0x81,0xd4,0xd8,0x7b,0x33,0x3f,0xeb,0x04,0x11,0x22,0xee,0xbe,0xb1,0x5d,0xd5,0x9b,0xee,0x8d,0xb9,0x3f,0x72,0x0a,0x37,0xab,0xc3,0xc9,0x91,0xd7,0x68,0x1c,0xbf,0xf1,0xa8,0x44,0xde,0x3c,0xfd,0x1c,0x19,0x44,0x6d,0x36,0x14,0x8c,0xbc,0xf2,0x43,0x17,0x3c,0x9e,0x3b,0x6c,0x85,0xb5,0xfc,0x26,0xda,0x2e,0x97,0xfb,0xa7,0x68,0x0e,0x2f,0xb8,0xcc,0x44,0x32,0x59,0xbc,0xe6,0xa4,0x67,0x41},
+ {0x00,0x27,0xf6,0x76,0x28,0x9d,0x3b,0x64,0xeb,0x68,0x76,0x0e,0x40,0x9d,0x1d,0x5d,0x84,0x06,0xfc,0x21,0x03,0x43,0x4b,0x1b,0x6a,0x24,0x55,0x22,0x7e,0xbb,0x38,0x79,0xee,0x8f,0xce,0xf8,0x65,0x26,0xbe,0xc2,0x2c,0xd6,0x80,0xe8,0x14,0xff,0x67,0xe9,0xee,0x4e,0x36,0x2f,0x7e,0x6e,0x2e,0xf1,0xf6,0xd2,0x7e,0xcb,0x70,0x33,0xb3,0x34,0xcc,0xd6,0x81,0x86,0xee,0x91,0xc5,0xcd,0x53,0xa7,0x85,0xed,0x9c,0x10,0x02,0xce,0x83,0x88,0x80,0x58,0xc1,0x85,0x74,0xed,0xe4,0x65,0xfe,0x2d,0x6e,0xfc,0x76,0x11},
+ {0x9b,0x61,0x9c,0x5b,0xd0,0x6c,0xaf,0xb4,0x80,0x84,0xa5,0xb2,0xf4,0xc9,0xdf,0x2d,0xc4,0x4d,0xe9,0xeb,0x02,0xa5,0x4f,0x3d,0x34,0x5f,0x7d,0x67,0x4c,0x3a,0xfc,0x08,0xb8,0x0e,0x77,0x49,0x89,0xe2,0x90,0xdb,0xa3,0x40,0xf4,0xac,0x2a,0xcc,0xfb,0x98,0x9b,0x87,0xd7,0xde,0xfe,0x4f,0x35,0x21,0xb6,0x06,0x69,0xf2,0x54,0x3e,0x6a,0x1f,0xea,0x34,0x07,0xd3,0x99,0xc1,0xa4,0x60,0xd6,0x5c,0x16,0x31,0xb6,0x85,0xc0,0x40,0x95,0x82,0x59,0xf7,0x23,0x3e,0x33,0xe2,0xd1,0x00,0xb9,0x16,0x01,0xad,0x2f,0x4f},
+ {0x54,0x4e,0xae,0x94,0x41,0xb2,0xbe,0x44,0x6c,0xef,0x57,0x18,0x51,0x1c,0x54,0x5f,0x98,0x04,0x8d,0x36,0x2d,0x6b,0x1e,0xa6,0xab,0xf7,0x2e,0x97,0xa4,0x84,0x54,0x44,0x38,0xb6,0x3b,0xb7,0x1d,0xd9,0x2c,0x96,0x08,0x9c,0x12,0xfc,0xaa,0x77,0x05,0xe6,0x89,0x16,0xb6,0xf3,0x39,0x9b,0x61,0x6f,0x81,0xee,0x44,0x29,0x5f,0x99,0x51,0x34,0x7c,0x7d,0xea,0x9f,0xd0,0xfc,0x52,0x91,0xf6,0x5c,0x93,0xb0,0x94,0x6c,0x81,0x4a,0x40,0x5c,0x28,0x47,0xaa,0x9a,0x8e,0x25,0xb7,0x93,0x28,0x04,0xa6,0x9c,0xb8,0x10},
+ {0x9c,0x28,0x18,0x97,0x49,0x47,0x59,0x3d,0x26,0x3f,0x53,0x24,0xc5,0xf8,0xeb,0x12,0x15,0xef,0xc3,0x14,0xcb,0xbf,0x62,0x02,0x8e,0x51,0xb7,0x77,0xd5,0x78,0xb8,0x20,0x6e,0xf0,0x45,0x5a,0xbe,0x41,0x39,0x75,0x65,0x5f,0x9c,0x6d,0xed,0xae,0x7c,0xd0,0xb6,0x51,0xff,0x72,0x9c,0x6b,0x77,0x11,0xa9,0x4d,0x0d,0xef,0xd9,0xd1,0xd2,0x17,0x6a,0x3e,0x3f,0x07,0x18,0xaf,0xf2,0x27,0x69,0x10,0x52,0xd7,0x19,0xe5,0x3f,0xfd,0x22,0x00,0xa6,0x3c,0x2c,0xb7,0xe3,0x22,0xa7,0xc6,0x65,0xcc,0x63,0x4f,0x21,0x72},
+ {0x93,0xa6,0x07,0x53,0x40,0x7f,0xe3,0xb4,0x95,0x67,0x33,0x2f,0xd7,0x14,0xa7,0xab,0x99,0x10,0x76,0x73,0xa7,0xd0,0xfb,0xd6,0xc9,0xcb,0x71,0x81,0xc5,0x48,0xdf,0x5f,0xc9,0x29,0x3b,0xf4,0xb9,0xb7,0x9d,0x1d,0x75,0x8f,0x51,0x4f,0x4a,0x82,0x05,0xd6,0xc4,0x9d,0x2f,0x31,0xbd,0x72,0xc0,0xf2,0xb0,0x45,0x15,0x5a,0x85,0xac,0x24,0x1f,0xaa,0x05,0x95,0x8e,0x32,0x08,0xd6,0x24,0xee,0x20,0x14,0x0c,0xd1,0xc1,0x48,0x47,0xa2,0x25,0xfb,0x06,0x5c,0xe4,0xff,0xc7,0xe6,0x95,0xe3,0x2a,0x9e,0x73,0xba,0x00},
+ {0xd6,0x90,0x87,0x5c,0xde,0x98,0x2e,0x59,0xdf,0xa2,0xc2,0x45,0xd3,0xb7,0xbf,0xe5,0x22,0x99,0xb4,0xf9,0x60,0x3b,0x5a,0x11,0xf3,0x78,0xad,0x67,0x3e,0x3a,0x28,0x03,0x26,0xbb,0x88,0xea,0xf5,0x26,0x44,0xae,0xfb,0x3b,0x97,0x84,0xd9,0x79,0x06,0x36,0x50,0x4e,0x69,0x26,0x0c,0x03,0x9f,0x5c,0x26,0xd2,0x18,0xd5,0xe7,0x7d,0x29,0x72,0x39,0xb9,0x0c,0xbe,0xc7,0x1d,0x24,0x48,0x80,0x30,0x63,0x8b,0x4d,0x9b,0xf1,0x32,0x08,0x93,0x28,0x02,0x0d,0xc9,0xdf,0xd3,0x45,0x19,0x27,0x46,0x68,0x29,0xe1,0x05},
+ {0x5a,0x49,0x9c,0x2d,0xb3,0xee,0x82,0xba,0x7c,0xb9,0x2b,0xf1,0xfc,0xc8,0xef,0xce,0xe0,0xd1,0xb5,0x93,0xae,0xab,0x2d,0xb0,0x9b,0x8d,0x69,0x13,0x9c,0x0c,0xc0,0x39,0x50,0x45,0x2c,0x24,0xc8,0xbb,0xbf,0xad,0xd9,0x81,0x30,0xd0,0xec,0x0c,0xc8,0xbc,0x92,0xdf,0xc8,0xf5,0xa6,0x66,0x35,0x84,0x4c,0xce,0x58,0x82,0xd3,0x25,0xcf,0x78,0x68,0x9d,0x48,0x31,0x8e,0x6b,0xae,0x15,0x87,0xf0,0x2b,0x9c,0xab,0x1c,0x85,0xaa,0x05,0xfa,0x4e,0xf0,0x97,0x5a,0xa7,0xc9,0x32,0xf8,0x3f,0x6b,0x07,0x52,0x6b,0x00},
+ {0x1c,0x78,0x95,0x9d,0xe1,0xcf,0xe0,0x29,0xe2,0x10,0x63,0x96,0x18,0xdf,0x81,0xb6,0x39,0x6b,0x51,0x70,0xd3,0x39,0xdf,0x57,0x22,0x61,0xc7,0x3b,0x44,0xe3,0x57,0x4d,0x2d,0x08,0xce,0xb9,0x16,0x7e,0xcb,0xf5,0x29,0xbc,0x7a,0x41,0x4c,0xf1,0x07,0x34,0xab,0xa7,0xf4,0x2b,0xce,0x6b,0xb3,0xd4,0xce,0x75,0x9f,0x1a,0x56,0xe9,0xe2,0x7d,0xcb,0x5e,0xa5,0xb6,0xf4,0xd4,0x70,0xde,0x99,0xdb,0x85,0x5d,0x7f,0x52,0x01,0x48,0x81,0x9a,0xee,0xd3,0x40,0xc4,0xc9,0xdb,0xed,0x29,0x60,0x1a,0xaf,0x90,0x2a,0x6b},
+ {0x97,0x1e,0xe6,0x9a,0xfc,0xf4,0x23,0x69,0xd1,0x5f,0x3f,0xe0,0x1d,0x28,0x35,0x57,0x2d,0xd1,0xed,0xe6,0x43,0xae,0x64,0xa7,0x4a,0x3e,0x2d,0xd1,0xe9,0xf4,0xd8,0x5f,0x0a,0xd8,0xb2,0x5b,0x24,0xf3,0xeb,0x77,0x9b,0x07,0xb9,0x2f,0x47,0x1b,0x30,0xd8,0x33,0x73,0xee,0x4c,0xf2,0xe6,0x47,0xc6,0x09,0x21,0x6c,0x27,0xc8,0x12,0x58,0x46,0xd9,0x62,0x10,0x2a,0xb2,0xbe,0x43,0x4d,0x16,0xdc,0x31,0x38,0x75,0xfb,0x65,0x70,0xd7,0x68,0x29,0xde,0x7b,0x4a,0x0d,0x18,0x90,0x67,0xb1,0x1c,0x2b,0x2c,0xb3,0x05},
+ {0xfd,0xa8,0x4d,0xd2,0xcc,0x5e,0xc0,0xc8,0x83,0xef,0xdf,0x05,0xac,0x1a,0xcf,0xa1,0x61,0xcd,0xf9,0x7d,0xf2,0xef,0xbe,0xdb,0x99,0x1e,0x47,0x7b,0xa3,0x56,0x55,0x3b,0x95,0x81,0xd5,0x7a,0x2c,0xa4,0xfc,0xf7,0xcc,0xf3,0x33,0x43,0x6e,0x28,0x14,0x32,0x9d,0x97,0x0b,0x34,0x0d,0x9d,0xc2,0xb6,0xe1,0x07,0x73,0x56,0x48,0x1a,0x77,0x31,0x82,0xd4,0x4d,0xe1,0x24,0xc5,0xb0,0x32,0xb6,0xa4,0x2b,0x1a,0x54,0x51,0xb3,0xed,0xf3,0x5a,0x2b,0x28,0x48,0x60,0xd1,0xa3,0xeb,0x36,0x73,0x7a,0xd2,0x79,0xc0,0x4f},
+ {0x7f,0x2f,0xbf,0x89,0xb0,0x38,0xc9,0x51,0xa7,0xe9,0xdf,0x02,0x65,0xbd,0x97,0x24,0x53,0xe4,0x80,0x78,0x9c,0xc0,0xff,0xff,0x92,0x8e,0xf9,0xca,0xce,0x67,0x45,0x12,0x0d,0xc5,0x86,0x0c,0x44,0x8b,0x34,0xdc,0x51,0xe6,0x94,0xcc,0xc9,0xcb,0x37,0x13,0xb9,0x3c,0x3e,0x64,0x4d,0xf7,0x22,0x64,0x08,0xcd,0xe3,0xba,0xc2,0x70,0x11,0x24,0xb4,0x73,0xc4,0x0a,0x86,0xab,0xf9,0x3f,0x35,0xe4,0x13,0x01,0xee,0x1d,0x91,0xf0,0xaf,0xc4,0xc6,0xeb,0x60,0x50,0xe7,0x4a,0x0d,0x00,0x87,0x6c,0x96,0x12,0x86,0x3f},
+ {0xde,0x0d,0x2a,0x78,0xc9,0x0c,0x9a,0x55,0x85,0x83,0x71,0xea,0xb2,0xcd,0x1d,0x55,0x8c,0x23,0xef,0x31,0x5b,0x86,0x62,0x7f,0x3d,0x61,0x73,0x79,0x76,0xa7,0x4a,0x50,0x13,0x8d,0x04,0x36,0xfa,0xfc,0x18,0x9c,0xdd,0x9d,0x89,0x73,0xb3,0x9d,0x15,0x29,0xaa,0xd0,0x92,0x9f,0x0b,0x35,0x9f,0xdc,0xd4,0x19,0x8a,0x87,0xee,0x7e,0xf5,0x26,0xb1,0xef,0x87,0x56,0xd5,0x2c,0xab,0x0c,0x7b,0xf1,0x7a,0x24,0x62,0xd1,0x80,0x51,0x67,0x24,0x5a,0x4f,0x34,0x5a,0xc1,0x85,0x69,0x30,0xba,0x9d,0x3d,0x94,0x41,0x40},
+ {0x96,0xcc,0xeb,0x43,0xba,0xee,0xc0,0xc3,0xaf,0x9c,0xea,0x26,0x9c,0x9c,0x74,0x8d,0xc6,0xcc,0x77,0x1c,0xee,0x95,0xfa,0xd9,0x0f,0x34,0x84,0x76,0xd9,0xa1,0x20,0x14,0xdd,0xaa,0x6c,0xa2,0x43,0x77,0x21,0x4b,0xce,0xb7,0x8a,0x64,0x24,0xb4,0xa6,0x47,0xe3,0xc9,0xfb,0x03,0x7a,0x4f,0x1d,0xcb,0x19,0xd0,0x00,0x98,0x42,0x31,0xd9,0x12,0x4f,0x59,0x37,0xd3,0x99,0x77,0xc6,0x00,0x7b,0xa4,0x3a,0xb2,0x40,0x51,0x3c,0x5e,0x95,0xf3,0x5f,0xe3,0x54,0x28,0x18,0x44,0x12,0xa0,0x59,0x43,0x31,0x92,0x4f,0x1b},
+ {0x51,0x09,0x15,0x89,0x9d,0x10,0x5c,0x3e,0x6a,0x69,0xe9,0x2d,0x91,0xfa,0xce,0x39,0x20,0x30,0x5f,0x97,0x3f,0xe4,0xea,0x20,0xae,0x2d,0x13,0x7f,0x2a,0x57,0x9b,0x23,0xb1,0x66,0x98,0xa4,0x30,0x30,0xcf,0x33,0x59,0x48,0x5f,0x21,0xd2,0x73,0x1f,0x25,0xf6,0xf4,0xde,0x51,0x40,0xaa,0x82,0xab,0xf6,0x23,0x9a,0x6f,0xd5,0x91,0xf1,0x5f,0x68,0x90,0x2d,0xac,0x33,0xd4,0x9e,0x81,0x23,0x85,0xc9,0x5f,0x79,0xab,0x83,0x28,0x3d,0xeb,0x93,0x55,0x80,0x72,0x45,0xef,0xcb,0x36,0x8f,0x75,0x6a,0x52,0x0c,0x02},
+ {0xbc,0xdb,0xd8,0x9e,0xf8,0x34,0x98,0x77,0x6c,0xa4,0x7c,0xdc,0xf9,0xaa,0xf2,0xc8,0x74,0xb0,0xe1,0xa3,0xdc,0x4c,0x52,0xa9,0x77,0x38,0x31,0x15,0x46,0xcc,0xaa,0x02,0x89,0xcc,0x42,0xf0,0x59,0xef,0x31,0xe9,0xb6,0x4b,0x12,0x8e,0x9d,0x9c,0x58,0x2c,0x97,0x59,0xc7,0xae,0x8a,0xe1,0xc8,0xad,0x0c,0xc5,0x02,0x56,0x0a,0xfe,0x2c,0x45,0xdf,0x77,0x78,0x64,0xa0,0xf7,0xa0,0x86,0x9f,0x7c,0x60,0x0e,0x27,0x64,0xc4,0xbb,0xc9,0x11,0xfb,0xf1,0x25,0xea,0x17,0xab,0x7b,0x87,0x4b,0x30,0x7b,0x7d,0xfb,0x4c},
+ {0xfe,0x75,0x9b,0xb8,0x6c,0x3d,0xb4,0x72,0x80,0xdc,0x6a,0x9c,0xd9,0x94,0xc6,0x54,0x9f,0x4c,0xe3,0x3e,0x37,0xaa,0xc3,0xb8,0x64,0x53,0x07,0x39,0x2b,0x62,0xb4,0x14,0x12,0xef,0x89,0x97,0xc2,0x99,0x86,0xe2,0x0d,0x19,0x57,0xdf,0x71,0xcd,0x6e,0x2b,0xd0,0x70,0xc9,0xec,0x57,0xc8,0x43,0xc3,0xc5,0x3a,0x4d,0x43,0xbc,0x4c,0x1d,0x5b,0x26,0x9f,0x0a,0xcc,0x15,0x26,0xfb,0xb6,0xe5,0xcc,0x8d,0xb8,0x2b,0x0e,0x4f,0x3a,0x05,0xa7,0x69,0x33,0x8b,0x49,0x01,0x13,0xd1,0x2d,0x59,0x58,0x12,0xf7,0x98,0x2f},
+ {0x56,0x9e,0x0f,0xb5,0x4c,0xa7,0x94,0x0c,0x20,0x13,0x8e,0x8e,0xa9,0xf4,0x1f,0x5b,0x67,0x0f,0x30,0x82,0x21,0xcc,0x2a,0x9a,0xf9,0xaa,0x06,0xd8,0x49,0xe2,0x6a,0x3a,0x01,0xa7,0x54,0x4f,0x44,0xae,0x12,0x2e,0xde,0xd7,0xcb,0xa9,0xf0,0x3e,0xfe,0xfc,0xe0,0x5d,0x83,0x75,0x0d,0x89,0xbf,0xce,0x54,0x45,0x61,0xe7,0xe9,0x62,0x80,0x1d,0x5a,0x7c,0x90,0xa9,0x85,0xda,0x7a,0x65,0x62,0x0f,0xb9,0x91,0xb5,0xa8,0x0e,0x1a,0xe9,0xb4,0x34,0xdf,0xfb,0x1d,0x0e,0x8d,0xf3,0x5f,0xf2,0xae,0xe8,0x8c,0x8b,0x29},
+ {0xb2,0x0c,0xf7,0xef,0x53,0x79,0x92,0x2a,0x76,0x70,0x15,0x79,0x2a,0xc9,0x89,0x4b,0x6a,0xcf,0xa7,0x30,0x7a,0x45,0x18,0x94,0x85,0xe4,0x5c,0x4d,0x40,0xa8,0xb8,0x34,0xde,0x65,0x21,0x0a,0xea,0x72,0x7a,0x83,0xf6,0x79,0xcf,0x0b,0xb4,0x07,0xab,0x3f,0x70,0xae,0x38,0x77,0xc7,0x36,0x16,0x52,0xdc,0xd7,0xa7,0x03,0x18,0x27,0xa6,0x6b,0x35,0x33,0x69,0x83,0xb5,0xec,0x6e,0xc2,0xfd,0xfe,0xb5,0x63,0xdf,0x13,0xa8,0xd5,0x73,0x25,0xb2,0xa4,0x9a,0xaa,0x93,0xa2,0x6a,0x1c,0x5e,0x46,0xdd,0x2b,0xd6,0x71},
+ {0x80,0xdf,0x78,0xd3,0x28,0xcc,0x33,0x65,0xb4,0xa4,0x0f,0x0a,0x79,0x43,0xdb,0xf6,0x5a,0xda,0x01,0xf7,0xf9,0x5f,0x64,0xe3,0xa4,0x2b,0x17,0xf3,0x17,0xf3,0xd5,0x74,0xf5,0x5e,0xf7,0xb1,0xda,0xb5,0x2d,0xcd,0xf5,0x65,0xb0,0x16,0xcf,0x95,0x7f,0xd7,0x85,0xf0,0x49,0x3f,0xea,0x1f,0x57,0x14,0x3d,0x2b,0x2b,0x26,0x21,0x36,0x33,0x1c,0x81,0xca,0xd9,0x67,0x54,0xe5,0x6f,0xa8,0x37,0x8c,0x29,0x2b,0x75,0x7c,0x8b,0x39,0x3b,0x62,0xac,0xe3,0x92,0x08,0x6d,0xda,0x8c,0xd9,0xe9,0x47,0x45,0xcc,0xeb,0x4a},
+ {0xc9,0x01,0x6d,0x27,0x1b,0x07,0xf0,0x12,0x70,0x8c,0xc4,0x86,0xc5,0xba,0xb8,0xe7,0xa9,0xfb,0xd6,0x71,0x9b,0x12,0x08,0x53,0x92,0xb7,0x3d,0x5a,0xf9,0xfb,0x88,0x5d,0x10,0xb6,0x54,0x73,0x9e,0x8d,0x40,0x0b,0x6e,0x5b,0xa8,0x5b,0x53,0x32,0x6b,0x80,0x07,0xa2,0x58,0x4a,0x03,0x3a,0xe6,0xdb,0x2c,0xdf,0xa1,0xc9,0xdd,0xd9,0x3b,0x17,0xdf,0x72,0x58,0xfe,0x1e,0x0f,0x50,0x2b,0xc1,0x18,0x39,0xd4,0x2e,0x58,0xd6,0x58,0xe0,0x3a,0x67,0xc9,0x8e,0x27,0xed,0xe6,0x19,0xa3,0x9e,0xb1,0x13,0xcd,0xe1,0x06},
+ {0x23,0x6f,0x16,0x6f,0x51,0xad,0xd0,0x40,0xbe,0x6a,0xab,0x1f,0x93,0x32,0x8e,0x11,0x8e,0x08,0x4d,0xa0,0x14,0x5e,0xe3,0x3f,0x66,0x62,0xe1,0x26,0x35,0x60,0x80,0x30,0x53,0x03,0x5b,0x9e,0x62,0xaf,0x2b,0x47,0x47,0x04,0x8d,0x27,0x90,0x0b,0xaa,0x3b,0x27,0xbf,0x43,0x96,0x46,0x5f,0x78,0x0c,0x13,0x7b,0x83,0x8d,0x1a,0x6a,0x3a,0x7f,0x0b,0x80,0x3d,0x5d,0x39,0x44,0xe6,0xf7,0xf6,0xed,0x01,0xc9,0x55,0xd5,0xa8,0x95,0x39,0x63,0x2c,0x59,0x30,0x78,0xcd,0x68,0x7e,0x30,0x51,0x2e,0xed,0xfd,0xd0,0x30},
+ {0xb3,0x33,0x12,0xf2,0x1a,0x4d,0x59,0xe0,0x9c,0x4d,0xcc,0xf0,0x8e,0xe7,0xdb,0x1b,0x77,0x9a,0x49,0x8f,0x7f,0x18,0x65,0x69,0x68,0x98,0x09,0x2c,0x20,0x14,0x92,0x0a,0x50,0x47,0xb8,0x68,0x1e,0x97,0xb4,0x9c,0xcf,0xbb,0x64,0x66,0x29,0x72,0x95,0xa0,0x2b,0x41,0xfa,0x72,0x26,0xe7,0x8d,0x5c,0xd9,0x89,0xc5,0x51,0x43,0x08,0x15,0x46,0x2e,0xa0,0xb9,0xae,0xc0,0x19,0x90,0xbc,0xae,0x4c,0x03,0x16,0x0d,0x11,0xc7,0x55,0xec,0x32,0x99,0x65,0x01,0xf5,0x6d,0x0e,0xfe,0x5d,0xca,0x95,0x28,0x0d,0xca,0x3b},
+ {0xa4,0x62,0x5d,0x3c,0xbc,0x31,0xf0,0x40,0x60,0x7a,0xf0,0xcf,0x3e,0x8b,0xfc,0x19,0x45,0xb5,0x0f,0x13,0xa2,0x3d,0x18,0x98,0xcd,0x13,0x8f,0xae,0xdd,0xde,0x31,0x56,0xbf,0x01,0xcc,0x9e,0xb6,0x8e,0x68,0x9c,0x6f,0x89,0x44,0xa6,0xad,0x83,0xbc,0xf0,0xe2,0x9f,0x7a,0x5f,0x5f,0x95,0x2d,0xca,0x41,0x82,0xf2,0x8d,0x03,0xb4,0xa8,0x4e,0x02,0xd2,0xca,0xf1,0x0a,0x46,0xed,0x2a,0x83,0xee,0x8c,0xa4,0x05,0x53,0x30,0x46,0x5f,0x1a,0xf1,0x49,0x45,0x77,0x21,0x91,0x63,0xa4,0x2c,0x54,0x30,0x09,0xce,0x24},
+ {0x06,0xc1,0x06,0xfd,0xf5,0x90,0xe8,0x1f,0xf2,0x10,0x88,0x5d,0x35,0x68,0xc4,0xb5,0x3e,0xaf,0x8c,0x6e,0xfe,0x08,0x78,0x82,0x4b,0xd7,0x06,0x8a,0xc2,0xe3,0xd4,0x41,0x85,0x0b,0xf3,0xfd,0x55,0xa1,0xcf,0x3f,0xa4,0x2e,0x37,0x36,0x8e,0x16,0xf7,0xd2,0x44,0xf8,0x92,0x64,0xde,0x64,0xe0,0xb2,0x80,0x42,0x4f,0x32,0xa7,0x28,0x99,0x54,0x2e,0x1a,0xee,0x63,0xa7,0x32,0x6e,0xf2,0xea,0xfd,0x5f,0xd2,0xb7,0xe4,0x91,0xae,0x69,0x4d,0x7f,0xd1,0x3b,0xd3,0x3b,0xbc,0x6a,0xff,0xdc,0xc0,0xde,0x66,0x1b,0x49},
+ {0xa7,0x32,0xea,0xc7,0x3d,0xb1,0xf5,0x98,0x98,0xdb,0x16,0x7e,0xcc,0xf8,0xd5,0xe3,0x47,0xd9,0xf8,0xcb,0x52,0xbf,0x0a,0xac,0xac,0xe4,0x5e,0xc8,0xd0,0x38,0xf3,0x08,0xa1,0x64,0xda,0xd0,0x8e,0x4a,0xf0,0x75,0x4b,0x28,0xe2,0x67,0xaf,0x2c,0x22,0xed,0xa4,0x7b,0x7b,0x1f,0x79,0xa3,0x34,0x82,0x67,0x8b,0x01,0xb7,0xb0,0xb8,0xf6,0x4c,0xbd,0x73,0x1a,0x99,0x21,0xa8,0x83,0xc3,0x7a,0x0c,0x32,0xdf,0x01,0xbc,0x27,0xab,0x63,0x70,0x77,0x84,0x1b,0x33,0x3d,0xc1,0x99,0x8a,0x07,0xeb,0x82,0x4a,0x0d,0x53},
+ {0x25,0x48,0xf9,0xe1,0x30,0x36,0x4c,0x00,0x5a,0x53,0xab,0x8c,0x26,0x78,0x2d,0x7e,0x8b,0xff,0x84,0xcc,0x23,0x23,0x48,0xc7,0xb9,0x70,0x17,0x10,0x3f,0x75,0xea,0x65,0x9e,0xbf,0x9a,0x6c,0x45,0x73,0x69,0x6d,0x80,0xa8,0x00,0x49,0xfc,0xb2,0x7f,0x25,0x50,0xb8,0xcf,0xc8,0x12,0xf4,0xac,0x2b,0x5b,0xbd,0xbf,0x0c,0xe0,0xe7,0xb3,0x0d,0x63,0x63,0x09,0xe2,0x3e,0xfc,0x66,0x3d,0x6b,0xcb,0xb5,0x61,0x7f,0x2c,0xd6,0x81,0x1a,0x3b,0x44,0x13,0x42,0x04,0xbe,0x0f,0xdb,0xa1,0xe1,0x21,0x19,0xec,0xa4,0x02},
+ {0xa2,0xb8,0x24,0x3b,0x9a,0x25,0xe6,0x5c,0xb8,0xa0,0xaf,0x45,0xcc,0x7a,0x57,0xb8,0x37,0x70,0xa0,0x8b,0xe8,0xe6,0xcb,0xcc,0xbf,0x09,0x78,0x12,0x51,0x3c,0x14,0x3d,0x5f,0x79,0xcf,0xf1,0x62,0x61,0xc8,0xf5,0xf2,0x57,0xee,0x26,0x19,0x86,0x8c,0x11,0x78,0x35,0x06,0x1c,0x85,0x24,0x21,0x17,0xcf,0x7f,0x06,0xec,0x5d,0x2b,0xd1,0x36,0x57,0x45,0x15,0x79,0x91,0x27,0x6d,0x12,0x0a,0x3a,0x78,0xfc,0x5c,0x8f,0xe4,0xd5,0xac,0x9b,0x17,0xdf,0xe8,0xb6,0xbd,0x36,0x59,0x28,0xa8,0x5b,0x88,0x17,0xf5,0x2e},
+ {0xdc,0xae,0x58,0x8c,0x4e,0x97,0x37,0x46,0xa4,0x41,0xf0,0xab,0xfb,0x22,0xef,0xb9,0x8a,0x71,0x80,0xe9,0x56,0xd9,0x85,0xe1,0xa6,0xa8,0x43,0xb1,0xfa,0x78,0x1b,0x2f,0x51,0x2f,0x5b,0x30,0xfb,0xbf,0xee,0x96,0xb8,0x96,0x95,0x88,0xad,0x38,0xf9,0xd3,0x25,0xdd,0xd5,0x46,0xc7,0x2d,0xf5,0xf0,0x95,0x00,0x3a,0xbb,0x90,0x82,0x96,0x57,0x01,0xe1,0x20,0x0a,0x43,0xb8,0x1a,0xf7,0x47,0xec,0xf0,0x24,0x8d,0x65,0x93,0xf3,0xd1,0xee,0xe2,0x6e,0xa8,0x09,0x75,0xcf,0xe1,0xa3,0x2a,0xdc,0x35,0x3e,0xc4,0x7d},
+ {0xc3,0xd9,0x7d,0x88,0x65,0x66,0x96,0x85,0x55,0x53,0xb0,0x4b,0x31,0x9b,0x0f,0xc9,0xb1,0x79,0x20,0xef,0xf8,0x8d,0xe0,0xc6,0x2f,0xc1,0x8c,0x75,0x16,0x20,0xf7,0x7e,0x18,0x97,0x3e,0x27,0x5c,0x2a,0x78,0x5a,0x94,0xfd,0x4e,0x5e,0x99,0xc6,0x76,0x35,0x3e,0x7d,0x23,0x1f,0x05,0xd8,0x2e,0x0f,0x99,0x0a,0xd5,0x82,0x1d,0xb8,0x4f,0x04,0xd9,0xe3,0x07,0xa9,0xc5,0x18,0xdf,0xc1,0x59,0x63,0x4c,0xce,0x1d,0x37,0xb3,0x57,0x49,0xbb,0x01,0xb2,0x34,0x45,0x70,0xca,0x2e,0xdd,0x30,0x9c,0x3f,0x82,0x79,0x7f},
+ {0xe8,0x13,0xb5,0xa3,0x39,0xd2,0x34,0x83,0xd8,0xa8,0x1f,0xb9,0xd4,0x70,0x36,0xc1,0x33,0xbd,0x90,0xf5,0x36,0x41,0xb5,0x12,0xb4,0xd9,0x84,0xd7,0x73,0x03,0x4e,0x0a,0xba,0x87,0xf5,0x68,0xf0,0x1f,0x9c,0x6a,0xde,0xc8,0x50,0x00,0x4e,0x89,0x27,0x08,0xe7,0x5b,0xed,0x7d,0x55,0x99,0xbf,0x3c,0xf0,0xd6,0x06,0x1c,0x43,0xb0,0xa9,0x64,0x19,0x29,0x7d,0x5b,0xa1,0xd6,0xb3,0x2e,0x35,0x82,0x3a,0xd5,0xa0,0xf6,0xb4,0xb0,0x47,0x5d,0xa4,0x89,0x43,0xce,0x56,0x71,0x6c,0x34,0x18,0xce,0x0a,0x7d,0x1a,0x07},
+ {0x0b,0xba,0x87,0xc8,0xaa,0x2d,0x07,0xd3,0xee,0x62,0xa5,0xbf,0x05,0x29,0x26,0x01,0x8b,0x76,0xef,0xc0,0x02,0x30,0x54,0xcf,0x9c,0x7e,0xea,0x46,0x71,0xcc,0x3b,0x2c,0x31,0x44,0xe1,0x20,0x52,0x35,0x0c,0xcc,0x41,0x51,0xb1,0x09,0x07,0x95,0x65,0x0d,0x36,0x5f,0x9d,0x20,0x1b,0x62,0xf5,0x9a,0xd3,0x55,0x77,0x61,0xf7,0xbc,0x69,0x7c,0x5f,0x29,0xe8,0x04,0xeb,0xd7,0xf0,0x07,0x7d,0xf3,0x50,0x2f,0x25,0x18,0xdb,0x10,0xd7,0x98,0x17,0x17,0xa3,0xa9,0x51,0xe9,0x1d,0xa5,0xac,0x22,0x73,0x9a,0x5a,0x6f},
+ {0xc5,0xc6,0x41,0x2f,0x0c,0x00,0xa1,0x8b,0x9b,0xfb,0xfe,0x0c,0xc1,0x79,0x9f,0xc4,0x9f,0x1c,0xc5,0x3c,0x70,0x47,0xfa,0x4e,0xca,0xaf,0x47,0xe1,0xa2,0x21,0x4e,0x49,0xbe,0x44,0xd9,0xa3,0xeb,0xd4,0x29,0xe7,0x9e,0xaf,0x78,0x80,0x40,0x09,0x9e,0x8d,0x03,0x9c,0x86,0x47,0x7a,0x56,0x25,0x45,0x24,0x3b,0x8d,0xee,0x80,0x96,0xab,0x02,0x9a,0x0d,0xe5,0xdd,0x85,0x8a,0xa4,0xef,0x49,0xa2,0xb9,0x0f,0x4e,0x22,0x9a,0x21,0xd9,0xf6,0x1e,0xd9,0x1d,0x1f,0x09,0xfa,0x34,0xbb,0x46,0xea,0xcb,0x76,0x5d,0x6b},
+ {0x94,0xd9,0x0c,0xec,0x6c,0x55,0x57,0x88,0xba,0x1d,0xd0,0x5c,0x6f,0xdc,0x72,0x64,0x77,0xb4,0x42,0x8f,0x14,0x69,0x01,0xaf,0x54,0x73,0x27,0x85,0xf6,0x33,0xe3,0x0a,0x22,0x25,0x78,0x1e,0x17,0x41,0xf9,0xe0,0xd3,0x36,0x69,0x03,0x74,0xae,0xe6,0xf1,0x46,0xc7,0xfc,0xd0,0xa2,0x3e,0x8b,0x40,0x3e,0x31,0xdd,0x03,0x9c,0x86,0xfb,0x16,0x62,0x09,0xb6,0x33,0x97,0x19,0x8e,0x28,0x33,0xe1,0xab,0xd8,0xb4,0x72,0xfc,0x24,0x3e,0xd0,0x91,0x09,0xed,0xf7,0x11,0x48,0x75,0xd0,0x70,0x8f,0x8b,0xe3,0x81,0x3f},
+ {0xfe,0xaf,0xd9,0x7e,0xcc,0x0f,0x91,0x7f,0x4b,0x87,0x65,0x24,0xa1,0xb8,0x5c,0x54,0x04,0x47,0x0c,0x4b,0xd2,0x7e,0x39,0xa8,0x93,0x09,0xf5,0x04,0xc1,0x0f,0x51,0x50,0x24,0xc8,0x17,0x5f,0x35,0x7f,0xdb,0x0a,0xa4,0x99,0x42,0xd7,0xc3,0x23,0xb9,0x74,0xf7,0xea,0xf8,0xcb,0x8b,0x3e,0x7c,0xd5,0x3d,0xdc,0xde,0x4c,0xd3,0xe2,0xd3,0x0a,0x9d,0x24,0x6e,0x33,0xc5,0x0f,0x0c,0x6f,0xd9,0xcf,0x31,0xc3,0x19,0xde,0x5e,0x74,0x1c,0xfe,0xee,0x09,0x00,0xfd,0xd6,0xf2,0xbe,0x1e,0xfa,0xf0,0x8b,0x15,0x7c,0x12},
+ {0xa2,0x79,0x98,0x2e,0x42,0x7c,0x19,0xf6,0x47,0x36,0xca,0x52,0xd4,0xdd,0x4a,0xa4,0xcb,0xac,0x4e,0x4b,0xc1,0x3f,0x41,0x9b,0x68,0x4f,0xef,0x07,0x7d,0xf8,0x4e,0x35,0x74,0xb9,0x51,0xae,0xc4,0x8f,0xa2,0xde,0x96,0xfe,0x4d,0x74,0xd3,0x73,0x99,0x1d,0xa8,0x48,0x38,0x87,0x0b,0x68,0x40,0x62,0x95,0xdf,0x67,0xd1,0x79,0x24,0xd8,0x4e,0x75,0xd9,0xc5,0x60,0x22,0xb5,0xe3,0xfe,0xb8,0xb0,0x41,0xeb,0xfc,0x2e,0x35,0x50,0x3c,0x65,0xf6,0xa9,0x30,0xac,0x08,0x88,0x6d,0x23,0x39,0x05,0xd2,0x92,0x2d,0x30},
+ {0x3d,0x28,0xa4,0xbc,0xa2,0xc1,0x13,0x78,0xd9,0x3d,0x86,0xa1,0x91,0xf0,0x62,0xed,0x86,0xfa,0x68,0xc2,0xb8,0xbc,0xc7,0xae,0x4c,0xae,0x1c,0x6f,0xb7,0xd3,0xe5,0x10,0x77,0xf1,0xe0,0xe4,0xb6,0x6f,0xbc,0x2d,0x93,0x6a,0xbd,0xa4,0x29,0xbf,0xe1,0x04,0xe8,0xf6,0x7a,0x78,0xd4,0x66,0x19,0x5e,0x60,0xd0,0x26,0xb4,0x5e,0x5f,0xdc,0x0e,0x67,0x8e,0xda,0x53,0xd6,0xbf,0x53,0x54,0x41,0xf6,0xa9,0x24,0xec,0x1e,0xdc,0xe9,0x23,0x8a,0x57,0x03,0x3b,0x26,0x87,0xbf,0x72,0xba,0x1c,0x36,0x51,0x6c,0xb4,0x45},
+ {0xa1,0x7f,0x4f,0x31,0xbf,0x2a,0x40,0xa9,0x50,0xf4,0x8c,0x8e,0xdc,0xf1,0x57,0xe2,0x84,0xbe,0xa8,0x23,0x4b,0xd5,0xbb,0x1d,0x3b,0x71,0xcb,0x6d,0xa3,0xbf,0x77,0x21,0xe4,0xe3,0x7f,0x8a,0xdd,0x4d,0x9d,0xce,0x30,0x0e,0x62,0x76,0x56,0x64,0x13,0xab,0x58,0x99,0x0e,0xb3,0x7b,0x4f,0x59,0x4b,0xdf,0x29,0x12,0x32,0xef,0x0a,0x1c,0x5c,0x8f,0xdb,0x79,0xfa,0xbc,0x1b,0x08,0x37,0xb3,0x59,0x5f,0xc2,0x1e,0x81,0x48,0x60,0x87,0x24,0x83,0x9c,0x65,0x76,0x7a,0x08,0xbb,0xb5,0x8a,0x7d,0x38,0x19,0xe6,0x4a},
+ {0x2e,0xa3,0x44,0x53,0xaa,0xf6,0xdb,0x8d,0x78,0x40,0x1b,0xb4,0xb4,0xea,0x88,0x7d,0x60,0x0d,0x13,0x4a,0x97,0xeb,0xb0,0x5e,0x03,0x3e,0xbf,0x17,0x1b,0xd9,0x00,0x1a,0x83,0xfb,0x5b,0x98,0x44,0x7e,0x11,0x61,0x36,0x31,0x96,0x71,0x2a,0x46,0xe0,0xfc,0x4b,0x90,0x25,0xd4,0x48,0x34,0xac,0x83,0x64,0x3d,0xa4,0x5b,0xbe,0x5a,0x68,0x75,0xb2,0xf2,0x61,0xeb,0x33,0x09,0x96,0x6e,0x52,0x49,0xff,0xc9,0xa8,0x0f,0x3d,0x54,0x69,0x65,0xf6,0x7a,0x10,0x75,0x72,0xdf,0xaa,0xe6,0xb0,0x23,0xb6,0x29,0x55,0x13},
+ {0x18,0xd5,0xd1,0xad,0xd7,0xdb,0xf0,0x18,0x11,0x1f,0xc1,0xcf,0x88,0x78,0x9f,0x97,0x9b,0x75,0x14,0x71,0xf0,0xe1,0x32,0x87,0x01,0x3a,0xca,0x65,0x1a,0xb8,0xb5,0x79,0xfe,0x83,0x2e,0xe2,0xbc,0x16,0xc7,0xf5,0xc1,0x85,0x09,0xe8,0x19,0xeb,0x2b,0xb4,0xae,0x4a,0x25,0x14,0x37,0xa6,0x9d,0xec,0x13,0xa6,0x90,0x15,0x05,0xea,0x72,0x59,0x11,0x78,0x8f,0xdc,0x20,0xac,0xd4,0x0f,0xa8,0x4f,0x4d,0xac,0x94,0xd2,0x9a,0x9a,0x34,0x04,0x36,0xb3,0x64,0x2d,0x1b,0xc0,0xdb,0x3b,0x5f,0x90,0x95,0x9c,0x7e,0x4f},
+ {0x2e,0x30,0x81,0x57,0xbc,0x4b,0x67,0x62,0x0f,0xdc,0xad,0x89,0x39,0x0f,0x52,0xd8,0xc6,0xd9,0xfb,0x53,0xae,0x99,0x29,0x8c,0x4c,0x8e,0x63,0x2e,0xd9,0x3a,0x99,0x31,0xfe,0x99,0x52,0x35,0x3d,0x44,0xc8,0x71,0xd7,0xea,0xeb,0xdb,0x1c,0x3b,0xcd,0x8b,0x66,0x94,0xa4,0xf1,0x9e,0x49,0x92,0x80,0xc8,0xad,0x44,0xa1,0xc4,0xee,0x42,0x19,0x92,0x49,0x23,0xae,0x19,0x53,0xac,0x7d,0x92,0x3e,0xea,0x0c,0x91,0x3d,0x1b,0x2c,0x22,0x11,0x3c,0x25,0x94,0xe4,0x3c,0x55,0x75,0xca,0xf9,0x4e,0x31,0x65,0x0a,0x2a},
+ {0xc2,0x27,0xf9,0xf7,0x7f,0x93,0xb7,0x2d,0x35,0xa6,0xd0,0x17,0x06,0x1f,0x74,0xdb,0x76,0xaf,0x55,0x11,0xa2,0xf3,0x82,0x59,0xed,0x2d,0x7c,0x64,0x18,0xe2,0xf6,0x4c,0x3a,0x79,0x1c,0x3c,0xcd,0x1a,0x36,0xcf,0x3b,0xbc,0x35,0x5a,0xac,0xbc,0x9e,0x2f,0xab,0xa6,0xcd,0xa8,0xe9,0x60,0xe8,0x60,0x13,0x1a,0xea,0x6d,0x9b,0xc3,0x5d,0x05,0xb6,0x5b,0x8d,0xc2,0x7c,0x22,0x19,0xb1,0xab,0xff,0x4d,0x77,0xbc,0x4e,0xe2,0x07,0x89,0x2c,0xa3,0xe4,0xce,0x78,0x3c,0xa8,0xb6,0x24,0xaa,0x10,0x77,0x30,0x1a,0x12},
+ {0x97,0x4a,0x03,0x9f,0x5e,0x5d,0xdb,0xe4,0x2d,0xbc,0x34,0x30,0x09,0xfc,0x53,0xe1,0xb1,0xd3,0x51,0x95,0x91,0x46,0x05,0x46,0x2d,0xe5,0x40,0x7a,0x6c,0xc7,0x3f,0x33,0xc9,0x83,0x74,0xc7,0x3e,0x71,0x59,0xd6,0xaf,0x96,0x2b,0xb8,0x77,0xe0,0xbf,0x88,0xd3,0xbc,0x97,0x10,0x23,0x28,0x9e,0x28,0x9b,0x3a,0xed,0x6c,0x4a,0xb9,0x7b,0x52,0x2e,0x48,0x5b,0x99,0x2a,0x99,0x3d,0x56,0x01,0x38,0x38,0x6e,0x7c,0xd0,0x05,0x34,0xe5,0xd8,0x64,0x2f,0xde,0x35,0x50,0x48,0xf7,0xa9,0xa7,0x20,0x9b,0x06,0x89,0x6b},
+ {0x0d,0x22,0x70,0x62,0x41,0xa0,0x2a,0x81,0x4e,0x5b,0x24,0xf9,0xfa,0x89,0x5a,0x99,0x05,0xef,0x72,0x50,0xce,0xc4,0xad,0xff,0x73,0xeb,0x73,0xaa,0x03,0x21,0xbc,0x23,0x77,0xdb,0xc7,0xb5,0x8c,0xfa,0x82,0x40,0x55,0xc1,0x34,0xc7,0xf8,0x86,0x86,0x06,0x7e,0xa5,0xe7,0xf6,0xd9,0xc8,0xe6,0x29,0xcf,0x9b,0x63,0xa7,0x08,0xd3,0x73,0x04,0x05,0x9e,0x58,0x03,0x26,0x79,0xee,0xca,0x92,0xc4,0xdc,0x46,0x12,0x42,0x4b,0x2b,0x4f,0xa9,0x01,0xe6,0x74,0xef,0xa1,0x02,0x1a,0x34,0x04,0xde,0xbf,0x73,0x2f,0x10},
+ {0xc6,0x45,0x57,0x7f,0xab,0xb9,0x18,0xeb,0x90,0xc6,0x87,0x57,0xee,0x8a,0x3a,0x02,0xa9,0xaf,0xf7,0x2d,0xda,0x12,0x27,0xb7,0x3d,0x01,0x5c,0xea,0x25,0x7d,0x59,0x36,0x9a,0x1c,0x51,0xb5,0xe0,0xda,0xb4,0xa2,0x06,0xff,0xff,0x2b,0x29,0x60,0xc8,0x7a,0x34,0x42,0x50,0xf5,0x5d,0x37,0x1f,0x98,0x2d,0xa1,0x4e,0xda,0x25,0xd7,0x6b,0x3f,0xac,0x58,0x60,0x10,0x7b,0x8d,0x4d,0x73,0x5f,0x90,0xc6,0x6f,0x9e,0x57,0x40,0xd9,0x2d,0x93,0x02,0x92,0xf9,0xf8,0x66,0x64,0xd0,0xd6,0x60,0xda,0x19,0xcc,0x7e,0x7b},
+ {0x0d,0x69,0x5c,0x69,0x3c,0x37,0xc2,0x78,0x6e,0x90,0x42,0x06,0x66,0x2e,0x25,0xdd,0xd2,0x2b,0xe1,0x4a,0x44,0x44,0x1d,0x95,0x56,0x39,0x74,0x01,0x76,0xad,0x35,0x42,0x9b,0xfa,0x7c,0xa7,0x51,0x4a,0xae,0x6d,0x50,0x86,0xa3,0xe7,0x54,0x36,0x26,0x82,0xdb,0x82,0x2d,0x8f,0xcd,0xff,0xbb,0x09,0xba,0xca,0xf5,0x1b,0x66,0xdc,0xbe,0x03,0xf5,0x75,0x89,0x07,0x0d,0xcb,0x58,0x62,0x98,0xf2,0x89,0x91,0x54,0x42,0x29,0x49,0xe4,0x6e,0xe3,0xe2,0x23,0xb4,0xca,0xa0,0xa1,0x66,0xf0,0xcd,0xb0,0xe2,0x7c,0x0e},
+ {0xa3,0x85,0x8c,0xc4,0x3a,0x64,0x94,0xc4,0xad,0x39,0x61,0x3c,0xf4,0x1d,0x36,0xfd,0x48,0x4d,0xe9,0x3a,0xdd,0x17,0xdb,0x09,0x4a,0x67,0xb4,0x8f,0x5d,0x0a,0x6e,0x66,0xf9,0x70,0x4b,0xd9,0xdf,0xfe,0xa6,0xfe,0x2d,0xba,0xfc,0xc1,0x51,0xc0,0x30,0xf1,0x89,0xab,0x2f,0x7f,0x7e,0xd4,0x82,0x48,0xb5,0xee,0xec,0x8a,0x13,0x56,0x52,0x61,0x0d,0xcb,0x70,0x48,0x4e,0xf6,0xbb,0x2a,0x6b,0x8b,0x45,0xaa,0xf0,0xbc,0x65,0xcd,0x5d,0x98,0xe8,0x75,0xba,0x4e,0xbe,0x9a,0xe4,0xde,0x14,0xd5,0x10,0xc8,0x0b,0x7f},
+ {0x6f,0x13,0xf4,0x26,0xa4,0x6b,0x00,0xb9,0x35,0x30,0xe0,0x57,0x9e,0x36,0x67,0x8d,0x28,0x3c,0x46,0x4f,0xd9,0xdf,0xc8,0xcb,0xf5,0xdb,0xee,0xf8,0xbc,0x8d,0x1f,0x0d,0xa0,0x13,0x72,0x73,0xad,0x9d,0xac,0x83,0x98,0x2e,0xf7,0x2e,0xba,0xf8,0xf6,0x9f,0x57,0x69,0xec,0x43,0xdd,0x2e,0x1e,0x31,0x75,0xab,0xc5,0xde,0x7d,0x90,0x3a,0x1d,0xdc,0x81,0xd0,0x3e,0x31,0x93,0x16,0xba,0x80,0x34,0x1b,0x85,0xad,0x9f,0x32,0x29,0xcb,0x21,0x03,0x03,0x3c,0x01,0x28,0x01,0xe3,0xfd,0x1b,0xa3,0x44,0x1b,0x01,0x00},
+ {0x0c,0x6c,0xc6,0x3f,0x6c,0xa0,0xdf,0x3f,0xd2,0x0d,0xd6,0x4d,0x8e,0xe3,0x40,0x5d,0x71,0x4d,0x8e,0x26,0x38,0x8b,0xe3,0x7a,0xe1,0x57,0x83,0x6e,0x91,0x8d,0xc4,0x3a,0x5c,0xa7,0x0a,0x6a,0x69,0x1f,0x56,0x16,0x6a,0xbd,0x52,0x58,0x5c,0x72,0xbf,0xc1,0xad,0x66,0x79,0x9a,0x7f,0xdd,0xa8,0x11,0x26,0x10,0x85,0xd2,0xa2,0x88,0xd9,0x63,0x2e,0x23,0xbd,0xaf,0x53,0x07,0x12,0x00,0x83,0xf6,0xd8,0xfd,0xb8,0xce,0x2b,0xe9,0x91,0x2b,0xe7,0x84,0xb3,0x69,0x16,0xf8,0x66,0xa0,0x68,0x23,0x2b,0xd5,0xfa,0x33},
+ {0x16,0x1e,0xe4,0xc5,0xc6,0x49,0x06,0x54,0x35,0x77,0x3f,0x33,0x30,0x64,0xf8,0x0a,0x46,0xe7,0x05,0xf3,0xd2,0xfc,0xac,0xb2,0xa7,0xdc,0x56,0xa2,0x29,0xf4,0xc0,0x16,0xe8,0xcf,0x22,0xc4,0xd0,0xc8,0x2c,0x8d,0xcb,0x3a,0xa1,0x05,0x7b,0x4f,0x2b,0x07,0x6f,0xa5,0xf6,0xec,0xe6,0xb6,0xfe,0xa3,0xe2,0x71,0x0a,0xb9,0xcc,0x55,0xc3,0x3c,0x31,0x91,0x3e,0x90,0x43,0x94,0xb6,0xe9,0xce,0x37,0x56,0x7a,0xcb,0x94,0xa4,0xb8,0x44,0x92,0xba,0xba,0xa4,0xd1,0x7c,0xc8,0x68,0x75,0xae,0x6b,0x42,0xaf,0x1e,0x63},
+ {0x9f,0xfe,0x66,0xda,0x10,0x04,0xe9,0xb3,0xa6,0xe5,0x16,0x6c,0x52,0x4b,0xdd,0x85,0x83,0xbf,0xf9,0x1e,0x61,0x97,0x3d,0xbc,0xb5,0x19,0xa9,0x1e,0x8b,0x64,0x99,0x55,0xe8,0x0d,0x70,0xa3,0xb9,0x75,0xd9,0x47,0x52,0x05,0xf8,0xe2,0xfb,0xc5,0x80,0x72,0xe1,0x5d,0xe4,0x32,0x27,0x8f,0x65,0x53,0xb5,0x80,0x5f,0x66,0x7f,0x2c,0x1f,0x43,0x19,0x7b,0x8f,0x85,0x44,0x63,0x02,0xd6,0x4a,0x51,0xea,0xa1,0x2f,0x35,0xab,0x14,0xd7,0xa9,0x90,0x20,0x1a,0x44,0x00,0x89,0x26,0x3b,0x25,0x91,0x5f,0x71,0x04,0x7b},
+ {0x43,0xae,0xf6,0xac,0x28,0xbd,0xed,0x83,0xb4,0x7a,0x5c,0x7d,0x8b,0x7c,0x35,0x86,0x44,0x2c,0xeb,0xb7,0x69,0x47,0x40,0xc0,0x3f,0x58,0xf6,0xc2,0xf5,0x7b,0xb3,0x59,0xc6,0xba,0xe6,0xc4,0x80,0xc2,0x76,0xb3,0x0b,0x9b,0x1d,0x6d,0xdd,0xd3,0x0e,0x97,0x44,0xf9,0x0b,0x45,0x58,0x95,0x9a,0xb0,0x23,0xe2,0xcd,0x57,0xfa,0xac,0xd0,0x48,0x71,0xe6,0xab,0x7d,0xe4,0x26,0x0f,0xb6,0x37,0x3a,0x2f,0x62,0x97,0xa1,0xd1,0xf1,0x94,0x03,0x96,0xe9,0x7e,0xce,0x08,0x42,0xdb,0x3b,0x6d,0x33,0x91,0x41,0x23,0x16},
+ {0xf6,0x7f,0x26,0xf6,0xde,0x99,0xe4,0xb9,0x43,0x08,0x2c,0x74,0x7b,0xca,0x72,0x77,0xb1,0xf2,0xa4,0xe9,0x3f,0x15,0xa0,0x23,0x06,0x50,0xd0,0xd5,0xec,0xdf,0xdf,0x2c,0x40,0x86,0xf3,0x1f,0xd6,0x9c,0x49,0xdd,0xa0,0x25,0x36,0x06,0xc3,0x9b,0xcd,0x29,0xc3,0x3d,0xd7,0x3d,0x02,0xd8,0xe2,0x51,0x31,0x92,0x3b,0x20,0x7a,0x70,0x25,0x4a,0x6a,0xed,0xf6,0x53,0x8a,0x66,0xb7,0x2a,0xa1,0x70,0xd1,0x1d,0x58,0x42,0x42,0x30,0x61,0x01,0xe2,0x3a,0x4c,0x14,0x00,0x40,0xfc,0x49,0x8e,0x24,0x6d,0x89,0x21,0x57},
+ {0xae,0x1b,0x18,0xfd,0x17,0x55,0x6e,0x0b,0xb4,0x63,0xb9,0x2b,0x9f,0x62,0x22,0x90,0x25,0x46,0x06,0x32,0xe9,0xbc,0x09,0x55,0xda,0x13,0x3c,0xf6,0x74,0xdd,0x8e,0x57,0x4e,0xda,0xd0,0xa1,0x91,0x50,0x5d,0x28,0x08,0x3e,0xfe,0xb5,0xa7,0x6f,0xaa,0x4b,0xb3,0x93,0x93,0xe1,0x7c,0x17,0xe5,0x63,0xfd,0x30,0xb0,0xc4,0xaf,0x35,0xc9,0x03,0x3d,0x0c,0x2b,0x49,0xc6,0x76,0x72,0x99,0xfc,0x05,0xe2,0xdf,0xc4,0xc2,0xcc,0x47,0x3c,0x3a,0x62,0xdd,0x84,0x9b,0xd2,0xdc,0xa2,0xc7,0x88,0x02,0x59,0xab,0xc2,0x3e},
+ {0xb9,0x7b,0xd8,0xe4,0x7b,0xd2,0xa0,0xa1,0xed,0x1a,0x39,0x61,0xeb,0x4d,0x8b,0xa9,0x83,0x9b,0xcb,0x73,0xd0,0xdd,0xa0,0x99,0xce,0xca,0x0f,0x20,0x5a,0xc2,0xd5,0x2d,0xcb,0xd1,0x32,0xae,0x09,0x3a,0x21,0xa7,0xd5,0xc2,0xf5,0x40,0xdf,0x87,0x2b,0x0f,0x29,0xab,0x1e,0xe8,0xc6,0xa4,0xae,0x0b,0x5e,0xac,0xdb,0x6a,0x6c,0xf6,0x1b,0x0e,0x7e,0x88,0x2c,0x79,0xe9,0xd5,0xab,0xe2,0x5d,0x6d,0x92,0xcb,0x18,0x00,0x02,0x1a,0x1e,0x5f,0xae,0xba,0xcd,0x69,0xba,0xbf,0x5f,0x8f,0xe8,0x5a,0xb3,0x48,0x05,0x73},
+ {0xee,0xb8,0xa8,0xcb,0xa3,0x51,0x35,0xc4,0x16,0x5f,0x11,0xb2,0x1d,0x6f,0xa2,0x65,0x50,0x38,0x8c,0xab,0x52,0x4f,0x0f,0x76,0xca,0xb8,0x1d,0x41,0x3b,0x44,0x43,0x30,0x34,0xe3,0xd6,0xa1,0x4b,0x09,0x5b,0x80,0x19,0x3f,0x35,0x09,0x77,0xf1,0x3e,0xbf,0x2b,0x70,0x22,0x06,0xcb,0x06,0x3f,0x42,0xdd,0x45,0x78,0xd8,0x77,0x22,0x5a,0x58,0x62,0x89,0xd4,0x33,0x82,0x5f,0x8a,0xa1,0x7f,0x25,0x78,0xec,0xb5,0xc4,0x98,0x66,0xff,0x41,0x3e,0x37,0xa5,0x6f,0x8e,0xa7,0x1f,0x98,0xef,0x50,0x89,0x27,0x56,0x76},
+ {0xc0,0xc8,0x1f,0xd5,0x59,0xcf,0xc3,0x38,0xf2,0xb6,0x06,0x05,0xfd,0xd2,0xed,0x9b,0x8f,0x0e,0x57,0xab,0x9f,0x10,0xbf,0x26,0xa6,0x46,0xb8,0xc1,0xa8,0x60,0x41,0x3f,0x9d,0xcf,0x86,0xea,0xa3,0x73,0x70,0xe1,0xdc,0x5f,0x15,0x07,0xb7,0xfb,0x8c,0x3a,0x8e,0x8a,0x83,0x31,0xfc,0xe7,0x53,0x48,0x16,0xf6,0x13,0xb6,0x84,0xf4,0xbb,0x28,0x7c,0x6c,0x13,0x6f,0x5c,0x2f,0x61,0xf2,0xbe,0x11,0xdd,0xf6,0x07,0xd1,0xea,0xaf,0x33,0x6f,0xde,0x13,0xd2,0x9a,0x7e,0x52,0x5d,0xf7,0x88,0x81,0x35,0xcb,0x79,0x1e},
+ {0xf1,0xe3,0xf7,0xee,0xc3,0x36,0x34,0x01,0xf8,0x10,0x9e,0xfe,0x7f,0x6a,0x8b,0x82,0xfc,0xde,0xf9,0xbc,0xe5,0x08,0xf9,0x7f,0x31,0x38,0x3b,0x3a,0x1b,0x95,0xd7,0x65,0x81,0x81,0xe0,0xf5,0xd8,0x53,0xe9,0x77,0xd9,0xde,0x9d,0x29,0x44,0x0c,0xa5,0x84,0xe5,0x25,0x45,0x86,0x0c,0x2d,0x6c,0xdc,0xf4,0xf2,0xd1,0x39,0x2d,0xb5,0x8a,0x47,0x59,0xd1,0x52,0x92,0xd3,0xa4,0xa6,0x66,0x07,0xc8,0x1a,0x87,0xbc,0xe1,0xdd,0xe5,0x6f,0xc9,0xc1,0xa6,0x40,0x6b,0x2c,0xb8,0x14,0x22,0x21,0x1a,0x41,0x7a,0xd8,0x16},
+ {0x15,0x62,0x06,0x42,0x5a,0x7e,0xbd,0xb3,0xc1,0x24,0x5a,0x0c,0xcd,0xe3,0x9b,0x87,0xb7,0x94,0xf9,0xd6,0xb1,0x5d,0xc0,0x57,0xa6,0x8c,0xf3,0x65,0x81,0x7c,0xf8,0x28,0x83,0x05,0x4e,0xd5,0xe2,0xd5,0xa4,0xfb,0xfa,0x99,0xbd,0x2e,0xd7,0xaf,0x1f,0xe2,0x8f,0x77,0xe9,0x6e,0x73,0xc2,0x7a,0x49,0xde,0x6d,0x5a,0x7a,0x57,0x0b,0x99,0x1f,0xd6,0xf7,0xe8,0x1b,0xad,0x4e,0x34,0xa3,0x8f,0x79,0xea,0xac,0xeb,0x50,0x1e,0x7d,0x52,0xe0,0x0d,0x52,0x9e,0x56,0xc6,0x77,0x3e,0x6d,0x4d,0x53,0xe1,0x2f,0x88,0x45},
+ {0xd6,0x83,0x79,0x75,0x5d,0x34,0x69,0x66,0xa6,0x11,0xaa,0x17,0x11,0xed,0xb6,0x62,0x8f,0x12,0x5e,0x98,0x57,0x18,0xdd,0x7d,0xdd,0xf6,0x26,0xf6,0xb8,0xe5,0x8f,0x68,0xe4,0x6f,0x3c,0x94,0x29,0x99,0xac,0xd8,0xa2,0x92,0x83,0xa3,0x61,0xf1,0xf9,0xb5,0xf3,0x9a,0xc8,0xbe,0x13,0xdb,0x99,0x26,0x74,0xf0,0x05,0xe4,0x3c,0x84,0xcf,0x7d,0xc0,0x32,0x47,0x4a,0x48,0xd6,0x90,0x6c,0x99,0x32,0x56,0xca,0xfd,0x43,0x21,0xd5,0xe1,0xc6,0x5d,0x91,0xc3,0x28,0xbe,0xb3,0x1b,0x19,0x27,0x73,0x7e,0x68,0x39,0x67},
+ {0xa6,0x75,0x56,0x38,0x14,0x20,0x78,0xef,0xe8,0xa9,0xfd,0xaa,0x30,0x9f,0x64,0xa2,0xcb,0xa8,0xdf,0x5c,0x50,0xeb,0xd1,0x4c,0xb3,0xc0,0x4d,0x1d,0xba,0x5a,0x11,0x46,0xc0,0x1a,0x0c,0xc8,0x9d,0xcc,0x6d,0xa6,0x36,0xa4,0x38,0x1b,0xf4,0x5c,0xa0,0x97,0xc6,0xd7,0xdb,0x95,0xbe,0xf3,0xeb,0xa7,0xab,0x7d,0x7e,0x8d,0xf6,0xb8,0xa0,0x7d,0x76,0xda,0xb5,0xc3,0x53,0x19,0x0f,0xd4,0x9b,0x9e,0x11,0x21,0x73,0x6f,0xac,0x1d,0x60,0x59,0xb2,0xfe,0x21,0x60,0xcc,0x03,0x4b,0x4b,0x67,0x83,0x7e,0x88,0x5f,0x5a},
+ {0x11,0x3d,0xa1,0x70,0xcf,0x01,0x63,0x8f,0xc4,0xd0,0x0d,0x35,0x15,0xb8,0xce,0xcf,0x7e,0xa4,0xbc,0xa4,0xd4,0x97,0x02,0xf7,0x34,0x14,0x4d,0xe4,0x56,0xb6,0x69,0x36,0xb9,0x43,0xa6,0xa0,0xd3,0x28,0x96,0x9e,0x64,0x20,0xc3,0xe6,0x00,0xcb,0xc3,0xb5,0x32,0xec,0x2d,0x7c,0x89,0x02,0x53,0x9b,0x0c,0xc7,0xd1,0xd5,0xe2,0x7a,0xe3,0x43,0x33,0xe1,0xa6,0xed,0x06,0x3f,0x7e,0x38,0xc0,0x3a,0xa1,0x99,0x51,0x1d,0x30,0x67,0x11,0x38,0x26,0x36,0xf8,0xd8,0x5a,0xbd,0xbe,0xe9,0xd5,0x4f,0xcd,0xe6,0x21,0x6a},
+ {0x5f,0xe6,0x46,0x30,0x0a,0x17,0xc6,0xf1,0x24,0x35,0xd2,0x00,0x2a,0x2a,0x71,0x58,0x55,0xb7,0x82,0x8c,0x3c,0xbd,0xdb,0x69,0x57,0xff,0x95,0xa1,0xf1,0xf9,0x6b,0x58,0xe3,0xb2,0x99,0x66,0x12,0x29,0x41,0xef,0x01,0x13,0x8d,0x70,0x47,0x08,0xd3,0x71,0xbd,0xb0,0x82,0x11,0xd0,0x32,0x54,0x32,0x36,0x8b,0x1e,0x00,0x07,0x1b,0x37,0x45,0x0b,0x79,0xf8,0x5e,0x8d,0x08,0xdb,0xa6,0xe5,0x37,0x09,0x61,0xdc,0xf0,0x78,0x52,0xb8,0x6e,0xa1,0x61,0xd2,0x49,0x03,0xac,0x79,0x21,0xe5,0x90,0x37,0xb0,0xaf,0x0e},
+ {0x2f,0x04,0x48,0x37,0xc1,0x55,0x05,0x96,0x11,0xaa,0x0b,0x82,0xe6,0x41,0x9a,0x21,0x0c,0x6d,0x48,0x73,0x38,0xf7,0x81,0x1c,0x61,0xc6,0x02,0x5a,0x67,0xcc,0x9a,0x30,0x1d,0xae,0x75,0x0f,0x5e,0x80,0x40,0x51,0x30,0xcc,0x62,0x26,0xe3,0xfb,0x02,0xec,0x6d,0x39,0x92,0xea,0x1e,0xdf,0xeb,0x2c,0xb3,0x5b,0x43,0xc5,0x44,0x33,0xae,0x44,0xee,0x43,0xa5,0xbb,0xb9,0x89,0xf2,0x9c,0x42,0x71,0xc9,0x5a,0x9d,0x0e,0x76,0xf3,0xaa,0x60,0x93,0x4f,0xc6,0xe5,0x82,0x1d,0x8f,0x67,0x94,0x7f,0x1b,0x22,0xd5,0x62},
+ {0x6d,0x93,0xd0,0x18,0x9c,0x29,0x4c,0x52,0x0c,0x1a,0x0c,0x8a,0x6c,0xb5,0x6b,0xc8,0x31,0x86,0x4a,0xdb,0x2e,0x05,0x75,0xa3,0x62,0x45,0x75,0xbc,0xe4,0xfd,0x0e,0x5c,0x3c,0x7a,0xf7,0x3a,0x26,0xd4,0x85,0x75,0x4d,0x14,0xe9,0xfe,0x11,0x7b,0xae,0xdf,0x3d,0x19,0xf7,0x59,0x80,0x70,0x06,0xa5,0x37,0x20,0x92,0x83,0x53,0x9a,0xf2,0x14,0xf5,0xd7,0xb2,0x25,0xdc,0x7e,0x71,0xdf,0x40,0x30,0xb5,0x99,0xdb,0x70,0xf9,0x21,0x62,0x4c,0xed,0xc3,0xb7,0x34,0x92,0xda,0x3e,0x09,0xee,0x7b,0x5c,0x36,0x72,0x5e},
+ {0x7f,0x21,0x71,0x45,0x07,0xfc,0x5b,0x57,0x5b,0xd9,0x94,0x06,0x5d,0x67,0x79,0x37,0x33,0x1e,0x19,0xf4,0xbb,0x37,0x0a,0x9a,0xbc,0xea,0xb4,0x47,0x4c,0x10,0xf1,0x77,0x3e,0xb3,0x08,0x2f,0x06,0x39,0x93,0x7d,0xbe,0x32,0x9f,0xdf,0xe5,0x59,0x96,0x5b,0xfd,0xbd,0x9e,0x1f,0xad,0x3d,0xff,0xac,0xb7,0x49,0x73,0xcb,0x55,0x05,0xb2,0x70,0x4c,0x2c,0x11,0x55,0xc5,0x13,0x51,0xbe,0xcd,0x1f,0x88,0x9a,0x3a,0x42,0x88,0x66,0x47,0x3b,0x50,0x5e,0x85,0x77,0x66,0x44,0x4a,0x40,0x06,0x4a,0x8f,0x39,0x34,0x0e},
+ {0xe8,0xbd,0xce,0x3e,0xd9,0x22,0x7d,0xb6,0x07,0x2f,0x82,0x27,0x41,0xe8,0xb3,0x09,0x8d,0x6d,0x5b,0xb0,0x1f,0xa6,0x3f,0x74,0x72,0x23,0x36,0x8a,0x36,0x05,0x54,0x5e,0x28,0x19,0x4b,0x3e,0x09,0x0b,0x93,0x18,0x40,0xf6,0xf3,0x73,0x0e,0xe1,0xe3,0x7d,0x6f,0x5d,0x39,0x73,0xda,0x17,0x32,0xf4,0x3e,0x9c,0x37,0xca,0xd6,0xde,0x8a,0x6f,0x9a,0xb2,0xb7,0xfd,0x3d,0x12,0x40,0xe3,0x91,0xb2,0x1a,0xa2,0xe1,0x97,0x7b,0x48,0x9e,0x94,0xe6,0xfd,0x02,0x7d,0x96,0xf9,0x97,0xde,0xd3,0xc8,0x2e,0xe7,0x0d,0x78},
+ {0xbc,0xe7,0x9a,0x08,0x45,0x85,0xe2,0x0a,0x06,0x4d,0x7f,0x1c,0xcf,0xde,0x8d,0x38,0xb8,0x11,0x48,0x0a,0x51,0x15,0xac,0x38,0xe4,0x8c,0x92,0x71,0xf6,0x8b,0xb2,0x0e,0x72,0x27,0xf4,0x00,0xf3,0xea,0x1f,0x67,0xaa,0x41,0x8c,0x2a,0x2a,0xeb,0x72,0x8f,0x92,0x32,0x37,0x97,0xd7,0x7f,0xa1,0x29,0xa6,0x87,0xb5,0x32,0xad,0xc6,0xef,0x1d,0xa7,0x95,0x51,0xef,0x1a,0xbe,0x5b,0xaf,0xed,0x15,0x7b,0x91,0x77,0x12,0x8c,0x14,0x2e,0xda,0xe5,0x7a,0xfb,0xf7,0x91,0x29,0x67,0x28,0xdd,0xf8,0x1b,0x20,0x7d,0x46},
+ {0xad,0x4f,0xef,0x74,0x9a,0x91,0xfe,0x95,0xa2,0x08,0xa3,0xf6,0xec,0x7b,0x82,0x3a,0x01,0x7b,0xa4,0x09,0xd3,0x01,0x4e,0x96,0x97,0xc7,0xa3,0x5b,0x4f,0x3c,0xc4,0x71,0xa9,0xe7,0x7a,0x56,0xbd,0xf4,0x1e,0xbc,0xbd,0x98,0x44,0xd6,0xb2,0x4c,0x62,0x3f,0xc8,0x4e,0x1f,0x2c,0xd2,0x64,0x10,0xe4,0x01,0x40,0x38,0xba,0xa5,0xc5,0xf9,0x2e,0xcd,0x74,0x9e,0xfa,0xf6,0x6d,0xfd,0xb6,0x7a,0x26,0xaf,0xe4,0xbc,0x78,0x82,0xf1,0x0e,0x99,0xef,0xf1,0xd0,0xb3,0x55,0x82,0x93,0xf2,0xc5,0x90,0xa3,0x8c,0x75,0x5a},
+ {0x95,0x24,0x46,0xd9,0x10,0x27,0xb7,0xa2,0x03,0x50,0x7d,0xd5,0xd2,0xc6,0xa8,0x3a,0xca,0x87,0xb4,0xa0,0xbf,0x00,0xd4,0xe3,0xec,0x72,0xeb,0xb3,0x44,0xe2,0xba,0x2d,0x94,0xdc,0x61,0x1d,0x8b,0x91,0xe0,0x8c,0x66,0x30,0x81,0x9a,0x46,0x36,0xed,0x8d,0xd3,0xaa,0xe8,0xaf,0x29,0xa8,0xe6,0xd4,0x3f,0xd4,0x39,0xf6,0x27,0x80,0x73,0x0a,0xcc,0xe1,0xff,0x57,0x2f,0x4a,0x0f,0x98,0x43,0x98,0x83,0xe1,0x0d,0x0d,0x67,0x00,0xfd,0x15,0xfb,0x49,0x4a,0x3f,0x5c,0x10,0x9c,0xa6,0x26,0x51,0x63,0xca,0x98,0x26},
+ {0x78,0xba,0xb0,0x32,0x88,0x31,0x65,0xe7,0x8b,0xff,0x5c,0x92,0xf7,0x31,0x18,0x38,0xcc,0x1f,0x29,0xa0,0x91,0x1b,0xa8,0x08,0x07,0xeb,0xca,0x49,0xcc,0x3d,0xb4,0x1f,0x0e,0xd9,0x3d,0x5e,0x2f,0x70,0x3d,0x2e,0x86,0x53,0xd2,0xe4,0x18,0x09,0x3f,0x9e,0x6a,0xa9,0x4d,0x02,0xf6,0x3e,0x77,0x5e,0x32,0x33,0xfa,0x4a,0x0c,0x4b,0x00,0x3c,0x2b,0xb8,0xf4,0x06,0xac,0x46,0xa9,0x9a,0xf3,0xc4,0x06,0xa8,0xa5,0x84,0xa2,0x1c,0x87,0x47,0xcd,0xc6,0x5f,0x26,0xd3,0x3e,0x17,0xd2,0x1f,0xcd,0x01,0xfd,0x43,0x6b},
+ {0x44,0xc5,0x97,0x46,0x4b,0x5d,0xa7,0xc7,0xbf,0xff,0x0f,0xdf,0x48,0xf8,0xfd,0x15,0x5a,0x78,0x46,0xaa,0xeb,0xb9,0x68,0x28,0x14,0xf7,0x52,0x5b,0x10,0xd7,0x68,0x5a,0xf3,0x0e,0x76,0x3e,0x58,0x42,0xc7,0xb5,0x90,0xb9,0x0a,0xee,0xb9,0x52,0xdc,0x75,0x3f,0x92,0x2b,0x07,0xc2,0x27,0x14,0xbf,0xf0,0xd9,0xf0,0x6f,0x2d,0x0b,0x42,0x73,0x06,0x1e,0x85,0x9e,0xcb,0xf6,0x2c,0xaf,0xc4,0x38,0x22,0xc6,0x13,0x39,0x59,0x8f,0x73,0xf3,0xfb,0x99,0x96,0xb8,0x8a,0xda,0x9e,0xbc,0x34,0xea,0x2f,0x63,0xb5,0x3d},
+ {0xd8,0xd9,0x5d,0xf7,0x2b,0xee,0x6e,0xf4,0xa5,0x59,0x67,0x39,0xf6,0xb1,0x17,0x0d,0x73,0x72,0x9e,0x49,0x31,0xd1,0xf2,0x1b,0x13,0x5f,0xd7,0x49,0xdf,0x1a,0x32,0x04,0xd5,0x25,0x98,0x82,0xb1,0x90,0x49,0x2e,0x91,0x89,0x9a,0x3e,0x87,0xeb,0xea,0xed,0xf8,0x4a,0x70,0x4c,0x39,0x3d,0xf0,0xee,0x0e,0x2b,0xdf,0x95,0xa4,0x7e,0x19,0x59,0xae,0x5a,0xe5,0xe4,0x19,0x60,0xe1,0x04,0xe9,0x92,0x2f,0x7e,0x7a,0x43,0x7b,0xe7,0xa4,0x9a,0x15,0x6f,0xc1,0x2d,0xce,0xc7,0xc0,0x0c,0xd7,0xf4,0xc1,0xfd,0xea,0x45},
+ {0x2b,0xd7,0x45,0x80,0x85,0x01,0x84,0x69,0x51,0x06,0x2f,0xcf,0xa2,0xfa,0x22,0x4c,0xc6,0x2d,0x22,0x6b,0x65,0x36,0x1a,0x94,0xde,0xda,0x62,0x03,0xc8,0xeb,0x5e,0x5a,0xed,0xb1,0xcc,0xcf,0x24,0x46,0x0e,0xb6,0x95,0x03,0x5c,0xbd,0x92,0xc2,0xdb,0x59,0xc9,0x81,0x04,0xdc,0x1d,0x9d,0xa0,0x31,0x40,0xd9,0x56,0x5d,0xea,0xce,0x73,0x3f,0xc6,0x8d,0x4e,0x0a,0xd1,0xbf,0xa7,0xb7,0x39,0xb3,0xc9,0x44,0x7e,0x00,0x57,0xbe,0xfa,0xae,0x57,0x15,0x7f,0x20,0xc1,0x60,0xdb,0x18,0x62,0x26,0x91,0x88,0x05,0x26},
+ {0x04,0xff,0x60,0x83,0xa6,0x04,0xf7,0x59,0xf4,0xe6,0x61,0x76,0xde,0x3f,0xd9,0xc3,0x51,0x35,0x87,0x12,0x73,0x2a,0x1b,0x83,0x57,0x5d,0x61,0x4e,0x2e,0x0c,0xad,0x54,0x42,0xe5,0x76,0xc6,0x3c,0x8e,0x81,0x4c,0xad,0xcc,0xce,0x03,0x93,0x2c,0x42,0x5e,0x08,0x9f,0x12,0xb4,0xca,0xcc,0x07,0xec,0xb8,0x43,0x44,0xb2,0x10,0xfa,0xed,0x0d,0x2a,0x52,0x2b,0xb8,0xd5,0x67,0x3b,0xee,0xeb,0xc1,0xa5,0x9f,0x46,0x63,0xf1,0x36,0xd3,0x9f,0xc1,0x6e,0xf2,0xd2,0xb4,0xa5,0x08,0x94,0x7a,0xa7,0xba,0xb2,0xec,0x62},
+ {0x3d,0x2b,0x15,0x61,0x52,0x79,0xed,0xe5,0xd1,0xd7,0xdd,0x0e,0x7d,0x35,0x62,0x49,0x71,0x4c,0x6b,0xb9,0xd0,0xc8,0x82,0x74,0xbe,0xd8,0x66,0xa9,0x19,0xf9,0x59,0x2e,0x74,0x28,0xb6,0xaf,0x36,0x28,0x07,0x92,0xa5,0x04,0xe1,0x79,0x85,0x5e,0xcd,0x5f,0x4a,0xa1,0x30,0xc6,0xad,0x01,0xad,0x5a,0x98,0x3f,0x66,0x75,0x50,0x3d,0x91,0x61,0xda,0x31,0x32,0x1a,0x36,0x2d,0xc6,0x0d,0x70,0x02,0x20,0x94,0x32,0x58,0x47,0xfa,0xce,0x94,0x95,0x3f,0x51,0x01,0xd8,0x02,0x5c,0x5d,0xc0,0x31,0xa1,0xc2,0xdb,0x3d},
+ {0x4b,0xc5,0x5e,0xce,0xf9,0x0f,0xdc,0x9a,0x0d,0x13,0x2f,0x8c,0x6b,0x2a,0x9c,0x03,0x15,0x95,0xf8,0xf0,0xc7,0x07,0x80,0x02,0x6b,0xb3,0x04,0xac,0x14,0x83,0x96,0x78,0x14,0xbb,0x96,0x27,0xa2,0x57,0xaa,0xf3,0x21,0xda,0x07,0x9b,0xb7,0xba,0x3a,0x88,0x1c,0x39,0xa0,0x31,0x18,0xe2,0x4b,0xe5,0xf9,0x05,0x32,0xd8,0x38,0xfb,0xe7,0x5e,0x8e,0x6a,0x44,0x41,0xcb,0xfd,0x8d,0x53,0xf9,0x37,0x49,0x43,0xa9,0xfd,0xac,0xa5,0x78,0x8c,0x3c,0x26,0x8d,0x90,0xaf,0x46,0x09,0x0d,0xca,0x9b,0x3c,0x63,0xd0,0x61},
+ {0x66,0x25,0xdb,0xff,0x35,0x49,0x74,0x63,0xbb,0x68,0x0b,0x78,0x89,0x6b,0xbd,0xc5,0x03,0xec,0x3e,0x55,0x80,0x32,0x1b,0x6f,0xf5,0xd7,0xae,0x47,0xd8,0x5f,0x96,0x6e,0xdf,0x73,0xfc,0xf8,0xbc,0x28,0xa3,0xad,0xfc,0x37,0xf0,0xa6,0x5d,0x69,0x84,0xee,0x09,0xa9,0xc2,0x38,0xdb,0xb4,0x7f,0x63,0xdc,0x7b,0x06,0xf8,0x2d,0xac,0x23,0x5b,0x7b,0x52,0x80,0xee,0x53,0xb9,0xd2,0x9a,0x8d,0x6d,0xde,0xfa,0xaa,0x19,0x8f,0xe8,0xcf,0x82,0x0e,0x15,0x04,0x17,0x71,0x0e,0xdc,0xde,0x95,0xdd,0xb9,0xbb,0xb9,0x79},
+ {0xc2,0x26,0x31,0x6a,0x40,0x55,0xb3,0xeb,0x93,0xc3,0xc8,0x68,0xa8,0x83,0x63,0xd2,0x82,0x7a,0xb9,0xe5,0x29,0x64,0x0c,0x6c,0x47,0x21,0xfd,0xc9,0x58,0xf1,0x65,0x50,0x74,0x73,0x9f,0x8e,0xae,0x7d,0x99,0xd1,0x16,0x08,0xbb,0xcf,0xf8,0xa2,0x32,0xa0,0x0a,0x5f,0x44,0x6d,0x12,0xba,0x6c,0xcd,0x34,0xb8,0xcc,0x0a,0x46,0x11,0xa8,0x1b,0x54,0x99,0x42,0x0c,0xfb,0x69,0x81,0x70,0x67,0xcf,0x6e,0xd7,0xac,0x00,0x46,0xe1,0xba,0x45,0xe6,0x70,0x8a,0xb9,0xaa,0x2e,0xf2,0xfa,0xa4,0x58,0x9e,0xf3,0x81,0x39},
+ {0x93,0x0a,0x23,0x59,0x75,0x8a,0xfb,0x18,0x5d,0xf4,0xe6,0x60,0x69,0x8f,0x16,0x1d,0xb5,0x3c,0xa9,0x14,0x45,0xa9,0x85,0x3a,0xfd,0xd0,0xac,0x05,0x37,0x08,0xdc,0x38,0xde,0x6f,0xe6,0x6d,0xa5,0xdf,0x45,0xc8,0x3a,0x48,0x40,0x2c,0x00,0xa5,0x52,0xe1,0x32,0xf6,0xb4,0xc7,0x63,0xe1,0xd2,0xe9,0x65,0x1b,0xbc,0xdc,0x2e,0x45,0xf4,0x30,0x40,0x97,0x75,0xc5,0x82,0x27,0x6d,0x85,0xcc,0xbe,0x9c,0xf9,0x69,0x45,0x13,0xfa,0x71,0x4e,0xea,0xc0,0x73,0xfc,0x44,0x88,0x69,0x24,0x3f,0x59,0x1a,0x9a,0x2d,0x63},
+ {0xa6,0xcb,0x07,0xb8,0x15,0x6b,0xbb,0xf6,0xd7,0xf0,0x54,0xbc,0xdf,0xc7,0x23,0x18,0x0b,0x67,0x29,0x6e,0x03,0x97,0x1d,0xbb,0x57,0x4a,0xed,0x47,0x88,0xf4,0x24,0x0b,0xa7,0x84,0x0c,0xed,0x11,0xfd,0x09,0xbf,0x3a,0x69,0x9f,0x0d,0x81,0x71,0xf0,0x63,0x79,0x87,0xcf,0x57,0x2d,0x8c,0x90,0x21,0xa2,0x4b,0xf6,0x8a,0xf2,0x7d,0x5a,0x3a,0xc7,0xea,0x1b,0x51,0xbe,0xd4,0xda,0xdc,0xf2,0xcc,0x26,0xed,0x75,0x80,0x53,0xa4,0x65,0x9a,0x5f,0x00,0x9f,0xff,0x9c,0xe1,0x63,0x1f,0x48,0x75,0x44,0xf7,0xfc,0x34},
+ {0xca,0x67,0x97,0x78,0x4c,0xe0,0x97,0xc1,0x7d,0x46,0xd9,0x38,0xcb,0x4d,0x71,0xb8,0xa8,0x5f,0xf9,0x83,0x82,0x88,0xde,0x55,0xf7,0x63,0xfa,0x4d,0x16,0xdc,0x3b,0x3d,0x98,0xaa,0xcf,0x78,0xab,0x1d,0xbb,0xa5,0xf2,0x72,0x0b,0x19,0x67,0xa2,0xed,0x5c,0x8e,0x60,0x92,0x0a,0x11,0xc9,0x09,0x93,0xb0,0x74,0xb3,0x2f,0x04,0xa3,0x19,0x01,0x7d,0x17,0xc2,0xe8,0x9c,0xd8,0xa2,0x67,0xc1,0xd0,0x95,0x68,0xf6,0xa5,0x9d,0x66,0xb0,0xa2,0x82,0xb2,0xe5,0x98,0x65,0xf5,0x73,0x0a,0xe2,0xed,0xf1,0x88,0xc0,0x56},
+ {0x17,0x6e,0xa8,0x10,0x11,0x3d,0x6d,0x33,0xfa,0xb2,0x75,0x0b,0x32,0x88,0xf3,0xd7,0x88,0x29,0x07,0x25,0x76,0x33,0x15,0xf9,0x87,0x8b,0x10,0x99,0x6b,0x4c,0x67,0x09,0x02,0x8f,0xf3,0x24,0xac,0x5f,0x1b,0x58,0xbd,0x0c,0xe3,0xba,0xfe,0xe9,0x0b,0xa9,0xf0,0x92,0xcf,0x8a,0x02,0x69,0x21,0x9a,0x8f,0x03,0x59,0x83,0xa4,0x7e,0x8b,0x03,0xf8,0x6f,0x31,0x99,0x21,0xf8,0x4e,0x9f,0x4f,0x8d,0xa7,0xea,0x82,0xd2,0x49,0x2f,0x74,0x31,0xef,0x5a,0xab,0xa5,0x71,0x09,0x65,0xeb,0x69,0x59,0x02,0x31,0x5e,0x6e},
+ {0xfb,0x93,0xe5,0x87,0xf5,0x62,0x6c,0xb1,0x71,0x3e,0x5d,0xca,0xde,0xed,0x99,0x49,0x6d,0x3e,0xcc,0x14,0xe0,0xc1,0x91,0xb4,0xa8,0xdb,0xa8,0x89,0x47,0x11,0xf5,0x08,0x22,0x62,0x06,0x63,0x0e,0xfb,0x04,0x33,0x3f,0xba,0xac,0x87,0x89,0x06,0x35,0xfb,0xa3,0x61,0x10,0x8c,0x77,0x24,0x19,0xbd,0x20,0x86,0x83,0xd1,0x43,0xad,0x58,0x30,0xd0,0x63,0x76,0xe5,0xfd,0x0f,0x3c,0x32,0x10,0xa6,0x2e,0xa2,0x38,0xdf,0xc3,0x05,0x9a,0x4f,0x99,0xac,0xbd,0x8a,0xc7,0xbd,0x99,0xdc,0xe3,0xef,0xa4,0x9f,0x54,0x26},
+ {0xd6,0xf9,0x6b,0x1e,0x46,0x5a,0x1d,0x74,0x81,0xa5,0x77,0x77,0xfc,0xb3,0x05,0x23,0xd9,0xd3,0x74,0x64,0xa2,0x74,0x55,0xd4,0xff,0xe0,0x01,0x64,0xdc,0xe1,0x26,0x19,0x6e,0x66,0x3f,0xaf,0x49,0x85,0x46,0xdb,0xa5,0x0e,0x4a,0xf1,0x04,0xcf,0x7f,0xd7,0x47,0x0c,0xba,0xa4,0xf7,0x3f,0xf2,0x3d,0x85,0x3c,0xce,0x32,0xe1,0xdf,0x10,0x3a,0xa0,0xce,0x17,0xea,0x8a,0x4e,0x7f,0xe0,0xfd,0xc1,0x1f,0x3a,0x46,0x15,0xd5,0x2f,0xf1,0xc0,0xf2,0x31,0xfd,0x22,0x53,0x17,0x15,0x5d,0x1e,0x86,0x1d,0xd0,0xa1,0x1f},
+ {0x32,0x98,0x59,0x7d,0x94,0x55,0x80,0xcc,0x20,0x55,0xf1,0x37,0xda,0x56,0x46,0x1e,0x20,0x93,0x05,0x4e,0x74,0xf7,0xf6,0x99,0x33,0xcf,0x75,0x6a,0xbc,0x63,0x35,0x77,0xab,0x94,0xdf,0xd1,0x00,0xac,0xdc,0x38,0xe9,0x0d,0x08,0xd1,0xdd,0x2b,0x71,0x2e,0x62,0xe2,0xd5,0xfd,0x3e,0xe9,0x13,0x7f,0xe5,0x01,0x9a,0xee,0x18,0xed,0xfc,0x73,0xb3,0x9c,0x13,0x63,0x08,0xe9,0xb1,0x06,0xcd,0x3e,0xa0,0xc5,0x67,0xda,0x93,0xa4,0x32,0x89,0x63,0xad,0xc8,0xce,0x77,0x8d,0x44,0x4f,0x86,0x1b,0x70,0x6b,0x42,0x1f},
+ {0x01,0x1c,0x91,0x41,0x4c,0x26,0xc9,0xef,0x25,0x2c,0xa2,0x17,0xb8,0xb7,0xa3,0xf1,0x47,0x14,0x0f,0xf3,0x6b,0xda,0x75,0x58,0x90,0xb0,0x31,0x1d,0x27,0xf5,0x1a,0x4e,0x52,0x25,0xa1,0x91,0xc8,0x35,0x7e,0xf1,0x76,0x9c,0x5e,0x57,0x53,0x81,0x6b,0xb7,0x3e,0x72,0x9b,0x0d,0x6f,0x40,0x83,0xfa,0x38,0xe4,0xa7,0x3f,0x1b,0xbb,0x76,0x0b,0x9b,0x93,0x92,0x7f,0xf9,0xc1,0xb8,0x08,0x6e,0xab,0x44,0xd4,0xcb,0x71,0x67,0xbe,0x17,0x80,0xbb,0x99,0x63,0x64,0xe5,0x22,0x55,0xa9,0x72,0xb7,0x1e,0xd6,0x6d,0x7b},
+ {0x92,0x3d,0xf3,0x50,0xe8,0xc1,0xad,0xb7,0xcf,0xd5,0x8c,0x60,0x4f,0xfa,0x98,0x79,0xdb,0x5b,0xfc,0x8d,0xbd,0x2d,0x96,0xad,0x4f,0x2f,0x1d,0xaf,0xce,0x9b,0x3e,0x70,0xc7,0xd2,0x01,0xab,0xf9,0xab,0x30,0x57,0x18,0x3b,0x14,0x40,0xdc,0x76,0xfb,0x16,0x81,0xb2,0xcb,0xa0,0x65,0xbe,0x6c,0x86,0xfe,0x6a,0xff,0x9b,0x65,0x9b,0xfa,0x53,0x55,0x54,0x88,0x94,0xe9,0xc8,0x14,0x6c,0xe5,0xd4,0xae,0x65,0x66,0x5d,0x3a,0x84,0xf1,0x5a,0xd6,0xbc,0x3e,0xb7,0x1b,0x18,0x50,0x1f,0xc6,0xc4,0xe5,0x93,0x8d,0x39},
+ {0xf3,0x48,0xe2,0x33,0x67,0xd1,0x4b,0x1c,0x5f,0x0a,0xbf,0x15,0x87,0x12,0x9e,0xbd,0x76,0x03,0x0b,0xa1,0xf0,0x8c,0x3f,0xd4,0x13,0x1b,0x19,0xdf,0x5d,0x9b,0xb0,0x53,0xf2,0xe3,0xe7,0xd2,0x60,0x7c,0x87,0xc3,0xb1,0x8b,0x82,0x30,0xa0,0xaa,0x34,0x3b,0x38,0xf1,0x9e,0x73,0xe7,0x26,0x3e,0x28,0x77,0x05,0xc3,0x02,0x90,0x9c,0x9c,0x69,0xcc,0xf1,0x46,0x59,0x23,0xa7,0x06,0xf3,0x7d,0xd9,0xe5,0xcc,0xb5,0x18,0x17,0x92,0x75,0xe9,0xb4,0x81,0x47,0xd2,0xcd,0x28,0x07,0xd9,0xcd,0x6f,0x0c,0xf3,0xca,0x51},
+ {0x0a,0xe0,0x74,0x76,0x42,0xa7,0x0b,0xa6,0xf3,0x7b,0x7a,0xa1,0x70,0x85,0x0e,0x63,0xcc,0x24,0x33,0xcf,0x3d,0x56,0x58,0x37,0xaa,0xfd,0x83,0x23,0x29,0xaa,0x04,0x55,0xc7,0x54,0xac,0x18,0x9a,0xf9,0x7a,0x73,0x0f,0xb3,0x1c,0xc5,0xdc,0x78,0x33,0x90,0xc7,0x0c,0xe1,0x4c,0x33,0xbc,0x89,0x2b,0x9a,0xe9,0xf8,0x89,0xc1,0x29,0xae,0x12,0xcf,0x01,0x0d,0x1f,0xcb,0xc0,0x9e,0xa9,0xae,0xf7,0x34,0x3a,0xcc,0xef,0xd1,0x0d,0x22,0x4e,0x9c,0xd0,0x21,0x75,0xca,0x55,0xea,0xa5,0xeb,0x58,0xe9,0x4f,0xd1,0x5f},
+ {0x2c,0xab,0x45,0x28,0xdf,0x2d,0xdc,0xb5,0x93,0xe9,0x7f,0x0a,0xb1,0x91,0x94,0x06,0x46,0xe3,0x02,0x40,0xd6,0xf3,0xaa,0x4d,0xd1,0x74,0x64,0x58,0x6e,0xf2,0x3f,0x09,0x8e,0xcb,0x93,0xbf,0x5e,0xfe,0x42,0x3c,0x5f,0x56,0xd4,0x36,0x51,0xa8,0xdf,0xbe,0xe8,0x20,0x42,0x88,0x9e,0x85,0xf0,0xe0,0x28,0xd1,0x25,0x07,0x96,0x3f,0xd7,0x7d,0x29,0x98,0x05,0x68,0xfe,0x24,0x0d,0xb1,0xe5,0x23,0xaf,0xdb,0x72,0x06,0x73,0x75,0x29,0xac,0x57,0xb4,0x3a,0x25,0x67,0x13,0xa4,0x70,0xb4,0x86,0xbc,0xbc,0x59,0x2f},
+ {0x5f,0x13,0x17,0x99,0x42,0x7d,0x84,0x83,0xd7,0x03,0x7d,0x56,0x1f,0x91,0x1b,0xad,0xd1,0xaa,0x77,0xbe,0xd9,0x48,0x77,0x7e,0x4a,0xaf,0x51,0x2e,0x2e,0xb4,0x58,0x54,0x01,0xc3,0x91,0xb6,0x60,0xd5,0x41,0x70,0x1e,0xe7,0xd7,0xad,0x3f,0x1b,0x20,0x85,0x85,0x55,0x33,0x11,0x63,0xe1,0xc2,0x16,0xb1,0x28,0x08,0x01,0x3d,0x5e,0xa5,0x2a,0x4f,0x44,0x07,0x0c,0xe6,0x92,0x51,0xed,0x10,0x1d,0x42,0x74,0x2d,0x4e,0xc5,0x42,0x64,0xc8,0xb5,0xfd,0x82,0x4c,0x2b,0x35,0x64,0x86,0x76,0x8a,0x4a,0x00,0xe9,0x13},
+ {0xdb,0xce,0x2f,0x83,0x45,0x88,0x9d,0x73,0x63,0xf8,0x6b,0xae,0xc9,0xd6,0x38,0xfa,0xf7,0xfe,0x4f,0xb7,0xca,0x0d,0xbc,0x32,0x5e,0xe4,0xbc,0x14,0x88,0x7e,0x93,0x73,0x7f,0x87,0x3b,0x19,0xc9,0x00,0x2e,0xbb,0x6b,0x50,0xdc,0xe0,0x90,0xa8,0xe3,0xec,0x9f,0x64,0xde,0x36,0xc0,0xb7,0xf3,0xec,0x1a,0x9e,0xde,0x98,0x08,0x04,0x46,0x5f,0x8d,0xf4,0x7b,0x29,0x16,0x71,0x03,0xb9,0x34,0x68,0xf0,0xd4,0x22,0x3b,0xd1,0xa9,0xc6,0xbd,0x96,0x46,0x57,0x15,0x97,0xe1,0x35,0xe8,0xd5,0x91,0xe8,0xa4,0xf8,0x2c},
+ {0x67,0x0f,0x11,0x07,0x87,0xfd,0x93,0x6d,0x49,0xb5,0x38,0x7c,0xd3,0x09,0x4c,0xdd,0x86,0x6a,0x73,0xc2,0x4c,0x6a,0xb1,0x7c,0x09,0x2a,0x25,0x58,0x6e,0xbd,0x49,0x20,0xa2,0x6b,0xd0,0x17,0x7e,0x48,0xb5,0x2c,0x6b,0x19,0x50,0x39,0x1c,0x38,0xd2,0x24,0x30,0x8a,0x97,0x85,0x81,0x9c,0x65,0xd7,0xf6,0xa4,0xd6,0x91,0x28,0x7f,0x6f,0x7a,0x49,0xef,0x9a,0x6a,0x8d,0xfd,0x09,0x7d,0x0b,0xb9,0x3d,0x5b,0xbe,0x60,0xee,0xf0,0xd4,0xbf,0x9e,0x51,0x2c,0xb5,0x21,0x4c,0x1d,0x94,0x45,0xc5,0xdf,0xaa,0x11,0x60},
+ {0x3c,0xf8,0x95,0xcf,0x6d,0x92,0x67,0x5f,0x71,0x90,0x28,0x71,0x61,0x85,0x7e,0x7c,0x5b,0x7a,0x8f,0x99,0xf3,0xe7,0xa1,0xd6,0xe0,0xf9,0x62,0x0b,0x1b,0xcc,0xc5,0x6f,0x90,0xf8,0xcb,0x02,0xc8,0xd0,0xde,0x63,0xaa,0x6a,0xff,0x0d,0xca,0x98,0xd0,0xfb,0x99,0xed,0xb6,0xb9,0xfd,0x0a,0x4d,0x62,0x1e,0x0b,0x34,0x79,0xb7,0x18,0xce,0x69,0xcb,0x79,0x98,0xb2,0x28,0x55,0xef,0xd1,0x92,0x90,0x7e,0xd4,0x3c,0xae,0x1a,0xdd,0x52,0x23,0x9f,0x18,0x42,0x04,0x7e,0x12,0xf1,0x01,0x71,0xe5,0x3a,0x6b,0x59,0x15},
+ {0xa2,0x79,0x91,0x3f,0xd2,0x39,0x27,0x46,0xcf,0xdd,0xd6,0x97,0x31,0x12,0x83,0xff,0x8a,0x14,0xf2,0x53,0xb5,0xde,0x07,0x13,0xda,0x4d,0x5f,0x7b,0x68,0x37,0x22,0x0d,0xca,0x24,0x51,0x7e,0x16,0x31,0xff,0x09,0xdf,0x45,0xc7,0xd9,0x8b,0x15,0xe4,0x0b,0xe5,0x56,0xf5,0x7e,0x22,0x7d,0x2b,0x29,0x38,0xd1,0xb6,0xaf,0x41,0xe2,0xa4,0x3a,0xf5,0x05,0x33,0x2a,0xbf,0x38,0xc1,0x2c,0xc3,0x26,0xe9,0xa2,0x8f,0x3f,0x58,0x48,0xeb,0xd2,0x49,0x55,0xa2,0xb1,0x3a,0x08,0x6c,0xa3,0x87,0x46,0x6e,0xaa,0xfc,0x32},
+ {0xf5,0x9a,0x7d,0xc5,0x8d,0x6e,0xc5,0x7b,0xf2,0xbd,0xf0,0x9d,0xed,0xd2,0x0b,0x3e,0xa3,0xe4,0xef,0x22,0xde,0x14,0xc0,0xaa,0x5c,0x6a,0xbd,0xfe,0xce,0xe9,0x27,0x46,0xdf,0xcc,0x87,0x27,0x73,0xa4,0x07,0x32,0xf8,0xe3,0x13,0xf2,0x08,0x19,0xe3,0x17,0x4e,0x96,0x0d,0xf6,0xd7,0xec,0xb2,0xd5,0xe9,0x0b,0x60,0xc2,0x36,0x63,0x6f,0x74,0x1c,0x97,0x6c,0xab,0x45,0xf3,0x4a,0x3f,0x1f,0x73,0x43,0x99,0x72,0xeb,0x88,0xe2,0x6d,0x18,0x44,0x03,0x8a,0x6a,0x59,0x33,0x93,0x62,0xd6,0x7e,0x00,0x17,0x49,0x7b},
+ {0x64,0xb0,0x84,0xab,0x5c,0xfb,0x85,0x2d,0x14,0xbc,0xf3,0x89,0xd2,0x10,0x78,0x49,0x0c,0xce,0x15,0x7b,0x44,0xdc,0x6a,0x47,0x7b,0xfd,0x44,0xf8,0x76,0xa3,0x2b,0x12,0xdd,0xa2,0x53,0xdd,0x28,0x1b,0x34,0x54,0x3f,0xfc,0x42,0xdf,0x5b,0x90,0x17,0xaa,0xf4,0xf8,0xd2,0x4d,0xd9,0x92,0xf5,0x0f,0x7d,0xd3,0x8c,0xe0,0x0f,0x62,0x03,0x1d,0x54,0xe5,0xb4,0xa2,0xcd,0x32,0x02,0xc2,0x7f,0x18,0x5d,0x11,0x42,0xfd,0xd0,0x9e,0xd9,0x79,0xd4,0x7d,0xbe,0xb4,0xab,0x2e,0x4c,0xec,0x68,0x2b,0xf5,0x0b,0xc7,0x02},
+ {0xbb,0x2f,0x0b,0x5d,0x4b,0xec,0x87,0xa2,0xca,0x82,0x48,0x07,0x90,0x57,0x5c,0x41,0x5c,0x81,0xd0,0xc1,0x1e,0xa6,0x44,0xe0,0xe0,0xf5,0x9e,0x40,0x0a,0x4f,0x33,0x26,0xe1,0x72,0x8d,0x45,0xbf,0x32,0xe5,0xac,0xb5,0x3c,0xb7,0x7c,0xe0,0x68,0xe7,0x5b,0xe7,0xbd,0x8b,0xee,0x94,0x7d,0xcf,0x56,0x03,0x3a,0xb4,0xfe,0xe3,0x97,0x06,0x6b,0xc0,0xa3,0x62,0xdf,0x4a,0xf0,0xc8,0xb6,0x5d,0xa4,0x6d,0x07,0xef,0x00,0xf0,0x3e,0xa9,0xd2,0xf0,0x49,0x58,0xb9,0x9c,0x9c,0xae,0x2f,0x1b,0x44,0x43,0x7f,0xc3,0x1c},
+ {0x4f,0x32,0xc7,0x5c,0x5a,0x56,0x8f,0x50,0x22,0xa9,0x06,0xe5,0xc0,0xc4,0x61,0xd0,0x19,0xac,0x45,0x5c,0xdb,0xab,0x18,0xfb,0x4a,0x31,0x80,0x03,0xc1,0x09,0x68,0x6c,0xb9,0xae,0xce,0xc9,0xf1,0x56,0x66,0xd7,0x6a,0x65,0xe5,0x18,0xf8,0x15,0x5b,0x1c,0x34,0x23,0x4c,0x84,0x32,0x28,0xe7,0x26,0x38,0x68,0x19,0x2f,0x77,0x6f,0x34,0x3a,0xc8,0x6a,0xda,0xe2,0x12,0x51,0xd5,0xd2,0xed,0x51,0xe8,0xb1,0x31,0x03,0xbd,0xe9,0x62,0x72,0xc6,0x8e,0xdd,0x46,0x07,0x96,0xd0,0xc5,0xf7,0x6e,0x9f,0x1b,0x91,0x05},
+ {0xbb,0x0e,0xdf,0xf5,0x83,0x99,0x33,0xc1,0xac,0x4c,0x2c,0x51,0x8f,0x75,0xf3,0xc0,0xe1,0x98,0xb3,0x0b,0x0a,0x13,0xf1,0x2c,0x62,0x0c,0x27,0xaa,0xf9,0xec,0x3c,0x6b,0xef,0xea,0x2e,0x51,0xf3,0xac,0x49,0x53,0x49,0xcb,0xc1,0x1c,0xd3,0x41,0xc1,0x20,0x8d,0x68,0x9a,0xa9,0x07,0x0c,0x18,0x24,0x17,0x2d,0x4b,0xc6,0xd1,0xf9,0x5e,0x55,0x08,0xbd,0x73,0x3b,0xba,0x70,0xa7,0x36,0x0c,0xbf,0xaf,0xa3,0x08,0xef,0x4a,0x62,0xf2,0x46,0x09,0xb4,0x98,0xff,0x37,0x57,0x9d,0x74,0x81,0x33,0xe1,0x4d,0x5f,0x67},
+ {0xfc,0x82,0x17,0x6b,0x03,0x52,0x2c,0x0e,0xb4,0x83,0xad,0x6c,0x81,0x6c,0x81,0x64,0x3e,0x07,0x64,0x69,0xd9,0xbd,0xdc,0xd0,0x20,0xc5,0x64,0x01,0xf7,0x9d,0xd9,0x13,0x1d,0xb3,0xda,0x3b,0xd9,0xf6,0x2f,0xa1,0xfe,0x2d,0x65,0x9d,0x0f,0xd8,0x25,0x07,0x87,0x94,0xbe,0x9a,0xf3,0x4f,0x9c,0x01,0x43,0x3c,0xcd,0x82,0xb8,0x50,0xf4,0x60,0xca,0xc0,0xe5,0x21,0xc3,0x5e,0x4b,0x01,0xa2,0xbf,0x19,0xd7,0xc9,0x69,0xcb,0x4f,0xa0,0x23,0x00,0x75,0x18,0x1c,0x5f,0x4e,0x80,0xac,0xed,0x55,0x9e,0xde,0x06,0x1c},
+ {0xe2,0xc4,0x3e,0xa3,0xd6,0x7a,0x0f,0x99,0x8e,0xe0,0x2e,0xbe,0x38,0xf9,0x08,0x66,0x15,0x45,0x28,0x63,0xc5,0x43,0xa1,0x9c,0x0d,0xb6,0x2d,0xec,0x1f,0x8a,0xf3,0x4c,0xaa,0x69,0x6d,0xff,0x40,0x2b,0xd5,0xff,0xbb,0x49,0x40,0xdc,0x18,0x0b,0x53,0x34,0x97,0x98,0x4d,0xa3,0x2f,0x5c,0x4a,0x5e,0x2d,0xba,0x32,0x7d,0x8e,0x6f,0x09,0x78,0xe7,0x5c,0xfa,0x0d,0x65,0xaa,0xaa,0xa0,0x8c,0x47,0xb5,0x48,0x2a,0x9e,0xc4,0xf9,0x5b,0x72,0x03,0x70,0x7d,0xcc,0x09,0x4f,0xbe,0x1a,0x09,0x26,0x3a,0xad,0x3c,0x37},
+ {0x7c,0xf5,0xc9,0x82,0x4d,0x63,0x94,0xb2,0x36,0x45,0x93,0x24,0xe1,0xfd,0xcb,0x1f,0x5a,0xdb,0x8c,0x41,0xb3,0x4d,0x9c,0x9e,0xfc,0x19,0x44,0x45,0xd9,0xf3,0x40,0x00,0xad,0xbb,0xdd,0x89,0xfb,0xa8,0xbe,0xf1,0xcb,0xae,0xae,0x61,0xbc,0x2c,0xcb,0x3b,0x9d,0x8d,0x9b,0x1f,0xbb,0xa7,0x58,0x8f,0x86,0xa6,0x12,0x51,0xda,0x7e,0x54,0x21,0xd3,0x86,0x59,0xfd,0x39,0xe9,0xfd,0xde,0x0c,0x38,0x0a,0x51,0x89,0x2c,0x27,0xf4,0xb9,0x19,0x31,0xbb,0x07,0xa4,0x2b,0xb7,0xf4,0x4d,0x25,0x4a,0x33,0x0a,0x55,0x63},
+ {0x37,0xcf,0x69,0xb5,0xed,0xd6,0x07,0x65,0xe1,0x2e,0xa5,0x0c,0xb0,0x29,0x84,0x17,0x5d,0xd6,0x6b,0xeb,0x90,0x00,0x7c,0xea,0x51,0x8f,0xf7,0xda,0xc7,0x62,0xea,0x3e,0x49,0x7b,0x54,0x72,0x45,0x58,0xba,0x9b,0xe0,0x08,0xc4,0xe2,0xfa,0xc6,0x05,0xf3,0x8d,0xf1,0x34,0xc7,0x69,0xfa,0xe8,0x60,0x7a,0x76,0x7d,0xaa,0xaf,0x2b,0xa9,0x39,0x4e,0x27,0x93,0xe6,0x13,0xc7,0x24,0x9d,0x75,0xd3,0xdb,0x68,0x77,0x85,0x63,0x5f,0x9a,0xb3,0x8a,0xeb,0x60,0x55,0x52,0x70,0xcd,0xc4,0xc9,0x65,0x06,0x6a,0x43,0x68},
+ {0x27,0x3f,0x2f,0x20,0xe8,0x35,0x02,0xbc,0xb0,0x75,0xf9,0x64,0xe2,0x00,0x5c,0xc7,0x16,0x24,0x8c,0xa3,0xd5,0xe9,0xa4,0x91,0xf9,0x89,0xb7,0x8a,0xf6,0xe7,0xb6,0x17,0x7c,0x10,0x20,0xe8,0x17,0xd3,0x56,0x1e,0x65,0xe9,0x0a,0x84,0x44,0x68,0x26,0xc5,0x7a,0xfc,0x0f,0x32,0xc6,0xa1,0xe0,0xc1,0x72,0x14,0x61,0x91,0x9c,0x66,0x73,0x53,0x57,0x52,0x0e,0x9a,0xab,0x14,0x28,0x5d,0xfc,0xb3,0xca,0xc9,0x84,0x20,0x8f,0x90,0xca,0x1e,0x2d,0x5b,0x88,0xf5,0xca,0xaf,0x11,0x7d,0xf8,0x78,0xa6,0xb5,0xb4,0x1c},
+ {0x6c,0xfc,0x4a,0x39,0x6b,0xc0,0x64,0xb6,0xb1,0x5f,0xda,0x98,0x24,0xde,0x88,0x0c,0x34,0xd8,0xca,0x4b,0x16,0x03,0x8d,0x4f,0xa2,0x34,0x74,0xde,0x78,0xca,0x0b,0x33,0xe7,0x07,0xa0,0xa2,0x62,0xaa,0x74,0x6b,0xb1,0xc7,0x71,0xf0,0xb0,0xe0,0x11,0xf3,0x23,0xe2,0x0b,0x00,0x38,0xe4,0x07,0x57,0xac,0x6e,0xef,0x82,0x2d,0xfd,0xc0,0x2d,0x4e,0x74,0x19,0x11,0x84,0xff,0x2e,0x98,0x24,0x47,0x07,0x2b,0x96,0x5e,0x69,0xf9,0xfb,0x53,0xc9,0xbf,0x4f,0xc1,0x8a,0xc5,0xf5,0x1c,0x9f,0x36,0x1b,0xbe,0x31,0x3c},
+ {0xee,0x8a,0x94,0x08,0x4d,0x86,0xf4,0xb0,0x6f,0x1c,0xba,0x91,0xee,0x19,0xdc,0x07,0x58,0xa1,0xac,0xa6,0xae,0xcd,0x75,0x79,0xbb,0xd4,0x62,0x42,0x13,0x61,0x0b,0x33,0x72,0x42,0xcb,0xf9,0x93,0xbc,0x68,0xc1,0x98,0xdb,0xce,0xc7,0x1f,0x71,0xb8,0xae,0x7a,0x8d,0xac,0x34,0xaa,0x52,0x0e,0x7f,0xbb,0x55,0x7d,0x7e,0x09,0xc1,0xce,0x41,0x8a,0x80,0x6d,0xa2,0xd7,0x19,0x96,0xf7,0x6d,0x15,0x9e,0x1d,0x9e,0xd4,0x1f,0xbb,0x27,0xdf,0xa1,0xdb,0x6c,0xc3,0xd7,0x73,0x7d,0x77,0x28,0x1f,0xd9,0x4c,0xb4,0x26},
+ {0x75,0x74,0x38,0x8f,0x47,0x48,0xf0,0x51,0x3c,0xcb,0xbe,0x9c,0xf4,0xbc,0x5d,0xb2,0x55,0x20,0x9f,0xd9,0x44,0x12,0xab,0x9a,0xd6,0xa5,0x10,0x1c,0x6c,0x9e,0x70,0x2c,0x83,0x03,0x73,0x62,0x93,0xf2,0xb7,0xe1,0x2c,0x8a,0xca,0xeb,0xff,0x79,0x52,0x4b,0x14,0x13,0xd4,0xbf,0x8a,0x77,0xfc,0xda,0x0f,0x61,0x72,0x9c,0x14,0x10,0xeb,0x7d,0x7a,0xee,0x66,0x87,0x6a,0xaf,0x62,0xcb,0x0e,0xcd,0x53,0x55,0x04,0xec,0xcb,0x66,0xb5,0xe4,0x0b,0x0f,0x38,0x01,0x80,0x58,0xea,0xe2,0x2c,0xf6,0x9f,0x8e,0xe6,0x08},
+ {0xad,0x30,0xc1,0x4b,0x0a,0x50,0xad,0x34,0x9c,0xd4,0x0b,0x3d,0x49,0xdb,0x38,0x8d,0xbe,0x89,0x0a,0x50,0x98,0x3d,0x5c,0xa2,0x09,0x3b,0xba,0xee,0x87,0x3f,0x1f,0x2f,0xf9,0xf2,0xb8,0x0a,0xd5,0x09,0x2d,0x2f,0xdf,0x23,0x59,0xc5,0x8d,0x21,0xb9,0xac,0xb9,0x6c,0x76,0x73,0x26,0x34,0x8f,0x4a,0xf5,0x19,0xf7,0x38,0xd7,0x3b,0xb1,0x4c,0x4a,0xb6,0x15,0xe5,0x75,0x8c,0x84,0xf7,0x38,0x90,0x4a,0xdb,0xba,0x01,0x95,0xa5,0x50,0x1b,0x75,0x3f,0x3f,0x31,0x0d,0xc2,0xe8,0x2e,0xae,0xc0,0x53,0xe3,0xa1,0x19},
+ {0xc3,0x05,0xfa,0xba,0x60,0x75,0x1c,0x7d,0x61,0x5e,0xe5,0xc6,0xa0,0xa0,0xe1,0xb3,0x73,0x64,0xd6,0xc0,0x18,0x97,0x52,0xe3,0x86,0x34,0x0c,0xc2,0x11,0x6b,0x54,0x41,0xbd,0xbd,0x96,0xd5,0xcd,0x72,0x21,0xb4,0x40,0xfc,0xee,0x98,0x43,0x45,0xe0,0x93,0xb5,0x09,0x41,0xb4,0x47,0x53,0xb1,0x9f,0x34,0xae,0x66,0x02,0x99,0xd3,0x6b,0x73,0xb4,0xb3,0x34,0x93,0x50,0x2d,0x53,0x85,0x73,0x65,0x81,0x60,0x4b,0x11,0xfd,0x46,0x75,0x83,0x5c,0x42,0x30,0x5f,0x5f,0xcc,0x5c,0xab,0x7f,0xb8,0xa2,0x95,0x22,0x41},
+ {0xe9,0xd6,0x7e,0xf5,0x88,0x9b,0xc9,0x19,0x25,0xc8,0xf8,0x6d,0x26,0xcb,0x93,0x53,0x73,0xd2,0x0a,0xb3,0x13,0x32,0xee,0x5c,0x34,0x2e,0x2d,0xb5,0xeb,0x53,0xe1,0x14,0xc6,0xea,0x93,0xe2,0x61,0x52,0x65,0x2e,0xdb,0xac,0x33,0x21,0x03,0x92,0x5a,0x84,0x6b,0x99,0x00,0x79,0xcb,0x75,0x09,0x46,0x80,0xdd,0x5a,0x19,0x8d,0xbb,0x60,0x07,0x8a,0x81,0xe6,0xcd,0x17,0x1a,0x3e,0x41,0x84,0xa0,0x69,0xed,0xa9,0x6d,0x15,0x57,0xb1,0xcc,0xca,0x46,0x8f,0x26,0xbf,0x2c,0xf2,0xc5,0x3a,0xc3,0x9b,0xbe,0x34,0x6b},
+ {0xb2,0xc0,0x78,0x3a,0x64,0x2f,0xdf,0xf3,0x7c,0x02,0x2e,0xf2,0x1e,0x97,0x3e,0x4c,0xa3,0xb5,0xc1,0x49,0x5e,0x1c,0x7d,0xec,0x2d,0xdd,0x22,0x09,0x8f,0xc1,0x12,0x20,0xd3,0xf2,0x71,0x65,0x65,0x69,0xfc,0x11,0x7a,0x73,0x0e,0x53,0x45,0xe8,0xc9,0xc6,0x35,0x50,0xfe,0xd4,0xa2,0xe7,0x3a,0xe3,0x0b,0xd3,0x6d,0x2e,0xb6,0xc7,0xb9,0x01,0x29,0x9d,0xc8,0x5a,0xe5,0x55,0x0b,0x88,0x63,0xa7,0xa0,0x45,0x1f,0x24,0x83,0x14,0x1f,0x6c,0xe7,0xc2,0xdf,0xef,0x36,0x3d,0xe8,0xad,0x4b,0x4e,0x78,0x5b,0xaf,0x08},
+ {0x33,0x25,0x1f,0x88,0xdc,0x99,0x34,0x28,0xb6,0x23,0x93,0x77,0xda,0x25,0x05,0x9d,0xf4,0x41,0x34,0x67,0xfb,0xdd,0x7a,0x89,0x8d,0x16,0x3a,0x16,0x71,0x9d,0xb7,0x32,0x4b,0x2c,0xcc,0x89,0xd2,0x14,0x73,0xe2,0x8d,0x17,0x87,0xa2,0x11,0xbd,0xe4,0x4b,0xce,0x64,0x33,0xfa,0xd6,0x28,0xd5,0x18,0x6e,0x82,0xd9,0xaf,0xd5,0xc1,0x23,0x64,0x6a,0xb3,0xfc,0xed,0xd9,0xf8,0x85,0xcc,0xf9,0xe5,0x46,0x37,0x8f,0xc2,0xbc,0x22,0xcd,0xd3,0xe5,0xf9,0x38,0xe3,0x9d,0xe4,0xcc,0x2d,0x3e,0xc1,0xfb,0x5e,0x0a,0x48},
+ {0x71,0x20,0x62,0x01,0x0b,0xe7,0x51,0x0b,0xc5,0xaf,0x1d,0x8b,0xcf,0x05,0xb5,0x06,0xcd,0xab,0x5a,0xef,0x61,0xb0,0x6b,0x2c,0x31,0xbf,0xb7,0x0c,0x60,0x27,0xaa,0x47,0x1f,0x22,0xce,0x42,0xe4,0x4c,0x61,0xb6,0x28,0x39,0x05,0x4c,0xcc,0x9d,0x19,0x6e,0x03,0xbe,0x1c,0xdc,0xa4,0xb4,0x3f,0x66,0x06,0x8e,0x1c,0x69,0x47,0x1d,0xb3,0x24,0xc3,0xf8,0x15,0xc0,0xed,0x1e,0x54,0x2a,0x7c,0x3f,0x69,0x7c,0x7e,0xfe,0xa4,0x11,0xd6,0x78,0xa2,0x4e,0x13,0x66,0xaf,0xf0,0x94,0xa0,0xdd,0x14,0x5d,0x58,0x5b,0x54},
+ {0x0f,0x3a,0xd4,0xa0,0x5e,0x27,0xbf,0x67,0xbe,0xee,0x9b,0x08,0x34,0x8e,0xe6,0xad,0x2e,0xe7,0x79,0xd4,0x4c,0x13,0x89,0x42,0x54,0x54,0xba,0x32,0xc3,0xf9,0x62,0x0f,0xe1,0x21,0xb3,0xe3,0xd0,0xe4,0x04,0x62,0x95,0x1e,0xff,0x28,0x7a,0x63,0xaa,0x3b,0x9e,0xbd,0x99,0x5b,0xfd,0xcf,0x0c,0x0b,0x71,0xd0,0xc8,0x64,0x3e,0xdc,0x22,0x4d,0x39,0x5f,0x3b,0xd6,0x89,0x65,0xb4,0xfc,0x61,0xcf,0xcb,0x57,0x3f,0x6a,0xae,0x5c,0x05,0xfa,0x3a,0x95,0xd2,0xc2,0xba,0xfe,0x36,0x14,0x37,0x36,0x1a,0xa0,0x0f,0x1c},
+ {0xff,0x3d,0x94,0x22,0xb6,0x04,0xc6,0xd2,0xa0,0xb3,0xcf,0x44,0xce,0xbe,0x8c,0xbc,0x78,0x86,0x80,0x97,0xf3,0x4f,0x25,0x5d,0xbf,0xa6,0x1c,0x3b,0x4f,0x61,0xa3,0x0f,0x50,0x6a,0x93,0x8c,0x0e,0x2b,0x08,0x69,0xb6,0xc5,0xda,0xc1,0x35,0xa0,0xc9,0xf9,0x34,0xb6,0xdf,0xc4,0x54,0x3e,0xb7,0x6f,0x40,0xc1,0x2b,0x1d,0x9b,0x41,0x05,0x40,0xf0,0x82,0xbe,0xb9,0xbd,0xfe,0x03,0xa0,0x90,0xac,0x44,0x3a,0xaf,0xc1,0x89,0x20,0x8e,0xfa,0x54,0x19,0x91,0x9f,0x49,0xf8,0x42,0xab,0x40,0xef,0x8a,0x21,0xba,0x1f},
+ {0x3e,0xf5,0xc8,0xfa,0x48,0x94,0x54,0xab,0x41,0x37,0xa6,0x7b,0x9a,0xe8,0xf6,0x81,0x01,0x5e,0x2b,0x6c,0x7d,0x6c,0xfd,0x74,0x42,0x6e,0xc8,0xa8,0xca,0x3a,0x2e,0x39,0x94,0x01,0x7b,0x3e,0x04,0x57,0x3e,0x4f,0x7f,0xaf,0xda,0x08,0xee,0x3e,0x1d,0xa8,0xf1,0xde,0xdc,0x99,0xab,0xc6,0x39,0xc8,0xd5,0x61,0x77,0xff,0x13,0x5d,0x53,0x6c,0xaf,0x35,0x8a,0x3e,0xe9,0x34,0xbd,0x4c,0x16,0xe8,0x87,0x58,0x44,0x81,0x07,0x2e,0xab,0xb0,0x9a,0xf2,0x76,0x9c,0x31,0x19,0x3b,0xc1,0x0a,0xd5,0xe4,0x7f,0xe1,0x25},
+ {0x76,0xf6,0x04,0x1e,0xd7,0x9b,0x28,0x0a,0x95,0x0f,0x42,0xd6,0x52,0x1c,0x8e,0x20,0xab,0x1f,0x69,0x34,0xb0,0xd8,0x86,0x51,0x51,0xb3,0x9f,0x2a,0x44,0x51,0x57,0x25,0xa7,0x21,0xf1,0x76,0xf5,0x7f,0x5f,0x91,0xe3,0x87,0xcd,0x2f,0x27,0x32,0x4a,0xc3,0x26,0xe5,0x1b,0x4d,0xde,0x2f,0xba,0xcc,0x9b,0x89,0x69,0x89,0x8f,0x82,0xba,0x6b,0x01,0x39,0xfe,0x90,0x66,0xbc,0xd1,0xe2,0xd5,0x7a,0x99,0xa0,0x18,0x4a,0xb5,0x4c,0xd4,0x60,0x84,0xaf,0x14,0x69,0x1d,0x97,0xe4,0x7b,0x6b,0x7f,0x4f,0x50,0x9d,0x55},
+ {0xd5,0x54,0xeb,0xb3,0x78,0x83,0x73,0xa7,0x7c,0x3c,0x55,0xa5,0x66,0xd3,0x69,0x1d,0xba,0x00,0x28,0xf9,0x62,0xcf,0x26,0x0a,0x17,0x32,0x7e,0x80,0xd5,0x12,0xab,0x01,0xfd,0x66,0xd2,0xf6,0xe7,0x91,0x48,0x9c,0x1b,0x78,0x07,0x03,0x9b,0xa1,0x44,0x07,0x3b,0xe2,0x61,0x60,0x1d,0x8f,0x38,0x88,0x0e,0xd5,0x4b,0x35,0xa3,0xa6,0x3e,0x12,0x96,0x2d,0xe3,0x41,0x90,0x18,0x8d,0x11,0x48,0x58,0x31,0xd8,0xc2,0xe3,0xed,0xb9,0xd9,0x45,0x32,0xd8,0x71,0x42,0xab,0x1e,0x54,0xa1,0x18,0xc9,0xe2,0x61,0x39,0x4a},
+ {0xa0,0xbb,0xe6,0xf8,0xe0,0x3b,0xdc,0x71,0x0a,0xe3,0xff,0x7e,0x34,0xf8,0xce,0xd6,0x6a,0x47,0x3a,0xe1,0x5f,0x42,0x92,0xa9,0x63,0xb7,0x1d,0xfb,0xe3,0xbc,0xd6,0x2c,0x1e,0x3f,0x23,0xf3,0x44,0xd6,0x27,0x03,0x16,0xf0,0xfc,0x34,0x0e,0x26,0x9a,0x49,0x79,0xb9,0xda,0xf2,0x16,0xa7,0xb5,0x83,0x1f,0x11,0xd4,0x9b,0xad,0xee,0xac,0x68,0x10,0xc2,0xd7,0xf3,0x0e,0xc9,0xb4,0x38,0x0c,0x04,0xad,0xb7,0x24,0x6e,0x8e,0x30,0x23,0x3e,0xe7,0xb7,0xf1,0xd9,0x60,0x38,0x97,0xf5,0x08,0xb5,0xd5,0x60,0x57,0x59},
+ {0x97,0x63,0xaa,0x04,0xe1,0xbf,0x29,0x61,0xcb,0xfc,0xa7,0xa4,0x08,0x00,0x96,0x8f,0x58,0x94,0x90,0x7d,0x89,0xc0,0x8b,0x3f,0xa9,0x91,0xb2,0xdc,0x3e,0xa4,0x9f,0x70,0x90,0x27,0x02,0xfd,0xeb,0xcb,0x2a,0x88,0x60,0x57,0x11,0xc4,0x05,0x33,0xaf,0x89,0xf4,0x73,0x34,0x7d,0xe3,0x92,0xf4,0x65,0x2b,0x5a,0x51,0x54,0xdf,0xc5,0xb2,0x2c,0xca,0x2a,0xfd,0x63,0x8c,0x5d,0x0a,0xeb,0xff,0x4e,0x69,0x2e,0x66,0xc1,0x2b,0xd2,0x3a,0xb0,0xcb,0xf8,0x6e,0xf3,0x23,0x27,0x1f,0x13,0xc8,0xf0,0xec,0x29,0xf0,0x70},
+ {0x33,0x3e,0xed,0x2e,0xb3,0x07,0x13,0x46,0xe7,0x81,0x55,0xa4,0x33,0x2f,0x04,0xae,0x66,0x03,0x5f,0x19,0xd3,0x49,0x44,0xc9,0x58,0x48,0x31,0x6c,0x8a,0x5d,0x7d,0x0b,0xb9,0xb0,0x10,0x5e,0xaa,0xaf,0x6a,0x2a,0xa9,0x1a,0x04,0xef,0x70,0xa3,0xf0,0x78,0x1f,0xd6,0x3a,0xaa,0x77,0xfb,0x3e,0x77,0xe1,0xd9,0x4b,0xa7,0xa2,0xa5,0xec,0x44,0x43,0xd5,0x95,0x7b,0x32,0x48,0xd4,0x25,0x1d,0x0f,0x34,0xa3,0x00,0x83,0xd3,0x70,0x2b,0xc5,0xe1,0x60,0x1c,0x53,0x1c,0xde,0xe4,0xe9,0x7d,0x2c,0x51,0x24,0x22,0x27},
+ {0x2e,0x34,0xc5,0x49,0xaf,0x92,0xbc,0x1a,0xd0,0xfa,0xe6,0xb2,0x11,0xd8,0xee,0xff,0x29,0x4e,0xc8,0xfc,0x8d,0x8c,0xa2,0xef,0x43,0xc5,0x4c,0xa4,0x18,0xdf,0xb5,0x11,0xfc,0x75,0xa9,0x42,0x8a,0xbb,0x7b,0xbf,0x58,0xa3,0xad,0x96,0x77,0x39,0x5c,0x8c,0x48,0xaa,0xed,0xcd,0x6f,0xc7,0x7f,0xe2,0xa6,0x20,0xbc,0xf6,0xd7,0x5f,0x73,0x19,0x66,0x42,0xc8,0x42,0xd0,0x90,0xab,0xe3,0x7e,0x54,0x19,0x7f,0x0f,0x8e,0x84,0xeb,0xb9,0x97,0xa4,0x65,0xd0,0xa1,0x03,0x25,0x5f,0x89,0xdf,0x91,0x11,0x91,0xef,0x0f}
+};
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/ed25519-donna/ed25519-donna-batchverify.h b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/ed25519-donna/ed25519-donna-batchverify.h
new file mode 100644
index 0000000..43c4923
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/ed25519-donna/ed25519-donna-batchverify.h
@@ -0,0 +1,275 @@
+/*
+ Ed25519 batch verification
+*/
+
+#define max_batch_size 64
+#define heap_batch_size ((max_batch_size * 2) + 1)
+
+/* which limb is the 128th bit in? */
+static const size_t limb128bits = (128 + bignum256modm_bits_per_limb - 1) / bignum256modm_bits_per_limb;
+
+typedef size_t heap_index_t;
+
+typedef struct batch_heap_t {
+ unsigned char r[heap_batch_size][16]; /* 128 bit random values */
+ ge25519 points[heap_batch_size];
+ bignum256modm scalars[heap_batch_size];
+ heap_index_t heap[heap_batch_size];
+ size_t size;
+} batch_heap;
+
+/* swap two values in the heap */
+static void
+heap_swap(heap_index_t *heap, size_t a, size_t b) {
+ heap_index_t temp;
+ temp = heap[a];
+ heap[a] = heap[b];
+ heap[b] = temp;
+}
+
+/* add the scalar at the end of the list to the heap */
+static void
+heap_insert_next(batch_heap *heap) {
+ size_t node = heap->size, parent;
+ heap_index_t *pheap = heap->heap;
+ bignum256modm *scalars = heap->scalars;
+
+ /* insert at the bottom */
+ pheap[node] = (heap_index_t)node;
+
+ /* sift node up to its sorted spot */
+ parent = (node - 1) / 2;
+ while (node && lt256_modm_batch(scalars[pheap[parent]], scalars[pheap[node]], bignum256modm_limb_size - 1)) {
+ heap_swap(pheap, parent, node);
+ node = parent;
+ parent = (node - 1) / 2;
+ }
+ heap->size++;
+}
+
+/* update the heap when the root element is updated */
+static void
+heap_updated_root(batch_heap *heap, size_t limbsize) {
+ size_t node, parent, childr, childl;
+ heap_index_t *pheap = heap->heap;
+ bignum256modm *scalars = heap->scalars;
+
+ /* sift root to the bottom */
+ parent = 0;
+ node = 1;
+ childl = 1;
+ childr = 2;
+ while ((childr < heap->size)) {
+ node = lt256_modm_batch(scalars[pheap[childl]], scalars[pheap[childr]], limbsize) ? childr : childl;
+ heap_swap(pheap, parent, node);
+ parent = node;
+ childl = (parent * 2) + 1;
+ childr = childl + 1;
+ }
+
+ /* sift root back up to its sorted spot */
+ parent = (node - 1) / 2;
+ while (node && lte256_modm_batch(scalars[pheap[parent]], scalars[pheap[node]], limbsize)) {
+ heap_swap(pheap, parent, node);
+ node = parent;
+ parent = (node - 1) / 2;
+ }
+}
+
+/* build the heap with count elements, count must be >= 3 */
+static void
+heap_build(batch_heap *heap, size_t count) {
+ heap->heap[0] = 0;
+ heap->size = 0;
+ while (heap->size < count)
+ heap_insert_next(heap);
+}
+
+/* extend the heap to contain new_count elements */
+static void
+heap_extend(batch_heap *heap, size_t new_count) {
+ while (heap->size < new_count)
+ heap_insert_next(heap);
+}
+
+/* get the top 2 elements of the heap */
+static void
+heap_get_top2(batch_heap *heap, heap_index_t *max1, heap_index_t *max2, size_t limbsize) {
+ heap_index_t h0 = heap->heap[0], h1 = heap->heap[1], h2 = heap->heap[2];
+ if (lt256_modm_batch(heap->scalars[h1], heap->scalars[h2], limbsize))
+ h1 = h2;
+ *max1 = h0;
+ *max2 = h1;
+}
+
+/* */
+static void
+ge25519_multi_scalarmult_vartime_final(ge25519 *r, ge25519 *point, bignum256modm scalar) {
+ const bignum256modm_element_t topbit = ((bignum256modm_element_t)1 << (bignum256modm_bits_per_limb - 1));
+ size_t limb = limb128bits;
+ bignum256modm_element_t flag;
+
+ if (isone256_modm_batch(scalar)) {
+ /* this will happen most of the time after bos-carter */
+ *r = *point;
+ return;
+ } else if (iszero256_modm_batch(scalar)) {
+ /* this will only happen if all scalars == 0 */
+ memset(r, 0, sizeof(*r));
+ r->y[0] = 1;
+ r->z[0] = 1;
+ return;
+ }
+
+ *r = *point;
+
+ /* find the limb where first bit is set */
+ while (!scalar[limb])
+ limb--;
+
+ /* find the first bit */
+ flag = topbit;
+ while ((scalar[limb] & flag) == 0)
+ flag >>= 1;
+
+ /* exponentiate */
+ for (;;) {
+ ge25519_double(r, r);
+ if (scalar[limb] & flag)
+ ge25519_add(r, r, point);
+
+ flag >>= 1;
+ if (!flag) {
+ if (!limb--)
+ break;
+ flag = topbit;
+ }
+ }
+}
+
+/* count must be >= 5 */
+static void
+ge25519_multi_scalarmult_vartime(ge25519 *r, batch_heap *heap, size_t count) {
+ heap_index_t max1, max2;
+
+ /* start with the full limb size */
+ size_t limbsize = bignum256modm_limb_size - 1;
+
+ /* whether the heap has been extended to include the 128 bit scalars */
+ int extended = 0;
+
+ /* grab an odd number of scalars to build the heap, unknown limb sizes */
+ heap_build(heap, ((count + 1) / 2) | 1);
+
+ for (;;) {
+ heap_get_top2(heap, &max1, &max2, limbsize);
+
+ /* only one scalar remaining, we're done */
+ if (iszero256_modm_batch(heap->scalars[max2]))
+ break;
+
+ /* exhausted another limb? */
+ if (!heap->scalars[max1][limbsize])
+ limbsize -= 1;
+
+ /* can we extend to the 128 bit scalars? */
+ if (!extended && isatmost128bits256_modm_batch(heap->scalars[max1])) {
+ heap_extend(heap, count);
+ heap_get_top2(heap, &max1, &max2, limbsize);
+ extended = 1;
+ }
+
+ sub256_modm_batch(heap->scalars[max1], heap->scalars[max1], heap->scalars[max2], limbsize);
+ ge25519_add(&heap->points[max2], &heap->points[max2], &heap->points[max1]);
+ heap_updated_root(heap, limbsize);
+ }
+
+ ge25519_multi_scalarmult_vartime_final(r, &heap->points[max1], heap->scalars[max1]);
+}
+
+/* not actually used for anything other than testing */
+unsigned char batch_point_buffer[3][32];
+
+static int
+ge25519_is_neutral_vartime(const ge25519 *p) {
+ static const unsigned char zero[32] = {0};
+ unsigned char point_buffer[3][32];
+ curve25519_contract(point_buffer[0], p->x);
+ curve25519_contract(point_buffer[1], p->y);
+ curve25519_contract(point_buffer[2], p->z);
+ memcpy(batch_point_buffer[1], point_buffer[1], 32);
+ return (memcmp(point_buffer[0], zero, 32) == 0) && (memcmp(point_buffer[1], point_buffer[2], 32) == 0);
+}
+
+int
+ED25519_FN(ed25519_sign_open_batch) (const unsigned char **m, size_t *mlen, const unsigned char **pk, const unsigned char **RS, size_t num, int *valid) {
+ batch_heap ALIGN(16) batch;
+ ge25519 ALIGN(16) p;
+ bignum256modm *r_scalars;
+ size_t i, batchsize;
+ unsigned char hram[64];
+ int ret = 0;
+
+ for (i = 0; i < num; i++)
+ valid[i] = 1;
+
+ while (num > 3) {
+ batchsize = (num > max_batch_size) ? max_batch_size : num;
+
+ /* generate r (scalars[batchsize+1]..scalars[2*batchsize] */
+ ED25519_FN(ed25519_randombytes_unsafe) (batch.r, batchsize * 16);
+ r_scalars = &batch.scalars[batchsize + 1];
+ for (i = 0; i < batchsize; i++)
+ expand256_modm(r_scalars[i], batch.r[i], 16);
+
+ /* compute scalars[0] = ((r1s1 + r2s2 + ...)) */
+ for (i = 0; i < batchsize; i++) {
+ expand256_modm(batch.scalars[i], RS[i] + 32, 32);
+ mul256_modm(batch.scalars[i], batch.scalars[i], r_scalars[i]);
+ }
+ for (i = 1; i < batchsize; i++)
+ add256_modm(batch.scalars[0], batch.scalars[0], batch.scalars[i]);
+
+ /* compute scalars[1]..scalars[batchsize] as r[i]*H(R[i],A[i],m[i]) */
+ for (i = 0; i < batchsize; i++) {
+ ed25519_hram(hram, RS[i], pk[i], m[i], mlen[i]);
+ expand256_modm(batch.scalars[i+1], hram, 64);
+ mul256_modm(batch.scalars[i+1], batch.scalars[i+1], r_scalars[i]);
+ }
+
+ /* compute points */
+ batch.points[0] = ge25519_basepoint;
+ for (i = 0; i < batchsize; i++)
+ if (!ge25519_unpack_negative_vartime(&batch.points[i+1], pk[i]))
+ goto fallback;
+ for (i = 0; i < batchsize; i++)
+ if (!ge25519_unpack_negative_vartime(&batch.points[batchsize+i+1], RS[i]))
+ goto fallback;
+
+ ge25519_multi_scalarmult_vartime(&p, &batch, (batchsize * 2) + 1);
+ if (!ge25519_is_neutral_vartime(&p)) {
+ ret |= 2;
+
+ fallback:
+ for (i = 0; i < batchsize; i++) {
+ valid[i] = ED25519_FN(ed25519_sign_open) (m[i], mlen[i], pk[i], RS[i]) ? 0 : 1;
+ ret |= (valid[i] ^ 1);
+ }
+ }
+
+ m += batchsize;
+ mlen += batchsize;
+ pk += batchsize;
+ RS += batchsize;
+ num -= batchsize;
+ valid += batchsize;
+ }
+
+ for (i = 0; i < num; i++) {
+ valid[i] = ED25519_FN(ed25519_sign_open) (m[i], mlen[i], pk[i], RS[i]) ? 0 : 1;
+ ret |= (valid[i] ^ 1);
+ }
+
+ return ret;
+}
+
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/ed25519-donna/ed25519-donna-impl-base.h b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/ed25519-donna/ed25519-donna-impl-base.h
new file mode 100644
index 0000000..48913ed
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/ed25519-donna/ed25519-donna-impl-base.h
@@ -0,0 +1,364 @@
+/*
+ conversions
+*/
+
+DONNA_INLINE static void
+ge25519_p1p1_to_partial(ge25519 *r, const ge25519_p1p1 *p) {
+ curve25519_mul(r->x, p->x, p->t);
+ curve25519_mul(r->y, p->y, p->z);
+ curve25519_mul(r->z, p->z, p->t);
+}
+
+DONNA_INLINE static void
+ge25519_p1p1_to_full(ge25519 *r, const ge25519_p1p1 *p) {
+ curve25519_mul(r->x, p->x, p->t);
+ curve25519_mul(r->y, p->y, p->z);
+ curve25519_mul(r->z, p->z, p->t);
+ curve25519_mul(r->t, p->x, p->y);
+}
+
+static void
+ge25519_full_to_pniels(ge25519_pniels *p, const ge25519 *r) {
+ curve25519_sub(p->ysubx, r->y, r->x);
+ curve25519_add(p->xaddy, r->y, r->x);
+ curve25519_copy(p->z, r->z);
+ curve25519_mul(p->t2d, r->t, ge25519_ec2d);
+}
+
+/*
+ adding & doubling
+*/
+
+static void
+ge25519_add_p1p1(ge25519_p1p1 *r, const ge25519 *p, const ge25519 *q) {
+ bignum25519 a,b,c,d,t,u;
+
+ curve25519_sub(a, p->y, p->x);
+ curve25519_add(b, p->y, p->x);
+ curve25519_sub(t, q->y, q->x);
+ curve25519_add(u, q->y, q->x);
+ curve25519_mul(a, a, t);
+ curve25519_mul(b, b, u);
+ curve25519_mul(c, p->t, q->t);
+ curve25519_mul(c, c, ge25519_ec2d);
+ curve25519_mul(d, p->z, q->z);
+ curve25519_add(d, d, d);
+ curve25519_sub(r->x, b, a);
+ curve25519_add(r->y, b, a);
+ curve25519_add_after_basic(r->z, d, c);
+ curve25519_sub_after_basic(r->t, d, c);
+}
+
+
+static void
+ge25519_double_p1p1(ge25519_p1p1 *r, const ge25519 *p) {
+ bignum25519 a,b,c;
+
+ curve25519_square(a, p->x);
+ curve25519_square(b, p->y);
+ curve25519_square(c, p->z);
+ curve25519_add_reduce(c, c, c);
+ curve25519_add(r->x, p->x, p->y);
+ curve25519_square(r->x, r->x);
+ curve25519_add(r->y, b, a);
+ curve25519_sub(r->z, b, a);
+ curve25519_sub_after_basic(r->x, r->x, r->y);
+ curve25519_sub_after_basic(r->t, c, r->z);
+}
+
+static void
+ge25519_nielsadd2_p1p1(ge25519_p1p1 *r, const ge25519 *p, const ge25519_niels *q, unsigned char signbit) {
+ const bignum25519 *qb = (const bignum25519 *)q;
+ bignum25519 *rb = (bignum25519 *)r;
+ bignum25519 a,b,c;
+
+ curve25519_sub(a, p->y, p->x);
+ curve25519_add(b, p->y, p->x);
+ curve25519_mul(a, a, qb[signbit]); /* x for +, y for - */
+ curve25519_mul(r->x, b, qb[signbit^1]); /* y for +, x for - */
+ curve25519_add(r->y, r->x, a);
+ curve25519_sub(r->x, r->x, a);
+ curve25519_mul(c, p->t, q->t2d);
+ curve25519_add_reduce(r->t, p->z, p->z);
+ curve25519_copy(r->z, r->t);
+ curve25519_add(rb[2+signbit], rb[2+signbit], c); /* z for +, t for - */
+ curve25519_sub(rb[2+(signbit^1)], rb[2+(signbit^1)], c); /* t for +, z for - */
+}
+
+static void
+ge25519_pnielsadd_p1p1(ge25519_p1p1 *r, const ge25519 *p, const ge25519_pniels *q, unsigned char signbit) {
+ const bignum25519 *qb = (const bignum25519 *)q;
+ bignum25519 *rb = (bignum25519 *)r;
+ bignum25519 a,b,c;
+
+ curve25519_sub(a, p->y, p->x);
+ curve25519_add(b, p->y, p->x);
+ curve25519_mul(a, a, qb[signbit]); /* ysubx for +, xaddy for - */
+ curve25519_mul(r->x, b, qb[signbit^1]); /* xaddy for +, ysubx for - */
+ curve25519_add(r->y, r->x, a);
+ curve25519_sub(r->x, r->x, a);
+ curve25519_mul(c, p->t, q->t2d);
+ curve25519_mul(r->t, p->z, q->z);
+ curve25519_add_reduce(r->t, r->t, r->t);
+ curve25519_copy(r->z, r->t);
+ curve25519_add(rb[2+signbit], rb[2+signbit], c); /* z for +, t for - */
+ curve25519_sub(rb[2+(signbit^1)], rb[2+(signbit^1)], c); /* t for +, z for - */
+}
+
+static void
+ge25519_double_partial(ge25519 *r, const ge25519 *p) {
+ ge25519_p1p1 t;
+ ge25519_double_p1p1(&t, p);
+ ge25519_p1p1_to_partial(r, &t);
+}
+
+static void
+ge25519_double(ge25519 *r, const ge25519 *p) {
+ ge25519_p1p1 t;
+ ge25519_double_p1p1(&t, p);
+ ge25519_p1p1_to_full(r, &t);
+}
+
+static void
+ge25519_add(ge25519 *r, const ge25519 *p, const ge25519 *q) {
+ ge25519_p1p1 t;
+ ge25519_add_p1p1(&t, p, q);
+ ge25519_p1p1_to_full(r, &t);
+}
+
+static void
+ge25519_nielsadd2(ge25519 *r, const ge25519_niels *q) {
+ bignum25519 a,b,c,e,f,g,h;
+
+ curve25519_sub(a, r->y, r->x);
+ curve25519_add(b, r->y, r->x);
+ curve25519_mul(a, a, q->ysubx);
+ curve25519_mul(e, b, q->xaddy);
+ curve25519_add(h, e, a);
+ curve25519_sub(e, e, a);
+ curve25519_mul(c, r->t, q->t2d);
+ curve25519_add(f, r->z, r->z);
+ curve25519_add_after_basic(g, f, c);
+ curve25519_sub_after_basic(f, f, c);
+ curve25519_mul(r->x, e, f);
+ curve25519_mul(r->y, h, g);
+ curve25519_mul(r->z, g, f);
+ curve25519_mul(r->t, e, h);
+}
+
+static void
+ge25519_pnielsadd(ge25519_pniels *r, const ge25519 *p, const ge25519_pniels *q) {
+ bignum25519 a,b,c,x,y,z,t;
+
+ curve25519_sub(a, p->y, p->x);
+ curve25519_add(b, p->y, p->x);
+ curve25519_mul(a, a, q->ysubx);
+ curve25519_mul(x, b, q->xaddy);
+ curve25519_add(y, x, a);
+ curve25519_sub(x, x, a);
+ curve25519_mul(c, p->t, q->t2d);
+ curve25519_mul(t, p->z, q->z);
+ curve25519_add(t, t, t);
+ curve25519_add_after_basic(z, t, c);
+ curve25519_sub_after_basic(t, t, c);
+ curve25519_mul(r->xaddy, x, t);
+ curve25519_mul(r->ysubx, y, z);
+ curve25519_mul(r->z, z, t);
+ curve25519_mul(r->t2d, x, y);
+ curve25519_copy(y, r->ysubx);
+ curve25519_sub(r->ysubx, r->ysubx, r->xaddy);
+ curve25519_add(r->xaddy, r->xaddy, y);
+ curve25519_mul(r->t2d, r->t2d, ge25519_ec2d);
+}
+
+
+/*
+ pack & unpack
+*/
+
+static void
+ge25519_pack(unsigned char r[32], const ge25519 *p) {
+ bignum25519 tx, ty, zi;
+ unsigned char parity[32];
+ curve25519_recip(zi, p->z);
+ curve25519_mul(tx, p->x, zi);
+ curve25519_mul(ty, p->y, zi);
+ curve25519_contract(r, ty);
+ curve25519_contract(parity, tx);
+ r[31] ^= ((parity[0] & 1) << 7);
+}
+
+static int
+ge25519_unpack_negative_vartime(ge25519 *r, const unsigned char p[32]) {
+ static const unsigned char zero[32] = {0};
+ static const bignum25519 one = {1};
+ unsigned char parity = p[31] >> 7;
+ unsigned char check[32];
+ bignum25519 t, root, num, den, d3;
+
+ curve25519_expand(r->y, p);
+ curve25519_copy(r->z, one);
+ curve25519_square(num, r->y); /* x = y^2 */
+ curve25519_mul(den, num, ge25519_ecd); /* den = dy^2 */
+ curve25519_sub_reduce(num, num, r->z); /* x = y^1 - 1 */
+ curve25519_add(den, den, r->z); /* den = dy^2 + 1 */
+
+ /* Computation of sqrt(num/den) */
+ /* 1.: computation of num^((p-5)/8)*den^((7p-35)/8) = (num*den^7)^((p-5)/8) */
+ curve25519_square(t, den);
+ curve25519_mul(d3, t, den);
+ curve25519_square(r->x, d3);
+ curve25519_mul(r->x, r->x, den);
+ curve25519_mul(r->x, r->x, num);
+ curve25519_pow_two252m3(r->x, r->x);
+
+ /* 2. computation of r->x = num * den^3 * (num*den^7)^((p-5)/8) */
+ curve25519_mul(r->x, r->x, d3);
+ curve25519_mul(r->x, r->x, num);
+
+ /* 3. Check if either of the roots works: */
+ curve25519_square(t, r->x);
+ curve25519_mul(t, t, den);
+ curve25519_sub_reduce(root, t, num);
+ curve25519_contract(check, root);
+ if (!ed25519_verify(check, zero, 32)) {
+ curve25519_add_reduce(t, t, num);
+ curve25519_contract(check, t);
+ if (!ed25519_verify(check, zero, 32))
+ return 0;
+ curve25519_mul(r->x, r->x, ge25519_sqrtneg1);
+ }
+
+ curve25519_contract(check, r->x);
+ if ((check[0] & 1) == parity) {
+ curve25519_copy(t, r->x);
+ curve25519_neg(r->x, t);
+ }
+ curve25519_mul(r->t, r->x, r->y);
+ return 1;
+}
+
+
+/*
+ scalarmults
+*/
+
+#define S1_SWINDOWSIZE 5
+#define S1_TABLE_SIZE (1<<(S1_SWINDOWSIZE-2))
+#define S2_SWINDOWSIZE 7
+#define S2_TABLE_SIZE (1<<(S2_SWINDOWSIZE-2))
+
+/* computes [s1]p1 + [s2]basepoint */
+static void
+ge25519_double_scalarmult_vartime(ge25519 *r, const ge25519 *p1, const bignum256modm s1, const bignum256modm s2) {
+ signed char slide1[256], slide2[256];
+ ge25519_pniels pre1[S1_TABLE_SIZE];
+ ge25519 d1;
+ ge25519_p1p1 t;
+ int32_t i;
+
+ contract256_slidingwindow_modm(slide1, s1, S1_SWINDOWSIZE);
+ contract256_slidingwindow_modm(slide2, s2, S2_SWINDOWSIZE);
+
+ ge25519_double(&d1, p1);
+ ge25519_full_to_pniels(pre1, p1);
+ for (i = 0; i < S1_TABLE_SIZE - 1; i++)
+ ge25519_pnielsadd(&pre1[i+1], &d1, &pre1[i]);
+
+ /* set neutral */
+ memset(r, 0, sizeof(ge25519));
+ r->y[0] = 1;
+ r->z[0] = 1;
+
+ i = 255;
+ while ((i >= 0) && !(slide1[i] | slide2[i]))
+ i--;
+
+ for (; i >= 0; i--) {
+ ge25519_double_p1p1(&t, r);
+
+ if (slide1[i]) {
+ ge25519_p1p1_to_full(r, &t);
+ ge25519_pnielsadd_p1p1(&t, r, &pre1[abs(slide1[i]) / 2], (unsigned char)slide1[i] >> 7);
+ }
+
+ if (slide2[i]) {
+ ge25519_p1p1_to_full(r, &t);
+ ge25519_nielsadd2_p1p1(&t, r, &ge25519_niels_sliding_multiples[abs(slide2[i]) / 2], (unsigned char)slide2[i] >> 7);
+ }
+
+ ge25519_p1p1_to_partial(r, &t);
+ }
+}
+
+
+
+#if !defined(HAVE_GE25519_SCALARMULT_BASE_CHOOSE_NIELS)
+
+static uint32_t
+ge25519_windowb_equal(uint32_t b, uint32_t c) {
+ return ((b ^ c) - 1) >> 31;
+}
+
+static void
+ge25519_scalarmult_base_choose_niels(ge25519_niels *t, const uint8_t table[256][96], uint32_t pos, signed char b) {
+ bignum25519 neg;
+ uint32_t sign = (uint32_t)((unsigned char)b >> 7);
+ uint32_t mask = ~(sign - 1);
+ uint32_t u = (b + mask) ^ mask;
+ uint32_t i;
+
+ /* ysubx, xaddy, t2d in packed form. initialize to ysubx = 1, xaddy = 1, t2d = 0 */
+ uint8_t packed[96] = {0};
+ packed[0] = 1;
+ packed[32] = 1;
+
+ for (i = 0; i < 8; i++)
+ curve25519_move_conditional_bytes(packed, table[(pos * 8) + i], ge25519_windowb_equal(u, i + 1));
+
+ /* expand in to t */
+ curve25519_expand(t->ysubx, packed + 0);
+ curve25519_expand(t->xaddy, packed + 32);
+ curve25519_expand(t->t2d , packed + 64);
+
+ /* adjust for sign */
+ curve25519_swap_conditional(t->ysubx, t->xaddy, sign);
+ curve25519_neg(neg, t->t2d);
+ curve25519_swap_conditional(t->t2d, neg, sign);
+}
+
+#endif /* HAVE_GE25519_SCALARMULT_BASE_CHOOSE_NIELS */
+
+
+/* computes [s]basepoint */
+static void
+ge25519_scalarmult_base_niels(ge25519 *r, const uint8_t basepoint_table[256][96], const bignum256modm s) {
+ signed char b[64];
+ uint32_t i;
+ ge25519_niels t;
+
+ contract256_window4_modm(b, s);
+
+ ge25519_scalarmult_base_choose_niels(&t, basepoint_table, 0, b[1]);
+ curve25519_sub_reduce(r->x, t.xaddy, t.ysubx);
+ curve25519_add_reduce(r->y, t.xaddy, t.ysubx);
+ memset(r->z, 0, sizeof(bignum25519));
+ curve25519_copy(r->t, t.t2d);
+ r->z[0] = 2;
+ for (i = 3; i < 64; i += 2) {
+ ge25519_scalarmult_base_choose_niels(&t, basepoint_table, i / 2, b[i]);
+ ge25519_nielsadd2(r, &t);
+ }
+ ge25519_double_partial(r, r);
+ ge25519_double_partial(r, r);
+ ge25519_double_partial(r, r);
+ ge25519_double(r, r);
+ ge25519_scalarmult_base_choose_niels(&t, basepoint_table, 0, b[0]);
+ curve25519_mul(t.t2d, t.t2d, ge25519_ecd);
+ ge25519_nielsadd2(r, &t);
+ for(i = 2; i < 64; i += 2) {
+ ge25519_scalarmult_base_choose_niels(&t, basepoint_table, i / 2, b[i]);
+ ge25519_nielsadd2(r, &t);
+ }
+}
+
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/ed25519-donna/ed25519-donna-portable-identify.h b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/ed25519-donna/ed25519-donna-portable-identify.h
new file mode 100644
index 0000000..26a264c
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/ed25519-donna/ed25519-donna-portable-identify.h
@@ -0,0 +1,103 @@
+/* os */
+#if defined(_WIN32) || defined(_WIN64) || defined(__TOS_WIN__) || defined(__WINDOWS__)
+ #define OS_WINDOWS
+#elif defined(sun) || defined(__sun) || defined(__SVR4) || defined(__svr4__)
+ #define OS_SOLARIS
+#else
+ #include <sys/param.h> /* need this to define BSD */
+ #define OS_NIX
+ #if defined(__linux__)
+ #define OS_LINUX
+ #elif defined(BSD)
+ #define OS_BSD
+ #if defined(MACOS_X) || (defined(__APPLE__) & defined(__MACH__))
+ #define OS_OSX
+ #elif defined(macintosh) || defined(Macintosh)
+ #define OS_MAC
+ #elif defined(__OpenBSD__)
+ #define OS_OPENBSD
+ #endif
+ #endif
+#endif
+
+
+/* compiler */
+#if defined(_MSC_VER)
+ #define COMPILER_MSVC
+#endif
+#if defined(__ICC)
+ #define COMPILER_INTEL
+#endif
+#if defined(__GNUC__)
+ #if (__GNUC__ >= 3)
+ #define COMPILER_GCC ((__GNUC__ * 10000) + (__GNUC_MINOR__ * 100) + (__GNUC_PATCHLEVEL__))
+ #else
+ #define COMPILER_GCC ((__GNUC__ * 10000) + (__GNUC_MINOR__ * 100) )
+ #endif
+#endif
+#if defined(__PATHCC__)
+ #define COMPILER_PATHCC
+#endif
+#if defined(__clang__)
+ #define COMPILER_CLANG ((__clang_major__ * 10000) + (__clang_minor__ * 100) + (__clang_patchlevel__))
+#endif
+
+
+
+/* cpu */
+#if defined(__amd64__) || defined(__amd64) || defined(__x86_64__ ) || defined(_M_X64)
+ #define CPU_X86_64
+#elif defined(__i586__) || defined(__i686__) || (defined(_M_IX86) && (_M_IX86 >= 500))
+ #define CPU_X86 500
+#elif defined(__i486__) || (defined(_M_IX86) && (_M_IX86 >= 400))
+ #define CPU_X86 400
+#elif defined(__i386__) || (defined(_M_IX86) && (_M_IX86 >= 300)) || defined(__X86__) || defined(_X86_) || defined(__I86__)
+ #define CPU_X86 300
+#elif defined(__ia64__) || defined(_IA64) || defined(__IA64__) || defined(_M_IA64) || defined(__ia64)
+ #define CPU_IA64
+#endif
+
+#if defined(__sparc__) || defined(__sparc) || defined(__sparcv9)
+ #define CPU_SPARC
+ #if defined(__sparcv9)
+ #define CPU_SPARC64
+ #endif
+#endif
+
+#if defined(powerpc) || defined(__PPC__) || defined(__ppc__) || defined(_ARCH_PPC) || defined(__powerpc__) || defined(__powerpc) || defined(POWERPC) || defined(_M_PPC)
+ #define CPU_PPC
+ #if defined(_ARCH_PWR7)
+ #define CPU_POWER7
+ #elif defined(__64BIT__)
+ #define CPU_PPC64
+ #else
+ #define CPU_PPC32
+ #endif
+#endif
+
+#if defined(__hppa__) || defined(__hppa)
+ #define CPU_HPPA
+#endif
+
+#if defined(__alpha__) || defined(__alpha) || defined(_M_ALPHA)
+ #define CPU_ALPHA
+#endif
+
+/* 64 bit cpu */
+#if defined(CPU_X86_64) || defined(CPU_IA64) || defined(CPU_SPARC64) || defined(__64BIT__) || defined(__LP64__) || defined(_LP64) || (defined(_MIPS_SZLONG) && (_MIPS_SZLONG == 64))
+ #define CPU_64BITS
+#endif
+
+#if defined(COMPILER_MSVC)
+ typedef signed char int8_t;
+ typedef unsigned char uint8_t;
+ typedef signed short int16_t;
+ typedef unsigned short uint16_t;
+ typedef signed int int32_t;
+ typedef unsigned int uint32_t;
+ typedef signed __int64 int64_t;
+ typedef unsigned __int64 uint64_t;
+#else
+ #include <stdint.h>
+#endif
+
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/ed25519-donna/ed25519-donna-portable.h b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/ed25519-donna/ed25519-donna-portable.h
new file mode 100644
index 0000000..0a0f7fc
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/ed25519-donna/ed25519-donna-portable.h
@@ -0,0 +1,135 @@
+#include "ed25519-donna-portable-identify.h"
+
+#define mul32x32_64(a,b) (((uint64_t)(a))*(b))
+
+/* platform */
+#if defined(COMPILER_MSVC)
+ #include <intrin.h>
+ #if !defined(_DEBUG)
+ #undef mul32x32_64
+ #define mul32x32_64(a,b) __emulu(a,b)
+ #endif
+ #undef inline
+ #define inline __forceinline
+ #define DONNA_INLINE __forceinline
+ #define DONNA_NOINLINE __declspec(noinline)
+ #define ALIGN(x) __declspec(align(x))
+ #define ROTL32(a,b) _rotl(a,b)
+ #define ROTR32(a,b) _rotr(a,b)
+#else
+ #include <sys/param.h>
+ #define DONNA_INLINE inline __attribute__((always_inline))
+ #define DONNA_NOINLINE __attribute__((noinline))
+ #define ALIGN(x) __attribute__((aligned(x)))
+ #define ROTL32(a,b) (((a) << (b)) | ((a) >> (32 - b)))
+ #define ROTR32(a,b) (((a) >> (b)) | ((a) << (32 - b)))
+#endif
+
+/* uint128_t */
+#if defined(CPU_64BITS) && !defined(ED25519_FORCE_32BIT)
+ #if defined(COMPILER_CLANG) && (COMPILER_CLANG >= 30100)
+ #define HAVE_NATIVE_UINT128
+ typedef unsigned __int128 uint128_t;
+ #elif defined(COMPILER_MSVC)
+ #define HAVE_UINT128
+ typedef struct uint128_t {
+ uint64_t lo, hi;
+ } uint128_t;
+ #define mul64x64_128(out,a,b) out.lo = _umul128(a,b,&out.hi);
+ #define shr128_pair(out,hi,lo,shift) out = __shiftright128(lo, hi, shift);
+ #define shl128_pair(out,hi,lo,shift) out = __shiftleft128(lo, hi, shift);
+ #define shr128(out,in,shift) shr128_pair(out, in.hi, in.lo, shift)
+ #define shl128(out,in,shift) shl128_pair(out, in.hi, in.lo, shift)
+ #define add128(a,b) { uint64_t p = a.lo; a.lo += b.lo; a.hi += b.hi + (a.lo < p); }
+ #define add128_64(a,b) { uint64_t p = a.lo; a.lo += b; a.hi += (a.lo < p); }
+ #define lo128(a) (a.lo)
+ #define hi128(a) (a.hi)
+ #elif defined(COMPILER_GCC) && !defined(HAVE_NATIVE_UINT128)
+ #if defined(__SIZEOF_INT128__)
+ #define HAVE_NATIVE_UINT128
+ typedef unsigned __int128 uint128_t;
+ #elif (COMPILER_GCC >= 40400)
+ #define HAVE_NATIVE_UINT128
+ typedef unsigned uint128_t __attribute__((mode(TI)));
+ #elif defined(CPU_X86_64)
+ #define HAVE_UINT128
+ typedef struct uint128_t {
+ uint64_t lo, hi;
+ } uint128_t;
+ #define mul64x64_128(out,a,b) __asm__ ("mulq %3" : "=a" (out.lo), "=d" (out.hi) : "a" (a), "rm" (b));
+ #define shr128_pair(out,hi,lo,shift) __asm__ ("shrdq %2,%1,%0" : "+r" (lo) : "r" (hi), "J" (shift)); out = lo;
+ #define shl128_pair(out,hi,lo,shift) __asm__ ("shldq %2,%1,%0" : "+r" (hi) : "r" (lo), "J" (shift)); out = hi;
+ #define shr128(out,in,shift) shr128_pair(out,in.hi, in.lo, shift)
+ #define shl128(out,in,shift) shl128_pair(out,in.hi, in.lo, shift)
+ #define add128(a,b) __asm__ ("addq %4,%2; adcq %5,%3" : "=r" (a.hi), "=r" (a.lo) : "1" (a.lo), "0" (a.hi), "rm" (b.lo), "rm" (b.hi) : "cc");
+ #define add128_64(a,b) __asm__ ("addq %4,%2; adcq $0,%3" : "=r" (a.hi), "=r" (a.lo) : "1" (a.lo), "0" (a.hi), "rm" (b) : "cc");
+ #define lo128(a) (a.lo)
+ #define hi128(a) (a.hi)
+ #endif
+ #endif
+
+ #if defined(HAVE_NATIVE_UINT128)
+ #define HAVE_UINT128
+ #define mul64x64_128(out,a,b) out = (uint128_t)a * b;
+ #define shr128_pair(out,hi,lo,shift) out = (uint64_t)((((uint128_t)hi << 64) | lo) >> (shift));
+ #define shl128_pair(out,hi,lo,shift) out = (uint64_t)(((((uint128_t)hi << 64) | lo) << (shift)) >> 64);
+ #define shr128(out,in,shift) out = (uint64_t)(in >> (shift));
+ #define shl128(out,in,shift) out = (uint64_t)((in << shift) >> 64);
+ #define add128(a,b) a += b;
+ #define add128_64(a,b) a += (uint64_t)b;
+ #define lo128(a) ((uint64_t)a)
+ #define hi128(a) ((uint64_t)(a >> 64))
+ #endif
+
+ #if !defined(HAVE_UINT128)
+ #error Need a uint128_t implementation!
+ #endif
+#endif
+
+/* endian */
+#if !defined(ED25519_OPENSSLRNG)
+static inline void U32TO8_LE(unsigned char *p, const uint32_t v) {
+ p[0] = (unsigned char)(v );
+ p[1] = (unsigned char)(v >> 8);
+ p[2] = (unsigned char)(v >> 16);
+ p[3] = (unsigned char)(v >> 24);
+}
+#endif
+
+#if !defined(HAVE_UINT128)
+static inline uint32_t U8TO32_LE(const unsigned char *p) {
+ return
+ (((uint32_t)(p[0]) ) |
+ ((uint32_t)(p[1]) << 8) |
+ ((uint32_t)(p[2]) << 16) |
+ ((uint32_t)(p[3]) << 24));
+}
+#else
+static inline uint64_t U8TO64_LE(const unsigned char *p) {
+ return
+ (((uint64_t)(p[0]) ) |
+ ((uint64_t)(p[1]) << 8) |
+ ((uint64_t)(p[2]) << 16) |
+ ((uint64_t)(p[3]) << 24) |
+ ((uint64_t)(p[4]) << 32) |
+ ((uint64_t)(p[5]) << 40) |
+ ((uint64_t)(p[6]) << 48) |
+ ((uint64_t)(p[7]) << 56));
+}
+
+static inline void U64TO8_LE(unsigned char *p, const uint64_t v) {
+ p[0] = (unsigned char)(v );
+ p[1] = (unsigned char)(v >> 8);
+ p[2] = (unsigned char)(v >> 16);
+ p[3] = (unsigned char)(v >> 24);
+ p[4] = (unsigned char)(v >> 32);
+ p[5] = (unsigned char)(v >> 40);
+ p[6] = (unsigned char)(v >> 48);
+ p[7] = (unsigned char)(v >> 56);
+}
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/ed25519-donna/ed25519-donna.h b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/ed25519-donna/ed25519-donna.h
new file mode 100644
index 0000000..fa95a09
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/ed25519-donna/ed25519-donna.h
@@ -0,0 +1,117 @@
+/*
+ Public domain by Andrew M. <liquidsun@gmail.com>
+ Modified from the amd64-51-30k implementation by
+ Daniel J. Bernstein
+ Niels Duif
+ Tanja Lange
+ Peter Schwabe
+ Bo-Yin Yang
+*/
+
+
+#include "ed25519-donna-portable.h"
+
+#if defined(ED25519_SSE2)
+#else
+ #if defined(HAVE_UINT128) && !defined(ED25519_FORCE_32BIT)
+ #define ED25519_64BIT
+ #else
+ #define ED25519_32BIT
+ #endif
+#endif
+
+#if !defined(ED25519_NO_INLINE_ASM)
+ /* detect extra features first so un-needed functions can be disabled throughout */
+ #if defined(ED25519_SSE2)
+ #if defined(COMPILER_GCC) && defined(CPU_X86)
+ #define ED25519_GCC_32BIT_SSE_CHOOSE
+ #elif defined(COMPILER_GCC) && defined(CPU_X86_64)
+ #define ED25519_GCC_64BIT_SSE_CHOOSE
+ #endif
+ #else
+ #if defined(CPU_X86_64)
+ #if defined(COMPILER_GCC)
+ #if defined(ED25519_64BIT)
+ #define ED25519_GCC_64BIT_X86_CHOOSE
+ #else
+ #define ED25519_GCC_64BIT_32BIT_CHOOSE
+ #endif
+ #endif
+ #endif
+ #endif
+#endif
+
+#if defined(ED25519_SSE2)
+ #include "curve25519-donna-sse2.h"
+#elif defined(ED25519_64BIT)
+ #include "curve25519-donna-64bit.h"
+#else
+ #include "curve25519-donna-32bit.h"
+#endif
+
+#include "curve25519-donna-helpers.h"
+
+/* separate uint128 check for 64 bit sse2 */
+#if defined(HAVE_UINT128) && !defined(ED25519_FORCE_32BIT)
+ #include "modm-donna-64bit.h"
+#else
+ #include "modm-donna-32bit.h"
+#endif
+
+typedef unsigned char hash_512bits[64];
+
+/*
+ Timing safe memory compare
+*/
+static int
+ed25519_verify(const unsigned char *x, const unsigned char *y, size_t len) {
+ size_t differentbits = 0;
+ while (len--)
+ differentbits |= (*x++ ^ *y++);
+ return (int) (1 & ((differentbits - 1) >> 8));
+}
+
+
+/*
+ * Arithmetic on the twisted Edwards curve -x^2 + y^2 = 1 + dx^2y^2
+ * with d = -(121665/121666) = 37095705934669439343138083508754565189542113879843219016388785533085940283555
+ * Base point: (15112221349535400772501151409588531511454012693041857206046113283949847762202,46316835694926478169428394003475163141307993866256225615783033603165251855960);
+ */
+
+typedef struct ge25519_t {
+ bignum25519 x, y, z, t;
+} ge25519;
+
+typedef struct ge25519_p1p1_t {
+ bignum25519 x, y, z, t;
+} ge25519_p1p1;
+
+typedef struct ge25519_niels_t {
+ bignum25519 ysubx, xaddy, t2d;
+} ge25519_niels;
+
+typedef struct ge25519_pniels_t {
+ bignum25519 ysubx, xaddy, z, t2d;
+} ge25519_pniels;
+
+#include "ed25519-donna-basepoint-table.h"
+
+#if defined(ED25519_64BIT)
+ #include "ed25519-donna-64bit-tables.h"
+ #include "ed25519-donna-64bit-x86.h"
+#else
+ #include "ed25519-donna-32bit-tables.h"
+ #if defined(ED25519_GCC_64BIT_32BIT_CHOOSE)
+ #include "ed25519-donna-64bit-x86-32bit.h"
+ #endif
+#endif
+
+
+#if defined(ED25519_SSE2)
+ #include "ed25519-donna-32bit-sse2.h"
+ #include "ed25519-donna-64bit-sse2.h"
+ #include "ed25519-donna-impl-sse2.h"
+#else
+ #include "ed25519-donna-impl-base.h"
+#endif
+
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/ed25519-donna/ed25519-hash-custom.h b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/ed25519-donna/ed25519-hash-custom.h
new file mode 100644
index 0000000..94a0076
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/ed25519-donna/ed25519-hash-custom.h
@@ -0,0 +1,23 @@
+#include <sodium.h>
+
+typedef crypto_generichash_state ed25519_hash_context;
+
+void ed25519_hash_init(ed25519_hash_context *ctx)
+{
+ crypto_generichash_init(ctx, 0, 0, 64);
+}
+
+void ed25519_hash_update(ed25519_hash_context *ctx, const uint8_t *in, size_t inlen)
+{
+ crypto_generichash_update(ctx, in, inlen);
+}
+
+void ed25519_hash_final(ed25519_hash_context *ctx, uint8_t *hash)
+{
+ crypto_generichash_final(ctx, hash, 64);
+}
+
+void ed25519_hash(uint8_t *hash, const uint8_t *in, size_t inlen)
+{
+ crypto_generichash(hash, 64, in, inlen, 0, 0);
+}
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/ed25519-donna/ed25519-hash.h b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/ed25519-donna/ed25519-hash.h
new file mode 100644
index 0000000..6ba8f52
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/ed25519-donna/ed25519-hash.h
@@ -0,0 +1,219 @@
+#if defined(ED25519_REFHASH)
+
+/* reference/slow SHA-512. really, do not use this */
+
+#define HASH_BLOCK_SIZE 128
+#define HASH_DIGEST_SIZE 64
+
+typedef struct sha512_state_t {
+ uint64_t H[8];
+ uint64_t T[2];
+ uint32_t leftover;
+ uint8_t buffer[HASH_BLOCK_SIZE];
+} sha512_state;
+
+typedef sha512_state ed25519_hash_context;
+
+static const uint64_t sha512_constants[80] = {
+ 0x428a2f98d728ae22ull, 0x7137449123ef65cdull, 0xb5c0fbcfec4d3b2full, 0xe9b5dba58189dbbcull,
+ 0x3956c25bf348b538ull, 0x59f111f1b605d019ull, 0x923f82a4af194f9bull, 0xab1c5ed5da6d8118ull,
+ 0xd807aa98a3030242ull, 0x12835b0145706fbeull, 0x243185be4ee4b28cull, 0x550c7dc3d5ffb4e2ull,
+ 0x72be5d74f27b896full, 0x80deb1fe3b1696b1ull, 0x9bdc06a725c71235ull, 0xc19bf174cf692694ull,
+ 0xe49b69c19ef14ad2ull, 0xefbe4786384f25e3ull, 0x0fc19dc68b8cd5b5ull, 0x240ca1cc77ac9c65ull,
+ 0x2de92c6f592b0275ull, 0x4a7484aa6ea6e483ull, 0x5cb0a9dcbd41fbd4ull, 0x76f988da831153b5ull,
+ 0x983e5152ee66dfabull, 0xa831c66d2db43210ull, 0xb00327c898fb213full, 0xbf597fc7beef0ee4ull,
+ 0xc6e00bf33da88fc2ull, 0xd5a79147930aa725ull, 0x06ca6351e003826full, 0x142929670a0e6e70ull,
+ 0x27b70a8546d22ffcull, 0x2e1b21385c26c926ull, 0x4d2c6dfc5ac42aedull, 0x53380d139d95b3dfull,
+ 0x650a73548baf63deull, 0x766a0abb3c77b2a8ull, 0x81c2c92e47edaee6ull, 0x92722c851482353bull,
+ 0xa2bfe8a14cf10364ull, 0xa81a664bbc423001ull, 0xc24b8b70d0f89791ull, 0xc76c51a30654be30ull,
+ 0xd192e819d6ef5218ull, 0xd69906245565a910ull, 0xf40e35855771202aull, 0x106aa07032bbd1b8ull,
+ 0x19a4c116b8d2d0c8ull, 0x1e376c085141ab53ull, 0x2748774cdf8eeb99ull, 0x34b0bcb5e19b48a8ull,
+ 0x391c0cb3c5c95a63ull, 0x4ed8aa4ae3418acbull, 0x5b9cca4f7763e373ull, 0x682e6ff3d6b2b8a3ull,
+ 0x748f82ee5defb2fcull, 0x78a5636f43172f60ull, 0x84c87814a1f0ab72ull, 0x8cc702081a6439ecull,
+ 0x90befffa23631e28ull, 0xa4506cebde82bde9ull, 0xbef9a3f7b2c67915ull, 0xc67178f2e372532bull,
+ 0xca273eceea26619cull, 0xd186b8c721c0c207ull, 0xeada7dd6cde0eb1eull, 0xf57d4f7fee6ed178ull,
+ 0x06f067aa72176fbaull, 0x0a637dc5a2c898a6ull, 0x113f9804bef90daeull, 0x1b710b35131c471bull,
+ 0x28db77f523047d84ull, 0x32caab7b40c72493ull, 0x3c9ebe0a15c9bebcull, 0x431d67c49c100d4cull,
+ 0x4cc5d4becb3e42b6ull, 0x597f299cfc657e2aull, 0x5fcb6fab3ad6faecull, 0x6c44198c4a475817ull
+};
+
+static uint64_t
+sha512_ROTR64(uint64_t x, int k) {
+ return (x >> k) | (x << (64 - k));
+}
+
+static uint64_t
+sha512_LOAD64_BE(const uint8_t *p) {
+ return
+ ((uint64_t)p[0] << 56) |
+ ((uint64_t)p[1] << 48) |
+ ((uint64_t)p[2] << 40) |
+ ((uint64_t)p[3] << 32) |
+ ((uint64_t)p[4] << 24) |
+ ((uint64_t)p[5] << 16) |
+ ((uint64_t)p[6] << 8) |
+ ((uint64_t)p[7] );
+}
+
+static void
+sha512_STORE64_BE(uint8_t *p, uint64_t v) {
+ p[0] = (uint8_t)(v >> 56);
+ p[1] = (uint8_t)(v >> 48);
+ p[2] = (uint8_t)(v >> 40);
+ p[3] = (uint8_t)(v >> 32);
+ p[4] = (uint8_t)(v >> 24);
+ p[5] = (uint8_t)(v >> 16);
+ p[6] = (uint8_t)(v >> 8);
+ p[7] = (uint8_t)(v );
+}
+
+#define Ch(x,y,z) (z ^ (x & (y ^ z)))
+#define Maj(x,y,z) (((x | y) & z) | (x & y))
+#define S0(x) (sha512_ROTR64(x, 28) ^ sha512_ROTR64(x, 34) ^ sha512_ROTR64(x, 39))
+#define S1(x) (sha512_ROTR64(x, 14) ^ sha512_ROTR64(x, 18) ^ sha512_ROTR64(x, 41))
+#define G0(x) (sha512_ROTR64(x, 1) ^ sha512_ROTR64(x, 8) ^ (x >> 7))
+#define G1(x) (sha512_ROTR64(x, 19) ^ sha512_ROTR64(x, 61) ^ (x >> 6))
+#define W0(in,i) (sha512_LOAD64_BE(&in[i * 8]))
+#define W1(i) (G1(w[i - 2]) + w[i - 7] + G0(w[i - 15]) + w[i - 16])
+#define STEP(i) \
+ t1 = S0(r[0]) + Maj(r[0], r[1], r[2]); \
+ t0 = r[7] + S1(r[4]) + Ch(r[4], r[5], r[6]) + sha512_constants[i] + w[i]; \
+ r[7] = r[6]; \
+ r[6] = r[5]; \
+ r[5] = r[4]; \
+ r[4] = r[3] + t0; \
+ r[3] = r[2]; \
+ r[2] = r[1]; \
+ r[1] = r[0]; \
+ r[0] = t0 + t1;
+
+static void
+sha512_blocks(sha512_state *S, const uint8_t *in, size_t blocks) {
+ uint64_t r[8], w[80], t0, t1;
+ size_t i;
+
+ for (i = 0; i < 8; i++) r[i] = S->H[i];
+
+ while (blocks--) {
+ for (i = 0; i < 16; i++) { w[i] = W0(in, i); }
+ for (i = 16; i < 80; i++) { w[i] = W1(i); }
+ for (i = 0; i < 80; i++) { STEP(i); }
+ for (i = 0; i < 8; i++) { r[i] += S->H[i]; S->H[i] = r[i]; }
+ S->T[0] += HASH_BLOCK_SIZE * 8;
+ S->T[1] += (!S->T[0]) ? 1 : 0;
+ in += HASH_BLOCK_SIZE;
+ }
+}
+
+static void
+ed25519_hash_init(sha512_state *S) {
+ S->H[0] = 0x6a09e667f3bcc908ull;
+ S->H[1] = 0xbb67ae8584caa73bull;
+ S->H[2] = 0x3c6ef372fe94f82bull;
+ S->H[3] = 0xa54ff53a5f1d36f1ull;
+ S->H[4] = 0x510e527fade682d1ull;
+ S->H[5] = 0x9b05688c2b3e6c1full;
+ S->H[6] = 0x1f83d9abfb41bd6bull;
+ S->H[7] = 0x5be0cd19137e2179ull;
+ S->T[0] = 0;
+ S->T[1] = 0;
+ S->leftover = 0;
+}
+
+static void
+ed25519_hash_update(sha512_state *S, const uint8_t *in, size_t inlen) {
+ size_t blocks, want;
+
+ /* handle the previous data */
+ if (S->leftover) {
+ want = (HASH_BLOCK_SIZE - S->leftover);
+ want = (want < inlen) ? want : inlen;
+ memcpy(S->buffer + S->leftover, in, want);
+ S->leftover += (uint32_t)want;
+ if (S->leftover < HASH_BLOCK_SIZE)
+ return;
+ in += want;
+ inlen -= want;
+ sha512_blocks(S, S->buffer, 1);
+ }
+
+ /* handle the current data */
+ blocks = (inlen & ~(HASH_BLOCK_SIZE - 1));
+ S->leftover = (uint32_t)(inlen - blocks);
+ if (blocks) {
+ sha512_blocks(S, in, blocks / HASH_BLOCK_SIZE);
+ in += blocks;
+ }
+
+ /* handle leftover data */
+ if (S->leftover)
+ memcpy(S->buffer, in, S->leftover);
+}
+
+static void
+ed25519_hash_final(sha512_state *S, uint8_t *hash) {
+ uint64_t t0 = S->T[0] + (S->leftover * 8), t1 = S->T[1];
+
+ S->buffer[S->leftover] = 0x80;
+ if (S->leftover <= 111) {
+ memset(S->buffer + S->leftover + 1, 0, 111 - S->leftover);
+ } else {
+ memset(S->buffer + S->leftover + 1, 0, 127 - S->leftover);
+ sha512_blocks(S, S->buffer, 1);
+ memset(S->buffer, 0, 112);
+ }
+
+ sha512_STORE64_BE(S->buffer + 112, t1);
+ sha512_STORE64_BE(S->buffer + 120, t0);
+ sha512_blocks(S, S->buffer, 1);
+
+ sha512_STORE64_BE(&hash[ 0], S->H[0]);
+ sha512_STORE64_BE(&hash[ 8], S->H[1]);
+ sha512_STORE64_BE(&hash[16], S->H[2]);
+ sha512_STORE64_BE(&hash[24], S->H[3]);
+ sha512_STORE64_BE(&hash[32], S->H[4]);
+ sha512_STORE64_BE(&hash[40], S->H[5]);
+ sha512_STORE64_BE(&hash[48], S->H[6]);
+ sha512_STORE64_BE(&hash[56], S->H[7]);
+}
+
+static void
+ed25519_hash(uint8_t *hash, const uint8_t *in, size_t inlen) {
+ ed25519_hash_context ctx;
+ ed25519_hash_init(&ctx);
+ ed25519_hash_update(&ctx, in, inlen);
+ ed25519_hash_final(&ctx, hash);
+}
+
+#elif defined(ED25519_CUSTOMHASH)
+
+#include "ed25519-hash-custom.h"
+
+#else
+
+#include <openssl/sha.h>
+
+typedef SHA512_CTX ed25519_hash_context;
+
+static void
+ed25519_hash_init(ed25519_hash_context *ctx) {
+ SHA512_Init(ctx);
+}
+
+static void
+ed25519_hash_update(ed25519_hash_context *ctx, const uint8_t *in, size_t inlen) {
+ SHA512_Update(ctx, in, inlen);
+}
+
+static void
+ed25519_hash_final(ed25519_hash_context *ctx, uint8_t *hash) {
+ SHA512_Final(hash, ctx);
+}
+
+static void
+ed25519_hash(uint8_t *hash, const uint8_t *in, size_t inlen) {
+ SHA512(in, inlen, hash);
+}
+
+#endif
+
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/ed25519-donna/ed25519-randombytes.h b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/ed25519-donna/ed25519-randombytes.h
new file mode 100644
index 0000000..1dc6290
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/ed25519-donna/ed25519-randombytes.h
@@ -0,0 +1,91 @@
+#if defined(ED25519_TEST)
+/*
+ ISAAC+ "variant", the paper is not clear on operator precedence and other
+ things. This is the "first in, first out" option!
+
+ Not threadsafe or securely initialized, only for deterministic testing
+*/
+typedef struct isaacp_state_t {
+ uint32_t state[256];
+ unsigned char buffer[1024];
+ uint32_t a, b, c;
+ size_t left;
+} isaacp_state;
+
+#define isaacp_step(offset, mix) \
+ x = mm[i + offset]; \
+ a = (a ^ (mix)) + (mm[(i + offset + 128) & 0xff]); \
+ y = (a ^ b) + mm[(x >> 2) & 0xff]; \
+ mm[i + offset] = y; \
+ b = (x + a) ^ mm[(y >> 10) & 0xff]; \
+ U32TO8_LE(out + (i + offset) * 4, b);
+
+static void
+isaacp_mix(isaacp_state *st) {
+ uint32_t i, x, y;
+ uint32_t a = st->a, b = st->b, c = st->c;
+ uint32_t *mm = st->state;
+ unsigned char *out = st->buffer;
+
+ c = c + 1;
+ b = b + c;
+
+ for (i = 0; i < 256; i += 4) {
+ isaacp_step(0, ROTL32(a,13))
+ isaacp_step(1, ROTR32(a, 6))
+ isaacp_step(2, ROTL32(a, 2))
+ isaacp_step(3, ROTR32(a,16))
+ }
+
+ st->a = a;
+ st->b = b;
+ st->c = c;
+ st->left = 1024;
+}
+
+static void
+isaacp_random(isaacp_state *st, void *p, size_t len) {
+ size_t use;
+ unsigned char *c = (unsigned char *)p;
+ while (len) {
+ use = (len > st->left) ? st->left : len;
+ memcpy(c, st->buffer + (sizeof(st->buffer) - st->left), use);
+
+ st->left -= use;
+ c += use;
+ len -= use;
+
+ if (!st->left)
+ isaacp_mix(st);
+ }
+}
+
+void
+ED25519_FN(ed25519_randombytes_unsafe) (void *p, size_t len) {
+ static int initialized = 0;
+ static isaacp_state rng;
+
+ if (!initialized) {
+ memset(&rng, 0, sizeof(rng));
+ isaacp_mix(&rng);
+ isaacp_mix(&rng);
+ initialized = 1;
+ }
+
+ isaacp_random(&rng, p, len);
+}
+#elif defined(ED25519_CUSTOMRANDOM)
+
+#include "ed25519-randombytes-custom.h"
+
+#else
+
+#include <openssl/rand.h>
+
+void
+ED25519_FN(ed25519_randombytes_unsafe) (void *p, size_t len) {
+
+ RAND_bytes(p, (int) len);
+
+}
+#endif
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/ed25519-donna/ed25519.c b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/ed25519-donna/ed25519.c
new file mode 100644
index 0000000..58a755b
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/ed25519-donna/ed25519.c
@@ -0,0 +1,150 @@
+/*
+ Public domain by Andrew M. <liquidsun@gmail.com>
+
+ Ed25519 reference implementation using Ed25519-donna
+*/
+
+
+/* define ED25519_SUFFIX to have it appended to the end of each public function */
+#if !defined(ED25519_SUFFIX)
+#define ED25519_SUFFIX
+#endif
+
+#define ED25519_FN3(fn,suffix) fn##suffix
+#define ED25519_FN2(fn,suffix) ED25519_FN3(fn,suffix)
+#define ED25519_FN(fn) ED25519_FN2(fn,ED25519_SUFFIX)
+
+#include "ed25519-donna.h"
+#include "ed25519.h"
+#include "ed25519-randombytes.h"
+#include "ed25519-hash.h"
+
+/*
+ Generates a (extsk[0..31]) and aExt (extsk[32..63])
+*/
+
+DONNA_INLINE static void
+ed25519_extsk(hash_512bits extsk, const ed25519_secret_key sk) {
+ ed25519_hash(extsk, sk, 32);
+ extsk[0] &= 248;
+ extsk[31] &= 127;
+ extsk[31] |= 64;
+}
+
+static void
+ed25519_hram(hash_512bits hram, const ed25519_signature RS, const ed25519_public_key pk, const unsigned char *m, size_t mlen) {
+ ed25519_hash_context ctx;
+ ed25519_hash_init(&ctx);
+ ed25519_hash_update(&ctx, RS, 32);
+ ed25519_hash_update(&ctx, pk, 32);
+ ed25519_hash_update(&ctx, m, mlen);
+ ed25519_hash_final(&ctx, hram);
+}
+
+void
+ED25519_FN(ed25519_publickey) (const ed25519_secret_key sk, ed25519_public_key pk) {
+ bignum256modm a;
+ ge25519 ALIGN(16) A;
+ hash_512bits extsk;
+
+ /* A = aB */
+ ed25519_extsk(extsk, sk);
+ expand256_modm(a, extsk, 32);
+ ge25519_scalarmult_base_niels(&A, ge25519_niels_base_multiples, a);
+ ge25519_pack(pk, &A);
+}
+
+
+void
+ED25519_FN(ed25519_sign) (const unsigned char *m, size_t mlen, const ed25519_secret_key sk, const ed25519_public_key pk, ed25519_signature RS) {
+ ed25519_hash_context ctx;
+ bignum256modm r, S, a;
+ ge25519 ALIGN(16) R;
+ hash_512bits extsk, hashr, hram;
+
+ ed25519_extsk(extsk, sk);
+
+ /* r = H(aExt[32..64], m) */
+ ed25519_hash_init(&ctx);
+ ed25519_hash_update(&ctx, extsk + 32, 32);
+ ed25519_hash_update(&ctx, m, mlen);
+ ed25519_hash_final(&ctx, hashr);
+ expand256_modm(r, hashr, 64);
+
+ /* R = rB */
+ ge25519_scalarmult_base_niels(&R, ge25519_niels_base_multiples, r);
+ ge25519_pack(RS, &R);
+
+ /* S = H(R,A,m).. */
+ ed25519_hram(hram, RS, pk, m, mlen);
+ expand256_modm(S, hram, 64);
+
+ /* S = H(R,A,m)a */
+ expand256_modm(a, extsk, 32);
+ mul256_modm(S, S, a);
+
+ /* S = (r + H(R,A,m)a) */
+ add256_modm(S, S, r);
+
+ /* S = (r + H(R,A,m)a) mod L */
+ contract256_modm(RS + 32, S);
+}
+
+int
+ED25519_FN(ed25519_sign_open) (const unsigned char *m, size_t mlen, const ed25519_public_key pk, const ed25519_signature RS) {
+ ge25519 ALIGN(16) R, A;
+ hash_512bits hash;
+ bignum256modm hram, S;
+ unsigned char checkR[32];
+
+ if ((RS[63] & 224) || !ge25519_unpack_negative_vartime(&A, pk))
+ return -1;
+
+ /* hram = H(R,A,m) */
+ ed25519_hram(hash, RS, pk, m, mlen);
+ expand256_modm(hram, hash, 64);
+
+ /* S */
+ expand256_modm(S, RS + 32, 32);
+
+ /* SB - H(R,A,m)A */
+ ge25519_double_scalarmult_vartime(&R, &A, hram, S);
+ ge25519_pack(checkR, &R);
+
+ /* check that R = SB - H(R,A,m)A */
+ return ed25519_verify(RS, checkR, 32) ? 0 : -1;
+}
+
+#include "ed25519-donna-batchverify.h"
+
+/*
+ Fast Curve25519 basepoint scalar multiplication
+*/
+
+void
+ED25519_FN(curved25519_scalarmult_basepoint) (curved25519_key pk, const curved25519_key e) {
+ curved25519_key ec;
+ bignum256modm s;
+ bignum25519 ALIGN(16) yplusz, zminusy;
+ ge25519 ALIGN(16) p;
+ size_t i;
+
+ /* clamp */
+ for (i = 0; i < 32; i++) ec[i] = e[i];
+ ec[0] &= 248;
+ ec[31] &= 127;
+ ec[31] |= 64;
+
+ expand_raw256_modm(s, ec);
+
+ /* scalar * basepoint */
+ ge25519_scalarmult_base_niels(&p, ge25519_niels_base_multiples, s);
+
+ /* u = (y + z) / (z - y) */
+ curve25519_add(yplusz, p.y, p.z);
+ curve25519_sub(zminusy, p.z, p.y);
+ curve25519_recip(zminusy, zminusy);
+ curve25519_mul(yplusz, yplusz, zminusy);
+ curve25519_contract(pk, yplusz);
+}
+
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/ed25519-donna/ed25519.h b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/ed25519-donna/ed25519.h
new file mode 100644
index 0000000..dc86675
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/ed25519-donna/ed25519.h
@@ -0,0 +1,30 @@
+#ifndef ED25519_H
+#define ED25519_H
+
+#include <stdlib.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+typedef unsigned char ed25519_signature[64];
+typedef unsigned char ed25519_public_key[32];
+typedef unsigned char ed25519_secret_key[32];
+
+typedef unsigned char curved25519_key[32];
+
+void ed25519_publickey(const ed25519_secret_key sk, ed25519_public_key pk);
+int ed25519_sign_open(const unsigned char *m, size_t mlen, const ed25519_public_key pk, const ed25519_signature RS);
+void ed25519_sign(const unsigned char *m, size_t mlen, const ed25519_secret_key sk, const ed25519_public_key pk, ed25519_signature RS);
+
+int ed25519_sign_open_batch(const unsigned char **m, size_t *mlen, const unsigned char **pk, const unsigned char **RS, size_t num, int *valid);
+
+void ed25519_randombytes_unsafe(void *out, size_t count);
+
+void curved25519_scalarmult_basepoint(curved25519_key pk, const curved25519_key e);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif // ED25519_H
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/ed25519-donna/modm-donna-32bit.h b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/ed25519-donna/modm-donna-32bit.h
new file mode 100644
index 0000000..62a5d3b
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/ed25519-donna/modm-donna-32bit.h
@@ -0,0 +1,469 @@
+ /*
+ Public domain by Andrew M. <liquidsun@gmail.com>
+*/
+
+
+/*
+ Arithmetic modulo the group order n = 2^252 + 27742317777372353535851937790883648493 = 7237005577332262213973186563042994240857116359379907606001950938285454250989
+
+ k = 32
+ b = 1 << 8 = 256
+ m = 2^252 + 27742317777372353535851937790883648493 = 0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed
+ mu = floor( b^(k*2) / m ) = 0xfffffffffffffffffffffffffffffffeb2106215d086329a7ed9ce5a30a2c131b
+*/
+
+#define bignum256modm_bits_per_limb 30
+#define bignum256modm_limb_size 9
+
+typedef uint32_t bignum256modm_element_t;
+typedef bignum256modm_element_t bignum256modm[9];
+
+static const bignum256modm modm_m = {
+ 0x1cf5d3ed, 0x20498c69, 0x2f79cd65, 0x37be77a8,
+ 0x00000014, 0x00000000, 0x00000000, 0x00000000,
+ 0x00001000
+};
+
+static const bignum256modm modm_mu = {
+ 0x0a2c131b, 0x3673968c, 0x06329a7e, 0x01885742,
+ 0x3fffeb21, 0x3fffffff, 0x3fffffff, 0x3fffffff,
+ 0x000fffff
+};
+
+static bignum256modm_element_t
+lt_modm(bignum256modm_element_t a, bignum256modm_element_t b) {
+ return (a - b) >> 31;
+}
+
+/* see HAC, Alg. 14.42 Step 4 */
+static void
+reduce256_modm(bignum256modm r) {
+ bignum256modm t;
+ bignum256modm_element_t b = 0, pb, mask;
+
+ /* t = r - m */
+ pb = 0;
+ pb += modm_m[0]; b = lt_modm(r[0], pb); t[0] = (r[0] - pb + (b << 30)); pb = b;
+ pb += modm_m[1]; b = lt_modm(r[1], pb); t[1] = (r[1] - pb + (b << 30)); pb = b;
+ pb += modm_m[2]; b = lt_modm(r[2], pb); t[2] = (r[2] - pb + (b << 30)); pb = b;
+ pb += modm_m[3]; b = lt_modm(r[3], pb); t[3] = (r[3] - pb + (b << 30)); pb = b;
+ pb += modm_m[4]; b = lt_modm(r[4], pb); t[4] = (r[4] - pb + (b << 30)); pb = b;
+ pb += modm_m[5]; b = lt_modm(r[5], pb); t[5] = (r[5] - pb + (b << 30)); pb = b;
+ pb += modm_m[6]; b = lt_modm(r[6], pb); t[6] = (r[6] - pb + (b << 30)); pb = b;
+ pb += modm_m[7]; b = lt_modm(r[7], pb); t[7] = (r[7] - pb + (b << 30)); pb = b;
+ pb += modm_m[8]; b = lt_modm(r[8], pb); t[8] = (r[8] - pb + (b << 16));
+
+ /* keep r if r was smaller than m */
+ mask = b - 1;
+ r[0] ^= mask & (r[0] ^ t[0]);
+ r[1] ^= mask & (r[1] ^ t[1]);
+ r[2] ^= mask & (r[2] ^ t[2]);
+ r[3] ^= mask & (r[3] ^ t[3]);
+ r[4] ^= mask & (r[4] ^ t[4]);
+ r[5] ^= mask & (r[5] ^ t[5]);
+ r[6] ^= mask & (r[6] ^ t[6]);
+ r[7] ^= mask & (r[7] ^ t[7]);
+ r[8] ^= mask & (r[8] ^ t[8]);
+}
+
+/*
+ Barrett reduction, see HAC, Alg. 14.42
+
+ Instead of passing in x, pre-process in to q1 and r1 for efficiency
+*/
+static void
+barrett_reduce256_modm(bignum256modm r, const bignum256modm q1, const bignum256modm r1) {
+ bignum256modm q3, r2;
+ uint64_t c;
+ bignum256modm_element_t f, b, pb;
+
+ /* q1 = x >> 248 = 264 bits = 9 30 bit elements
+ q2 = mu * q1
+ q3 = (q2 / 256(32+1)) = q2 / (2^8)^(32+1) = q2 >> 264 */
+ c = mul32x32_64(modm_mu[0], q1[7]) + mul32x32_64(modm_mu[1], q1[6]) + mul32x32_64(modm_mu[2], q1[5]) + mul32x32_64(modm_mu[3], q1[4]) + mul32x32_64(modm_mu[4], q1[3]) + mul32x32_64(modm_mu[5], q1[2]) + mul32x32_64(modm_mu[6], q1[1]) + mul32x32_64(modm_mu[7], q1[0]);
+ c >>= 30;
+ c += mul32x32_64(modm_mu[0], q1[8]) + mul32x32_64(modm_mu[1], q1[7]) + mul32x32_64(modm_mu[2], q1[6]) + mul32x32_64(modm_mu[3], q1[5]) + mul32x32_64(modm_mu[4], q1[4]) + mul32x32_64(modm_mu[5], q1[3]) + mul32x32_64(modm_mu[6], q1[2]) + mul32x32_64(modm_mu[7], q1[1]) + mul32x32_64(modm_mu[8], q1[0]);
+ f = (bignum256modm_element_t)c; q3[0] = (f >> 24) & 0x3f; c >>= 30;
+ c += mul32x32_64(modm_mu[1], q1[8]) + mul32x32_64(modm_mu[2], q1[7]) + mul32x32_64(modm_mu[3], q1[6]) + mul32x32_64(modm_mu[4], q1[5]) + mul32x32_64(modm_mu[5], q1[4]) + mul32x32_64(modm_mu[6], q1[3]) + mul32x32_64(modm_mu[7], q1[2]) + mul32x32_64(modm_mu[8], q1[1]);
+ f = (bignum256modm_element_t)c; q3[0] |= (f << 6) & 0x3fffffff; q3[1] = (f >> 24) & 0x3f; c >>= 30;
+ c += mul32x32_64(modm_mu[2], q1[8]) + mul32x32_64(modm_mu[3], q1[7]) + mul32x32_64(modm_mu[4], q1[6]) + mul32x32_64(modm_mu[5], q1[5]) + mul32x32_64(modm_mu[6], q1[4]) + mul32x32_64(modm_mu[7], q1[3]) + mul32x32_64(modm_mu[8], q1[2]);
+ f = (bignum256modm_element_t)c; q3[1] |= (f << 6) & 0x3fffffff; q3[2] = (f >> 24) & 0x3f; c >>= 30;
+ c += mul32x32_64(modm_mu[3], q1[8]) + mul32x32_64(modm_mu[4], q1[7]) + mul32x32_64(modm_mu[5], q1[6]) + mul32x32_64(modm_mu[6], q1[5]) + mul32x32_64(modm_mu[7], q1[4]) + mul32x32_64(modm_mu[8], q1[3]);
+ f = (bignum256modm_element_t)c; q3[2] |= (f << 6) & 0x3fffffff; q3[3] = (f >> 24) & 0x3f; c >>= 30;
+ c += mul32x32_64(modm_mu[4], q1[8]) + mul32x32_64(modm_mu[5], q1[7]) + mul32x32_64(modm_mu[6], q1[6]) + mul32x32_64(modm_mu[7], q1[5]) + mul32x32_64(modm_mu[8], q1[4]);
+ f = (bignum256modm_element_t)c; q3[3] |= (f << 6) & 0x3fffffff; q3[4] = (f >> 24) & 0x3f; c >>= 30;
+ c += mul32x32_64(modm_mu[5], q1[8]) + mul32x32_64(modm_mu[6], q1[7]) + mul32x32_64(modm_mu[7], q1[6]) + mul32x32_64(modm_mu[8], q1[5]);
+ f = (bignum256modm_element_t)c; q3[4] |= (f << 6) & 0x3fffffff; q3[5] = (f >> 24) & 0x3f; c >>= 30;
+ c += mul32x32_64(modm_mu[6], q1[8]) + mul32x32_64(modm_mu[7], q1[7]) + mul32x32_64(modm_mu[8], q1[6]);
+ f = (bignum256modm_element_t)c; q3[5] |= (f << 6) & 0x3fffffff; q3[6] = (f >> 24) & 0x3f; c >>= 30;
+ c += mul32x32_64(modm_mu[7], q1[8]) + mul32x32_64(modm_mu[8], q1[7]);
+ f = (bignum256modm_element_t)c; q3[6] |= (f << 6) & 0x3fffffff; q3[7] = (f >> 24) & 0x3f; c >>= 30;
+ c += mul32x32_64(modm_mu[8], q1[8]);
+ f = (bignum256modm_element_t)c; q3[7] |= (f << 6) & 0x3fffffff; q3[8] = (bignum256modm_element_t)(c >> 24);
+
+ /* r1 = (x mod 256^(32+1)) = x mod (2^8)(31+1) = x & ((1 << 264) - 1)
+ r2 = (q3 * m) mod (256^(32+1)) = (q3 * m) & ((1 << 264) - 1) */
+ c = mul32x32_64(modm_m[0], q3[0]);
+ r2[0] = (bignum256modm_element_t)(c & 0x3fffffff); c >>= 30;
+ c += mul32x32_64(modm_m[0], q3[1]) + mul32x32_64(modm_m[1], q3[0]);
+ r2[1] = (bignum256modm_element_t)(c & 0x3fffffff); c >>= 30;
+ c += mul32x32_64(modm_m[0], q3[2]) + mul32x32_64(modm_m[1], q3[1]) + mul32x32_64(modm_m[2], q3[0]);
+ r2[2] = (bignum256modm_element_t)(c & 0x3fffffff); c >>= 30;
+ c += mul32x32_64(modm_m[0], q3[3]) + mul32x32_64(modm_m[1], q3[2]) + mul32x32_64(modm_m[2], q3[1]) + mul32x32_64(modm_m[3], q3[0]);
+ r2[3] = (bignum256modm_element_t)(c & 0x3fffffff); c >>= 30;
+ c += mul32x32_64(modm_m[0], q3[4]) + mul32x32_64(modm_m[1], q3[3]) + mul32x32_64(modm_m[2], q3[2]) + mul32x32_64(modm_m[3], q3[1]) + mul32x32_64(modm_m[4], q3[0]);
+ r2[4] = (bignum256modm_element_t)(c & 0x3fffffff); c >>= 30;
+ c += mul32x32_64(modm_m[0], q3[5]) + mul32x32_64(modm_m[1], q3[4]) + mul32x32_64(modm_m[2], q3[3]) + mul32x32_64(modm_m[3], q3[2]) + mul32x32_64(modm_m[4], q3[1]) + mul32x32_64(modm_m[5], q3[0]);
+ r2[5] = (bignum256modm_element_t)(c & 0x3fffffff); c >>= 30;
+ c += mul32x32_64(modm_m[0], q3[6]) + mul32x32_64(modm_m[1], q3[5]) + mul32x32_64(modm_m[2], q3[4]) + mul32x32_64(modm_m[3], q3[3]) + mul32x32_64(modm_m[4], q3[2]) + mul32x32_64(modm_m[5], q3[1]) + mul32x32_64(modm_m[6], q3[0]);
+ r2[6] = (bignum256modm_element_t)(c & 0x3fffffff); c >>= 30;
+ c += mul32x32_64(modm_m[0], q3[7]) + mul32x32_64(modm_m[1], q3[6]) + mul32x32_64(modm_m[2], q3[5]) + mul32x32_64(modm_m[3], q3[4]) + mul32x32_64(modm_m[4], q3[3]) + mul32x32_64(modm_m[5], q3[2]) + mul32x32_64(modm_m[6], q3[1]) + mul32x32_64(modm_m[7], q3[0]);
+ r2[7] = (bignum256modm_element_t)(c & 0x3fffffff); c >>= 30;
+ c += mul32x32_64(modm_m[0], q3[8]) + mul32x32_64(modm_m[1], q3[7]) + mul32x32_64(modm_m[2], q3[6]) + mul32x32_64(modm_m[3], q3[5]) + mul32x32_64(modm_m[4], q3[4]) + mul32x32_64(modm_m[5], q3[3]) + mul32x32_64(modm_m[6], q3[2]) + mul32x32_64(modm_m[7], q3[1]) + mul32x32_64(modm_m[8], q3[0]);
+ r2[8] = (bignum256modm_element_t)(c & 0xffffff);
+
+ /* r = r1 - r2
+ if (r < 0) r += (1 << 264) */
+ pb = 0;
+ pb += r2[0]; b = lt_modm(r1[0], pb); r[0] = (r1[0] - pb + (b << 30)); pb = b;
+ pb += r2[1]; b = lt_modm(r1[1], pb); r[1] = (r1[1] - pb + (b << 30)); pb = b;
+ pb += r2[2]; b = lt_modm(r1[2], pb); r[2] = (r1[2] - pb + (b << 30)); pb = b;
+ pb += r2[3]; b = lt_modm(r1[3], pb); r[3] = (r1[3] - pb + (b << 30)); pb = b;
+ pb += r2[4]; b = lt_modm(r1[4], pb); r[4] = (r1[4] - pb + (b << 30)); pb = b;
+ pb += r2[5]; b = lt_modm(r1[5], pb); r[5] = (r1[5] - pb + (b << 30)); pb = b;
+ pb += r2[6]; b = lt_modm(r1[6], pb); r[6] = (r1[6] - pb + (b << 30)); pb = b;
+ pb += r2[7]; b = lt_modm(r1[7], pb); r[7] = (r1[7] - pb + (b << 30)); pb = b;
+ pb += r2[8]; b = lt_modm(r1[8], pb); r[8] = (r1[8] - pb + (b << 24));
+
+ reduce256_modm(r);
+ reduce256_modm(r);
+}
+
+/* addition modulo m */
+static void
+add256_modm(bignum256modm r, const bignum256modm x, const bignum256modm y) {
+ bignum256modm_element_t c;
+
+ c = x[0] + y[0]; r[0] = c & 0x3fffffff; c >>= 30;
+ c += x[1] + y[1]; r[1] = c & 0x3fffffff; c >>= 30;
+ c += x[2] + y[2]; r[2] = c & 0x3fffffff; c >>= 30;
+ c += x[3] + y[3]; r[3] = c & 0x3fffffff; c >>= 30;
+ c += x[4] + y[4]; r[4] = c & 0x3fffffff; c >>= 30;
+ c += x[5] + y[5]; r[5] = c & 0x3fffffff; c >>= 30;
+ c += x[6] + y[6]; r[6] = c & 0x3fffffff; c >>= 30;
+ c += x[7] + y[7]; r[7] = c & 0x3fffffff; c >>= 30;
+ c += x[8] + y[8]; r[8] = c;
+
+ reduce256_modm(r);
+}
+
+/* multiplication modulo m */
+static void
+mul256_modm(bignum256modm r, const bignum256modm x, const bignum256modm y) {
+ bignum256modm r1, q1;
+ uint64_t c;
+ bignum256modm_element_t f;
+
+ /* r1 = (x mod 256^(32+1)) = x mod (2^8)(31+1) = x & ((1 << 264) - 1)
+ q1 = x >> 248 = 264 bits = 9 30 bit elements */
+ c = mul32x32_64(x[0], y[0]);
+ f = (bignum256modm_element_t)c; r1[0] = (f & 0x3fffffff); c >>= 30;
+ c += mul32x32_64(x[0], y[1]) + mul32x32_64(x[1], y[0]);
+ f = (bignum256modm_element_t)c; r1[1] = (f & 0x3fffffff); c >>= 30;
+ c += mul32x32_64(x[0], y[2]) + mul32x32_64(x[1], y[1]) + mul32x32_64(x[2], y[0]);
+ f = (bignum256modm_element_t)c; r1[2] = (f & 0x3fffffff); c >>= 30;
+ c += mul32x32_64(x[0], y[3]) + mul32x32_64(x[1], y[2]) + mul32x32_64(x[2], y[1]) + mul32x32_64(x[3], y[0]);
+ f = (bignum256modm_element_t)c; r1[3] = (f & 0x3fffffff); c >>= 30;
+ c += mul32x32_64(x[0], y[4]) + mul32x32_64(x[1], y[3]) + mul32x32_64(x[2], y[2]) + mul32x32_64(x[3], y[1]) + mul32x32_64(x[4], y[0]);
+ f = (bignum256modm_element_t)c; r1[4] = (f & 0x3fffffff); c >>= 30;
+ c += mul32x32_64(x[0], y[5]) + mul32x32_64(x[1], y[4]) + mul32x32_64(x[2], y[3]) + mul32x32_64(x[3], y[2]) + mul32x32_64(x[4], y[1]) + mul32x32_64(x[5], y[0]);
+ f = (bignum256modm_element_t)c; r1[5] = (f & 0x3fffffff); c >>= 30;
+ c += mul32x32_64(x[0], y[6]) + mul32x32_64(x[1], y[5]) + mul32x32_64(x[2], y[4]) + mul32x32_64(x[3], y[3]) + mul32x32_64(x[4], y[2]) + mul32x32_64(x[5], y[1]) + mul32x32_64(x[6], y[0]);
+ f = (bignum256modm_element_t)c; r1[6] = (f & 0x3fffffff); c >>= 30;
+ c += mul32x32_64(x[0], y[7]) + mul32x32_64(x[1], y[6]) + mul32x32_64(x[2], y[5]) + mul32x32_64(x[3], y[4]) + mul32x32_64(x[4], y[3]) + mul32x32_64(x[5], y[2]) + mul32x32_64(x[6], y[1]) + mul32x32_64(x[7], y[0]);
+ f = (bignum256modm_element_t)c; r1[7] = (f & 0x3fffffff); c >>= 30;
+ c += mul32x32_64(x[0], y[8]) + mul32x32_64(x[1], y[7]) + mul32x32_64(x[2], y[6]) + mul32x32_64(x[3], y[5]) + mul32x32_64(x[4], y[4]) + mul32x32_64(x[5], y[3]) + mul32x32_64(x[6], y[2]) + mul32x32_64(x[7], y[1]) + mul32x32_64(x[8], y[0]);
+ f = (bignum256modm_element_t)c; r1[8] = (f & 0x00ffffff); q1[0] = (f >> 8) & 0x3fffff; c >>= 30;
+ c += mul32x32_64(x[1], y[8]) + mul32x32_64(x[2], y[7]) + mul32x32_64(x[3], y[6]) + mul32x32_64(x[4], y[5]) + mul32x32_64(x[5], y[4]) + mul32x32_64(x[6], y[3]) + mul32x32_64(x[7], y[2]) + mul32x32_64(x[8], y[1]);
+ f = (bignum256modm_element_t)c; q1[0] = (q1[0] | (f << 22)) & 0x3fffffff; q1[1] = (f >> 8) & 0x3fffff; c >>= 30;
+ c += mul32x32_64(x[2], y[8]) + mul32x32_64(x[3], y[7]) + mul32x32_64(x[4], y[6]) + mul32x32_64(x[5], y[5]) + mul32x32_64(x[6], y[4]) + mul32x32_64(x[7], y[3]) + mul32x32_64(x[8], y[2]);
+ f = (bignum256modm_element_t)c; q1[1] = (q1[1] | (f << 22)) & 0x3fffffff; q1[2] = (f >> 8) & 0x3fffff; c >>= 30;
+ c += mul32x32_64(x[3], y[8]) + mul32x32_64(x[4], y[7]) + mul32x32_64(x[5], y[6]) + mul32x32_64(x[6], y[5]) + mul32x32_64(x[7], y[4]) + mul32x32_64(x[8], y[3]);
+ f = (bignum256modm_element_t)c; q1[2] = (q1[2] | (f << 22)) & 0x3fffffff; q1[3] = (f >> 8) & 0x3fffff; c >>= 30;
+ c += mul32x32_64(x[4], y[8]) + mul32x32_64(x[5], y[7]) + mul32x32_64(x[6], y[6]) + mul32x32_64(x[7], y[5]) + mul32x32_64(x[8], y[4]);
+ f = (bignum256modm_element_t)c; q1[3] = (q1[3] | (f << 22)) & 0x3fffffff; q1[4] = (f >> 8) & 0x3fffff; c >>= 30;
+ c += mul32x32_64(x[5], y[8]) + mul32x32_64(x[6], y[7]) + mul32x32_64(x[7], y[6]) + mul32x32_64(x[8], y[5]);
+ f = (bignum256modm_element_t)c; q1[4] = (q1[4] | (f << 22)) & 0x3fffffff; q1[5] = (f >> 8) & 0x3fffff; c >>= 30;
+ c += mul32x32_64(x[6], y[8]) + mul32x32_64(x[7], y[7]) + mul32x32_64(x[8], y[6]);
+ f = (bignum256modm_element_t)c; q1[5] = (q1[5] | (f << 22)) & 0x3fffffff; q1[6] = (f >> 8) & 0x3fffff; c >>= 30;
+ c += mul32x32_64(x[7], y[8]) + mul32x32_64(x[8], y[7]);
+ f = (bignum256modm_element_t)c; q1[6] = (q1[6] | (f << 22)) & 0x3fffffff; q1[7] = (f >> 8) & 0x3fffff; c >>= 30;
+ c += mul32x32_64(x[8], y[8]);
+ f = (bignum256modm_element_t)c; q1[7] = (q1[7] | (f << 22)) & 0x3fffffff; q1[8] = (f >> 8) & 0x3fffff;
+
+ barrett_reduce256_modm(r, q1, r1);
+}
+
+static void
+expand256_modm(bignum256modm out, const unsigned char *in, size_t len) {
+ unsigned char work[64] = {0};
+ bignum256modm_element_t x[16];
+ bignum256modm q1;
+
+ memcpy(work, in, len);
+ x[0] = U8TO32_LE(work + 0);
+ x[1] = U8TO32_LE(work + 4);
+ x[2] = U8TO32_LE(work + 8);
+ x[3] = U8TO32_LE(work + 12);
+ x[4] = U8TO32_LE(work + 16);
+ x[5] = U8TO32_LE(work + 20);
+ x[6] = U8TO32_LE(work + 24);
+ x[7] = U8TO32_LE(work + 28);
+ x[8] = U8TO32_LE(work + 32);
+ x[9] = U8TO32_LE(work + 36);
+ x[10] = U8TO32_LE(work + 40);
+ x[11] = U8TO32_LE(work + 44);
+ x[12] = U8TO32_LE(work + 48);
+ x[13] = U8TO32_LE(work + 52);
+ x[14] = U8TO32_LE(work + 56);
+ x[15] = U8TO32_LE(work + 60);
+
+ /* r1 = (x mod 256^(32+1)) = x mod (2^8)(31+1) = x & ((1 << 264) - 1) */
+ out[0] = ( x[0]) & 0x3fffffff;
+ out[1] = ((x[ 0] >> 30) | (x[ 1] << 2)) & 0x3fffffff;
+ out[2] = ((x[ 1] >> 28) | (x[ 2] << 4)) & 0x3fffffff;
+ out[3] = ((x[ 2] >> 26) | (x[ 3] << 6)) & 0x3fffffff;
+ out[4] = ((x[ 3] >> 24) | (x[ 4] << 8)) & 0x3fffffff;
+ out[5] = ((x[ 4] >> 22) | (x[ 5] << 10)) & 0x3fffffff;
+ out[6] = ((x[ 5] >> 20) | (x[ 6] << 12)) & 0x3fffffff;
+ out[7] = ((x[ 6] >> 18) | (x[ 7] << 14)) & 0x3fffffff;
+ out[8] = ((x[ 7] >> 16) | (x[ 8] << 16)) & 0x00ffffff;
+
+ /* 8*31 = 248 bits, no need to reduce */
+ if (len < 32)
+ return;
+
+ /* q1 = x >> 248 = 264 bits = 9 30 bit elements */
+ q1[0] = ((x[ 7] >> 24) | (x[ 8] << 8)) & 0x3fffffff;
+ q1[1] = ((x[ 8] >> 22) | (x[ 9] << 10)) & 0x3fffffff;
+ q1[2] = ((x[ 9] >> 20) | (x[10] << 12)) & 0x3fffffff;
+ q1[3] = ((x[10] >> 18) | (x[11] << 14)) & 0x3fffffff;
+ q1[4] = ((x[11] >> 16) | (x[12] << 16)) & 0x3fffffff;
+ q1[5] = ((x[12] >> 14) | (x[13] << 18)) & 0x3fffffff;
+ q1[6] = ((x[13] >> 12) | (x[14] << 20)) & 0x3fffffff;
+ q1[7] = ((x[14] >> 10) | (x[15] << 22)) & 0x3fffffff;
+ q1[8] = ((x[15] >> 8) );
+
+ barrett_reduce256_modm(out, q1, out);
+}
+
+static void
+expand_raw256_modm(bignum256modm out, const unsigned char in[32]) {
+ bignum256modm_element_t x[8];
+
+ x[0] = U8TO32_LE(in + 0);
+ x[1] = U8TO32_LE(in + 4);
+ x[2] = U8TO32_LE(in + 8);
+ x[3] = U8TO32_LE(in + 12);
+ x[4] = U8TO32_LE(in + 16);
+ x[5] = U8TO32_LE(in + 20);
+ x[6] = U8TO32_LE(in + 24);
+ x[7] = U8TO32_LE(in + 28);
+
+ out[0] = ( x[0]) & 0x3fffffff;
+ out[1] = ((x[ 0] >> 30) | (x[ 1] << 2)) & 0x3fffffff;
+ out[2] = ((x[ 1] >> 28) | (x[ 2] << 4)) & 0x3fffffff;
+ out[3] = ((x[ 2] >> 26) | (x[ 3] << 6)) & 0x3fffffff;
+ out[4] = ((x[ 3] >> 24) | (x[ 4] << 8)) & 0x3fffffff;
+ out[5] = ((x[ 4] >> 22) | (x[ 5] << 10)) & 0x3fffffff;
+ out[6] = ((x[ 5] >> 20) | (x[ 6] << 12)) & 0x3fffffff;
+ out[7] = ((x[ 6] >> 18) | (x[ 7] << 14)) & 0x3fffffff;
+ out[8] = ((x[ 7] >> 16) ) & 0x0000ffff;
+}
+
+static void
+contract256_modm(unsigned char out[32], const bignum256modm in) {
+ U32TO8_LE(out + 0, (in[0] ) | (in[1] << 30));
+ U32TO8_LE(out + 4, (in[1] >> 2) | (in[2] << 28));
+ U32TO8_LE(out + 8, (in[2] >> 4) | (in[3] << 26));
+ U32TO8_LE(out + 12, (in[3] >> 6) | (in[4] << 24));
+ U32TO8_LE(out + 16, (in[4] >> 8) | (in[5] << 22));
+ U32TO8_LE(out + 20, (in[5] >> 10) | (in[6] << 20));
+ U32TO8_LE(out + 24, (in[6] >> 12) | (in[7] << 18));
+ U32TO8_LE(out + 28, (in[7] >> 14) | (in[8] << 16));
+}
+
+
+
+static void
+contract256_window4_modm(signed char r[64], const bignum256modm in) {
+ char carry;
+ signed char *quads = r;
+ bignum256modm_element_t i, j, v;
+
+ for (i = 0; i < 8; i += 2) {
+ v = in[i];
+ for (j = 0; j < 7; j++) {
+ *quads++ = (v & 15);
+ v >>= 4;
+ }
+ v |= (in[i+1] << 2);
+ for (j = 0; j < 8; j++) {
+ *quads++ = (v & 15);
+ v >>= 4;
+ }
+ }
+ v = in[8];
+ *quads++ = (v & 15); v >>= 4;
+ *quads++ = (v & 15); v >>= 4;
+ *quads++ = (v & 15); v >>= 4;
+ *quads++ = (v & 15); v >>= 4;
+
+ /* making it signed */
+ carry = 0;
+ for(i = 0; i < 63; i++) {
+ r[i] += carry;
+ r[i+1] += (r[i] >> 4);
+ r[i] &= 15;
+ carry = (r[i] >> 3);
+ r[i] -= (carry << 4);
+ }
+ r[63] += carry;
+}
+
+static void
+contract256_slidingwindow_modm(signed char r[256], const bignum256modm s, int windowsize) {
+ int i,j,k,b;
+ int m = (1 << (windowsize - 1)) - 1, soplen = 256;
+ signed char *bits = r;
+ bignum256modm_element_t v;
+
+ /* first put the binary expansion into r */
+ for (i = 0; i < 8; i++) {
+ v = s[i];
+ for (j = 0; j < 30; j++, v >>= 1)
+ *bits++ = (v & 1);
+ }
+ v = s[8];
+ for (j = 0; j < 16; j++, v >>= 1)
+ *bits++ = (v & 1);
+
+ /* Making it sliding window */
+ for (j = 0; j < soplen; j++) {
+ if (!r[j])
+ continue;
+
+ for (b = 1; (b < (soplen - j)) && (b <= 6); b++) {
+ if ((r[j] + (r[j + b] << b)) <= m) {
+ r[j] += r[j + b] << b;
+ r[j + b] = 0;
+ } else if ((r[j] - (r[j + b] << b)) >= -m) {
+ r[j] -= r[j + b] << b;
+ for (k = j + b; k < soplen; k++) {
+ if (!r[k]) {
+ r[k] = 1;
+ break;
+ }
+ r[k] = 0;
+ }
+ } else if (r[j + b]) {
+ break;
+ }
+ }
+ }
+}
+
+
+/*
+ helpers for batch verifcation, are allowed to be vartime
+*/
+
+/* out = a - b, a must be larger than b */
+static void
+sub256_modm_batch(bignum256modm out, const bignum256modm a, const bignum256modm b, size_t limbsize) {
+ size_t i = 0;
+ bignum256modm_element_t carry = 0;
+ switch (limbsize) {
+ case 8: out[i] = (a[i] - b[i]) - carry; carry = (out[i] >> 31); out[i] &= 0x3fffffff; i++; /* FALLTHRU */
+ case 7: out[i] = (a[i] - b[i]) - carry; carry = (out[i] >> 31); out[i] &= 0x3fffffff; i++; /* FALLTHRU */
+ case 6: out[i] = (a[i] - b[i]) - carry; carry = (out[i] >> 31); out[i] &= 0x3fffffff; i++; /* FALLTHRU */
+ case 5: out[i] = (a[i] - b[i]) - carry; carry = (out[i] >> 31); out[i] &= 0x3fffffff; i++; /* FALLTHRU */
+ case 4: out[i] = (a[i] - b[i]) - carry; carry = (out[i] >> 31); out[i] &= 0x3fffffff; i++; /* FALLTHRU */
+ case 3: out[i] = (a[i] - b[i]) - carry; carry = (out[i] >> 31); out[i] &= 0x3fffffff; i++; /* FALLTHRU */
+ case 2: out[i] = (a[i] - b[i]) - carry; carry = (out[i] >> 31); out[i] &= 0x3fffffff; i++; /* FALLTHRU */
+ case 1: out[i] = (a[i] - b[i]) - carry; carry = (out[i] >> 31); out[i] &= 0x3fffffff; i++; /* FALLTHRU */
+ case 0:
+ default: out[i] = (a[i] - b[i]) - carry;
+ }
+}
+
+
+/* is a < b */
+static int
+lt256_modm_batch(const bignum256modm a, const bignum256modm b, size_t limbsize) {
+ switch (limbsize) {
+ case 8: if (a[8] > b[8]) return 0; if (a[8] < b[8]) return 1; /* FALLTHRU */
+ case 7: if (a[7] > b[7]) return 0; if (a[7] < b[7]) return 1; /* FALLTHRU */
+ case 6: if (a[6] > b[6]) return 0; if (a[6] < b[6]) return 1; /* FALLTHRU */
+ case 5: if (a[5] > b[5]) return 0; if (a[5] < b[5]) return 1; /* FALLTHRU */
+ case 4: if (a[4] > b[4]) return 0; if (a[4] < b[4]) return 1; /* FALLTHRU */
+ case 3: if (a[3] > b[3]) return 0; if (a[3] < b[3]) return 1; /* FALLTHRU */
+ case 2: if (a[2] > b[2]) return 0; if (a[2] < b[2]) return 1; /* FALLTHRU */
+ case 1: if (a[1] > b[1]) return 0; if (a[1] < b[1]) return 1; /* FALLTHRU */
+ case 0: if (a[0] > b[0]) return 0; if (a[0] < b[0]) return 1; /* FALLTHRU */
+ }
+ return 0;
+}
+
+/* is a <= b */
+static int
+lte256_modm_batch(const bignum256modm a, const bignum256modm b, size_t limbsize) {
+ switch (limbsize) {
+ case 8: if (a[8] > b[8]) return 0; if (a[8] < b[8]) return 1; /* FALLTHRU */
+ case 7: if (a[7] > b[7]) return 0; if (a[7] < b[7]) return 1; /* FALLTHRU */
+ case 6: if (a[6] > b[6]) return 0; if (a[6] < b[6]) return 1; /* FALLTHRU */
+ case 5: if (a[5] > b[5]) return 0; if (a[5] < b[5]) return 1; /* FALLTHRU */
+ case 4: if (a[4] > b[4]) return 0; if (a[4] < b[4]) return 1; /* FALLTHRU */
+ case 3: if (a[3] > b[3]) return 0; if (a[3] < b[3]) return 1; /* FALLTHRU */
+ case 2: if (a[2] > b[2]) return 0; if (a[2] < b[2]) return 1; /* FALLTHRU */
+ case 1: if (a[1] > b[1]) return 0; if (a[1] < b[1]) return 1; /* FALLTHRU */
+ case 0: if (a[0] > b[0]) return 0; if (a[0] < b[0]) return 1; /* FALLTHRU */
+ }
+ return 1;
+}
+
+
+/* is a == 0 */
+static int
+iszero256_modm_batch(const bignum256modm a) {
+ size_t i;
+ for (i = 0; i < 9; i++)
+ if (a[i])
+ return 0;
+ return 1;
+}
+
+/* is a == 1 */
+static int
+isone256_modm_batch(const bignum256modm a) {
+ size_t i;
+ if (a[0] != 1)
+ return 0;
+ for (i = 1; i < 9; i++)
+ if (a[i])
+ return 0;
+ return 1;
+}
+
+/* can a fit in to (at most) 128 bits */
+static int
+isatmost128bits256_modm_batch(const bignum256modm a) {
+ uint32_t mask =
+ ((a[8] ) | /* 16 */
+ (a[7] ) | /* 46 */
+ (a[6] ) | /* 76 */
+ (a[5] ) | /* 106 */
+ (a[4] & 0x3fffff00)); /* 128 */
+
+ return (mask == 0);
+}
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/LICENCE b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/LICENCE
new file mode 100644
index 0000000..0e259d4
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/LICENCE
@@ -0,0 +1,121 @@
+Creative Commons Legal Code
+
+CC0 1.0 Universal
+
+ CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
+ LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
+ ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
+ INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
+ REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
+ PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
+ THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
+ HEREUNDER.
+
+Statement of Purpose
+
+The laws of most jurisdictions throughout the world automatically confer
+exclusive Copyright and Related Rights (defined below) upon the creator
+and subsequent owner(s) (each and all, an "owner") of an original work of
+authorship and/or a database (each, a "Work").
+
+Certain owners wish to permanently relinquish those rights to a Work for
+the purpose of contributing to a commons of creative, cultural and
+scientific works ("Commons") that the public can reliably and without fear
+of later claims of infringement build upon, modify, incorporate in other
+works, reuse and redistribute as freely as possible in any form whatsoever
+and for any purposes, including without limitation commercial purposes.
+These owners may contribute to the Commons to promote the ideal of a free
+culture and the further production of creative, cultural and scientific
+works, or to gain reputation or greater distribution for their Work in
+part through the use and efforts of others.
+
+For these and/or other purposes and motivations, and without any
+expectation of additional consideration or compensation, the person
+associating CC0 with a Work (the "Affirmer"), to the extent that he or she
+is an owner of Copyright and Related Rights in the Work, voluntarily
+elects to apply CC0 to the Work and publicly distribute the Work under its
+terms, with knowledge of his or her Copyright and Related Rights in the
+Work and the meaning and intended legal effect of CC0 on those rights.
+
+1. Copyright and Related Rights. A Work made available under CC0 may be
+protected by copyright and related or neighboring rights ("Copyright and
+Related Rights"). Copyright and Related Rights include, but are not
+limited to, the following:
+
+ i. the right to reproduce, adapt, distribute, perform, display,
+ communicate, and translate a Work;
+ ii. moral rights retained by the original author(s) and/or performer(s);
+iii. publicity and privacy rights pertaining to a person's image or
+ likeness depicted in a Work;
+ iv. rights protecting against unfair competition in regards to a Work,
+ subject to the limitations in paragraph 4(a), below;
+ v. rights protecting the extraction, dissemination, use and reuse of data
+ in a Work;
+ vi. database rights (such as those arising under Directive 96/9/EC of the
+ European Parliament and of the Council of 11 March 1996 on the legal
+ protection of databases, and under any national implementation
+ thereof, including any amended or successor version of such
+ directive); and
+vii. other similar, equivalent or corresponding rights throughout the
+ world based on applicable law or treaty, and any national
+ implementations thereof.
+
+2. Waiver. To the greatest extent permitted by, but not in contravention
+of, applicable law, Affirmer hereby overtly, fully, permanently,
+irrevocably and unconditionally waives, abandons, and surrenders all of
+Affirmer's Copyright and Related Rights and associated claims and causes
+of action, whether now known or unknown (including existing as well as
+future claims and causes of action), in the Work (i) in all territories
+worldwide, (ii) for the maximum duration provided by applicable law or
+treaty (including future time extensions), (iii) in any current or future
+medium and for any number of copies, and (iv) for any purpose whatsoever,
+including without limitation commercial, advertising or promotional
+purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
+member of the public at large and to the detriment of Affirmer's heirs and
+successors, fully intending that such Waiver shall not be subject to
+revocation, rescission, cancellation, termination, or any other legal or
+equitable action to disrupt the quiet enjoyment of the Work by the public
+as contemplated by Affirmer's express Statement of Purpose.
+
+3. Public License Fallback. Should any part of the Waiver for any reason
+be judged legally invalid or ineffective under applicable law, then the
+Waiver shall be preserved to the maximum extent permitted taking into
+account Affirmer's express Statement of Purpose. In addition, to the
+extent the Waiver is so judged Affirmer hereby grants to each affected
+person a royalty-free, non transferable, non sublicensable, non exclusive,
+irrevocable and unconditional license to exercise Affirmer's Copyright and
+Related Rights in the Work (i) in all territories worldwide, (ii) for the
+maximum duration provided by applicable law or treaty (including future
+time extensions), (iii) in any current or future medium and for any number
+of copies, and (iv) for any purpose whatsoever, including without
+limitation commercial, advertising or promotional purposes (the
+"License"). The License shall be deemed effective as of the date CC0 was
+applied by Affirmer to the Work. Should any part of the License for any
+reason be judged legally invalid or ineffective under applicable law, such
+partial invalidity or ineffectiveness shall not invalidate the remainder
+of the License, and in such case Affirmer hereby affirms that he or she
+will not (i) exercise any of his or her remaining Copyright and Related
+Rights in the Work or (ii) assert any associated claims and causes of
+action with respect to the Work, in either case contrary to Affirmer's
+express Statement of Purpose.
+
+4. Limitations and Disclaimers.
+
+ a. No trademark or patent rights held by Affirmer are waived, abandoned,
+ surrendered, licensed or otherwise affected by this document.
+ b. Affirmer offers the Work as-is and makes no representations or
+ warranties of any kind concerning the Work, express, implied,
+ statutory or otherwise, including without limitation warranties of
+ title, merchantability, fitness for a particular purpose, non
+ infringement, or the absence of latent or other defects, accuracy, or
+ the present or absence of errors, whether or not discoverable, all to
+ the greatest extent permissible under applicable law.
+ c. Affirmer disclaims responsibility for clearing rights of other persons
+ that may apply to the Work or any use thereof, including without
+ limitation any person's Copyright and Related Rights in the Work.
+ Further, Affirmer disclaims responsibility for obtaining any necessary
+ consents, permissions or other rights required for any use of the
+ Work.
+ d. Affirmer understands and acknowledges that Creative Commons is not a
+ party to this document and has no duty or obligation with respect to
+ this CC0 or use of the Work.
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/cleanup.c b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/cleanup.c
new file mode 100644
index 0000000..e126d36
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/cleanup.c
@@ -0,0 +1,9 @@
+#include "cleanup.h"
+
+void cleanup_(void *yv, long long ylen) {
+ volatile char *y = (volatile char *)yv;
+ while (ylen > 0) { *y++ = 0; --ylen; }
+#ifdef HASASMVOLATILEMEMORY
+ __asm__ __volatile__("" : : "r"(yv) : "memory");
+#endif
+}
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/cleanup.h b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/cleanup.h
new file mode 100644
index 0000000..a42fcb3
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/cleanup.h
@@ -0,0 +1,7 @@
+#ifndef _CLEANUP_H____
+#define _CLEANUP_H____
+
+extern void cleanup_(void *, long long);
+#define cleanup(x) cleanup_((x), sizeof(x))
+
+#endif
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/crypto_hash_sha512.c b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/crypto_hash_sha512.c
new file mode 100644
index 0000000..06a2d9e
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/crypto_hash_sha512.c
@@ -0,0 +1,110 @@
+/*
+20180104
+*/
+/*
+- based on tweetnacl 20140427 (http://tweetnacl.cr.yp.to/software.html)
+- slightly modified
+*/
+
+#include "crypto_hash_sha512.h"
+
+static void store64_bigendian(unsigned char *y, unsigned long long x) {
+
+ long long i;
+
+ for (i = 7; i >= 0; --i) { y[i] = x; x >>= 8; }
+}
+
+static unsigned long long load64_bigendian(const unsigned char *x) {
+
+ unsigned long long y = 0;
+ long long i;
+
+ for (i = 0; i < 8; ++i) y = (y << 8) | x[i];
+ return y;
+}
+
+static unsigned long long R(unsigned long long x,int c) { return (x >> c) | ((x & 0xffffffffffffffffULL) << (64 - c)); }
+static unsigned long long Ch(unsigned long long x, unsigned long long y, unsigned long long z) { return (x & y) ^ (~x & z); }
+static unsigned long long Maj(unsigned long long x, unsigned long long y, unsigned long long z) { return (x & y) ^ (x & z) ^ (y & z); }
+static unsigned long long Sigma0(unsigned long long x) { return R(x, 28) ^ R(x, 34) ^ R(x, 39); }
+static unsigned long long Sigma1(unsigned long long x) { return R(x, 14) ^ R(x, 18) ^ R(x, 41); }
+static unsigned long long sigma0(unsigned long long x) { return R(x, 1) ^ R(x, 8) ^ (x >> 7); }
+static unsigned long long sigma1(unsigned long long x) { return R(x, 19) ^ R(x, 61) ^ (x >> 6); }
+
+static const unsigned long long K[80] = {
+ 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
+ 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
+ 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
+ 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
+ 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
+ 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
+ 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
+ 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
+ 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
+ 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
+ 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
+ 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
+ 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
+ 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
+ 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
+ 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
+ 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
+ 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
+ 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
+ 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL
+};
+
+static void blocks(unsigned long long *z, const unsigned char *m, unsigned long long n) {
+
+ unsigned long long b[8], a[8], w[80], t;
+ long long i, j;
+
+ for (i = 0; i < 8; ++i) a[i] = z[i];
+
+ while (n >= 128) {
+ for (i = 0; i < 16; ++i) w[i] = load64_bigendian(m + 8 * i);
+ for (i = 16; i < 80; ++i) w[i] = (sigma1(w[i - 2]) + w[i - 7] + sigma0(w[i - 15]) + w[i - 16]) & 0xffffffffffffffffULL;
+
+ for (i = 0; i < 80; ++i) {
+ for (j = 0; j < 8; ++j) b[j] = a[j];
+ t = a[7] + Sigma1(a[4]) + Ch(a[4], a[5], a[6]) + K[i] + w[i];
+ b[7] = t + Sigma0(a[0]) + Maj(a[0], a[1], a[2]);
+ b[3] += t;
+ for (j = 0; j < 8; ++j) a[(j + 1) % 8] = b[j] & 0xffffffffffffffffULL;
+ }
+
+ for (i = 0; i < 8; ++i) { a[i] += z[i]; a[i] &= 0xffffffffffffffffULL; z[i] = a[i]; }
+
+ m += 128;
+ n -= 128;
+ }
+}
+
+int crypto_hash_sha512_tinyssh(unsigned char *o,const unsigned char *m, unsigned long long n) {
+
+ long long i;
+ unsigned char x[256];
+ unsigned long long b = n;
+ unsigned long long h[8] = {
+ 0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL, 0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL,
+ 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL, 0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL
+ };
+
+ blocks(h, m, n);
+ m += n;
+ n &= 127;
+ m -= n;
+
+ for (i = 0; i < sizeof x; ++i) x[i] = 0;
+ for (i = 0; i < n; ++i) x[i] = m[i];
+ x[n] = 128;
+
+ n = 256 - 128 * (n < 112);
+ x[n - 9] = b >> 61;
+ store64_bigendian(x + n - 8, b << 3);
+ blocks(h, x, n);
+
+ for (i = 0; i < 8; ++i) store64_bigendian(o + 8 * i, h[i]);
+ return 0;
+}
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/crypto_hash_sha512.h b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/crypto_hash_sha512.h
new file mode 100644
index 0000000..7b1d1ac
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/crypto_hash_sha512.h
@@ -0,0 +1,12 @@
+#ifndef crypto_hash_sha512_H
+#define crypto_hash_sha512_H
+
+#define crypto_hash_sha512_tinyssh_BYTES 64
+extern int crypto_hash_sha512_tinyssh(unsigned char *, const unsigned char *, unsigned long long);
+
+#define crypto_hash_sha512 crypto_hash_sha512_tinyssh
+#define crypto_hash_sha512_BYTES crypto_hash_sha512_tinyssh_BYTES
+#define crypto_hash_sha512_IMPLEMENTATION "tinyssh"
+#define crypto_hash_sha512_VERSION "-"
+
+#endif
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/crypto_int64.h b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/crypto_int64.h
new file mode 100644
index 0000000..acfd192
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/crypto_int64.h
@@ -0,0 +1,8 @@
+#ifndef crypto_int64_h
+#define crypto_int64_h
+
+#include <stdint.h>
+
+typedef int64_t crypto_int64;
+
+#endif
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/crypto_onetimeauth_poly1305.c b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/crypto_onetimeauth_poly1305.c
new file mode 100644
index 0000000..631e733
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/crypto_onetimeauth_poly1305.c
@@ -0,0 +1,154 @@
+/*
+20200202
+*/
+/*
+Based on poly1305-donna (https://github.com/floodyberry/poly1305-opt/blob/master/extensions/poly1305_ref-32.c)
+- modified for NaCl API
+*/
+
+#include "crypto_onetimeauth_poly1305.h"
+
+/* clang-format off */
+static inline unsigned long unpack32(const unsigned char *x) {
+ return
+ (unsigned long) (x[0]) \
+ | (((unsigned long) (x[1])) << 8) \
+ | (((unsigned long) (x[2])) << 16) \
+ | (((unsigned long) (x[3])) << 24);
+}
+static inline void pack32(unsigned char *x, unsigned long u) {
+ x[0] = u; u >>= 8;
+ x[1] = u; u >>= 8;
+ x[2] = u; u >>= 8;
+ x[3] = u;
+}
+
+int crypto_onetimeauth_poly1305_tinyssh(unsigned char *o, const unsigned char *m, unsigned long long n, const unsigned char *k) {
+
+ unsigned long h0, h1, h2, h3, h4;
+ unsigned long r0, r1, r2, r3, r4;
+ unsigned long s1, s2, s3, s4;
+ unsigned long long d0, d1, d2, d3, d4;
+ unsigned long c, mask;
+ unsigned long long f;
+ long long i;
+
+
+ /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
+ r0 = (unpack32(k + 0) ) & 0x3ffffff;
+ r1 = (unpack32(k + 3) >> 2) & 0x3ffff03;
+ r2 = (unpack32(k + 6) >> 4) & 0x3ffc0ff;
+ r3 = (unpack32(k + 9) >> 6) & 0x3f03fff;
+ r4 = (unpack32(k + 12) >> 8) & 0x00fffff;
+
+ s1 = r1 * 5;
+ s2 = r2 * 5;
+ s3 = r3 * 5;
+ s4 = r4 * 5;
+
+ /* h = 0 */
+ h0 = h1 = h2 = h3 = h4 = 0;
+
+ while (n > 0) {
+ /* h += m[i] */
+ if (n >= 16) {
+ h0 += (unpack32(m ) ) & 0x3ffffff;
+ h1 += (unpack32(m + 3) >> 2) & 0x3ffffff;
+ h2 += (unpack32(m + 6) >> 4) & 0x3ffffff;
+ h3 += (unpack32(m + 9) >> 6) & 0x3ffffff;
+ h4 += (unpack32(m + 12) >> 8) | 16777216;
+ m += 16;
+ n -= 16;
+ }
+ else {
+ unsigned char mm[16];
+ for (i = 0; i < 16; ++i) mm[i] = 0;
+ for (i = 0; i < n; ++i) mm[i] = m[i];
+ mm[i] = 1;
+ h0 += (unpack32(mm ) ) & 0x3ffffff;
+ h1 += (unpack32(mm + 3) >> 2) & 0x3ffffff;
+ h2 += (unpack32(mm + 6) >> 4) & 0x3ffffff;
+ h3 += (unpack32(mm + 9) >> 6) & 0x3ffffff;
+ h4 += (unpack32(mm + 12) >> 8);
+ n = 0;
+ }
+
+ /* h *= r */
+ d0 = ((unsigned long long)h0 * r0) + ((unsigned long long)h1 * s4) + ((unsigned long long)h2 * s3) + ((unsigned long long)h3 * s2) + ((unsigned long long)h4 * s1);
+ d1 = ((unsigned long long)h0 * r1) + ((unsigned long long)h1 * r0) + ((unsigned long long)h2 * s4) + ((unsigned long long)h3 * s3) + ((unsigned long long)h4 * s2);
+ d2 = ((unsigned long long)h0 * r2) + ((unsigned long long)h1 * r1) + ((unsigned long long)h2 * r0) + ((unsigned long long)h3 * s4) + ((unsigned long long)h4 * s3);
+ d3 = ((unsigned long long)h0 * r3) + ((unsigned long long)h1 * r2) + ((unsigned long long)h2 * r1) + ((unsigned long long)h3 * r0) + ((unsigned long long)h4 * s4);
+ d4 = ((unsigned long long)h0 * r4) + ((unsigned long long)h1 * r3) + ((unsigned long long)h2 * r2) + ((unsigned long long)h3 * r1) + ((unsigned long long)h4 * r0);
+
+ /* (partial) h %= p */
+ c = (unsigned long)(d0 >> 26); h0 = (unsigned long)d0 & 0x3ffffff;
+ d1 += c; c = (unsigned long)(d1 >> 26); h1 = (unsigned long)d1 & 0x3ffffff;
+ d2 += c; c = (unsigned long)(d2 >> 26); h2 = (unsigned long)d2 & 0x3ffffff;
+ d3 += c; c = (unsigned long)(d3 >> 26); h3 = (unsigned long)d3 & 0x3ffffff;
+ d4 += c; c = (unsigned long)(d4 >> 26); h4 = (unsigned long)d4 & 0x3ffffff;
+ h0 += c * 5; c = (h0 >> 26); h0 = h0 & 0x3ffffff;
+ h1 += c;
+ }
+
+
+ /* fully carry h */
+ c = h1 >> 26; h1 = h1 & 0x3ffffff;
+ h2 += c; c = h2 >> 26; h2 = h2 & 0x3ffffff;
+ h3 += c; c = h3 >> 26; h3 = h3 & 0x3ffffff;
+ h4 += c; c = h4 >> 26; h4 = h4 & 0x3ffffff;
+ h0 += c * 5; c = h0 >> 26; h0 = h0 & 0x3ffffff;
+ h1 += c;
+
+ /* compute h + -p */
+ r0 = h0 + 5; c = r0 >> 26; r0 &= 0x3ffffff;
+ r1 = h1 + c; c = r1 >> 26; r1 &= 0x3ffffff;
+ r2 = h2 + c; c = r2 >> 26; r2 &= 0x3ffffff;
+ r3 = h3 + c; c = r3 >> 26; r3 &= 0x3ffffff;
+ r4 = h4 + c - (1 << 26);
+
+ /* select h if h < p, or h + -p if h >= p */
+ mask = (r4 >> ((sizeof(unsigned long) * 8) - 1)) - 1;
+ r0 &= mask;
+ r1 &= mask;
+ r2 &= mask;
+ r3 &= mask;
+ r4 &= mask;
+ mask = ~mask;
+ h0 = (h0 & mask) | r0;
+ h1 = (h1 & mask) | r1;
+ h2 = (h2 & mask) | r2;
+ h3 = (h3 & mask) | r3;
+ h4 = (h4 & mask) | r4;
+
+ /* h = h % (2^128) */
+ h0 = ((h0 ) | (h1 << 26)) & 0xffffffff;
+ h1 = ((h1 >> 6) | (h2 << 20)) & 0xffffffff;
+ h2 = ((h2 >> 12) | (h3 << 14)) & 0xffffffff;
+ h3 = ((h3 >> 18) | (h4 << 8)) & 0xffffffff;
+
+ /* mac = (h + pad) % (2^128) */
+ f = (unsigned long long)h0 + unpack32(k + 16) ; h0 = (unsigned long)f;
+ f = (unsigned long long)h1 + unpack32(k + 20) + (f >> 32); h1 = (unsigned long)f;
+ f = (unsigned long long)h2 + unpack32(k + 24) + (f >> 32); h2 = (unsigned long)f;
+ f = (unsigned long long)h3 + unpack32(k + 28) + (f >> 32); h3 = (unsigned long)f;
+
+ pack32(o + 0, h0);
+ pack32(o + 4, h1);
+ pack32(o + 8, h2);
+ pack32(o + 12, h3);
+
+ return 0;
+}
+
+int crypto_onetimeauth_poly1305_tinyssh_verify(const unsigned char *h, const unsigned char *in, unsigned long long l, const unsigned char *k) {
+
+ unsigned char correct[16];
+ unsigned int d = 0;
+ long long i;
+
+ crypto_onetimeauth_poly1305(correct, in, l, k);
+
+ for (i = 0; i < 16; ++i) d |= correct[i] ^ h[i];
+ return (1 & ((d - 1) >> 8)) - 1;
+}
+/* clang-format on */
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/crypto_onetimeauth_poly1305.h b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/crypto_onetimeauth_poly1305.h
new file mode 100644
index 0000000..3d9f9ea
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/crypto_onetimeauth_poly1305.h
@@ -0,0 +1,16 @@
+#ifndef crypto_onetimeauth_poly1305_H
+#define crypto_onetimeauth_poly1305_H
+
+#define crypto_onetimeauth_poly1305_tinyssh_BYTES 16
+#define crypto_onetimeauth_poly1305_tinyssh_KEYBYTES 32
+extern int crypto_onetimeauth_poly1305_tinyssh(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *);
+extern int crypto_onetimeauth_poly1305_tinyssh_verify(const unsigned char *,const unsigned char *,unsigned long long,const unsigned char *);
+
+#define crypto_onetimeauth_poly1305 crypto_onetimeauth_poly1305_tinyssh
+#define crypto_onetimeauth_poly1305_verify crypto_onetimeauth_poly1305_tinyssh_verify
+#define crypto_onetimeauth_poly1305_BYTES crypto_onetimeauth_poly1305_tinyssh_BYTES
+#define crypto_onetimeauth_poly1305_KEYBYTES crypto_onetimeauth_poly1305_tinyssh_KEYBYTES
+#define crypto_onetimeauth_poly1305_IMPLEMENTATION "tinyssh"
+#define crypto_onetimeauth_poly1305_VERSION "-"
+
+#endif
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/crypto_scalarmult_curve25519.c b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/crypto_scalarmult_curve25519.c
new file mode 100644
index 0000000..6681128
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/crypto_scalarmult_curve25519.c
@@ -0,0 +1,73 @@
+#include "cleanup.h"
+#include "fe25519.h"
+#include "crypto_scalarmult_curve25519.h"
+
+int crypto_scalarmult_curve25519_tinyssh(unsigned char *q, const unsigned char *n, const unsigned char *p) {
+
+ unsigned char e[32];
+ fe x1, x2, z2, x3, z3, tmp0, tmp1;
+ long long i;
+ unsigned int d = 0;
+ int pos;
+ crypto_uint32 swap, b;
+
+ for (i = 0; i < 32; ++i) e[i] = n[i];
+ e[0] &= 248;
+ e[31] &= 127;
+ e[31] |= 64;
+ fe25519_frombytes(x1, p);
+ fe_1(x2);
+ fe_0(z2);
+ fe_copy(x3, x1);
+ fe_1(z3);
+
+ swap = 0;
+ for (pos = 254; pos >= 0; --pos) {
+ b = e[pos / 8] >> (pos & 7);
+ b &= 1;
+ swap ^= b;
+ fe_cswap(x2, x3, swap);
+ fe_cswap(z2, z3, swap);
+ swap = b;
+
+ fe25519_sub(tmp0, x3, z3);
+ fe25519_sub(tmp1, x2, z2);
+ fe25519_add(x2, x2, z2);
+ fe25519_add(z2, x3, z3);
+ fe25519_mul(z3, tmp0, x2);
+ fe25519_mul(z2, z2, tmp1);
+ fe25519_sq(tmp0, tmp1);
+ fe25519_sq(tmp1, x2);
+ fe25519_add(x3, z3, z2);
+ fe25519_sub(z2, z3, z2);
+ fe25519_mul(x2, tmp1, tmp0);
+ fe25519_sub(tmp1, tmp1, tmp0);
+ fe25519_sq(z2, z2);
+ fe25519_mul121666(z3, tmp1);
+ fe25519_sq(x3, x3);
+ fe25519_add(tmp0, tmp0, z3);
+ fe25519_mul(z3, x1, z2);
+ fe25519_mul(z2, tmp1, tmp0);
+ }
+
+ fe_cswap(x2, x3, swap);
+ fe_cswap(z2, z3, swap);
+
+ fe25519_inv(z2, z2);
+ fe25519_mul(x2, x2, z2);
+ fe25519_tobytes(q, x2);
+
+ cleanup(e);
+ cleanup(tmp0); cleanup(tmp1);
+ cleanup(x1); cleanup(x2); cleanup(x3);
+ cleanup(z2); cleanup(z3);
+
+ for (i = 0; i < 32; ++i) d |= q[i];
+ return -(1 & ((d - 1) >> 8));
+}
+
+static const unsigned char basepoint[32] = {9};
+
+int crypto_scalarmult_curve25519_tinyssh_base(unsigned char *q, const unsigned char *n) {
+ return crypto_scalarmult_curve25519_tinyssh(q, n, basepoint);
+}
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/crypto_scalarmult_curve25519.h b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/crypto_scalarmult_curve25519.h
new file mode 100644
index 0000000..98a3ccf
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/crypto_scalarmult_curve25519.h
@@ -0,0 +1,16 @@
+#ifndef crypto_scalarmult_curve25519_H
+#define crypto_scalarmult_curve25519_H
+
+#define crypto_scalarmult_curve25519_tinyssh_BYTES 32
+#define crypto_scalarmult_curve25519_tinyssh_SCALARBYTES 32
+extern int crypto_scalarmult_curve25519_tinyssh(unsigned char *,const unsigned char *,const unsigned char *);
+extern int crypto_scalarmult_curve25519_tinyssh_base(unsigned char *,const unsigned char *);
+
+#define crypto_scalarmult_curve25519 crypto_scalarmult_curve25519_tinyssh
+#define crypto_scalarmult_curve25519_base crypto_scalarmult_curve25519_tinyssh_base
+#define crypto_scalarmult_curve25519_BYTES crypto_scalarmult_curve25519_tinyssh_BYTES
+#define crypto_scalarmult_curve25519_SCALARBYTES crypto_scalarmult_curve25519_tinyssh_SCALARBYTES
+#define crypto_scalarmult_curve25519_IMPLEMENTATION "tinyssh"
+#define crypto_scalarmult_curve25519_VERSION "-"
+
+#endif
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/crypto_sign_ed25519.c b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/crypto_sign_ed25519.c
new file mode 100644
index 0000000..d16164c
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/crypto_sign_ed25519.c
@@ -0,0 +1,121 @@
+#include "randombytes.h"
+#include "cleanup.h"
+#include "crypto_hash_sha512.h"
+#include "crypto_verify_32.h"
+#include "ge25519.h"
+#include "sc25519.h"
+#include "crypto_sign_ed25519.h"
+
+int crypto_sign_ed25519_tinyssh(unsigned char *sm, unsigned long long *smlen, const unsigned char *m, unsigned long long n, const unsigned char *skorig) {
+
+ long long i;
+ unsigned char nonce[64], hram[64], sk[64], pk[32];
+ ge25519 R;
+
+ /* compute secret key from seed sk = H(skorig), H = sha512 */
+ crypto_hash_sha512(sk, skorig, 32);
+ sk[0] &= 248;
+ sk[31] &= 63;
+ sk[31] |= 64;
+
+ /* copy m to sm, copy secret key and public key */
+ *smlen = n + 64;
+ for (i = 31; i >= 0; --i) pk[i ] = skorig[i + 32];
+ for (i = n - 1; i >= 0; --i) sm[i + 64] = m[i];
+ for (i = 31; i >= 0; --i) sm[i + 32] = sk[i + 32];
+
+ /* get pseudorandom nonce = H(sk2, m) */
+ crypto_hash_sha512(nonce, sm + 32, n + 32);
+ sc25519_reduce(nonce);
+
+ /* copy pk to sm */
+ for (i = 31; i >= 0; --i) sm[i + 32] = pk[i];
+
+ /* compute R */
+ ge25519_scalarmult_base(R, nonce);
+ ge25519_tobytes(sm, R);
+
+ /* calculate hram = H(r, a, m) */
+ crypto_hash_sha512(hram, sm, n + 64);
+ sc25519_reduce(hram);
+
+ /* compute S */
+ sc25519_muladd(sm + 32, hram, sk, nonce);
+
+ /* cleanup */
+ cleanup(nonce); cleanup(hram); cleanup(sk); cleanup(pk); cleanup(R);
+ return 0;
+}
+
+int crypto_sign_ed25519_tinyssh_open(unsigned char *m, unsigned long long *mlen, const unsigned char *sm, unsigned long long n, const unsigned char *pk) {
+
+ long long i;
+ unsigned char pkcopy[32], rcopy[32], scopy[32], hram[64], rcheck[32];
+ ge25519 R, S, A;
+ int ret = -1;
+
+ /* check input */
+ if (n < 64) goto fail;
+ if (sm[63] & 224) goto fail;
+
+ /* unpack pk */
+ if (ge25519_frombytes_negate_vartime(A, pk) != 0) goto fail;
+
+ /* copy pk, r, s */
+ for (i = 0; i < 32; ++i) pkcopy[i] = pk[i];
+ for (i = 0; i < 32; ++i) rcopy[i] = sm[i];
+ for (i = 0; i < 32; ++i) scopy[i] = sm[i + 32];
+
+ /* copy sm to m and copy pk to m */
+ for (i = n - 1; i >= 0; --i) m[i] = sm[i];
+ for (i = 0; i < 32; ++i) m[i + 32] = pkcopy[i];
+
+ /* calculate hram = H(r, a, m) */
+ crypto_hash_sha512(hram, m, n);
+ sc25519_reduce(hram);
+
+ /* compute R */
+ ge25519_scalarmult(A, A, hram);
+ ge25519_scalarmult_base(S, scopy);
+ ge25519_add(R, S, A);
+
+ /* check R */
+ ge25519_tobytes(rcheck, R);
+ if (crypto_verify_32(rcheck, rcopy) != 0) goto fail;
+
+ /* copy message */
+ n -= 64; *mlen = n;
+ for (i = 0; i < n; ++i) m[i] = m[i + 64];
+ for (i = 0; i < 64; ++i) m[i + n] = 0;
+ ret = 0;
+ goto cleanup;
+
+fail:
+ for (i = 0; i < n; ++i) m[i] = 0;
+
+cleanup:
+ cleanup(pkcopy); cleanup(rcopy); cleanup(scopy);
+ cleanup(hram); cleanup(rcheck);
+ cleanup(R); cleanup(S); cleanup(A);
+ return ret;
+}
+
+int crypto_sign_ed25519_tinyssh_keypair(unsigned char *pk, unsigned char *sk) {
+
+ unsigned char h[64];
+ ge25519 A;
+ long long i;
+
+ randombytes(sk, 32);
+ crypto_hash_sha512(h, sk, 32);
+ h[0] &= 248;
+ h[31] &= 63;
+ h[31] |= 64;
+
+ ge25519_scalarmult_base(A, h);
+ ge25519_tobytes(pk, A);
+
+ for (i = 31; i >= 0; --i) sk[i + 32] = pk[i];
+ cleanup(h); cleanup(A);
+ return 0;
+}
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/crypto_sign_ed25519.h b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/crypto_sign_ed25519.h
new file mode 100644
index 0000000..e777efa
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/crypto_sign_ed25519.h
@@ -0,0 +1,20 @@
+#ifndef crypto_sign_ed25519_H
+#define crypto_sign_ed25519_H
+
+#define crypto_sign_ed25519_tinyssh_SECRETKEYBYTES 64
+#define crypto_sign_ed25519_tinyssh_PUBLICKEYBYTES 32
+#define crypto_sign_ed25519_tinyssh_BYTES 64
+extern int crypto_sign_ed25519_tinyssh(unsigned char *,unsigned long long *,const unsigned char *,unsigned long long,const unsigned char *);
+extern int crypto_sign_ed25519_tinyssh_open(unsigned char *,unsigned long long *,const unsigned char *,unsigned long long,const unsigned char *);
+extern int crypto_sign_ed25519_tinyssh_keypair(unsigned char *,unsigned char *);
+
+#define crypto_sign_ed25519 crypto_sign_ed25519_tinyssh
+#define crypto_sign_ed25519_open crypto_sign_ed25519_tinyssh_open
+#define crypto_sign_ed25519_keypair crypto_sign_ed25519_tinyssh_keypair
+#define crypto_sign_ed25519_BYTES crypto_sign_ed25519_tinyssh_BYTES
+#define crypto_sign_ed25519_PUBLICKEYBYTES crypto_sign_ed25519_tinyssh_PUBLICKEYBYTES
+#define crypto_sign_ed25519_SECRETKEYBYTES crypto_sign_ed25519_tinyssh_SECRETKEYBYTES
+#define crypto_sign_ed25519_IMPLEMENTATION "tinyssh"
+#define crypto_sign_ed25519_VERSION "-"
+
+#endif
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/crypto_stream_chacha20.c b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/crypto_stream_chacha20.c
new file mode 100644
index 0000000..6104a4c
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/crypto_stream_chacha20.c
@@ -0,0 +1,145 @@
+/*
+20210508
+Jan Mojzis
+Public domain.
+*/
+
+#include <stdint.h>
+#include "crypto_stream_chacha20.h"
+
+/* clang-format off */
+static inline uint32_t unpack32(const unsigned char *x) {
+ return
+ (uint32_t) (x[0]) \
+ | (((uint32_t) (x[1])) << 8) \
+ | (((uint32_t) (x[2])) << 16) \
+ | (((uint32_t) (x[3])) << 24);
+}
+static inline void pack32(unsigned char *x, uint32_t u) {
+ x[0] = u; u >>= 8;
+ x[1] = u; u >>= 8;
+ x[2] = u; u >>= 8;
+ x[3] = u;
+}
+
+#define ROTATE(x, c) ((x) << (c)) ^ ((x) >> (32 - (c)))
+
+#define QUARTERROUND(a, b, c, d) \
+ a += b; d = ROTATE(d ^ a, 16); \
+ c += d; b = ROTATE(b ^ c, 12); \
+ a += b; d = ROTATE(d ^ a, 8); \
+ c += d; b = ROTATE(b ^ c, 7);
+
+#define TWOROUNDS \
+ QUARTERROUND( x0, x4, x8, x12) \
+ QUARTERROUND( x1, x5, x9, x13) \
+ QUARTERROUND( x2, x6, x10, x14) \
+ QUARTERROUND( x3, x7, x11, x15) \
+ QUARTERROUND( x0, x5, x10, x15) \
+ QUARTERROUND( x1, x6, x11, x12) \
+ QUARTERROUND( x2, x7, x8, x13) \
+ QUARTERROUND( x3, x4, x9, x14)
+
+#define XORBLOCK(o, i) \
+ x0 = s0; \
+ x1 = s1; \
+ x2 = s2; \
+ x3 = s3; \
+ x4 = k0; \
+ x5 = k1; \
+ x6 = k2; \
+ x7 = k3; \
+ x8 = k4; \
+ x9 = k5; \
+ x10 = k6; \
+ x11 = k7; \
+ x12 = n0; \
+ x13 = n1; \
+ x14 = n2; \
+ x15 = n3; \
+ \
+ TWOROUNDS /* round 1, 2 */ \
+ TWOROUNDS /* round 3, 4 */ \
+ TWOROUNDS /* round 5, 6 */ \
+ TWOROUNDS /* round 7, 8 */ \
+ TWOROUNDS /* round 9, 10 */ \
+ TWOROUNDS /* round 11, 12 */ \
+ TWOROUNDS /* round 13, 14 */ \
+ TWOROUNDS /* round 15, 16 */ \
+ TWOROUNDS /* round 17, 18 */ \
+ TWOROUNDS /* round 19, 20 */ \
+ \
+ pack32(o , (x0 + s0) ^ unpack32(i )); \
+ pack32(o + 4, (x1 + s1) ^ unpack32(i + 4)); \
+ pack32(o + 8, (x2 + s2) ^ unpack32(i + 8)); \
+ pack32(o + 12, (x3 + s3) ^ unpack32(i + 12)); \
+ pack32(o + 16, (x4 + k0) ^ unpack32(i + 16)); \
+ pack32(o + 20, (x5 + k1) ^ unpack32(i + 20)); \
+ pack32(o + 24, (x6 + k2) ^ unpack32(i + 24)); \
+ pack32(o + 28, (x7 + k3) ^ unpack32(i + 28)); \
+ pack32(o + 32, (x8 + k4) ^ unpack32(i + 32)); \
+ pack32(o + 36, (x9 + k5) ^ unpack32(i + 36)); \
+ pack32(o + 40, (x10 + k6) ^ unpack32(i + 40)); \
+ pack32(o + 44, (x11 + k7) ^ unpack32(i + 44)); \
+ pack32(o + 48, (x12 + n0) ^ unpack32(i + 48)); \
+ pack32(o + 52, (x13 + n1) ^ unpack32(i + 52)); \
+ pack32(o + 56, (x14 + n2) ^ unpack32(i + 56)); \
+ pack32(o + 60, (x15 + n3) ^ unpack32(i + 60));
+
+int crypto_stream_chacha20_tinyssh_xor(unsigned char *c, const unsigned char *m, unsigned long long l, const unsigned char *n, const unsigned char *k) {
+
+ register uint32_t x0, x1, x2, x3, x4, x5, x6, x7;
+ register uint32_t x8, x9, x10, x11, x12, x13, x14, x15;
+ uint32_t k0 = unpack32(k );
+ uint32_t k1 = unpack32(k + 4);
+ uint32_t k2 = unpack32(k + 8);
+ uint32_t k3 = unpack32(k + 12);
+ uint32_t k4 = unpack32(k + 16);
+ uint32_t k5 = unpack32(k + 20);
+ uint32_t k6 = unpack32(k + 24);
+ uint32_t k7 = unpack32(k + 28);
+ uint32_t n0 = 0;
+ uint32_t n1 = 0;
+ uint32_t n2 = unpack32(n );
+ uint32_t n3 = unpack32(n + 4);
+ uint32_t s0 = 0x61707865;
+ uint32_t s1 = 0x3320646E;
+ uint32_t s2 = 0x79622D32;
+ uint32_t s3 = 0x6B206574;
+ uint64_t u = 0;
+
+ if (!l) return 0;
+
+ while (l >= 64) {
+ XORBLOCK(c, m);
+
+ if (!++u) return -1;
+ n0 = u;
+ n1 = u >> 32;
+
+ l -= 64;
+ c += 64;
+ m += 64;
+ }
+ if (l) {
+ unsigned char b[64] = {0};
+ unsigned long long j;
+
+ for (j = 0; j < l; ++j) b[j] = m[j];
+ XORBLOCK(b, b);
+ for (j = 0; j < l; ++j) c[j] = b[j];
+ }
+ return 0;
+}
+
+int crypto_stream_chacha20_tinyssh(unsigned char *c, unsigned long long l, const unsigned char *n, const unsigned char *k) {
+
+ unsigned long long j;
+ unsigned char ncopy[8], kcopy[32];
+
+ for (j = 0; j < 32; ++j) kcopy[j] = k[j];
+ for (j = 0; j < 8; ++j) ncopy[j] = n[j];
+ for (j = 0; j < l; ++j) c[j] = 0;
+ return crypto_stream_chacha20_tinyssh_xor(c, c, l, ncopy, kcopy);
+}
+/* clang-format on */
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/crypto_stream_chacha20.h b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/crypto_stream_chacha20.h
new file mode 100644
index 0000000..1451757
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/crypto_stream_chacha20.h
@@ -0,0 +1,16 @@
+#ifndef crypto_stream_chacha20_H
+#define crypto_stream_chacha20_H
+
+#define crypto_stream_chacha20_tinyssh_KEYBYTES 32
+#define crypto_stream_chacha20_tinyssh_NONCEBYTES 8
+extern int crypto_stream_chacha20_tinyssh(unsigned char *, unsigned long long, const unsigned char *, const unsigned char *);
+extern int crypto_stream_chacha20_tinyssh_xor(unsigned char *, const unsigned char *, unsigned long long, const unsigned char *, const unsigned char *);
+
+#define crypto_stream_chacha20 crypto_stream_chacha20_tinyssh
+#define crypto_stream_chacha20_xor crypto_stream_chacha20_tinyssh_xor
+#define crypto_stream_chacha20_KEYBYTES crypto_stream_chacha20_tinyssh_KEYBYTES
+#define crypto_stream_chacha20_NONCEBYTES crypto_stream_chacha20_tinyssh_NONCEBYTES
+#define crypto_stream_chacha20_IMPLEMENTATION "tinyssh"
+#define crypto_stream_chacha20_VERSION "-"
+
+#endif
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/crypto_uint32.h b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/crypto_uint32.h
new file mode 100644
index 0000000..73f22b1
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/crypto_uint32.h
@@ -0,0 +1,8 @@
+#ifndef crypto_uint32_h
+#define crypto_uint32_h
+
+#include <stdint.h>
+
+typedef uint32_t crypto_uint32;
+
+#endif
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/crypto_uint64.h b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/crypto_uint64.h
new file mode 100644
index 0000000..b1b47a9
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/crypto_uint64.h
@@ -0,0 +1,8 @@
+#ifndef crypto_uint64_h
+#define crypto_uint64_h
+
+#include <stdint.h>
+
+typedef uint64_t crypto_uint64;
+
+#endif
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/crypto_verify_32.c b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/crypto_verify_32.c
new file mode 100644
index 0000000..a7b5bec
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/crypto_verify_32.c
@@ -0,0 +1,6 @@
+#include "verify.h"
+#include "crypto_verify_32.h"
+
+int crypto_verify_32_tinyssh(const unsigned char *x, const unsigned char *y) {
+ return verify(x, y, 32);
+}
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/crypto_verify_32.h b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/crypto_verify_32.h
new file mode 100644
index 0000000..87767b9
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/crypto_verify_32.h
@@ -0,0 +1,12 @@
+#ifndef crypto_verify_32_H
+#define crypto_verify_32_H
+
+#define crypto_verify_32_tinyssh_BYTES 32
+extern int crypto_verify_32_tinyssh(const unsigned char *, const unsigned char *);
+
+#define crypto_verify_32 crypto_verify_32_tinyssh
+#define crypto_verify_32_BYTES crypto_verify_32_tinyssh_BYTES
+#define crypto_verify_32_IMPLEMENTATION "tinyssh"
+#define crypto_verify_32_VERSION "-"
+
+#endif
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/fe.c b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/fe.c
new file mode 100644
index 0000000..cf66d8d
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/fe.c
@@ -0,0 +1,171 @@
+/*
+20140918
+Jan Mojzis
+Public domain.
+*/
+
+#include "fe.h"
+
+/*
+o = 0
+*/
+void fe_0(fe o) {
+
+ long long i;
+ for (i = 0; i < 8; ++i) o[i] = 0;
+}
+
+/*
+o = 1
+*/
+void fe_1(fe o) {
+
+ fe_0(o);
+ o[0] = 1;
+}
+
+/*
+o = x
+*/
+void fe_copy(fe o, const fe x) {
+
+ long long i;
+ for (i = 0; i < 8; ++i) o[i] = x[i];
+}
+
+/*
+if (b) swap(f, g)
+*/
+void fe_cswap(fe f, fe g, crypto_uint32 b) {
+
+ long long i;
+ fe t;
+
+ b = -b;
+
+ for (i = 0; i < 8; ++i) t[i] = b & (f[i] ^ g[i]);
+ for (i = 0; i < 8; ++i) f[i] ^= t[i];
+ for (i = 0; i < 8; ++i) g[i] ^= t[i];
+ fe_0(t);
+}
+
+/*
+if (b) f = g
+*/
+void fe_cmov(fe f, const fe g, crypto_uint32 b) {
+
+ long long i;
+ fe t;
+
+ b = -b;
+
+ for (i = 0; i < 8; ++i) t[i] = b & (f[i] ^ g[i]);
+ for (i = 0; i < 8; ++i) f[i] ^= t[i];
+ fe_0(t);
+}
+
+
+/*
+o = a * b
+*/
+/*
+Implementation note: fe_mul_() is unrolled version of:
+void fe_mul_(fel o, const fe a, const fe b) {
+
+ crypto_uint64 u;
+ long long i, j;
+
+ for (i = 0; i < 16; ++i) o[i] = 0;
+ for (i = 0; i < 8; ++i) for (j = 0; j < 8; ++j) {
+ u = (crypto_uint64)a[i] * (crypto_uint64)b[j];
+ o[i + j ] += u & 0xffffffff;
+ o[i + j + 1] += u >> 32;
+ }
+}
+*/
+#define M(i, j) u = (crypto_uint64)a[i] * (crypto_uint64)b[j]; \
+ o[i + j ] += u & 0xffffffff; \
+ o[i + j + 1] += u >> 32;
+void fe_mul_(fel o, const fe a, const fe b) {
+
+ crypto_uint64 u;
+ long long i;
+
+ for (i = 0; i < 16; ++i) o[i] = 0;
+
+ M(0, 0); M(0, 1); M(0, 2); M(0, 3); M(0, 4); M(0, 5); M(0, 6); M(0, 7);
+ M(1, 0); M(1, 1); M(1, 2); M(1, 3); M(1, 4); M(1, 5); M(1, 6); M(1, 7);
+ M(2, 0); M(2, 1); M(2, 2); M(2, 3); M(2, 4); M(2, 5); M(2, 6); M(2, 7);
+ M(3, 0); M(3, 1); M(3, 2); M(3, 3); M(3, 4); M(3, 5); M(3, 6); M(3, 7);
+ M(4, 0); M(4, 1); M(4, 2); M(4, 3); M(4, 4); M(4, 5); M(4, 6); M(4, 7);
+ M(5, 0); M(5, 1); M(5, 2); M(5, 3); M(5, 4); M(5, 5); M(5, 6); M(5, 7);
+ M(6, 0); M(6, 1); M(6, 2); M(6, 3); M(6, 4); M(6, 5); M(6, 6); M(6, 7);
+ M(7, 0); M(7, 1); M(7, 2); M(7, 3); M(7, 4); M(7, 5); M(7, 6); M(7, 7);
+}
+
+/*
+o = x ^ 2
+*/
+/*
+Implementation note: fe_sq_() is unrolled version of:
+void fe_sq_(fel o, const fe a) {
+
+ crypto_uint64 u;
+ long long i, j;
+
+ for (i = 0; i < 16; ++i) o[i] = 0;
+ for (i = 0; i < 8; ++i) for (j = i + 1; j < 8; ++j) {
+ u = (crypto_uint64)a[i] * (crypto_uint64)a[j];
+ o[i + j ] += 2 * (u & 0xffffffff);
+ o[i + j + 1] += 2 * (u >> 32);
+ }
+ for (i = 0; i < 8; ++i) {
+ u = (crypto_uint64)a[i] * (crypto_uint64)a[i];
+ o[2 * i ] += (u & 0xffffffff);
+ o[2 * i + 1] += (u >> 32);
+ }
+}
+*/
+#define M2(i, j) u = (crypto_uint64)a[i] * (crypto_uint64)a[j]; \
+ o[i + j ] += 2 * (u & 0xffffffff); \
+ o[i + j + 1] += 2 * (u >> 32);
+#define SQ(i) u = (crypto_uint64)a[i] * (crypto_uint64)a[i]; \
+ o[2 * i ] += (u & 0xffffffff); \
+ o[2 * i + 1] += (u >> 32)
+void fe_sq_(fel o, const fe a) {
+
+ crypto_uint64 u;
+ long long i;
+
+ for (i = 0; i < 16; ++i) o[i] = 0;
+
+ M2(0, 1); M2(0, 2); M2(0, 3); M2(0, 4); M2(0, 5); M2(0, 6); M2(0, 7);
+ M2(1, 2); M2(1, 3); M2(1, 4); M2(1, 5); M2(1, 6); M2(1, 7);
+ M2(2, 3); M2(2, 4); M2(2, 5); M2(2, 6); M2(2, 7);
+ M2(3, 4); M2(3, 5); M2(3, 6); M2(3, 7);
+ M2(4, 5); M2(4, 6); M2(4, 7);
+ M2(5, 6); M2(5, 7);
+ M2(6, 7);
+ SQ(0); SQ(1); SQ(2); SQ(3); SQ(4); SQ(5); SQ(6); SQ(7);
+}
+
+/*
+if (p < r) r -= p
+*/
+void fe_reducesmall(fe r, const fe p, const crypto_uint64 carry) {
+
+ crypto_uint64 pb = 0, b;
+ long long i;
+ fe t;
+
+ for (i = 0; i < 8; ++i) {
+ pb += (crypto_uint64)p[i];
+ b = (crypto_uint64)r[i] - pb; b >>= 63;
+ t[i] = (crypto_uint64)r[i] - pb + (b << 32);
+ pb = b;
+ }
+ b = carry - pb; b >>= 63;
+ b -= 1;
+ for (i = 0; i < 8; ++i) r[i] ^= b & (r[i] ^ t[i]);
+ fe_0(t);
+}
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/fe.h b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/fe.h
new file mode 100644
index 0000000..5eeb93d
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/fe.h
@@ -0,0 +1,21 @@
+#ifndef _FE_H____
+#define _FE_H____
+
+#include "crypto_uint32.h"
+#include "crypto_uint64.h"
+
+typedef crypto_uint32 fe[8];
+typedef crypto_uint64 fel[16];
+
+extern void fe_0(fe);
+extern void fe_1(fe);
+extern void fe_copy(fe, const fe);
+extern void fe_cswap(fe, fe, crypto_uint32);
+extern void fe_cmov(fe, const fe, crypto_uint32);
+
+extern void fe_mul_(fel, const fe, const fe);
+extern void fe_sq_(fel, const fe);
+
+extern void fe_reducesmall(fe, const fe, const crypto_uint64);
+
+#endif
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/fe25519.c b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/fe25519.c
new file mode 100644
index 0000000..fb6e08e
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/fe25519.c
@@ -0,0 +1,236 @@
+#include "uint32_pack.h"
+#include "uint32_unpack.h"
+#include "crypto_verify_32.h"
+#include "cleanup.h"
+#include "fe.h"
+#include "fe25519.h"
+
+/*
+p = 2^255 - 19
+*/
+static const fe p = {
+ 0xffffffed, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0x7fffffff
+};
+
+/*
+p3 = 3 * p
+*/
+static const crypto_uint64 p3[8] = {
+ 0x2ffffffc7ULL, 0x2fffffffdULL, 0x2fffffffdULL, 0x2fffffffdULL,
+ 0x2fffffffdULL, 0x2fffffffdULL, 0x2fffffffdULL, 0x17ffffffdULL
+};
+
+/*
+reduction modulo p: 16 limbs -> 8 limbs
+*/
+static void fe25519_reducebig(fe o, fel t) {
+
+ crypto_uint64 u = 0;
+ long long i;
+
+ for (i = 0; i < 7; ++i) { u += t[i] + 38ULL * t[i + 8]; t[i] = u & 0xffffffff; u >>= 32; }
+ u += t[i] + 38ULL * t[i + 8]; t[i] = u & 0x7fffffff; u >>= 31;
+ u *= 19ULL;
+ for (i = 0; i < 8; ++i) { u += t[i]; o[i] = u & 0xffffffff; u >>= 32; }
+}
+
+/*
+o = (a * b) % p
+*/
+void fe25519_mul(fe o, const fe a, const fe b) {
+
+ fel t;
+
+ fe_mul_(t, a, b);
+ fe25519_reducebig(o, t);
+
+ cleanup(t);
+}
+
+/*
+o = (a ^ 2) % p
+*/
+void fe25519_sq(fe o, const fe a) {
+
+ fel t;
+
+ fe_sq_(t, a);
+ fe25519_reducebig(o, t);
+
+ cleanup(t);
+}
+
+/*
+o = (121666 * f) % p;
+*/
+void fe25519_mul121666(fe o, const fe f) {
+
+ crypto_uint64 u = 0;
+ long long i;
+
+ for (i = 0; i < 7; ++i) { u += (crypto_uint64)121666 * (crypto_uint64)f[i]; o[i] = u & 0xffffffff; u >>= 32; }
+ u += (crypto_uint64)121666 * (crypto_uint64)f[i]; o[i] = u & 0x7fffffff; u >>= 31;
+ u *= 19ULL;
+ for (i = 0; i < 8; ++i) { u += o[i]; o[i] = u & 0xffffffff; u >>= 32; }
+}
+
+/*
+o = (x + y) % p
+*/
+void fe25519_add(fe o, const fe x, const fe y) {
+
+ crypto_uint64 u = 0;
+ long long i;
+
+ for (i = 0; i < 7; ++i) { u += (crypto_uint64)x[i] + (crypto_uint64)y[i]; o[i] = u & 0xffffffff; u >>= 32; }
+ u += (crypto_uint64)x[i] + (crypto_uint64)y[i]; o[i] = u & 0x7fffffff; u >>= 31;
+ u *= 19ULL;
+ for (i = 0; i < 8; ++i) { u += o[i]; o[i] = u & 0xffffffff; u >>= 32; }
+}
+
+/*
+o = (x - y) % p
+*/
+void fe25519_sub(fe o, const fe x, const fe y) {
+
+ crypto_uint64 u = 0;
+ long long i;
+
+ for (i = 0; i < 7; ++i) { u += p3[i] - (crypto_uint64)y[i] + (crypto_uint64)x[i]; o[i] = u & 0xffffffff; u >>= 32; }
+ u += p3[i] - (crypto_uint64)y[i] + (crypto_uint64)x[i]; o[i] = u & 0x7fffffff; u >>= 31;
+ u *= 19ULL;
+ for (i = 0; i < 8; ++i) { u += o[i]; o[i] = u & 0xffffffff; u >>= 32; }
+}
+
+/*
+o = -x % p
+*/
+void fe25519_neg(fe o, const fe x) {
+
+ fe t;
+
+ fe_0(t);
+ fe25519_sub(o, t, x);
+}
+
+
+/*
+o = (1 / z) % p
+... using Fermat's Little Theorem
+*/
+void fe25519_inv(fe o, const fe z) {
+
+ fe t0, t1, t2, t3;
+ long long i;
+
+ fe25519_sq(t0, z); for (i = 1; i < 1; ++i) fe25519_sq(t0, t0);
+ fe25519_sq(t1,t0); for (i = 1; i < 2; ++i) fe25519_sq(t1, t1);
+ fe25519_mul(t1, z, t1);
+ fe25519_mul(t0, t0, t1);
+ fe25519_sq(t2, t0); for (i = 1; i < 1; ++i) fe25519_sq(t2, t2);
+ fe25519_mul(t1, t1, t2);
+ fe25519_sq(t2, t1); for (i = 1; i < 5; ++i) fe25519_sq(t2, t2);
+ fe25519_mul(t1, t2, t1);
+ fe25519_sq(t2, t1); for (i = 1; i < 10; ++i) fe25519_sq(t2, t2);
+ fe25519_mul(t2, t2, t1);
+ fe25519_sq(t3, t2); for (i = 1; i < 20; ++i) fe25519_sq(t3, t3);
+ fe25519_mul(t2, t3, t2);
+ fe25519_sq(t2, t2); for (i = 1; i < 10; ++i) fe25519_sq(t2, t2);
+ fe25519_mul(t1, t2, t1);
+ fe25519_sq(t2, t1); for (i = 1; i < 50; ++i) fe25519_sq(t2, t2);
+ fe25519_mul(t2, t2, t1);
+ fe25519_sq(t3, t2); for (i = 1; i < 100; ++i) fe25519_sq(t3, t3);
+ fe25519_mul(t2, t3, t2);
+ fe25519_sq(t2, t2); for (i = 1; i < 50; ++i) fe25519_sq(t2, t2);
+ fe25519_mul(t1, t2, t1);
+ fe25519_sq(t1, t1); for (i = 1; i < 5; ++i) fe25519_sq(t1, t1);
+ fe25519_mul(o, t1, t0);
+
+ cleanup(t0); cleanup(t1); cleanup(t2); cleanup(t3);
+}
+
+void fe25519_pow22523(fe out, const fe z) {
+
+ fe t0, t1, t2;
+ long long i;
+
+ fe25519_sq(t0, z); for (i = 1; i < 1; ++i) fe25519_sq(t0, t0);
+ fe25519_sq(t1, t0); for (i = 1; i < 2; ++i) fe25519_sq(t1, t1);
+ fe25519_mul(t1, z, t1);
+ fe25519_mul(t0, t0, t1);
+ fe25519_sq(t0, t0); for (i = 1; i < 1; ++i) fe25519_sq(t0, t0);
+ fe25519_mul(t0, t1, t0);
+ fe25519_sq(t1, t0); for (i = 1; i < 5; ++i) fe25519_sq(t1, t1);
+ fe25519_mul(t0, t1, t0);
+ fe25519_sq(t1, t0); for (i = 1; i < 10; ++i) fe25519_sq(t1, t1);
+ fe25519_mul(t1, t1, t0);
+ fe25519_sq(t2, t1); for (i = 1; i < 20; ++i) fe25519_sq(t2, t2);
+ fe25519_mul(t1, t2, t1);
+ fe25519_sq(t1, t1); for (i = 1; i < 10; ++i) fe25519_sq(t1, t1);
+ fe25519_mul(t0, t1, t0);
+ fe25519_sq(t1, t0); for (i = 1; i < 50; ++i) fe25519_sq(t1, t1);
+ fe25519_mul(t1, t1, t0);
+ fe25519_sq(t2, t1); for (i = 1; i < 100; ++i) fe25519_sq(t2, t2);
+ fe25519_mul(t1, t2, t1);
+ fe25519_sq(t1, t1); for (i = 1; i < 50; ++i) fe25519_sq(t1, t1);
+ fe25519_mul(t0, t1, t0);
+ fe25519_sq(t0, t0); for (i = 1; i < 2; ++i) fe25519_sq(t0, t0);
+ fe25519_mul(out, t0, z);
+
+ cleanup(t0); cleanup(t1); cleanup(t2);
+}
+
+/*
+converts field-element into byte-array
+*/
+void fe25519_tobytes(unsigned char *out, const fe in) {
+
+ long long i;
+ fe x;
+
+ fe_copy(x, in);
+ fe_reducesmall(x, p, 0);
+ for (i = 0; i < 8; ++i) uint32_pack(out + 4 * i, x[i]);
+ cleanup(x);
+}
+
+/*
+converts byte-array into field-element
+*/
+void fe25519_frombytes(fe out, const unsigned char *in) {
+
+ long long i;
+
+ for (i = 0; i < 8; ++i) out[i] = uint32_unpack(in + 4 * i);
+ out[7] &= 0x7fffffff;
+}
+
+
+/*
+if (f == 0) return 0;
+else return -1;
+*/
+static const unsigned char zero[32] = {0};
+int fe25519_isnonzero(const fe f) {
+ unsigned char s[32];
+ int r;
+ fe25519_tobytes(s, f);
+ r = crypto_verify_32(s, zero);
+ cleanup(s);
+ return r;
+}
+
+
+/*
+if (f >= 0) return 0;
+else return -1;
+*/
+int fe25519_isnegative(const fe f) {
+ unsigned char s[32];
+ int r;
+ fe25519_tobytes(s,f);
+ r = s[0] & 1;
+ cleanup(s);
+ return r;
+}
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/fe25519.h b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/fe25519.h
new file mode 100644
index 0000000..2722d26
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/fe25519.h
@@ -0,0 +1,22 @@
+#ifndef _FE25519_H____
+#define _FE25519_H____
+
+#include "fe.h"
+
+extern void fe25519_mul(fe, const fe, const fe);
+extern void fe25519_sq(fe, const fe);
+extern void fe25519_add(fe, const fe, const fe);
+extern void fe25519_mul121666(fe, const fe);
+extern void fe25519_sub(fe, const fe, const fe);
+extern void fe25519_neg(fe, const fe);
+extern void fe25519_inv(fe, const fe);
+extern void fe25519_pow22523(fe, const fe);
+
+extern void fe25519_tobytes(unsigned char *, const fe);
+extern void fe25519_frombytes(fe, const unsigned char *);
+
+extern int fe25519_isnonzero(const fe);
+extern int fe25519_isnegative(const fe);
+
+#endif
+
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/ge25519.c b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/ge25519.c
new file mode 100644
index 0000000..31af206
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/ge25519.c
@@ -0,0 +1,226 @@
+#include "fe25519.h"
+#include "cleanup.h"
+#include "ge25519.h"
+
+/* D = -121665/121666 */
+static fe D = {
+ 0x135978a3, 0x75eb4dca, 0x4141d8ab, 0x00700a4d,
+ 0x7779e898, 0x8cc74079, 0x2b6ffe73, 0x52036cee
+};
+/* D2 = 2 * -121665/121666 */
+static fe D2 = {
+ 0x26b2f159, 0xebd69b94, 0x8283b156, 0x00e0149a,
+ 0xeef3d130, 0x198e80f2, 0x56dffce7, 0x2406d9dc
+};
+
+static fe sqrtm1 = {
+ 0x4a0ea0b0, 0xc4ee1b27, 0xad2fe478, 0x2f431806,
+ 0x3dfbd7a7, 0x2b4d0099, 0x4fc1df0b, 0x2b832480,
+};
+
+static void neutral(ge25519 p) {
+ fe_0(p[0]);
+ fe_1(p[1]);
+ fe_1(p[2]);
+ fe_0(p[3]);
+}
+
+
+/*
+p = q
+*/
+static void copy(ge25519 p, ge25519 q) {
+
+ fe_copy(p[0], q[0]);
+ fe_copy(p[1], q[1]);
+ fe_copy(p[2], q[2]);
+ fe_copy(p[3], q[3]);
+}
+
+
+/*
+if (b) p = q;
+*/
+static void cmov(ge25519 p, ge25519 q, crypto_uint32 b) {
+
+ fe_cmov(p[0], q[0], b);
+ fe_cmov(p[1], q[1], b);
+ fe_cmov(p[2], q[2], b);
+ fe_cmov(p[3], q[3], b);
+}
+
+void ge25519_add(ge25519 o, ge25519 p, ge25519 q) {
+
+ fe a, b, c, d, t, e, f, g, h;
+
+ fe25519_sub(a, p[1], p[0]);
+ fe25519_sub(t, q[1], q[0]);
+ fe25519_mul(a, a, t);
+ fe25519_add(b, p[0], p[1]);
+ fe25519_add(t, q[0], q[1]);
+ fe25519_mul(b, b, t);
+ fe25519_mul(c, p[3], q[3]);
+ fe25519_mul(c, c, D2);
+ fe25519_mul(d, p[2], q[2]);
+ fe25519_add(d, d, d);
+ fe25519_sub(e, b, a);
+ fe25519_sub(f, d, c);
+ fe25519_add(g, d, c);
+ fe25519_add(h, b, a);
+
+ fe25519_mul(o[0], e, f);
+ fe25519_mul(o[1], h, g);
+ fe25519_mul(o[2], g, f);
+ fe25519_mul(o[3], e, h);
+
+ cleanup(a); cleanup(b); cleanup(c); cleanup(d); cleanup(t);
+ cleanup(e); cleanup(f); cleanup(g); cleanup(h);
+}
+
+
+/* https://hyperelliptic.org/EFD/g1p/auto-code/twisted/extended/doubling/dbl-2008-hwcd.op3 */
+static void dbl(ge25519 o, ge25519 p) {
+
+ fe a, b, c, d, e, f, g, h;
+
+ fe25519_sq(a, p[0]); /* A = X1^2 */
+ fe25519_sq(b, p[1]); /* B = Y1^2 */
+ fe25519_sq(c, p[2]); /* t0 = Z1^2 */
+ fe25519_add(c, c, c); /* C = 2*t0 */
+ fe25519_neg(d, a); /* D = a*A */
+ fe25519_add(e, p[0], p[1]); /* t1 = X1+Y1 */
+ fe25519_sq(e, e); /* t2 = t1^2 */
+ fe25519_sub(e, e, a); /* t3 = t2-A */
+ fe25519_sub(e, e, b); /* E = t3-B */
+ fe25519_add(g, d, b); /* G = D+B */
+ fe25519_sub(f, g, c); /* F = G-C */
+ fe25519_sub(h, d, b); /* H = D-B */
+
+ fe25519_mul(o[0], e, f); /* X3 = E*F */
+ fe25519_mul(o[1], g, h); /* Y3 = G*H */
+ fe25519_mul(o[2], f, g); /* Z3 = F*G */
+ fe25519_mul(o[3], e, h); /* T3 = E*H */
+
+ cleanup(a); cleanup(b); cleanup(c); cleanup(d);
+ cleanup(e); cleanup(f); cleanup(g); cleanup(h);
+}
+
+
+void ge25519_tobytes(unsigned char *s, ge25519 h) {
+
+ fe x, y, z;
+
+ fe25519_inv(z, h[2]);
+ fe25519_mul(x, h[0], z);
+ fe25519_mul(y, h[1], z);
+ fe25519_tobytes(s, y);
+ s[31] ^= fe25519_isnegative(x) << 7;
+
+ cleanup(x); cleanup(y); cleanup(z);
+}
+
+int ge25519_frombytes_negate_vartime(ge25519 h, const unsigned char *s) {
+
+ fe u, v, v3, vxx, check;
+ int ret = -1;
+
+ fe25519_frombytes(h[1], s);
+ fe_1(h[2]);
+ fe25519_sq(u,h[1]);
+ fe25519_mul(v,u,D);
+ fe25519_sub(u,u,h[2]); /* u = y^2-1 */
+ fe25519_add(v,v,h[2]); /* v = dy^2+1 */
+
+ fe25519_sq(v3,v);
+ fe25519_mul(v3,v3,v); /* v3 = v^3 */
+ fe25519_sq(h[0],v3);
+ fe25519_mul(h[0],h[0],v);
+ fe25519_mul(h[0],h[0],u); /* x = uv^7 */
+
+ fe25519_pow22523(h[0],h[0]); /* x = (uv^7)^((q-5)/8) */
+ fe25519_mul(h[0],h[0],v3);
+ fe25519_mul(h[0],h[0],u); /* x = uv^3(uv^7)^((q-5)/8) */
+
+ fe25519_sq(vxx,h[0]);
+ fe25519_mul(vxx,vxx,v);
+ fe25519_sub(check,vxx,u); /* vx^2-u */
+ if (fe25519_isnonzero(check)) {
+ fe25519_add(check,vxx,u); /* vx^2+u */
+ if (fe25519_isnonzero(check)) {
+ goto cleanup;
+ }
+ fe25519_mul(h[0],h[0],sqrtm1);
+ }
+
+ if (fe25519_isnegative(h[0]) == (s[31] >> 7))
+ fe25519_neg(h[0], h[0]);
+
+ fe25519_mul(h[3],h[0],h[1]);
+ ret = 0;
+
+cleanup:
+ cleanup(u); cleanup(v); cleanup(v3);
+ cleanup(vxx); cleanup(check);
+ return ret;
+}
+
+
+/*
+if (a == b) return 1;
+else return 0;
+*/
+static unsigned char equal(unsigned char a, unsigned char b) {
+
+ unsigned char x = a ^ b;
+ crypto_uint32 y = x;
+ y -= 1;
+ y >>= 31;
+ return y;
+}
+
+/*
+point multiplication using windowed method
+*/
+void ge25519_scalarmult(ge25519 o, ge25519 q, const unsigned char *a) {
+
+ long long i, j;
+ ge25519 t[16], sp, p;
+ unsigned char e[64];
+
+ for (i = 0; i < 32; ++i) {
+ e[2 * i + 0] = (a[i] >> 0) & 0x0f;
+ e[2 * i + 1] = (a[i] >> 4) & 0x0f;
+ }
+
+ neutral(p);
+
+ /* precompute points */
+ copy(t[0], p);
+ copy(t[1], q);
+ for (i = 2; i < 16; ++i) {
+ if ((i & 1) == 0) dbl(t[i], t[i / 2]);
+ else ge25519_add(t[i], t[i - 1], q);
+ }
+
+ for (i = 63; i >= 0; --i) {
+ for (j = 0; j < 4; ++j) dbl(p, p);
+ for (j = 0; j < 16; ++j) cmov(sp, t[j], equal(e[i], j));
+ ge25519_add(p, p, sp);
+ }
+
+ copy(o, p);
+
+ cleanup(p); cleanup(t); cleanup(sp); cleanup(e);
+}
+
+static ge25519 baseq = {
+ { 0x8f25d51a,0xc9562d60,0x9525a7b2,0x692cc760,0xfdd6dc5c,0xc0a4e231,0xcd6e53fe,0x216936d3 },
+ { 0x66666658,0x66666666,0x66666666,0x66666666,0x66666666,0x66666666,0x66666666,0x66666666 },
+ { 0x00000001,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 },
+ { 0xa5b7dda3,0x6dde8ab3,0x775152f5,0x20f09f80,0x64abe37d,0x66ea4e8e,0xd78b7665,0x67875f0f },
+ };
+
+void ge25519_scalarmult_base(ge25519 p, const unsigned char *a) {
+
+ ge25519_scalarmult(p, baseq, a);
+}
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/ge25519.h b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/ge25519.h
new file mode 100644
index 0000000..0428b73
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/ge25519.h
@@ -0,0 +1,14 @@
+#ifndef _GE25519_H____
+#define _GE25519_H____
+
+#include "fe.h"
+
+typedef fe ge25519[4]; /* X, Y, Z, T */
+
+extern void ge25519_tobytes(unsigned char *, ge25519);
+extern int ge25519_frombytes_negate_vartime(ge25519, const unsigned char *);
+extern void ge25519_add(ge25519, ge25519, ge25519);
+extern void ge25519_scalarmult(ge25519, ge25519, const unsigned char *);
+extern void ge25519_scalarmult_base(ge25519, const unsigned char *);
+
+#endif
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/randombytes.c b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/randombytes.c
new file mode 100644
index 0000000..95645a9
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/randombytes.c
@@ -0,0 +1,41 @@
+/* taken from nacl-20110221, from randombytes/devurandom.c, added close-on-exec */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include "randombytes.h"
+
+/* it's really stupid that there isn't a syscall for this */
+
+static int fd = -1;
+
+void randombytes(unsigned char *x,unsigned long long xlen)
+{
+ int i;
+
+ if (fd == -1) {
+ for (;;) {
+#ifdef O_CLOEXEC
+ fd = open("/dev/urandom",O_RDONLY | O_CLOEXEC);
+#else
+ fd = open("/dev/urandom",O_RDONLY);
+ fcntl(fd,F_SETFD,1);
+#endif
+ if (fd != -1) break;
+ sleep(1);
+ }
+ }
+
+ while (xlen > 0) {
+ if (xlen < 1048576) i = xlen; else i = 1048576;
+
+ i = read(fd,x,i);
+ if (i < 1) {
+ sleep(1);
+ continue;
+ }
+
+ x += i;
+ xlen -= i;
+ }
+}
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/randombytes.h b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/randombytes.h
new file mode 100644
index 0000000..724104f
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/randombytes.h
@@ -0,0 +1,10 @@
+#ifndef _RANDOMBYTES_H____
+#define _RANDOMBYTES_H____
+
+extern void randombytes(unsigned char *, unsigned long long);
+
+#ifndef randombytes_implementation
+#define randombytes_implementation "tinyssh"
+#endif
+
+#endif
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/sc25519.c b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/sc25519.c
new file mode 100644
index 0000000..12610c3
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/sc25519.c
@@ -0,0 +1,67 @@
+/*
+- based on tweetnacl 20140427 (http://tweetnacl.cr.yp.to/software.html)
+*/
+
+#include "crypto_int64.h"
+#include "crypto_uint32.h"
+#include "crypto_uint64.h"
+#include "cleanup.h"
+#include "sc25519.h"
+
+#define FOR(i,n) for (i = 0;i < n;++i)
+
+static const crypto_uint64 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};
+
+static void modL(unsigned char *r,crypto_int64 x[64])
+{
+ crypto_int64 carry,i,j;
+ for (i = 63;i >= 32;--i) {
+ carry = 0;
+ for (j = i - 32;j < i - 12;++j) {
+ x[j] += carry - 16 * x[i] * L[j - (i - 32)];
+ carry = (x[j] + 128) >> 8;
+ x[j] -= carry << 8;
+ }
+ x[j] += carry;
+ x[i] = 0;
+ }
+ carry = 0;
+ FOR(j,32) {
+ x[j] += carry - (x[31] >> 4) * L[j];
+ carry = x[j] >> 8;
+ x[j] &= 255;
+ }
+ FOR(j,32) x[j] -= carry * L[j];
+ FOR(i,32) {
+ x[i+1] += x[i] >> 8;
+ r[i] = x[i] & 255;
+ }
+}
+
+void sc25519_reduce(unsigned char *s) {
+
+ crypto_int64 t[64], i;
+
+ for (i = 0; i < 64; ++i) t[i] = s[i];
+ for (i = 0; i < 64; ++i) s[i] = 0;
+ modL(s, t);
+
+ cleanup(t);
+}
+
+void sc25519_muladd(unsigned char *s, const unsigned char *a, const unsigned char *b, const unsigned char *c) {
+
+ crypto_int64 t[64], i, j;
+
+
+ for (i = 0; i < 64; ++i) t[i] = 0;
+
+ for (i = 0; i < 32; ++i) for (j = 0; j < 32; ++j) {
+ t[i + j] += (crypto_int64)a[i] * (crypto_int64)b[j];
+ }
+
+ for (i = 0; i < 32; ++i) t[i] += c[i];
+ modL(s, t);
+
+ cleanup(t);
+}
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/sc25519.h b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/sc25519.h
new file mode 100644
index 0000000..c08df70
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/sc25519.h
@@ -0,0 +1,7 @@
+#ifndef _SC25519_H____
+#define _SC25519_H____
+
+extern void sc25519_reduce(unsigned char *);
+extern void sc25519_muladd(unsigned char *, const unsigned char *, const unsigned char *, const unsigned char *);
+
+#endif
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/uint32_pack.c b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/uint32_pack.c
new file mode 100644
index 0000000..8bf87fb
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/uint32_pack.c
@@ -0,0 +1,11 @@
+#include "uint32_pack.h"
+
+/*
+The 'uint32_pack' function converts 32-bit unsigned
+integer into 4 bytes stored in little-endian format
+*/
+void uint32_pack(unsigned char *y, crypto_uint32 x) {
+
+ long long i;
+ for (i = 0; i < 4; ++i) { y[i] = x; x >>= 8; }
+}
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/uint32_pack.h b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/uint32_pack.h
new file mode 100644
index 0000000..6f4f053
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/uint32_pack.h
@@ -0,0 +1,8 @@
+#ifndef _UINT32_PACK_H____
+#define _UINT32_PACK_H____
+
+#include "crypto_uint32.h"
+
+extern void uint32_pack(unsigned char *, crypto_uint32);
+
+#endif
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/uint32_unpack.c b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/uint32_unpack.c
new file mode 100644
index 0000000..172c65d
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/uint32_unpack.c
@@ -0,0 +1,13 @@
+#include "uint32_unpack.h"
+
+/*
+The 'uint32_unpack' function converts 4 bytes
+in little-endian format into 32-bit unsigned integer.
+*/
+crypto_uint32 uint32_unpack(const unsigned char *x) {
+
+ crypto_uint32 y = 0;
+ long long i;
+ for (i = 3; i >= 0; --i) y = (y << 8) | x[i];
+ return y;
+}
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/uint32_unpack.h b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/uint32_unpack.h
new file mode 100644
index 0000000..fb0588a
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/uint32_unpack.h
@@ -0,0 +1,8 @@
+#ifndef _UINT32_UNPACK_H____
+#define _UINT32_UNPACK_H____
+
+#include "crypto_uint32.h"
+
+extern crypto_uint32 uint32_unpack(const unsigned char *);
+
+#endif
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/verify.c b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/verify.c
new file mode 100644
index 0000000..9dcf121
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/verify.c
@@ -0,0 +1,10 @@
+#include "verify.h"
+
+int verify(const unsigned char *x, const unsigned char *y, long long n) {
+
+ unsigned int d = 0;
+ long long i;
+
+ for (i = 0; i < n; ++i) d |= x[i] ^ y[i];
+ return (1 & ((d - 1) >> 8)) - 1;
+}
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/verify.h b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/verify.h
new file mode 100644
index 0000000..718b831
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tinyssh/verify.h
@@ -0,0 +1,6 @@
+#ifndef _VERIFY_H____
+#define _VERIFY_H____
+
+extern int verify(const unsigned char *, const unsigned char *, long long);
+
+#endif
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tweetnacl/AUTHORS.md b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tweetnacl/AUTHORS.md
new file mode 100644
index 0000000..e3300f3
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tweetnacl/AUTHORS.md
@@ -0,0 +1,20 @@
+The code of TweetNaCl has been written by:
+
+* Daniel J. Bernstein
+* Bernard von Gastel
+* Wesley Janssen
+* Tanja Lange
+* Peter Schwabe
+* Sjaak Smetsers
+
+TweetNaCl has been dedicated to the public domain;
+refer to <https://tweetnacl.cr.yp.to/>
+("TweetNaCl is a self-contained public-domain C library, [...]")
+and Daniel J. Bernstein et al., TweetNaCl: a crypto library in
+100 tweets, LATINCRYPT 2014, pp. 64-83, (also available from
+<https://tweetnacl.cr.yp.to/tweetnacl-20140917.pdf>), p. 3:
+"We have placed TweetNaCl into the public domain, and we encourage
+applications to make use of it".
+
+TweetNaCl has been obtained via <https://tweetnacl.cr.yp.to/>.
+
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tweetnacl/tweetnacl.c b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tweetnacl/tweetnacl.c
new file mode 100644
index 0000000..8ac0a18
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tweetnacl/tweetnacl.c
@@ -0,0 +1,809 @@
+#include "tweetnacl.h"
+#define FOR(i,n) for (i = 0;i < n;++i)
+#define sv static void
+
+typedef unsigned char u8;
+typedef unsigned long u32;
+typedef unsigned long long u64;
+typedef long long i64;
+typedef i64 gf[16];
+extern void randombytes(u8 *,u64);
+
+static const u8
+ _0[16],
+ _9[32] = {9};
+static const gf
+ gf0,
+ gf1 = {1},
+ _121665 = {0xDB41,1},
+ D = {0x78a3, 0x1359, 0x4dca, 0x75eb, 0xd8ab, 0x4141, 0x0a4d, 0x0070, 0xe898, 0x7779, 0x4079, 0x8cc7, 0xfe73, 0x2b6f, 0x6cee, 0x5203},
+ D2 = {0xf159, 0x26b2, 0x9b94, 0xebd6, 0xb156, 0x8283, 0x149a, 0x00e0, 0xd130, 0xeef3, 0x80f2, 0x198e, 0xfce7, 0x56df, 0xd9dc, 0x2406},
+ X = {0xd51a, 0x8f25, 0x2d60, 0xc956, 0xa7b2, 0x9525, 0xc760, 0x692c, 0xdc5c, 0xfdd6, 0xe231, 0xc0a4, 0x53fe, 0xcd6e, 0x36d3, 0x2169},
+ Y = {0x6658, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666},
+ I = {0xa0b0, 0x4a0e, 0x1b27, 0xc4ee, 0xe478, 0xad2f, 0x1806, 0x2f43, 0xd7a7, 0x3dfb, 0x0099, 0x2b4d, 0xdf0b, 0x4fc1, 0x2480, 0x2b83};
+
+static u32 L32(u32 x,int c) { return (x << c) | ((x&0xffffffff) >> (32 - c)); }
+
+static u32 ld32(const u8 *x)
+{
+ u32 u = x[3];
+ u = (u<<8)|x[2];
+ u = (u<<8)|x[1];
+ return (u<<8)|x[0];
+}
+
+static u64 dl64(const u8 *x)
+{
+ u64 i,u=0;
+ FOR(i,8) u=(u<<8)|x[i];
+ return u;
+}
+
+sv st32(u8 *x,u32 u)
+{
+ int i;
+ FOR(i,4) { x[i] = u; u >>= 8; }
+}
+
+sv ts64(u8 *x,u64 u)
+{
+ int i;
+ for (i = 7;i >= 0;--i) { x[i] = u; u >>= 8; }
+}
+
+static int vn(const u8 *x,const u8 *y,int n)
+{
+ u32 i,d = 0;
+ FOR(i,n) d |= x[i]^y[i];
+ return (1 & ((d - 1) >> 8)) - 1;
+}
+
+int crypto_verify_16(const u8 *x,const u8 *y)
+{
+ return vn(x,y,16);
+}
+
+int crypto_verify_32(const u8 *x,const u8 *y)
+{
+ return vn(x,y,32);
+}
+
+sv core(u8 *out,const u8 *in,const u8 *k,const u8 *c,int h)
+{
+ u32 w[16],x[16],y[16],t[4];
+ int i,j,m;
+
+ FOR(i,4) {
+ x[5*i] = ld32(c+4*i);
+ x[1+i] = ld32(k+4*i);
+ x[6+i] = ld32(in+4*i);
+ x[11+i] = ld32(k+16+4*i);
+ }
+
+ FOR(i,16) y[i] = x[i];
+
+ FOR(i,20) {
+ FOR(j,4) {
+ FOR(m,4) t[m] = x[(5*j+4*m)%16];
+ t[1] ^= L32(t[0]+t[3], 7);
+ t[2] ^= L32(t[1]+t[0], 9);
+ t[3] ^= L32(t[2]+t[1],13);
+ t[0] ^= L32(t[3]+t[2],18);
+ FOR(m,4) w[4*j+(j+m)%4] = t[m];
+ }
+ FOR(m,16) x[m] = w[m];
+ }
+
+ if (h) {
+ FOR(i,16) x[i] += y[i];
+ FOR(i,4) {
+ x[5*i] -= ld32(c+4*i);
+ x[6+i] -= ld32(in+4*i);
+ }
+ FOR(i,4) {
+ st32(out+4*i,x[5*i]);
+ st32(out+16+4*i,x[6+i]);
+ }
+ } else
+ FOR(i,16) st32(out + 4 * i,x[i] + y[i]);
+}
+
+int crypto_core_salsa20(u8 *out,const u8 *in,const u8 *k,const u8 *c)
+{
+ core(out,in,k,c,0);
+ return 0;
+}
+
+int crypto_core_hsalsa20(u8 *out,const u8 *in,const u8 *k,const u8 *c)
+{
+ core(out,in,k,c,1);
+ return 0;
+}
+
+static const u8 sigma[16] = "expand 32-byte k";
+
+int crypto_stream_salsa20_xor(u8 *c,const u8 *m,u64 b,const u8 *n,const u8 *k)
+{
+ u8 z[16],x[64];
+ u32 u,i;
+ if (!b) return 0;
+ FOR(i,16) z[i] = 0;
+ FOR(i,8) z[i] = n[i];
+ while (b >= 64) {
+ crypto_core_salsa20(x,z,k,sigma);
+ FOR(i,64) c[i] = (m?m[i]:0) ^ x[i];
+ u = 1;
+ for (i = 8;i < 16;++i) {
+ u += (u32) z[i];
+ z[i] = u;
+ u >>= 8;
+ }
+ b -= 64;
+ c += 64;
+ if (m) m += 64;
+ }
+ if (b) {
+ crypto_core_salsa20(x,z,k,sigma);
+ FOR(i,b) c[i] = (m?m[i]:0) ^ x[i];
+ }
+ return 0;
+}
+
+int crypto_stream_salsa20(u8 *c,u64 d,const u8 *n,const u8 *k)
+{
+ return crypto_stream_salsa20_xor(c,0,d,n,k);
+}
+
+int crypto_stream(u8 *c,u64 d,const u8 *n,const u8 *k)
+{
+ u8 s[32];
+ crypto_core_hsalsa20(s,n,k,sigma);
+ return crypto_stream_salsa20(c,d,n+16,s);
+}
+
+int crypto_stream_xor(u8 *c,const u8 *m,u64 d,const u8 *n,const u8 *k)
+{
+ u8 s[32];
+ crypto_core_hsalsa20(s,n,k,sigma);
+ return crypto_stream_salsa20_xor(c,m,d,n+16,s);
+}
+
+sv add1305(u32 *h,const u32 *c)
+{
+ u32 j,u = 0;
+ FOR(j,17) {
+ u += h[j] + c[j];
+ h[j] = u & 255;
+ u >>= 8;
+ }
+}
+
+static const u32 minusp[17] = {
+ 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252
+} ;
+
+int crypto_onetimeauth(u8 *out,const u8 *m,u64 n,const u8 *k)
+{
+ u32 s,i,j,u,x[17],r[17],h[17],c[17],g[17];
+
+ FOR(j,17) r[j]=h[j]=0;
+ FOR(j,16) r[j]=k[j];
+ r[3]&=15;
+ r[4]&=252;
+ r[7]&=15;
+ r[8]&=252;
+ r[11]&=15;
+ r[12]&=252;
+ r[15]&=15;
+
+ while (n > 0) {
+ FOR(j,17) c[j] = 0;
+ for (j = 0;(j < 16) && (j < n);++j) c[j] = m[j];
+ c[j] = 1;
+ m += j; n -= j;
+ add1305(h,c);
+ FOR(i,17) {
+ x[i] = 0;
+ FOR(j,17) x[i] += h[j] * ((j <= i) ? r[i - j] : 320 * r[i + 17 - j]);
+ }
+ FOR(i,17) h[i] = x[i];
+ u = 0;
+ FOR(j,16) {
+ u += h[j];
+ h[j] = u & 255;
+ u >>= 8;
+ }
+ u += h[16]; h[16] = u & 3;
+ u = 5 * (u >> 2);
+ FOR(j,16) {
+ u += h[j];
+ h[j] = u & 255;
+ u >>= 8;
+ }
+ u += h[16]; h[16] = u;
+ }
+
+ FOR(j,17) g[j] = h[j];
+ add1305(h,minusp);
+ s = -(h[16] >> 7);
+ FOR(j,17) h[j] ^= s & (g[j] ^ h[j]);
+
+ FOR(j,16) c[j] = k[j + 16];
+ c[16] = 0;
+ add1305(h,c);
+ FOR(j,16) out[j] = h[j];
+ return 0;
+}
+
+int crypto_onetimeauth_verify(const u8 *h,const u8 *m,u64 n,const u8 *k)
+{
+ u8 x[16];
+ crypto_onetimeauth(x,m,n,k);
+ return crypto_verify_16(h,x);
+}
+
+int crypto_secretbox(u8 *c,const u8 *m,u64 d,const u8 *n,const u8 *k)
+{
+ int i;
+ if (d < 32) return -1;
+ crypto_stream_xor(c,m,d,n,k);
+ crypto_onetimeauth(c + 16,c + 32,d - 32,c);
+ FOR(i,16) c[i] = 0;
+ return 0;
+}
+
+int crypto_secretbox_open(u8 *m,const u8 *c,u64 d,const u8 *n,const u8 *k)
+{
+ int i;
+ u8 x[32];
+ if (d < 32) return -1;
+ crypto_stream(x,32,n,k);
+ if (crypto_onetimeauth_verify(c + 16,c + 32,d - 32,x) != 0) return -1;
+ crypto_stream_xor(m,c,d,n,k);
+ FOR(i,32) m[i] = 0;
+ return 0;
+}
+
+sv set25519(gf r, const gf a)
+{
+ int i;
+ FOR(i,16) r[i]=a[i];
+}
+
+sv car25519(gf o)
+{
+ int i;
+ i64 c;
+ FOR(i,16) {
+ o[i]+=(1LL<<16);
+ c=o[i]>>16;
+ o[(i+1)*(i<15)]+=c-1+37*(c-1)*(i==15);
+ o[i]-=c<<16;
+ }
+}
+
+sv sel25519(gf p,gf q,int b)
+{
+ i64 t,i,c=~(b-1);
+ FOR(i,16) {
+ t= c&(p[i]^q[i]);
+ p[i]^=t;
+ q[i]^=t;
+ }
+}
+
+sv pack25519(u8 *o,const gf n)
+{
+ int i,j,b;
+ gf m,t;
+ FOR(i,16) t[i]=n[i];
+ car25519(t);
+ car25519(t);
+ car25519(t);
+ FOR(j,2) {
+ m[0]=t[0]-0xffed;
+ for(i=1;i<15;i++) {
+ m[i]=t[i]-0xffff-((m[i-1]>>16)&1);
+ m[i-1]&=0xffff;
+ }
+ m[15]=t[15]-0x7fff-((m[14]>>16)&1);
+ b=(m[15]>>16)&1;
+ m[14]&=0xffff;
+ sel25519(t,m,1-b);
+ }
+ FOR(i,16) {
+ o[2*i]=t[i]&0xff;
+ o[2*i+1]=t[i]>>8;
+ }
+}
+
+static int neq25519(const gf a, const gf b)
+{
+ u8 c[32],d[32];
+ pack25519(c,a);
+ pack25519(d,b);
+ return crypto_verify_32(c,d);
+}
+
+static u8 par25519(const gf a)
+{
+ u8 d[32];
+ pack25519(d,a);
+ return d[0]&1;
+}
+
+sv unpack25519(gf o, const u8 *n)
+{
+ int i;
+ FOR(i,16) o[i]=n[2*i]+((i64)n[2*i+1]<<8);
+ o[15]&=0x7fff;
+}
+
+sv A(gf o,const gf a,const gf b)
+{
+ int i;
+ FOR(i,16) o[i]=a[i]+b[i];
+}
+
+sv Z(gf o,const gf a,const gf b)
+{
+ int i;
+ FOR(i,16) o[i]=a[i]-b[i];
+}
+
+sv M(gf o,const gf a,const gf b)
+{
+ i64 i,j,t[31];
+ FOR(i,31) t[i]=0;
+ FOR(i,16) FOR(j,16) t[i+j]+=a[i]*b[j];
+ FOR(i,15) t[i]+=38*t[i+16];
+ FOR(i,16) o[i]=t[i];
+ car25519(o);
+ car25519(o);
+}
+
+sv S(gf o,const gf a)
+{
+ M(o,a,a);
+}
+
+sv inv25519(gf o,const gf i)
+{
+ gf c;
+ int a;
+ FOR(a,16) c[a]=i[a];
+ for(a=253;a>=0;a--) {
+ S(c,c);
+ if(a!=2&&a!=4) M(c,c,i);
+ }
+ FOR(a,16) o[a]=c[a];
+}
+
+sv pow2523(gf o,const gf i)
+{
+ gf c;
+ int a;
+ FOR(a,16) c[a]=i[a];
+ for(a=250;a>=0;a--) {
+ S(c,c);
+ if(a!=1) M(c,c,i);
+ }
+ FOR(a,16) o[a]=c[a];
+}
+
+int crypto_scalarmult(u8 *q,const u8 *n,const u8 *p)
+{
+ u8 z[32];
+ i64 x[80],r,i;
+ gf a,b,c,d,e,f;
+ FOR(i,31) z[i]=n[i];
+ z[31]=(n[31]&127)|64;
+ z[0]&=248;
+ unpack25519(x,p);
+ FOR(i,16) {
+ b[i]=x[i];
+ d[i]=a[i]=c[i]=0;
+ }
+ a[0]=d[0]=1;
+ for(i=254;i>=0;--i) {
+ r=(z[i>>3]>>(i&7))&1;
+ sel25519(a,b,r);
+ sel25519(c,d,r);
+ A(e,a,c);
+ Z(a,a,c);
+ A(c,b,d);
+ Z(b,b,d);
+ S(d,e);
+ S(f,a);
+ M(a,c,a);
+ M(c,b,e);
+ A(e,a,c);
+ Z(a,a,c);
+ S(b,a);
+ Z(c,d,f);
+ M(a,c,_121665);
+ A(a,a,d);
+ M(c,c,a);
+ M(a,d,f);
+ M(d,b,x);
+ S(b,e);
+ sel25519(a,b,r);
+ sel25519(c,d,r);
+ }
+ FOR(i,16) {
+ x[i+16]=a[i];
+ x[i+32]=c[i];
+ x[i+48]=b[i];
+ x[i+64]=d[i];
+ }
+ inv25519(x+32,x+32);
+ M(x+16,x+16,x+32);
+ pack25519(q,x+16);
+ return 0;
+}
+
+int crypto_scalarmult_base(u8 *q,const u8 *n)
+{
+ return crypto_scalarmult(q,n,_9);
+}
+
+int crypto_box_keypair(u8 *y,u8 *x)
+{
+ randombytes(x,32);
+ return crypto_scalarmult_base(y,x);
+}
+
+int crypto_box_beforenm(u8 *k,const u8 *y,const u8 *x)
+{
+ u8 s[32];
+ crypto_scalarmult(s,x,y);
+ return crypto_core_hsalsa20(k,_0,s,sigma);
+}
+
+int crypto_box_afternm(u8 *c,const u8 *m,u64 d,const u8 *n,const u8 *k)
+{
+ return crypto_secretbox(c,m,d,n,k);
+}
+
+int crypto_box_open_afternm(u8 *m,const u8 *c,u64 d,const u8 *n,const u8 *k)
+{
+ return crypto_secretbox_open(m,c,d,n,k);
+}
+
+int crypto_box(u8 *c,const u8 *m,u64 d,const u8 *n,const u8 *y,const u8 *x)
+{
+ u8 k[32];
+ crypto_box_beforenm(k,y,x);
+ return crypto_box_afternm(c,m,d,n,k);
+}
+
+int crypto_box_open(u8 *m,const u8 *c,u64 d,const u8 *n,const u8 *y,const u8 *x)
+{
+ u8 k[32];
+ crypto_box_beforenm(k,y,x);
+ return crypto_box_open_afternm(m,c,d,n,k);
+}
+
+static u64 R(u64 x,int c) { return (x >> c) | (x << (64 - c)); }
+static u64 Ch(u64 x,u64 y,u64 z) { return (x & y) ^ (~x & z); }
+static u64 Maj(u64 x,u64 y,u64 z) { return (x & y) ^ (x & z) ^ (y & z); }
+static u64 Sigma0(u64 x) { return R(x,28) ^ R(x,34) ^ R(x,39); }
+static u64 Sigma1(u64 x) { return R(x,14) ^ R(x,18) ^ R(x,41); }
+static u64 sigma0(u64 x) { return R(x, 1) ^ R(x, 8) ^ (x >> 7); }
+static u64 sigma1(u64 x) { return R(x,19) ^ R(x,61) ^ (x >> 6); }
+
+static const u64 K[80] =
+{
+ 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
+ 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
+ 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
+ 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
+ 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
+ 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
+ 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
+ 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
+ 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
+ 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
+ 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
+ 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
+ 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
+ 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
+ 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
+ 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
+ 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
+ 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
+ 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
+ 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL
+};
+
+int crypto_hashblocks(u8 *x,const u8 *m,u64 n)
+{
+ u64 z[8],b[8],a[8],w[16],t;
+ int i,j;
+
+ FOR(i,8) z[i] = a[i] = dl64(x + 8 * i);
+
+ while (n >= 128) {
+ FOR(i,16) w[i] = dl64(m + 8 * i);
+
+ FOR(i,80) {
+ FOR(j,8) b[j] = a[j];
+ t = a[7] + Sigma1(a[4]) + Ch(a[4],a[5],a[6]) + K[i] + w[i%16];
+ b[7] = t + Sigma0(a[0]) + Maj(a[0],a[1],a[2]);
+ b[3] += t;
+ FOR(j,8) a[(j+1)%8] = b[j];
+ if (i%16 == 15)
+ FOR(j,16)
+ w[j] += w[(j+9)%16] + sigma0(w[(j+1)%16]) + sigma1(w[(j+14)%16]);
+ }
+
+ FOR(i,8) { a[i] += z[i]; z[i] = a[i]; }
+
+ m += 128;
+ n -= 128;
+ }
+
+ FOR(i,8) ts64(x+8*i,z[i]);
+
+ return n;
+}
+
+static const u8 iv[64] = {
+ 0x6a,0x09,0xe6,0x67,0xf3,0xbc,0xc9,0x08,
+ 0xbb,0x67,0xae,0x85,0x84,0xca,0xa7,0x3b,
+ 0x3c,0x6e,0xf3,0x72,0xfe,0x94,0xf8,0x2b,
+ 0xa5,0x4f,0xf5,0x3a,0x5f,0x1d,0x36,0xf1,
+ 0x51,0x0e,0x52,0x7f,0xad,0xe6,0x82,0xd1,
+ 0x9b,0x05,0x68,0x8c,0x2b,0x3e,0x6c,0x1f,
+ 0x1f,0x83,0xd9,0xab,0xfb,0x41,0xbd,0x6b,
+ 0x5b,0xe0,0xcd,0x19,0x13,0x7e,0x21,0x79
+} ;
+
+int crypto_hash(u8 *out,const u8 *m,u64 n)
+{
+ u8 h[64],x[256];
+ u64 i,b = n;
+
+ FOR(i,64) h[i] = iv[i];
+
+ crypto_hashblocks(h,m,n);
+ m += n;
+ n &= 127;
+ m -= n;
+
+ FOR(i,256) x[i] = 0;
+ FOR(i,n) x[i] = m[i];
+ x[n] = 128;
+
+ n = 256-128*(n<112);
+ x[n-9] = b >> 61;
+ ts64(x+n-8,b<<3);
+ crypto_hashblocks(h,x,n);
+
+ FOR(i,64) out[i] = h[i];
+
+ return 0;
+}
+
+sv add(gf p[4],gf q[4])
+{
+ gf a,b,c,d,t,e,f,g,h;
+
+ Z(a, p[1], p[0]);
+ Z(t, q[1], q[0]);
+ M(a, a, t);
+ A(b, p[0], p[1]);
+ A(t, q[0], q[1]);
+ M(b, b, t);
+ M(c, p[3], q[3]);
+ M(c, c, D2);
+ M(d, p[2], q[2]);
+ A(d, d, d);
+ Z(e, b, a);
+ Z(f, d, c);
+ A(g, d, c);
+ A(h, b, a);
+
+ M(p[0], e, f);
+ M(p[1], h, g);
+ M(p[2], g, f);
+ M(p[3], e, h);
+}
+
+sv cswap(gf p[4],gf q[4],u8 b)
+{
+ int i;
+ FOR(i,4)
+ sel25519(p[i],q[i],b);
+}
+
+sv pack(u8 *r,gf p[4])
+{
+ gf tx, ty, zi;
+ inv25519(zi, p[2]);
+ M(tx, p[0], zi);
+ M(ty, p[1], zi);
+ pack25519(r, ty);
+ r[31] ^= par25519(tx) << 7;
+}
+
+sv scalarmult(gf p[4],gf q[4],const u8 *s)
+{
+ int i;
+ set25519(p[0],gf0);
+ set25519(p[1],gf1);
+ set25519(p[2],gf1);
+ set25519(p[3],gf0);
+ for (i = 255;i >= 0;--i) {
+ u8 b = (s[i/8]>>(i&7))&1;
+ cswap(p,q,b);
+ add(q,p);
+ add(p,p);
+ cswap(p,q,b);
+ }
+}
+
+sv scalarbase(gf p[4],const u8 *s)
+{
+ gf q[4];
+ set25519(q[0],X);
+ set25519(q[1],Y);
+ set25519(q[2],gf1);
+ M(q[3],X,Y);
+ scalarmult(p,q,s);
+}
+
+int crypto_sign_keypair(u8 *pk, u8 *sk)
+{
+ u8 d[64];
+ gf p[4];
+ int i;
+
+ randombytes(sk, 32);
+ crypto_hash(d, sk, 32);
+ d[0] &= 248;
+ d[31] &= 127;
+ d[31] |= 64;
+
+ scalarbase(p,d);
+ pack(pk,p);
+
+ FOR(i,32) sk[32 + i] = pk[i];
+ return 0;
+}
+
+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};
+
+sv modL(u8 *r,i64 x[64])
+{
+ i64 carry,i,j;
+ for (i = 63;i >= 32;--i) {
+ carry = 0;
+ for (j = i - 32;j < i - 12;++j) {
+ x[j] += carry - 16 * x[i] * L[j - (i - 32)];
+ carry = (x[j] + 128) >> 8;
+ x[j] -= carry << 8;
+ }
+ x[j] += carry;
+ x[i] = 0;
+ }
+ carry = 0;
+ FOR(j,32) {
+ x[j] += carry - (x[31] >> 4) * L[j];
+ carry = x[j] >> 8;
+ x[j] &= 255;
+ }
+ FOR(j,32) x[j] -= carry * L[j];
+ FOR(i,32) {
+ x[i+1] += x[i] >> 8;
+ r[i] = x[i] & 255;
+ }
+}
+
+sv reduce(u8 *r)
+{
+ i64 x[64],i;
+ FOR(i,64) x[i] = (u64) r[i];
+ FOR(i,64) r[i] = 0;
+ modL(r,x);
+}
+
+int crypto_sign(u8 *sm,u64 *smlen,const u8 *m,u64 n,const u8 *sk)
+{
+ u8 d[64],h[64],r[64];
+ i64 i,j,x[64];
+ gf p[4];
+
+ crypto_hash(d, sk, 32);
+ d[0] &= 248;
+ d[31] &= 127;
+ d[31] |= 64;
+
+ *smlen = n+64;
+ FOR(i,n) sm[64 + i] = m[i];
+ FOR(i,32) sm[32 + i] = d[32 + i];
+
+ crypto_hash(r, sm+32, n+32);
+ reduce(r);
+ scalarbase(p,r);
+ pack(sm,p);
+
+ FOR(i,32) sm[i+32] = sk[i+32];
+ crypto_hash(h,sm,n + 64);
+ reduce(h);
+
+ FOR(i,64) x[i] = 0;
+ FOR(i,32) x[i] = (u64) r[i];
+ FOR(i,32) FOR(j,32) x[i+j] += h[i] * (u64) d[j];
+ modL(sm + 32,x);
+
+ return 0;
+}
+
+static int unpackneg(gf r[4],const u8 p[32])
+{
+ gf t, chk, num, den, den2, den4, den6;
+ set25519(r[2],gf1);
+ unpack25519(r[1],p);
+ S(num,r[1]);
+ M(den,num,D);
+ Z(num,num,r[2]);
+ A(den,r[2],den);
+
+ S(den2,den);
+ S(den4,den2);
+ M(den6,den4,den2);
+ M(t,den6,num);
+ M(t,t,den);
+
+ pow2523(t,t);
+ M(t,t,num);
+ M(t,t,den);
+ M(t,t,den);
+ M(r[0],t,den);
+
+ S(chk,r[0]);
+ M(chk,chk,den);
+ if (neq25519(chk, num)) M(r[0],r[0],I);
+
+ S(chk,r[0]);
+ M(chk,chk,den);
+ if (neq25519(chk, num)) return -1;
+
+ if (par25519(r[0]) == (p[31]>>7)) Z(r[0],gf0,r[0]);
+
+ M(r[3],r[0],r[1]);
+ return 0;
+}
+
+int crypto_sign_open(u8 *m,u64 *mlen,const u8 *sm,u64 n,const u8 *pk)
+{
+ int i;
+ u8 t[32],h[64];
+ gf p[4],q[4];
+
+ *mlen = -1;
+ if (n < 64) return -1;
+
+ if (unpackneg(q,pk)) return -1;
+
+ FOR(i,n) m[i] = sm[i];
+ FOR(i,32) m[i+32] = pk[i];
+ crypto_hash(h,m,n);
+ reduce(h);
+ scalarmult(p,q,h);
+
+ scalarbase(q,sm + 32);
+ add(p,q);
+ pack(t,p);
+
+ n -= 64;
+ if (crypto_verify_32(sm, t)) {
+ FOR(i,n) m[i] = 0;
+ return -1;
+ }
+
+ FOR(i,n) m[i] = sm[i + 64];
+ *mlen = n;
+ return 0;
+}
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tweetnacl/tweetnacl.h b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tweetnacl/tweetnacl.h
new file mode 100644
index 0000000..9277fbf
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/externals/tweetnacl/tweetnacl.h
@@ -0,0 +1,272 @@
+#ifndef TWEETNACL_H
+#define TWEETNACL_H
+#define crypto_auth_PRIMITIVE "hmacsha512256"
+#define crypto_auth crypto_auth_hmacsha512256
+#define crypto_auth_verify crypto_auth_hmacsha512256_verify
+#define crypto_auth_BYTES crypto_auth_hmacsha512256_BYTES
+#define crypto_auth_KEYBYTES crypto_auth_hmacsha512256_KEYBYTES
+#define crypto_auth_IMPLEMENTATION crypto_auth_hmacsha512256_IMPLEMENTATION
+#define crypto_auth_VERSION crypto_auth_hmacsha512256_VERSION
+#define crypto_auth_hmacsha512256_tweet_BYTES 32
+#define crypto_auth_hmacsha512256_tweet_KEYBYTES 32
+extern int crypto_auth_hmacsha512256_tweet(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *);
+extern int crypto_auth_hmacsha512256_tweet_verify(const unsigned char *,const unsigned char *,unsigned long long,const unsigned char *);
+#define crypto_auth_hmacsha512256_tweet_VERSION "-"
+#define crypto_auth_hmacsha512256 crypto_auth_hmacsha512256_tweet
+#define crypto_auth_hmacsha512256_verify crypto_auth_hmacsha512256_tweet_verify
+#define crypto_auth_hmacsha512256_BYTES crypto_auth_hmacsha512256_tweet_BYTES
+#define crypto_auth_hmacsha512256_KEYBYTES crypto_auth_hmacsha512256_tweet_KEYBYTES
+#define crypto_auth_hmacsha512256_VERSION crypto_auth_hmacsha512256_tweet_VERSION
+#define crypto_auth_hmacsha512256_IMPLEMENTATION "crypto_auth/hmacsha512256/tweet"
+#define crypto_box_PRIMITIVE "curve25519xsalsa20poly1305"
+#define crypto_box crypto_box_curve25519xsalsa20poly1305
+#define crypto_box_open crypto_box_curve25519xsalsa20poly1305_open
+#define crypto_box_keypair crypto_box_curve25519xsalsa20poly1305_keypair
+#define crypto_box_beforenm crypto_box_curve25519xsalsa20poly1305_beforenm
+#define crypto_box_afternm crypto_box_curve25519xsalsa20poly1305_afternm
+#define crypto_box_open_afternm crypto_box_curve25519xsalsa20poly1305_open_afternm
+#define crypto_box_PUBLICKEYBYTES crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES
+#define crypto_box_SECRETKEYBYTES crypto_box_curve25519xsalsa20poly1305_SECRETKEYBYTES
+#define crypto_box_BEFORENMBYTES crypto_box_curve25519xsalsa20poly1305_BEFORENMBYTES
+#define crypto_box_NONCEBYTES crypto_box_curve25519xsalsa20poly1305_NONCEBYTES
+#define crypto_box_ZEROBYTES crypto_box_curve25519xsalsa20poly1305_ZEROBYTES
+#define crypto_box_BOXZEROBYTES crypto_box_curve25519xsalsa20poly1305_BOXZEROBYTES
+#define crypto_box_IMPLEMENTATION crypto_box_curve25519xsalsa20poly1305_IMPLEMENTATION
+#define crypto_box_VERSION crypto_box_curve25519xsalsa20poly1305_VERSION
+#define crypto_box_curve25519xsalsa20poly1305_tweet_PUBLICKEYBYTES 32
+#define crypto_box_curve25519xsalsa20poly1305_tweet_SECRETKEYBYTES 32
+#define crypto_box_curve25519xsalsa20poly1305_tweet_BEFORENMBYTES 32
+#define crypto_box_curve25519xsalsa20poly1305_tweet_NONCEBYTES 24
+#define crypto_box_curve25519xsalsa20poly1305_tweet_ZEROBYTES 32
+#define crypto_box_curve25519xsalsa20poly1305_tweet_BOXZEROBYTES 16
+extern int crypto_box_curve25519xsalsa20poly1305_tweet(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *,const unsigned char *);
+extern int crypto_box_curve25519xsalsa20poly1305_tweet_open(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *,const unsigned char *);
+extern int crypto_box_curve25519xsalsa20poly1305_tweet_keypair(unsigned char *,unsigned char *);
+extern int crypto_box_curve25519xsalsa20poly1305_tweet_beforenm(unsigned char *,const unsigned char *,const unsigned char *);
+extern int crypto_box_curve25519xsalsa20poly1305_tweet_afternm(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *);
+extern int crypto_box_curve25519xsalsa20poly1305_tweet_open_afternm(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *);
+#define crypto_box_curve25519xsalsa20poly1305_tweet_VERSION "-"
+#define crypto_box_curve25519xsalsa20poly1305 crypto_box_curve25519xsalsa20poly1305_tweet
+#define crypto_box_curve25519xsalsa20poly1305_open crypto_box_curve25519xsalsa20poly1305_tweet_open
+#define crypto_box_curve25519xsalsa20poly1305_keypair crypto_box_curve25519xsalsa20poly1305_tweet_keypair
+#define crypto_box_curve25519xsalsa20poly1305_beforenm crypto_box_curve25519xsalsa20poly1305_tweet_beforenm
+#define crypto_box_curve25519xsalsa20poly1305_afternm crypto_box_curve25519xsalsa20poly1305_tweet_afternm
+#define crypto_box_curve25519xsalsa20poly1305_open_afternm crypto_box_curve25519xsalsa20poly1305_tweet_open_afternm
+#define crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES crypto_box_curve25519xsalsa20poly1305_tweet_PUBLICKEYBYTES
+#define crypto_box_curve25519xsalsa20poly1305_SECRETKEYBYTES crypto_box_curve25519xsalsa20poly1305_tweet_SECRETKEYBYTES
+#define crypto_box_curve25519xsalsa20poly1305_BEFORENMBYTES crypto_box_curve25519xsalsa20poly1305_tweet_BEFORENMBYTES
+#define crypto_box_curve25519xsalsa20poly1305_NONCEBYTES crypto_box_curve25519xsalsa20poly1305_tweet_NONCEBYTES
+#define crypto_box_curve25519xsalsa20poly1305_ZEROBYTES crypto_box_curve25519xsalsa20poly1305_tweet_ZEROBYTES
+#define crypto_box_curve25519xsalsa20poly1305_BOXZEROBYTES crypto_box_curve25519xsalsa20poly1305_tweet_BOXZEROBYTES
+#define crypto_box_curve25519xsalsa20poly1305_VERSION crypto_box_curve25519xsalsa20poly1305_tweet_VERSION
+#define crypto_box_curve25519xsalsa20poly1305_IMPLEMENTATION "crypto_box/curve25519xsalsa20poly1305/tweet"
+#define crypto_core_PRIMITIVE "salsa20"
+#define crypto_core crypto_core_salsa20
+#define crypto_core_OUTPUTBYTES crypto_core_salsa20_OUTPUTBYTES
+#define crypto_core_INPUTBYTES crypto_core_salsa20_INPUTBYTES
+#define crypto_core_KEYBYTES crypto_core_salsa20_KEYBYTES
+#define crypto_core_CONSTBYTES crypto_core_salsa20_CONSTBYTES
+#define crypto_core_IMPLEMENTATION crypto_core_salsa20_IMPLEMENTATION
+#define crypto_core_VERSION crypto_core_salsa20_VERSION
+#define crypto_core_salsa20_tweet_OUTPUTBYTES 64
+#define crypto_core_salsa20_tweet_INPUTBYTES 16
+#define crypto_core_salsa20_tweet_KEYBYTES 32
+#define crypto_core_salsa20_tweet_CONSTBYTES 16
+extern int crypto_core_salsa20_tweet(unsigned char *,const unsigned char *,const unsigned char *,const unsigned char *);
+#define crypto_core_salsa20_tweet_VERSION "-"
+#define crypto_core_salsa20 crypto_core_salsa20_tweet
+#define crypto_core_salsa20_OUTPUTBYTES crypto_core_salsa20_tweet_OUTPUTBYTES
+#define crypto_core_salsa20_INPUTBYTES crypto_core_salsa20_tweet_INPUTBYTES
+#define crypto_core_salsa20_KEYBYTES crypto_core_salsa20_tweet_KEYBYTES
+#define crypto_core_salsa20_CONSTBYTES crypto_core_salsa20_tweet_CONSTBYTES
+#define crypto_core_salsa20_VERSION crypto_core_salsa20_tweet_VERSION
+#define crypto_core_salsa20_IMPLEMENTATION "crypto_core/salsa20/tweet"
+#define crypto_core_hsalsa20_tweet_OUTPUTBYTES 32
+#define crypto_core_hsalsa20_tweet_INPUTBYTES 16
+#define crypto_core_hsalsa20_tweet_KEYBYTES 32
+#define crypto_core_hsalsa20_tweet_CONSTBYTES 16
+extern int crypto_core_hsalsa20_tweet(unsigned char *,const unsigned char *,const unsigned char *,const unsigned char *);
+#define crypto_core_hsalsa20_tweet_VERSION "-"
+#define crypto_core_hsalsa20 crypto_core_hsalsa20_tweet
+#define crypto_core_hsalsa20_OUTPUTBYTES crypto_core_hsalsa20_tweet_OUTPUTBYTES
+#define crypto_core_hsalsa20_INPUTBYTES crypto_core_hsalsa20_tweet_INPUTBYTES
+#define crypto_core_hsalsa20_KEYBYTES crypto_core_hsalsa20_tweet_KEYBYTES
+#define crypto_core_hsalsa20_CONSTBYTES crypto_core_hsalsa20_tweet_CONSTBYTES
+#define crypto_core_hsalsa20_VERSION crypto_core_hsalsa20_tweet_VERSION
+#define crypto_core_hsalsa20_IMPLEMENTATION "crypto_core/hsalsa20/tweet"
+#define crypto_hashblocks_PRIMITIVE "sha512"
+#define crypto_hashblocks crypto_hashblocks_sha512
+#define crypto_hashblocks_STATEBYTES crypto_hashblocks_sha512_STATEBYTES
+#define crypto_hashblocks_BLOCKBYTES crypto_hashblocks_sha512_BLOCKBYTES
+#define crypto_hashblocks_IMPLEMENTATION crypto_hashblocks_sha512_IMPLEMENTATION
+#define crypto_hashblocks_VERSION crypto_hashblocks_sha512_VERSION
+#define crypto_hashblocks_sha512_tweet_STATEBYTES 64
+#define crypto_hashblocks_sha512_tweet_BLOCKBYTES 128
+extern int crypto_hashblocks_sha512_tweet(unsigned char *,const unsigned char *,unsigned long long);
+#define crypto_hashblocks_sha512_tweet_VERSION "-"
+#define crypto_hashblocks_sha512 crypto_hashblocks_sha512_tweet
+#define crypto_hashblocks_sha512_STATEBYTES crypto_hashblocks_sha512_tweet_STATEBYTES
+#define crypto_hashblocks_sha512_BLOCKBYTES crypto_hashblocks_sha512_tweet_BLOCKBYTES
+#define crypto_hashblocks_sha512_VERSION crypto_hashblocks_sha512_tweet_VERSION
+#define crypto_hashblocks_sha512_IMPLEMENTATION "crypto_hashblocks/sha512/tweet"
+#define crypto_hashblocks_sha256_tweet_STATEBYTES 32
+#define crypto_hashblocks_sha256_tweet_BLOCKBYTES 64
+extern int crypto_hashblocks_sha256_tweet(unsigned char *,const unsigned char *,unsigned long long);
+#define crypto_hashblocks_sha256_tweet_VERSION "-"
+#define crypto_hashblocks_sha256 crypto_hashblocks_sha256_tweet
+#define crypto_hashblocks_sha256_STATEBYTES crypto_hashblocks_sha256_tweet_STATEBYTES
+#define crypto_hashblocks_sha256_BLOCKBYTES crypto_hashblocks_sha256_tweet_BLOCKBYTES
+#define crypto_hashblocks_sha256_VERSION crypto_hashblocks_sha256_tweet_VERSION
+#define crypto_hashblocks_sha256_IMPLEMENTATION "crypto_hashblocks/sha256/tweet"
+#define crypto_hash_PRIMITIVE "sha512"
+#define crypto_hash crypto_hash_sha512
+#define crypto_hash_BYTES crypto_hash_sha512_BYTES
+#define crypto_hash_IMPLEMENTATION crypto_hash_sha512_IMPLEMENTATION
+#define crypto_hash_VERSION crypto_hash_sha512_VERSION
+#define crypto_hash_sha512_tweet_BYTES 64
+extern int crypto_hash_sha512_tweet(unsigned char *,const unsigned char *,unsigned long long);
+#define crypto_hash_sha512_tweet_VERSION "-"
+#define crypto_hash_sha512 crypto_hash_sha512_tweet
+#define crypto_hash_sha512_BYTES crypto_hash_sha512_tweet_BYTES
+#define crypto_hash_sha512_VERSION crypto_hash_sha512_tweet_VERSION
+#define crypto_hash_sha512_IMPLEMENTATION "crypto_hash/sha512/tweet"
+#define crypto_hash_sha256_tweet_BYTES 32
+extern int crypto_hash_sha256_tweet(unsigned char *,const unsigned char *,unsigned long long);
+#define crypto_hash_sha256_tweet_VERSION "-"
+#define crypto_hash_sha256 crypto_hash_sha256_tweet
+#define crypto_hash_sha256_BYTES crypto_hash_sha256_tweet_BYTES
+#define crypto_hash_sha256_VERSION crypto_hash_sha256_tweet_VERSION
+#define crypto_hash_sha256_IMPLEMENTATION "crypto_hash/sha256/tweet"
+#define crypto_onetimeauth_PRIMITIVE "poly1305"
+#define crypto_onetimeauth crypto_onetimeauth_poly1305
+#define crypto_onetimeauth_verify crypto_onetimeauth_poly1305_verify
+#define crypto_onetimeauth_BYTES crypto_onetimeauth_poly1305_BYTES
+#define crypto_onetimeauth_KEYBYTES crypto_onetimeauth_poly1305_KEYBYTES
+#define crypto_onetimeauth_IMPLEMENTATION crypto_onetimeauth_poly1305_IMPLEMENTATION
+#define crypto_onetimeauth_VERSION crypto_onetimeauth_poly1305_VERSION
+#define crypto_onetimeauth_poly1305_tweet_BYTES 16
+#define crypto_onetimeauth_poly1305_tweet_KEYBYTES 32
+extern int crypto_onetimeauth_poly1305_tweet(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *);
+extern int crypto_onetimeauth_poly1305_tweet_verify(const unsigned char *,const unsigned char *,unsigned long long,const unsigned char *);
+#define crypto_onetimeauth_poly1305_tweet_VERSION "-"
+#define crypto_onetimeauth_poly1305 crypto_onetimeauth_poly1305_tweet
+#define crypto_onetimeauth_poly1305_verify crypto_onetimeauth_poly1305_tweet_verify
+#define crypto_onetimeauth_poly1305_BYTES crypto_onetimeauth_poly1305_tweet_BYTES
+#define crypto_onetimeauth_poly1305_KEYBYTES crypto_onetimeauth_poly1305_tweet_KEYBYTES
+#define crypto_onetimeauth_poly1305_VERSION crypto_onetimeauth_poly1305_tweet_VERSION
+#define crypto_onetimeauth_poly1305_IMPLEMENTATION "crypto_onetimeauth/poly1305/tweet"
+#define crypto_scalarmult_PRIMITIVE "curve25519"
+#define crypto_scalarmult crypto_scalarmult_curve25519
+#define crypto_scalarmult_base crypto_scalarmult_curve25519_base
+#define crypto_scalarmult_BYTES crypto_scalarmult_curve25519_BYTES
+#define crypto_scalarmult_SCALARBYTES crypto_scalarmult_curve25519_SCALARBYTES
+#define crypto_scalarmult_IMPLEMENTATION crypto_scalarmult_curve25519_IMPLEMENTATION
+#define crypto_scalarmult_VERSION crypto_scalarmult_curve25519_VERSION
+#define crypto_scalarmult_curve25519_tweet_BYTES 32
+#define crypto_scalarmult_curve25519_tweet_SCALARBYTES 32
+extern int crypto_scalarmult_curve25519_tweet(unsigned char *,const unsigned char *,const unsigned char *);
+extern int crypto_scalarmult_curve25519_tweet_base(unsigned char *,const unsigned char *);
+#define crypto_scalarmult_curve25519_tweet_VERSION "-"
+#define crypto_scalarmult_curve25519 crypto_scalarmult_curve25519_tweet
+#define crypto_scalarmult_curve25519_base crypto_scalarmult_curve25519_tweet_base
+#define crypto_scalarmult_curve25519_BYTES crypto_scalarmult_curve25519_tweet_BYTES
+#define crypto_scalarmult_curve25519_SCALARBYTES crypto_scalarmult_curve25519_tweet_SCALARBYTES
+#define crypto_scalarmult_curve25519_VERSION crypto_scalarmult_curve25519_tweet_VERSION
+#define crypto_scalarmult_curve25519_IMPLEMENTATION "crypto_scalarmult/curve25519/tweet"
+#define crypto_secretbox_PRIMITIVE "xsalsa20poly1305"
+#define crypto_secretbox crypto_secretbox_xsalsa20poly1305
+#define crypto_secretbox_open crypto_secretbox_xsalsa20poly1305_open
+#define crypto_secretbox_KEYBYTES crypto_secretbox_xsalsa20poly1305_KEYBYTES
+#define crypto_secretbox_NONCEBYTES crypto_secretbox_xsalsa20poly1305_NONCEBYTES
+#define crypto_secretbox_ZEROBYTES crypto_secretbox_xsalsa20poly1305_ZEROBYTES
+#define crypto_secretbox_BOXZEROBYTES crypto_secretbox_xsalsa20poly1305_BOXZEROBYTES
+#define crypto_secretbox_IMPLEMENTATION crypto_secretbox_xsalsa20poly1305_IMPLEMENTATION
+#define crypto_secretbox_VERSION crypto_secretbox_xsalsa20poly1305_VERSION
+#define crypto_secretbox_xsalsa20poly1305_tweet_KEYBYTES 32
+#define crypto_secretbox_xsalsa20poly1305_tweet_NONCEBYTES 24
+#define crypto_secretbox_xsalsa20poly1305_tweet_ZEROBYTES 32
+#define crypto_secretbox_xsalsa20poly1305_tweet_BOXZEROBYTES 16
+extern int crypto_secretbox_xsalsa20poly1305_tweet(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *);
+extern int crypto_secretbox_xsalsa20poly1305_tweet_open(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *);
+#define crypto_secretbox_xsalsa20poly1305_tweet_VERSION "-"
+#define crypto_secretbox_xsalsa20poly1305 crypto_secretbox_xsalsa20poly1305_tweet
+#define crypto_secretbox_xsalsa20poly1305_open crypto_secretbox_xsalsa20poly1305_tweet_open
+#define crypto_secretbox_xsalsa20poly1305_KEYBYTES crypto_secretbox_xsalsa20poly1305_tweet_KEYBYTES
+#define crypto_secretbox_xsalsa20poly1305_NONCEBYTES crypto_secretbox_xsalsa20poly1305_tweet_NONCEBYTES
+#define crypto_secretbox_xsalsa20poly1305_ZEROBYTES crypto_secretbox_xsalsa20poly1305_tweet_ZEROBYTES
+#define crypto_secretbox_xsalsa20poly1305_BOXZEROBYTES crypto_secretbox_xsalsa20poly1305_tweet_BOXZEROBYTES
+#define crypto_secretbox_xsalsa20poly1305_VERSION crypto_secretbox_xsalsa20poly1305_tweet_VERSION
+#define crypto_secretbox_xsalsa20poly1305_IMPLEMENTATION "crypto_secretbox/xsalsa20poly1305/tweet"
+#define crypto_sign_PRIMITIVE "ed25519"
+#define crypto_sign crypto_sign_ed25519
+#define crypto_sign_open crypto_sign_ed25519_open
+#define crypto_sign_keypair crypto_sign_ed25519_keypair
+#define crypto_sign_BYTES crypto_sign_ed25519_BYTES
+#define crypto_sign_PUBLICKEYBYTES crypto_sign_ed25519_PUBLICKEYBYTES
+#define crypto_sign_SECRETKEYBYTES crypto_sign_ed25519_SECRETKEYBYTES
+#define crypto_sign_IMPLEMENTATION crypto_sign_ed25519_IMPLEMENTATION
+#define crypto_sign_VERSION crypto_sign_ed25519_VERSION
+#define crypto_sign_ed25519_tweet_BYTES 64
+#define crypto_sign_ed25519_tweet_PUBLICKEYBYTES 32
+#define crypto_sign_ed25519_tweet_SECRETKEYBYTES 64
+extern int crypto_sign_ed25519_tweet(unsigned char *,unsigned long long *,const unsigned char *,unsigned long long,const unsigned char *);
+extern int crypto_sign_ed25519_tweet_open(unsigned char *,unsigned long long *,const unsigned char *,unsigned long long,const unsigned char *);
+extern int crypto_sign_ed25519_tweet_keypair(unsigned char *,unsigned char *);
+#define crypto_sign_ed25519_tweet_VERSION "-"
+#define crypto_sign_ed25519 crypto_sign_ed25519_tweet
+#define crypto_sign_ed25519_open crypto_sign_ed25519_tweet_open
+#define crypto_sign_ed25519_keypair crypto_sign_ed25519_tweet_keypair
+#define crypto_sign_ed25519_BYTES crypto_sign_ed25519_tweet_BYTES
+#define crypto_sign_ed25519_PUBLICKEYBYTES crypto_sign_ed25519_tweet_PUBLICKEYBYTES
+#define crypto_sign_ed25519_SECRETKEYBYTES crypto_sign_ed25519_tweet_SECRETKEYBYTES
+#define crypto_sign_ed25519_VERSION crypto_sign_ed25519_tweet_VERSION
+#define crypto_sign_ed25519_IMPLEMENTATION "crypto_sign/ed25519/tweet"
+#define crypto_stream_PRIMITIVE "xsalsa20"
+#define crypto_stream crypto_stream_xsalsa20
+#define crypto_stream_xor crypto_stream_xsalsa20_xor
+#define crypto_stream_KEYBYTES crypto_stream_xsalsa20_KEYBYTES
+#define crypto_stream_NONCEBYTES crypto_stream_xsalsa20_NONCEBYTES
+#define crypto_stream_IMPLEMENTATION crypto_stream_xsalsa20_IMPLEMENTATION
+#define crypto_stream_VERSION crypto_stream_xsalsa20_VERSION
+#define crypto_stream_xsalsa20_tweet_KEYBYTES 32
+#define crypto_stream_xsalsa20_tweet_NONCEBYTES 24
+extern int crypto_stream_xsalsa20_tweet(unsigned char *,unsigned long long,const unsigned char *,const unsigned char *);
+extern int crypto_stream_xsalsa20_tweet_xor(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *);
+#define crypto_stream_xsalsa20_tweet_VERSION "-"
+#define crypto_stream_xsalsa20 crypto_stream_xsalsa20_tweet
+#define crypto_stream_xsalsa20_xor crypto_stream_xsalsa20_tweet_xor
+#define crypto_stream_xsalsa20_KEYBYTES crypto_stream_xsalsa20_tweet_KEYBYTES
+#define crypto_stream_xsalsa20_NONCEBYTES crypto_stream_xsalsa20_tweet_NONCEBYTES
+#define crypto_stream_xsalsa20_VERSION crypto_stream_xsalsa20_tweet_VERSION
+#define crypto_stream_xsalsa20_IMPLEMENTATION "crypto_stream/xsalsa20/tweet"
+#define crypto_stream_salsa20_tweet_KEYBYTES 32
+#define crypto_stream_salsa20_tweet_NONCEBYTES 8
+extern int crypto_stream_salsa20_tweet(unsigned char *,unsigned long long,const unsigned char *,const unsigned char *);
+extern int crypto_stream_salsa20_tweet_xor(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *);
+#define crypto_stream_salsa20_tweet_VERSION "-"
+#define crypto_stream_salsa20 crypto_stream_salsa20_tweet
+#define crypto_stream_salsa20_xor crypto_stream_salsa20_tweet_xor
+#define crypto_stream_salsa20_KEYBYTES crypto_stream_salsa20_tweet_KEYBYTES
+#define crypto_stream_salsa20_NONCEBYTES crypto_stream_salsa20_tweet_NONCEBYTES
+#define crypto_stream_salsa20_VERSION crypto_stream_salsa20_tweet_VERSION
+#define crypto_stream_salsa20_IMPLEMENTATION "crypto_stream/salsa20/tweet"
+#define crypto_verify_PRIMITIVE "16"
+#define crypto_verify crypto_verify_16
+#define crypto_verify_BYTES crypto_verify_16_BYTES
+#define crypto_verify_IMPLEMENTATION crypto_verify_16_IMPLEMENTATION
+#define crypto_verify_VERSION crypto_verify_16_VERSION
+#define crypto_verify_16_tweet_BYTES 16
+extern int crypto_verify_16_tweet(const unsigned char *,const unsigned char *);
+#define crypto_verify_16_tweet_VERSION "-"
+#define crypto_verify_16 crypto_verify_16_tweet
+#define crypto_verify_16_BYTES crypto_verify_16_tweet_BYTES
+#define crypto_verify_16_VERSION crypto_verify_16_tweet_VERSION
+#define crypto_verify_16_IMPLEMENTATION "crypto_verify/16/tweet"
+#define crypto_verify_32_tweet_BYTES 32
+extern int crypto_verify_32_tweet(const unsigned char *,const unsigned char *);
+#define crypto_verify_32_tweet_VERSION "-"
+#define crypto_verify_32 crypto_verify_32_tweet
+#define crypto_verify_32_BYTES crypto_verify_32_tweet_BYTES
+#define crypto_verify_32_VERSION crypto_verify_32_tweet_VERSION
+#define crypto_verify_32_IMPLEMENTATION "crypto_verify/32/tweet"
+#endif
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/formal-analysis.sh b/lib/Utils.Cryptography/monocypher/vendor/tests/formal-analysis.sh
new file mode 100644
index 0000000..741a13e
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/formal-analysis.sh
@@ -0,0 +1,66 @@
+#! /bin/sh
+
+# This file is dual-licensed. Choose whichever licence you want from
+# the two licences listed below.
+#
+# The first licence is a regular 2-clause BSD licence. The second licence
+# is the CC-0 from Creative Commons. It is intended to release Monocypher
+# to the public domain. The BSD licence serves as a fallback option.
+#
+# SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+#
+# ------------------------------------------------------------------------
+#
+# Copyright (c) 2017-2019, Loup Vaillant
+# All rights reserved.
+#
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# ------------------------------------------------------------------------
+#
+# Written in 2017-2019 by Loup Vaillant
+#
+# To the extent possible under law, the author(s) have dedicated all copyright
+# and related neighboring rights to this software to the public domain
+# worldwide. This software is distributed without any warranty.
+#
+# You should have received a copy of the CC0 Public Domain Dedication along
+# with this software. If not, see
+# <https://creativecommons.org/publicdomain/zero/1.0/>
+
+mkdir -p tests/formal-analysis
+cp src/monocypher.c \
+ src/monocypher.h \
+ src/optional/monocypher-ed25519.h \
+ src/optional/monocypher-ed25519.c \
+ tests/utils.h \
+ tests/utils.c \
+ tests/test.c \
+ tests/vectors.h \
+ tests/formal-analysis
+
+# Get rid of the `volatile` keyword that confuses the TIS interpreter
+sed -i 's/volatile //g' tests/formal-analysis/monocypher.c
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/frama-c.sh b/lib/Utils.Cryptography/monocypher/vendor/tests/frama-c.sh
new file mode 100644
index 0000000..dc23c6b
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/frama-c.sh
@@ -0,0 +1,61 @@
+#! /bin/sh
+
+# This file is dual-licensed. Choose whichever licence you want from
+# the two licences listed below.
+#
+# The first licence is a regular 2-clause BSD licence. The second licence
+# is the CC-0 from Creative Commons. It is intended to release Monocypher
+# to the public domain. The BSD licence serves as a fallback option.
+#
+# SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+#
+# ------------------------------------------------------------------------
+#
+# Copyright (c) 2017-2019, Loup Vaillant
+# All rights reserved.
+#
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# ------------------------------------------------------------------------
+#
+# Written in 2017-2019 by Loup Vaillant
+#
+# To the extent possible under law, the author(s) have dedicated all copyright
+# and related neighboring rights to this software to the public domain
+# worldwide. This software is distributed without any warranty.
+#
+# You should have received a copy of the CC0 Public Domain Dedication along
+# with this software. If not, see
+# <https://creativecommons.org/publicdomain/zero/1.0/>
+
+# Parses the source code
+frama-c tests/formal-analysis/*.c -save parsed.sav
+
+# Analyses the source code
+frama-c -load parsed.sav -val-builtins-auto -val -save value.sav -no-val-show-progress -memexec-all
+
+# Launches the Gui
+frama-c-gui -load value.sav
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/gen/aead_8439.c b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/aead_8439.c
new file mode 100644
index 0000000..57edf03
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/aead_8439.c
@@ -0,0 +1,83 @@
+// This file is dual-licensed. Choose whichever licence you want from
+// the two licences listed below.
+//
+// The first licence is a regular 2-clause BSD licence. The second licence
+// is the CC-0 from Creative Commons. It is intended to release Monocypher
+// to the public domain. The BSD licence serves as a fallback option.
+//
+// SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+//
+// ------------------------------------------------------------------------
+//
+// Copyright (c) 2022, Loup Vaillant
+// All rights reserved.
+//
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// ------------------------------------------------------------------------
+//
+// Written in 2022 by Loup Vaillant
+//
+// To the extent possible under law, the author(s) have dedicated all copyright
+// and related neighboring rights to this software to the public domain
+// worldwide. This software is distributed without any warranty.
+//
+// You should have received a copy of the CC0 Public Domain Dedication along
+// with this software. If not, see
+// <https://creativecommons.org/publicdomain/zero/1.0/>
+
+#include <sodium.h>
+#include "utils.h"
+
+static void test(size_t text_size, size_t ad_size)
+{
+ RANDOM_INPUT(key , 32);
+ RANDOM_INPUT(nonce, 12);
+ RANDOM_INPUT(ad , 32); // ad size <= 32
+ RANDOM_INPUT(text , 128); // text_size <= 128
+ u8 out[16 + 128]; // text_size <= 128
+
+ crypto_aead_chacha20poly1305_ietf_encrypt_detached(
+ out + 16, out, 0, text, text_size, ad, ad_size, 0, nonce, key);
+
+ print_vector(key , 32);
+ print_vector(nonce , 12);
+ print_vector(ad , ad_size);
+ print_vector(text , text_size);
+ print_vector(out , text_size + 16);
+ printf("\n");
+}
+
+int main(void)
+{
+ SODIUM_INIT;
+ // regular tests
+ FOR (text_size, 0, 128) { test(text_size, 0); }
+ FOR (text_size, 0, 128) { test(text_size, 4); }
+ FOR ( ad_size, 0, 32) { test(0, ad_size); }
+ FOR ( ad_size, 0, 32) { test(16, ad_size); }
+ return 0;
+}
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/gen/aead_ietf.c b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/aead_ietf.c
new file mode 100644
index 0000000..a45547e
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/aead_ietf.c
@@ -0,0 +1,83 @@
+// This file is dual-licensed. Choose whichever licence you want from
+// the two licences listed below.
+//
+// The first licence is a regular 2-clause BSD licence. The second licence
+// is the CC-0 from Creative Commons. It is intended to release Monocypher
+// to the public domain. The BSD licence serves as a fallback option.
+//
+// SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+//
+// ------------------------------------------------------------------------
+//
+// Copyright (c) 2017-2019, Loup Vaillant
+// All rights reserved.
+//
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// ------------------------------------------------------------------------
+//
+// Written in 2017-2019 by Loup Vaillant
+//
+// To the extent possible under law, the author(s) have dedicated all copyright
+// and related neighboring rights to this software to the public domain
+// worldwide. This software is distributed without any warranty.
+//
+// You should have received a copy of the CC0 Public Domain Dedication along
+// with this software. If not, see
+// <https://creativecommons.org/publicdomain/zero/1.0/>
+
+#include <sodium.h>
+#include "utils.h"
+
+static void test(size_t text_size, size_t ad_size)
+{
+ RANDOM_INPUT(key , 32);
+ RANDOM_INPUT(nonce, 24);
+ RANDOM_INPUT(ad , 32); // ad size <= 32
+ RANDOM_INPUT(text , 128); // text_size <= 128
+ u8 out[16 + 128]; // text_size <= 128
+
+ crypto_aead_xchacha20poly1305_ietf_encrypt_detached(
+ out + 16, out, 0, text, text_size, ad, ad_size, 0, nonce, key);
+
+ print_vector(key , 32);
+ print_vector(nonce , 24);
+ print_vector(ad , ad_size);
+ print_vector(text , text_size);
+ print_vector(out , text_size + 16);
+ printf("\n");
+}
+
+int main(void)
+{
+ SODIUM_INIT;
+ // regular tests
+ FOR (text_size, 0, 128) { test(text_size, 0); }
+ FOR (text_size, 0, 128) { test(text_size, 4); }
+ FOR ( ad_size, 0, 32) { test(0, ad_size); }
+ FOR ( ad_size, 0, 32) { test(16, ad_size); }
+ return 0;
+}
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/gen/argon2.c b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/argon2.c
new file mode 100644
index 0000000..75dd4ca
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/argon2.c
@@ -0,0 +1,99 @@
+// This file is dual-licensed. Choose whichever licence you want from
+// the two licences listed below.
+//
+// The first licence is a regular 2-clause BSD licence. The second licence
+// is the CC-0 from Creative Commons. It is intended to release Monocypher
+// to the public domain. The BSD licence serves as a fallback option.
+//
+// SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+//
+// ------------------------------------------------------------------------
+//
+// Copyright (c) 2017-2019, Loup Vaillant
+// All rights reserved.
+//
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// ------------------------------------------------------------------------
+//
+// Written in 2017-2019 by Loup Vaillant
+//
+// To the extent possible under law, the author(s) have dedicated all copyright
+// and related neighboring rights to this software to the public domain
+// worldwide. This software is distributed without any warranty.
+//
+// You should have received a copy of the CC0 Public Domain Dedication along
+// with this software. If not, see
+// <https://creativecommons.org/publicdomain/zero/1.0/>
+
+#include <sodium.h>
+#include "utils.h"
+
+static void test(u32 alg, size_t nb_blocks, size_t hash_size, size_t nb_passes)
+{
+ RANDOM_INPUT(password, 16 );
+ RANDOM_INPUT(salt , crypto_pwhash_SALTBYTES);
+ u8 hash[256];
+
+ int algorithm = -1;
+ switch (alg) {
+ case 0: fprintf(stderr, "Libsodium does not support Argon2d"); break;
+ case 1: algorithm = crypto_pwhash_ALG_ARGON2I13; break;
+ case 2: algorithm = crypto_pwhash_ALG_ARGON2ID13; break;
+ default: fprintf(stderr, "Unknown algorithm");
+ }
+
+ if (crypto_pwhash(hash, hash_size, (char*)password, 16, salt,
+ nb_passes, nb_blocks * 1024, algorithm)) {
+ fprintf(stderr, "Argon2i failed. "
+ "nb_blocks = %lu, "
+ "hash_size = %lu "
+ "nb_passes = %lu\n",
+ nb_blocks, hash_size, nb_passes);
+ printf(":deadbeef:\n"); // prints a canary to fail subsequent tests
+ }
+
+ print_number(alg);
+ print_number(nb_blocks);
+ print_number(nb_passes);
+ print_number(1); // one lane (no parallelism)
+ print_vector(password, 16);
+ print_vector(salt , crypto_pwhash_SALTBYTES);
+ printf(":\n"); // no key
+ printf(":\n"); // no additionnal data
+ print_vector(hash, hash_size);
+ printf("\n");
+}
+
+int main(void)
+{
+ SODIUM_INIT;
+ FOR (nb_blocks, 508, 517) { test(1, nb_blocks, 32 , 3 ); }
+ FOR (nb_blocks, 508, 517) { test(2, nb_blocks, 32 , 3 ); }
+ FOR (hash_size, 63, 65) { test(1, 8 , hash_size, 3 ); }
+ FOR (nb_passes, 3, 6) { test(1, 8 , 32 , nb_passes); }
+ return 0;
+}
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/gen/blake2b.c b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/blake2b.c
new file mode 100644
index 0000000..97b629b
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/blake2b.c
@@ -0,0 +1,83 @@
+// This file is dual-licensed. Choose whichever licence you want from
+// the two licences listed below.
+//
+// The first licence is a regular 2-clause BSD licence. The second licence
+// is the CC-0 from Creative Commons. It is intended to release Monocypher
+// to the public domain. The BSD licence serves as a fallback option.
+//
+// SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+//
+// ------------------------------------------------------------------------
+//
+// Copyright (c) 2017-2019, Loup Vaillant
+// All rights reserved.
+//
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// ------------------------------------------------------------------------
+//
+// Written in 2017-2019 by Loup Vaillant
+//
+// To the extent possible under law, the author(s) have dedicated all copyright
+// and related neighboring rights to this software to the public domain
+// worldwide. This software is distributed without any warranty.
+//
+// You should have received a copy of the CC0 Public Domain Dedication along
+// with this software. If not, see
+// <https://creativecommons.org/publicdomain/zero/1.0/>
+
+#include <sodium.h>
+#include "utils.h"
+
+static void test(size_t size, size_t key_size, size_t hash_size)
+{
+ RANDOM_INPUT(in , 256);
+ RANDOM_INPUT(key , 64);
+ u8 hash[64];
+
+ crypto_generichash(hash, hash_size, in, size, key, key_size);
+
+ print_vector(in , size);
+ print_vector(key , key_size);
+ print_vector(hash, hash_size);
+ printf("\n");
+}
+
+int main(void)
+{
+ SODIUM_INIT;
+ // Official test vectors test for all message sizes, so no need to
+ // repeat ourselves here. However they only test keys and hashes of size 64.
+ // Here we're testing many possible key and hash sizes.
+ for (size_t key_size = 0; key_size <= 64; key_size += 16) {
+ for (size_t hash_size = 0; hash_size <= 64; hash_size += 16) {
+ for (size_t input_size = 0; input_size <= 256; input_size += 16) {
+ test(input_size, key_size, hash_size);
+ }
+ }
+ }
+ return 0;
+}
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/gen/chacha20.c b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/chacha20.c
new file mode 100644
index 0000000..1ebdc6d
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/chacha20.c
@@ -0,0 +1,82 @@
+// This file is dual-licensed. Choose whichever licence you want from
+// the two licences listed below.
+//
+// The first licence is a regular 2-clause BSD licence. The second licence
+// is the CC-0 from Creative Commons. It is intended to release Monocypher
+// to the public domain. The BSD licence serves as a fallback option.
+//
+// SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+//
+// ------------------------------------------------------------------------
+//
+// Copyright (c) 2017-2019, Loup Vaillant
+// All rights reserved.
+//
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// ------------------------------------------------------------------------
+//
+// Written in 2017-2019 by Loup Vaillant
+//
+// To the extent possible under law, the author(s) have dedicated all copyright
+// and related neighboring rights to this software to the public domain
+// worldwide. This software is distributed without any warranty.
+//
+// You should have received a copy of the CC0 Public Domain Dedication along
+// with this software. If not, see
+// <https://creativecommons.org/publicdomain/zero/1.0/>
+
+#include <sodium.h>
+#include "utils.h"
+
+static void test(size_t size, u64 ctr)
+{
+ RANDOM_INPUT(key , 32);
+ RANDOM_INPUT(nonce, 8);
+ RANDOM_INPUT(in , 128); // size <= 128
+ u8 out [128]; // size <= 128
+
+ crypto_stream_chacha20_xor_ic(out, in, size, nonce, ctr, key);
+
+ print_vector(key , 32);
+ print_vector(nonce , 8);
+ print_vector(in , size);
+ print_number(ctr );
+ print_vector(out, size);
+ printf("\n");
+}
+
+int main(void)
+{
+ SODIUM_INIT;
+ // regular tests
+ FOR (size, 0, 128) { test(size, rand64()); }
+ // counter overflow (should wrap around)
+ test(128, -1);
+ test(128, -2);
+ test(128, -3);
+ return 0;
+}
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/gen/edDSA.c b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/edDSA.c
new file mode 100644
index 0000000..835344d
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/edDSA.c
@@ -0,0 +1,74 @@
+// This file is dual-licensed. Choose whichever licence you want from
+// the two licences listed below.
+//
+// The first licence is a regular 2-clause BSD licence. The second licence
+// is the CC-0 from Creative Commons. It is intended to release Monocypher
+// to the public domain. The BSD licence serves as a fallback option.
+//
+// SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+//
+// ------------------------------------------------------------------------
+//
+// Copyright (c) 2017-2019, Loup Vaillant
+// All rights reserved.
+//
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// ------------------------------------------------------------------------
+//
+// Written in 2017-2019 by Loup Vaillant
+//
+// To the extent possible under law, the author(s) have dedicated all copyright
+// and related neighboring rights to this software to the public domain
+// worldwide. This software is distributed without any warranty.
+//
+// You should have received a copy of the CC0 Public Domain Dedication along
+// with this software. If not, see
+// <https://creativecommons.org/publicdomain/zero/1.0/>
+
+#include "utils.h"
+#include "ed25519.h"
+
+static void test(size_t msg_size)
+{
+ RANDOM_INPUT(sk , 32);
+ RANDOM_INPUT(msg, 256);
+ u8 pk[32], sig[64];
+
+ ed25519_publickey(sk, pk);
+ ed25519_sign(msg, msg_size, sk, pk, sig);
+
+ print_vector(sk , 32 );
+ print_vector(pk , 32 );
+ print_vector(msg, msg_size);
+ print_vector(sig, 64 );
+}
+
+int main(void)
+{
+ FOR (msg_size, 0, 256) { test(msg_size); }
+ return 0;
+}
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/gen/edDSA_pk.c b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/edDSA_pk.c
new file mode 100644
index 0000000..420bb2e
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/edDSA_pk.c
@@ -0,0 +1,76 @@
+// This file is dual-licensed. Choose whichever licence you want from
+// the two licences listed below.
+//
+// The first licence is a regular 2-clause BSD licence. The second licence
+// is the CC-0 from Creative Commons. It is intended to release Monocypher
+// to the public domain. The BSD licence serves as a fallback option.
+//
+// SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+//
+// ------------------------------------------------------------------------
+//
+// Copyright (c) 2017-2019, Loup Vaillant
+// All rights reserved.
+//
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// ------------------------------------------------------------------------
+//
+// Written in 2017-2019 by Loup Vaillant
+//
+// To the extent possible under law, the author(s) have dedicated all copyright
+// and related neighboring rights to this software to the public domain
+// worldwide. This software is distributed without any warranty.
+//
+// You should have received a copy of the CC0 Public Domain Dedication along
+// with this software. If not, see
+// <https://creativecommons.org/publicdomain/zero/1.0/>
+
+#include "utils.h"
+#include "ed25519.h"
+
+static void test(u8 sk[32])
+{
+ u8 pk[32];
+ ed25519_publickey(sk, pk);
+
+ print_vector(sk, 32);
+ print_vector(pk, 32);
+}
+
+int main(void)
+{
+ // random secret keys
+ FOR (msg_size, 0, 256) {
+ RANDOM_INPUT(sk, 32);
+ test(sk);
+ }
+ // zero secret key
+ u8 sk[32] = {0};
+ test(sk);
+
+ return 0;
+}
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/gen/ed_25519.c b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/ed_25519.c
new file mode 100644
index 0000000..47a1c5a
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/ed_25519.c
@@ -0,0 +1,75 @@
+// This file is dual-licensed. Choose whichever licence you want from
+// the two licences listed below.
+//
+// The first licence is a regular 2-clause BSD licence. The second licence
+// is the CC-0 from Creative Commons. It is intended to release Monocypher
+// to the public domain. The BSD licence serves as a fallback option.
+//
+// SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+//
+// ------------------------------------------------------------------------
+//
+// Copyright (c) 2017-2019, Loup Vaillant
+// All rights reserved.
+//
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// ------------------------------------------------------------------------
+//
+// Written in 2017-2019 by Loup Vaillant
+//
+// To the extent possible under law, the author(s) have dedicated all copyright
+// and related neighboring rights to this software to the public domain
+// worldwide. This software is distributed without any warranty.
+//
+// You should have received a copy of the CC0 Public Domain Dedication along
+// with this software. If not, see
+// <https://creativecommons.org/publicdomain/zero/1.0/>
+
+#include <sodium.h>
+#include "utils.h"
+
+static void test(size_t msg_size)
+{
+ RANDOM_INPUT(seed, 32);
+ RANDOM_INPUT(msg , 256);
+ u8 pk[32], sk[64], sig[64];
+
+ crypto_sign_seed_keypair(pk, sk, seed);
+ crypto_sign_detached(sig, 0, msg, msg_size, sk);
+
+ print_vector(sk , 32 );
+ print_vector(pk , 32 );
+ print_vector(msg, msg_size);
+ print_vector(sig, 64 );
+}
+
+int main(void)
+{
+ SODIUM_INIT;
+ FOR (msg_size, 0, 256) { test(msg_size); }
+ return 0;
+}
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/gen/ed_25519_pk.c b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/ed_25519_pk.c
new file mode 100644
index 0000000..dc5db7e
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/ed_25519_pk.c
@@ -0,0 +1,77 @@
+// This file is dual-licensed. Choose whichever licence you want from
+// the two licences listed below.
+//
+// The first licence is a regular 2-clause BSD licence. The second licence
+// is the CC-0 from Creative Commons. It is intended to release Monocypher
+// to the public domain. The BSD licence serves as a fallback option.
+//
+// SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+//
+// ------------------------------------------------------------------------
+//
+// Copyright (c) 2017-2019, Loup Vaillant
+// All rights reserved.
+//
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// ------------------------------------------------------------------------
+//
+// Written in 2017-2019 by Loup Vaillant
+//
+// To the extent possible under law, the author(s) have dedicated all copyright
+// and related neighboring rights to this software to the public domain
+// worldwide. This software is distributed without any warranty.
+//
+// You should have received a copy of the CC0 Public Domain Dedication along
+// with this software. If not, see
+// <https://creativecommons.org/publicdomain/zero/1.0/>
+
+#include <sodium.h>
+#include "utils.h"
+
+static void test(u8 seed[32])
+{
+ u8 pk[32];
+ u8 sk[64];
+ crypto_sign_seed_keypair(pk, sk, seed);
+ print_vector(sk, 32);
+ print_vector(pk, 32);
+}
+
+int main(void)
+{
+ SODIUM_INIT;
+ // random secret keys
+ FOR (msg_size, 0, 256) {
+ RANDOM_INPUT(sk, 32);
+ test(sk);
+ }
+ // zero secret key
+ u8 sk[32] = {0};
+ test(sk);
+
+ return 0;
+}
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/gen/elligator-direct.py b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/elligator-direct.py
new file mode 100644
index 0000000..a0d38e2
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/elligator-direct.py
@@ -0,0 +1,84 @@
+#! /usr/bin/env python3
+
+# This file is dual-licensed. Choose whichever licence you want from
+# the two licences listed below.
+#
+# The first licence is a regular 2-clause BSD licence. The second licence
+# is the CC-0 from Creative Commons. It is intended to release Monocypher
+# to the public domain. The BSD licence serves as a fallback option.
+#
+# SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+#
+# ------------------------------------------------------------------------
+#
+# Copyright (c) 2020, Loup Vaillant
+# Copyright (c) 2020, Fabio Scotoni
+# All rights reserved.
+#
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# ------------------------------------------------------------------------
+#
+# Written in 2020 by Loup Vaillant and Fabio Scotoni
+#
+# To the extent possible under law, the author(s) have dedicated all copyright
+# and related neighboring rights to this software to the public domain
+# worldwide. This software is distributed without any warranty.
+#
+# You should have received a copy of the CC0 Public Domain Dedication along
+# with this software. If not, see
+# <https://creativecommons.org/publicdomain/zero/1.0/>
+
+from elligator import fe
+from elligator import curve_to_hash
+from elligator import hash_to_curve
+from elligator import fast_hash_to_curve
+from elligator import p
+from elligator import print_raw
+from random import randrange
+from random import seed
+
+def direct(r1, padding):
+ q1 = hash_to_curve(r1)
+ q2 = fast_hash_to_curve(r1)
+ r2 = curve_to_hash(q1[0], q1[1].is_negative())
+ if q1 != q2: raise ValueError('Incorrect fast_hash_to_curve')
+ if r1 != r2: raise ValueError('Round trip failure')
+ print_raw(r1.val + padding * 2**254)
+ q1[0].print() # u coordinate only
+ print()
+
+direct(fe(0), 0) # representative 0 maps to point (0, 0)
+direct(fe(0), 1) # representative 0 maps to point (0, 0)
+direct(fe(0), 2) # representative 0 maps to point (0, 0)
+direct(fe(0), 3) # representative 0 maps to point (0, 0)
+
+# Make test vector generation deterministic, the actual randomness does
+# not matter here since these are just tests.
+seed(12345)
+
+for i in range(50):
+ direct(fe(randrange(0, (p-1)//2)), i % 4)
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/gen/elligator-inverse.py b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/elligator-inverse.py
new file mode 100644
index 0000000..f607ee4
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/elligator-inverse.py
@@ -0,0 +1,128 @@
+#! /usr/bin/env python3
+
+# This file is dual-licensed. Choose whichever licence you want from
+# the two licences listed below.
+#
+# The first licence is a regular 2-clause BSD licence. The second licence
+# is the CC-0 from Creative Commons. It is intended to release Monocypher
+# to the public domain. The BSD licence serves as a fallback option.
+#
+# SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+#
+# ------------------------------------------------------------------------
+#
+# Copyright (c) 2020, Loup Vaillant
+# Copyright (c) 2020, Fabio Scotoni
+# All rights reserved.
+#
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# ------------------------------------------------------------------------
+#
+# Written in 2020 by Loup Vaillant and Fabio Scotoni
+#
+# To the extent possible under law, the author(s) have dedicated all copyright
+# and related neighboring rights to this software to the public domain
+# worldwide. This software is distributed without any warranty.
+#
+# You should have received a copy of the CC0 Public Domain Dedication along
+# with this software. If not, see
+# <https://creativecommons.org/publicdomain/zero/1.0/>
+
+from elligator import can_curve_to_hash
+from elligator import curve_to_hash
+from elligator import fast_curve_to_hash
+from elligator import fe
+from elligator import hash_to_curve
+from elligator import print_raw
+
+from elligator_scalarmult import scalarmult
+
+from random import randrange
+from random import seed
+
+def redundant_curve_to_hash(u, tweak):
+ v_is_negative = tweak % 2 == 1;
+ r1 = None
+ if can_curve_to_hash(u):
+ r1 = curve_to_hash(u, v_is_negative)
+ r2 = fast_curve_to_hash(u, v_is_negative)
+ if r1 != r2: raise ValueError('Incoherent hash_to_curve')
+ return r1
+
+def private_to_curve_and_hash(scalar, tweak):
+ cofactor = scalar % 8
+ msb = (tweak // 2**6) * 2**254
+ u = scalarmult(scalar, cofactor)
+ r1 = redundant_curve_to_hash(u, tweak)
+ if r1 is None:
+ return u, None
+ if r1.val > 2**254: raise ValueError('Representative too big')
+ u2, v2 = hash_to_curve(r1)
+ if u2 != u: raise ValueError('Round trip failure')
+ return (u, r1.val + msb)
+
+# Make test vector generation deterministic, the actual randomness does
+# not matter here since these are just tests.
+seed(12345)
+
+# Zero
+for tweak in range(2):
+ print_raw(0)
+ print(format(tweak, '02x') + ":")
+ print('00:') # Success
+ redundant_curve_to_hash(fe(0), tweak).print()
+ print()
+
+# All possible failures
+for cofactor in range(8):
+ tweak = randrange(0, 256)
+ while True:
+ scalar = randrange(0, 2**253) * 8 + cofactor
+ u, r = private_to_curve_and_hash(scalar, tweak)
+ if r is None:
+ u.print()
+ print(format(tweak, '02x') + ":")
+ print('ff:') # Failure
+ print(':') # dummy value for the hash
+ print()
+ break
+
+# All possible successes
+for cofactor in range(8):
+ for sign in range(2):
+ for msb in range(4):
+ tweak = sign + randrange(0, 32) * 2 + msb * 64
+ while True:
+ scalar = randrange(0, 2**253) * 8 + cofactor
+ u, r = private_to_curve_and_hash(scalar, tweak)
+ if r is not None:
+ u.print()
+ print(format(tweak, '02x') + ":")
+ print('00:') # Success
+ print_raw(r)
+ print()
+ break
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/gen/elligator.py b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/elligator.py
new file mode 100644
index 0000000..b1362bd
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/elligator.py
@@ -0,0 +1,370 @@
+#! /usr/bin/env python3
+
+# This file is dual-licensed. Choose whichever licence you want from
+# the two licences listed below.
+#
+# The first licence is a regular 2-clause BSD licence. The second licence
+# is the CC-0 from Creative Commons. It is intended to release Monocypher
+# to the public domain. The BSD licence serves as a fallback option.
+#
+# SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+#
+# ------------------------------------------------------------------------
+#
+# Copyright (c) 2020, Loup Vaillant and Andrew Moon
+# All rights reserved.
+#
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# ------------------------------------------------------------------------
+#
+# Written in 2020 by Loup Vaillant and Andrew Moon
+#
+# To the extent possible under law, the author(s) have dedicated all copyright
+# and related neighboring rights to this software to the public domain
+# worldwide. This software is distributed without any warranty.
+#
+# You should have received a copy of the CC0 Public Domain Dedication along
+# with this software. If not, see
+# <https://creativecommons.org/publicdomain/zero/1.0/>
+
+####################
+# Field arithmetic #
+####################
+class fe:
+ """Prime field over 2^255 - 19"""
+ p = 2**255 - 19
+ def __init__(self, x):
+ self.val = x % self.p
+
+ # Basic arithmetic operations
+ def __neg__ (self ): return fe(-self.val )
+ def __add__ (self, o): return fe( self.val + o.val )
+ def __sub__ (self, o): return fe( self.val - o.val )
+ def __mul__ (self, o): return fe((self.val * o.val ) % self.p)
+ def __truediv__ (self, o): return fe((self.val * o.invert().val) % self.p)
+ def __floordiv__(self, o): return fe( self.val // o )
+ def __pow__ (self, s): return fe(pow(self.val, s , self.p))
+ def invert (self ): return fe(pow(self.val, self.p-2, self.p))
+
+ def __eq__(self, other): return self.val % self.p == other.val % self.p
+ def __ne__(self, other): return self.val % self.p != other.val % self.p
+ def is_positive(self) : return self.val % self.p <= (p-1) // 2
+ def is_negative(self) : return self.val % self.p > (p-1) // 2
+
+ def abs(self):
+ if self.is_positive(): return self
+ else : return -self
+
+ def print(self):
+ """prints a field element in little endian"""
+ m = self.val % self.p
+ for _ in range(32):
+ print(format(m % 256, '02x'), end='')
+ m //= 256
+ if m != 0: raise ValueError('number is too big!!')
+ print(':')
+
+def print_raw(raw):
+ """prints a raw element in little endian"""
+ for _ in range(32):
+ print(format(raw % 256, '02x'), end='')
+ raw //= 256
+ if raw != 0: raise ValueError('number is too big!!')
+ print(':')
+
+########################
+# Curve25519 constants #
+########################
+p = fe.p
+A = fe(486662)
+# B = 1
+
+###############
+# Square root #
+###############
+
+# Legendre symbol:
+# - 0 if n is zero
+# - 1 if n is a non-zero square
+# - -1 if n is not a square
+# We take for granted that n^((p-1)/2) does what we want
+def chi (n): return n**((p-1)//2)
+def is_square(n): return n == fe(0) or chi(n) == fe(1)
+
+# square root of -1
+sqrtm1 = (fe(2)**((p-1) // 4)).abs()
+if sqrtm1 * sqrtm1 != fe(-1): raise ValueError('Wrong sqrtm1')
+
+# The square root of n, if n is a square.
+#
+# Note that p is congruent to 5 modulo 8, so (p+3)/8 is an integer.
+# If n is zero, then n^((p+3)/8) is zero (zero is its own square root).
+# Otherwise:
+# (n^((p+3)/8))^4 = n^((p+3)/2)
+# (n^((p+3)/8))^4 = n^((p-1)/2) * n^2
+# (n^((p+3)/8))^4 = chi(n) * n^2 -- chi(n) == 1
+# (n^((p+3)/8))^4 = n^2 -- because n is a non-zero square
+# (n^((p+3)/8))^2 = n or -n
+# case n:
+# (n^((p+3)/8))^2 = n
+# n^((p+3)/8) = sqrt(n) or -sqrt(n)
+# case -n:
+# (n^((p+3)/8))^2 = -n
+# -1 * (n^((p+3)/8))^2 = n
+# sqrt(-1) * n^((p+3)/8) = sqrt(n) or -sqrt(n)
+#
+# We then choose the positive square root, between 0 and (p-1)/2
+def sqrt(n):
+ if not is_square(n) : raise ValueError('Not a square!')
+ root = n**((p+3) // 8)
+ if root * root != n: root = (root * sqrtm1)
+ if root * root != n: raise ValueError('Should be a square!!')
+ return root.abs()
+
+###########################
+# Elligator 2 (reference) #
+###########################
+
+# Elligator: Elliptic-curve points indistinguishable from uniform random strings
+# by Daniel J. Bernstein, Mike Hamburg, Anna Krasnova, and Tanja Lange
+# 2013
+# https://elligator.cr.yp.to/
+
+# Arbitrary non square, typically chosen to minimise computation.
+# 2 and sqrt(-1) both work fairly well, but 2 seems to be more popular.
+# We stick to 2 for compatibility.
+non_square = fe(2)
+
+# Representative to curve point, straight from the paper.
+
+# Unlike the paper, curve coordinates are called (u, v) to follow
+# established conventions. Thus, "v" in the paper is called "w" here.
+def hash_to_curve(r):
+ w = -A / (fe(1) + non_square * r**2)
+ e = chi(w**3 + A*w**2 + w)
+ u = e*w - (fe(1)-e)*(A//2)
+ v = -e * sqrt(u**3 + A*u**2 + u)
+ return (u, v)
+
+# Test whether a point has a representative, straight from the paper.
+def can_curve_to_hash(u):
+ return u != -A and is_square(-non_square * u * (u+A))
+
+# Computes the representative of a point, straight from the paper.
+def curve_to_hash(u, v_is_negative):
+ if not can_curve_to_hash(u):
+ raise ValueError('cannot curve to hash')
+ sq1 = sqrt(-u / (non_square * (u+A)))
+ sq2 = sqrt(-(u+A) / (non_square * u ))
+ if v_is_negative: return sq2
+ else : return sq1
+
+#####################
+# Elligator2 (fast) #
+#####################
+
+# Inverse square root.
+# Returns (0 , True ) if x is zero.
+# Returns (sqrt(1/x) , True ) if x is non-zero square.
+# Returns (sqrt(sqrt(-1)/x), False) if x is not a square.
+# We do not guarantee the sign of the square root.
+#
+# Notes:
+# Let quartic = x^((p-1)/4)
+#
+# x^((p-1)/2) = chi(x)
+# quartic^2 = chi(x)
+# quartic = sqrt(chi(x))
+# quartic = 1 or -1 or sqrt(-1) or -sqrt(-1)
+#
+# Note that x is a square if quartic is 1 or -1
+# There are 4 cases to consider:
+#
+# if quartic = 1 (x is a square)
+# then x^((p-1)/4) = 1
+# x^((p-5)/4) * x = 1
+# x^((p-5)/4) = 1/x
+# x^((p-5)/8) = sqrt(1/x) or -sqrt(1/x)
+#
+# if quartic = -1 (x is a square)
+# then x^((p-1)/4) = -1
+# x^((p-5)/4) * x = -1
+# x^((p-5)/4) = -1/x
+# x^((p-5)/8) = sqrt(-1) / sqrt(x)
+# x^((p-5)/8) * sqrt(-1) = sqrt(-1)^2 / sqrt(x)
+# x^((p-5)/8) * sqrt(-1) = -1/sqrt(x)
+# x^((p-5)/8) * sqrt(-1) = -sqrt(1/x) or sqrt(1/x)
+#
+# if quartic = sqrt(-1) (x is not a square)
+# then x^((p-1)/4) = sqrt(-1)
+# x^((p-5)/4) * x = sqrt(-1)
+# x^((p-5)/4) = sqrt(-1)/x
+# x^((p-5)/8) = sqrt(sqrt(-1)/x) or -sqrt(sqrt(-1)/x)
+#
+# Note that the product of two non-squares is always a square:
+# For any non-squares a and b, chi(a) = -1 and chi(b) = -1.
+# Since chi(x) = x^((p-1)/2), chi(a)*chi(b) = chi(a*b) = 1.
+# Therefore a*b is a square.
+#
+# Since sqrt(-1) and x are both non-squares, their product is a
+# square, and we can compute their square root.
+#
+# if quartic = -sqrt(-1) (x is not a square)
+# then x^((p-1)/4) = -sqrt(-1)
+# x^((p-5)/4) * x = -sqrt(-1)
+# x^((p-5)/4) = -sqrt(-1)/x
+# x^((p-5)/8) = sqrt(-sqrt(-1)/x)
+# x^((p-5)/8) = sqrt( sqrt(-1)/x) * sqrt(-1)
+# x^((p-5)/8) * sqrt(-1) = sqrt( sqrt(-1)/x) * sqrt(-1)^2
+# x^((p-5)/8) * sqrt(-1) = sqrt( sqrt(-1)/x) * -1
+# x^((p-5)/8) * sqrt(-1) = -sqrt(sqrt(-1)/x) or sqrt(sqrt(-1)/x)
+def invsqrt(x):
+ isr = x**((p - 5) // 8)
+ quartic = x * isr**2
+ if quartic == fe(-1) or quartic == -sqrtm1:
+ isr = isr * sqrtm1
+ is_square = quartic == fe(1) or quartic == fe(-1) or x == fe(0)
+ return isr, is_square
+
+# From the paper:
+# w = -A / (fe(1) + non_square * r^2)
+# e = chi(w^3 + A*w^2 + w)
+# u = e*w - (fe(1)-e)*(A//2)
+# v = -e * sqrt(u^3 + A*u^2 + u)
+#
+# Note that e is either 0, 1 or -1
+# if e = 0
+# (u, v) = (0, 0)
+# if e = 1
+# u = w
+# v = -sqrt(u^3 + A*u^2 + u)
+# if e = -1
+# u = -w - A = w * non_square * r^2
+# v = sqrt(u^3 + A*u^2 + u)
+#
+# Let r1 = non_square * r^2
+# Let r2 = 1 + r1
+# Note that r2 cannot be zero, -1/non_square is not a square.
+# We can (tediously) verify that:
+# w^3 + A*w^2 + w = (A^2*r1 - r2^2) * A / r2^3
+# Therefore:
+# chi(w^3 + A*w^2 + w) = chi((A^2*r1 - r2^2) * (A / r2^3))
+# chi(w^3 + A*w^2 + w) = chi((A^2*r1 - r2^2) * (A / r2^3)) * 1
+# chi(w^3 + A*w^2 + w) = chi((A^2*r1 - r2^2) * (A / r2^3)) * chi(r2^6)
+# chi(w^3 + A*w^2 + w) = chi((A^2*r1 - r2^2) * (A / r2^3) * r2^6)
+# chi(w^3 + A*w^2 + w) = chi((A^2*r1 - r2^2) * A * r2^3)
+# Corollary:
+# e = 1 if (A^2*r1 - r2^2) * A * r2^3) is a non-zero square
+# e = -1 if (A^2*r1 - r2^2) * A * r2^3) is not a square
+# Note that w^3 + A*w^2 + w (and therefore e) can never be zero:
+# w^3 + A*w^2 + w = w * (w^2 + A*w + 1)
+# w^3 + A*w^2 + w = w * (w^2 + A*w + A^2/4 - A^2/4 + 1)
+# w^3 + A*w^2 + w = w * (w + A/2)^2 - A^2/4 + 1)
+# which is zero only if:
+# w = 0 (impossible)
+# (w + A/2)^2 = A^2/4 - 1 (impossible, because A^2/4-1 is not a square)
+#
+# Let isr = invsqrt((A^2*r1 - r2^2) * A * r2^3)
+# isr = sqrt(1 / ((A^2*r1 - r2^2) * A * r2^3)) if e = 1
+# isr = strt(sqrt(-1) / ((A^2*r1 - r2^2) * A * r2^3)) if e = -1
+#
+# if e = 1
+# let u1 = -A * (A^2*r1 - r2^2) * A * r2^2 * isr^2
+# u1 = w
+# u1 = u
+# let v1 = -(A^2*r1 - r2^2) * A * isr
+# v1 = -sqrt((A^2*r1 - r2^2) * A / r2^3)
+# v1 = -sqrt(w^3 + A*w^2 + w)
+# v1 = -sqrt(u^3 + A*u^2 + u) (because u = w)
+# v1 = v
+#
+# if e = -1
+# let ufactor = -non_square * sqrt(-1) * r^2
+# let vfactor = sqrt(ufactor)
+# let u2 = -A * (A^2*r1 - r2^2) * A * r2^2 * isr^2 * ufactor
+# u2 = w * -1 * -non_square * r^2
+# u2 = w * non_square * r^2
+# u2 = u
+# let v2 = (A^2*r1 - r2^2) * A * isr * vfactor
+# v2 = sqrt(non_square * r^2 * (A^2*r1 - r2^2) * A / r2^3)
+# v2 = sqrt(non_square * r^2 * (w^3 + A*w^2 + w))
+# v2 = sqrt(non_square * r^2 * w * (w^2 + A*w + 1))
+# v2 = sqrt(u (w^2 + A*w + 1))
+# v2 = sqrt(u ((-u-A)^2 + A*(-u-A) + 1))
+# v2 = sqrt(u (u^2 + A^2 + 2*A*u - A*u -A^2) + 1))
+# v2 = sqrt(u (u^2 + A*u + 1))
+# v2 = sqrt(u^3 + A*u^2 + u)
+# v2 = v
+ufactor = -non_square * sqrtm1
+vfactor = sqrt(ufactor)
+
+def fast_hash_to_curve(r):
+ t1 = r**2 * non_square # r1
+ u = t1 + fe(1) # r2
+ t2 = u**2
+ t3 = (A**2 * t1 - t2) * A # numerator
+ t1 = t2 * u # denominator
+ t1, is_square = invsqrt(t3 * t1)
+ u = r**2 * ufactor
+ v = r * vfactor
+ if is_square: u = fe(1)
+ if is_square: v = fe(1)
+ v = v * t3 * t1
+ t1 = t1**2
+ u = u * -A * t3 * t2 * t1
+ if is_square != v.is_negative(): # XOR
+ v = -v
+ return (u, v)
+
+# From the paper:
+# Let sq = -non_square * u * (u+A)
+# if sq is not a square, or u = -A, there is no mapping
+# Assuming there is a mapping:
+# if v is positive: r = sqrt(-u / (non_square * (u+A)))
+# if v is negative: r = sqrt(-(u+A) / (non_square * u ))
+#
+# We compute isr = invsqrt(-non_square * u * (u+A))
+# if it wasn't a square, abort.
+# else, isr = sqrt(-1 / (non_square * u * (u+A))
+#
+# If v is positive, we return isr * u:
+# isr * u = sqrt(-1 / (non_square * u * (u+A)) * u
+# isr * u = sqrt(-u / (non_square * (u+A))
+#
+# If v is negative, we return isr * (u+A):
+# isr * (u+A) = sqrt(-1 / (non_square * u * (u+A)) * (u+A)
+# isr * (u+A) = sqrt(-(u+A) / (non_square * u)
+def fast_curve_to_hash(u, v_is_negative):
+ t = u + A
+ r = -non_square * u * t
+ isr, is_square = invsqrt(r)
+ if not is_square:
+ return None
+ if v_is_negative: u = t
+ r = u * isr
+ r = r.abs()
+ return r
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/gen/elligator_scalarmult.py b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/elligator_scalarmult.py
new file mode 100644
index 0000000..a0d84e0
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/elligator_scalarmult.py
@@ -0,0 +1,230 @@
+#! /usr/bin/env python3
+
+# This file is dual-licensed. Choose whichever licence you want from
+# the two licences listed below.
+#
+# The first licence is a regular 2-clause BSD licence. The second licence
+# is the CC-0 from Creative Commons. It is intended to release Monocypher
+# to the public domain. The BSD licence serves as a fallback option.
+#
+# SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+#
+# ------------------------------------------------------------------------
+#
+# Copyright (c) 2020, Loup Vaillant
+# All rights reserved.
+#
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# ------------------------------------------------------------------------
+#
+# Written in 2020 by Loup Vaillant
+#
+# To the extent possible under law, the author(s) have dedicated all copyright
+# and related neighboring rights to this software to the public domain
+# worldwide. This software is distributed without any warranty.
+#
+# You should have received a copy of the CC0 Public Domain Dedication along
+# with this software. If not, see
+# <https://creativecommons.org/publicdomain/zero/1.0/>
+
+from elligator import fe
+from elligator import sqrt
+from elligator import sqrtm1
+from elligator import A
+
+#########################################
+# scalar multiplication (Edwards space) #
+#########################################
+
+# Edwards25519 equation (d defined below):
+# -x^2 + y^2 = 1 + d*x^2*y^2
+d = fe(-121665) / fe(121666)
+
+# Point addition:
+# denum = d*x1*x2*y1*y2
+# x = (x1*y2 + x2*y1) / (1 + denum)
+# y = (y1*y2 + x1*x2) / (1 - denum)
+# To avoid divisions, we use affine coordinates: x = X/Z, y = Y/Z.
+# We can multiply Z instead of dividing X and Y.
+def point_add(a, b):
+ x1, y1, z1 = a
+ x2, y2, z2 = b
+ denum = d*x1*x2*y1*y2
+ z1z2 = z1 * z2
+ z1z22 = z1z2**2
+ xt = z1z2 * (x1*y2 + x2*y1)
+ yt = z1z2 * (y1*y2 + x1*x2)
+ zx = z1z22 + denum
+ zy = z1z22 - denum
+ return (xt*zy, yt*zx, zx*zy)
+
+# Point addition, with the final division
+def point_add2(p1, p2):
+ x1, y1 = p1
+ x2, y2 = p2
+ z1, z2 = (fe(1), fe(1))
+ x, y, z = point_add((x1, y1, z1), (x2, y2, z2))
+ div = z.invert()
+ return (x*div, y*div)
+
+# scalar multiplication in edwards space:
+# point + point + ... + point, scalar times
+# (using a double and add ladder for speed)
+def ed_scalarmult(point, scalar):
+ affine = (point[0], point[1], fe(1))
+ acc = (fe(0), fe(1), fe(1))
+ binary = [int(c) for c in list(format(scalar, 'b'))]
+ for i in binary:
+ acc = point_add(acc, acc)
+ if i == 1:
+ acc = point_add(acc, affine)
+ return acc
+
+# convert the point to Montgomery (u coordinate only)
+# (u, v) = ((1+y)/(1-y), sqrt(-486664)*u/x)
+# (x, y) = (sqrt(-486664)*u/v, (u-1)/(u+1))
+def from_edwards(point):
+ x, y, z = point
+ return (z + y) / (z - y)
+
+# edwards base point
+eby = fe(4) / fe(5)
+ebx = sqrt((eby**2 - fe(1)) / (fe(1) + d * eby**2))
+edwards_base = (ebx, eby)
+
+############################################
+# scalar multiplication (Montgomery space) #
+############################################
+def mt_scalarmult(u, scalar):
+ x1 = u
+ x2, z2 = fe(1), fe(0) # "zero" point
+ x3, z3 = x1 , fe(1) # "one" point
+ binary = [int(c) for c in list(format(scalar, 'b'))]
+ for b in binary:
+ # Montgomery ladder step:
+ # if b == 0, then (P2, P3) == (P2*2 , P2+P3)
+ # if b == 1, then (P2, P3) == (P2+P3, P3*2 )
+ if b == 1:
+ x2, x3 = x3, x2
+ z2, z3 = z3, z2
+ x3, z3 = ((x2*x3 - z2*z3)**2,
+ (x2*z3 - z2*x3)**2 * x1)
+ x2, z2 = ((x2**2 - z2**2)**2,
+ fe(4)*x2*z2*(x2**2 + A*x2*z2 + z2**2))
+ if b == 1:
+ x2, x3 = x3, x2
+ z2, z3 = z3, z2
+ return x2 / z2
+
+montgomery_base = 9
+
+############################
+# Scalarmult with cofactor #
+############################
+
+# Keeping a random cofactor is important to keep points
+# indistinguishable from random. (Else we'd notice all representatives
+# represent points with cleared cofactor. Not exactly random.)
+
+# Point of order 8, used to add the cofactor component
+low_order_point_x = sqrt((sqrt(d + fe(1)) + fe(1)) / d)
+low_order_point_y = -low_order_point_x * sqrtm1
+low_order_point_1 = (low_order_point_x, low_order_point_y)
+low_order_point_2 = point_add2(low_order_point_1, low_order_point_1)
+low_order_point_4 = point_add2(low_order_point_2, low_order_point_2)
+low_order_point_8 = point_add2(low_order_point_4, low_order_point_4)
+low_order_point_5 = point_add2(low_order_point_1, low_order_point_4)
+
+def check_low_order_point():
+ lop2 = low_order_point_2
+ lop4 = low_order_point_4
+ lop8 = low_order_point_8
+ zero = (fe(0), fe(1))
+ if lop8 != zero: raise ValueError('low_order_point does not have low order')
+ if lop2 == zero: raise ValueError('low_order_point only has order 2')
+ if lop4 == zero: raise ValueError('low_order_point only has order 4')
+check_low_order_point()
+
+# base point + low order point
+ed_base_1 = point_add2(low_order_point_1, edwards_base) # in Edwards space
+ed_base_5 = point_add2(low_order_point_5, edwards_base) # in Edwards space
+mt_base_1 = (fe(1)+ed_base_1[1]) / (fe(1)-ed_base_1[1]) # in Montgomery space
+mt_base_5 = (fe(1)+ed_base_5[1]) / (fe(1)-ed_base_5[1]) # in Montgomery space
+
+# Clamp the scalar.
+# % 8 stops subgroup attacks
+# Clearing bit 255 and setting bit 254 facilitates constant time ladders.
+# We're not supposed to clear the cofactor, but scalar multiplication
+# usually does, and we want to reuse existing code as much as possible.
+def trim(scalar):
+ trimmed = scalar - scalar % 8
+ trimmed = trimmed % 2**254
+ trimmed = trimmed + 2**254
+ return trimmed
+
+order = 2**252 + 27742317777372353535851937790883648493
+
+# Single scalar multiplication (in Edwards space)
+def scalarmult1(scalar, cofactor):
+ co_cleared = ((cofactor * 5) % 8) * order # cleared main factor
+ combined = trim(scalar) + co_cleared
+ return from_edwards(ed_scalarmult(ed_base_1, combined))
+
+# Single scalar multiplication (in Edwards space, simplified)
+def scalarmult2(scalar, cofactor):
+ co_cleared = (cofactor % 8) * order # cleared main factor
+ combined = trim(scalar) + co_cleared
+ return from_edwards(ed_scalarmult(ed_base_5, combined))
+
+# Single scalar multiplication (in Montgomery space)
+def scalarmult3(scalar, cofactor):
+ co_cleared = ((cofactor * 5) % 8) * order # cleared main factor
+ combined = trim(scalar) + co_cleared
+ return mt_scalarmult(mt_base_1, combined)
+
+# Single scalar multiplication (in Montgomery space, simplified)
+def scalarmult4(scalar, cofactor):
+ co_cleared = (cofactor % 8) * order # cleared main factor
+ combined = trim(scalar) + co_cleared
+ return mt_scalarmult(mt_base_5, combined)
+
+# Double scalar multiplication (reuses EdDSA code)
+def scalarmult5(scalar, cofactor):
+ main_point = ed_scalarmult(edwards_base , trim(scalar))
+ low_order = ed_scalarmult(low_order_point_1, cofactor )
+ return from_edwards(point_add(main_point, low_order))
+
+# Combine and compare all ways of doing the scalar multiplication
+def scalarmult(scalar, cofactor):
+ p1 = scalarmult1(scalar, cofactor)
+ p2 = scalarmult2(scalar, cofactor)
+ p3 = scalarmult3(scalar, cofactor)
+ p4 = scalarmult4(scalar, cofactor)
+ p5 = scalarmult5(scalar, cofactor)
+ if p1 != p2 or p1 != p3 or p1 != p4 or p1 != p5:
+ raise ValueError('Incoherent scalarmult')
+ return p1
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/gen/hchacha20.c b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/hchacha20.c
new file mode 100644
index 0000000..55b5369
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/hchacha20.c
@@ -0,0 +1,73 @@
+// This file is dual-licensed. Choose whichever licence you want from
+// the two licences listed below.
+//
+// The first licence is a regular 2-clause BSD licence. The second licence
+// is the CC-0 from Creative Commons. It is intended to release Monocypher
+// to the public domain. The BSD licence serves as a fallback option.
+//
+// SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+//
+// ------------------------------------------------------------------------
+//
+// Copyright (c) 2017-2019, Loup Vaillant
+// All rights reserved.
+//
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// ------------------------------------------------------------------------
+//
+// Written in 2017-2019 by Loup Vaillant
+//
+// To the extent possible under law, the author(s) have dedicated all copyright
+// and related neighboring rights to this software to the public domain
+// worldwide. This software is distributed without any warranty.
+//
+// You should have received a copy of the CC0 Public Domain Dedication along
+// with this software. If not, see
+// <https://creativecommons.org/publicdomain/zero/1.0/>
+
+#include <sodium.h>
+#include "utils.h"
+
+int main(void)
+{
+ SODIUM_INIT;
+
+ FOR (size, 0, 50) {
+ RANDOM_INPUT(key , 32);
+ RANDOM_INPUT(in , 16);
+ u8 out[32];
+
+ crypto_core_hchacha20(out, in, key, 0);
+
+ print_vector(key , 32);
+ print_vector(in , 16);
+ print_vector(out , 32);
+ printf("\n");
+ }
+
+ return 0;
+}
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/gen/ietf_chacha20.c b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/ietf_chacha20.c
new file mode 100644
index 0000000..21e01e9
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/ietf_chacha20.c
@@ -0,0 +1,77 @@
+// This file is dual-licensed. Choose whichever licence you want from
+// the two licences listed below.
+//
+// The first licence is a regular 2-clause BSD licence. The second licence
+// is the CC-0 from Creative Commons. It is intended to release Monocypher
+// to the public domain. The BSD licence serves as a fallback option.
+//
+// SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+//
+// ------------------------------------------------------------------------
+//
+// Copyright (c) 2017-2019, Loup Vaillant
+// All rights reserved.
+//
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// ------------------------------------------------------------------------
+//
+// Written in 2017-2019 by Loup Vaillant
+//
+// To the extent possible under law, the author(s) have dedicated all copyright
+// and related neighboring rights to this software to the public domain
+// worldwide. This software is distributed without any warranty.
+//
+// You should have received a copy of the CC0 Public Domain Dedication along
+// with this software. If not, see
+// <https://creativecommons.org/publicdomain/zero/1.0/>
+
+#include <sodium.h>
+#include "utils.h"
+
+static void test(size_t size, u32 ctr)
+{
+ RANDOM_INPUT(key , 32);
+ RANDOM_INPUT(nonce, 12);
+ RANDOM_INPUT(in , 128); // size <= 128
+ u8 out[128]; // size <= 128
+
+ crypto_stream_chacha20_ietf_xor_ic(out, in, size, nonce, ctr, key);
+
+ print_vector(key , 32);
+ print_vector(nonce, 12);
+ print_vector(in , size);
+ print_number(ctr );
+ print_vector(out , size);
+ printf("\n");
+}
+
+int main(void)
+{
+ SODIUM_INIT;
+ FOR (size, 0, 128) { test(size, (u32)rand64()); }
+ return 0;
+}
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/gen/makefile b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/makefile
new file mode 100644
index 0000000..0adc512
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/makefile
@@ -0,0 +1,150 @@
+# This file is dual-licensed. Choose whichever licence you want from
+# the two licences listed below.
+#
+# The first licence is a regular 2-clause BSD licence. The second licence
+# is the CC-0 from Creative Commons. It is intended to release Monocypher
+# to the public domain. The BSD licence serves as a fallback option.
+#
+# SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+#
+# ------------------------------------------------------------------------
+#
+# Copyright (c) 2017-2019, Loup Vaillant
+# Copyright (c) 2017, 2019, Fabio Scotoni
+# All rights reserved.
+#
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# ------------------------------------------------------------------------
+#
+# Written in 2017-2019 by Loup Vaillant and Fabio Scotoni
+#
+# To the extent possible under law, the author(s) have dedicated all copyright
+# and related neighboring rights to this software to the public domain
+# worldwide. This software is distributed without any warranty.
+#
+# You should have received a copy of the CC0 Public Domain Dedication along
+# with this software. If not, see
+# <https://creativecommons.org/publicdomain/zero/1.0/>
+CC ?= gcc -std=c99
+CFLAGS ?= -pedantic -Wall -Wextra
+
+.PHONY: all clean
+
+VEC = chacha20 hchacha20 xchacha20 ietf_chacha20 \
+ aead_ietf aead_8439 \
+ poly1305 blake2b sha512 sha512_hmac sha512_hkdf argon2 \
+ edDSA edDSA_pk ed_25519 ed_25519_pk ed_25519_check \
+ ed_25519ph \
+ x25519 x25519_pk elligator_inv elligator_dir
+VEC2 = $(patsubst %, %.all.vec, $(VEC))
+HEADERS = $(patsubst %, %.h.vec , $(VEC))
+VECTORS = ../vectors.h
+
+all: $(VECTORS)
+
+clean:
+ rm -f *.out *.vec *.o
+ rm -f $(VECTORS)
+
+elligator_inv.vec: elligator-inverse.py elligator.py elligator_scalarmult.py
+ ./$< >$@
+elligator_dir.vec: elligator-direct.py elligator.py
+ ./$< >$@
+sha512_hkdf.vec: sha512_hkdf.py
+ ./$< >$@
+%.vec: %.out
+ ./$< > $@
+
+utils.o: utils.c utils.h
+ $(CC) $(CFLAGS) -c $< -o $@
+
+%.o: %.c ../utils.h ../externals/ed25519-donna/ed25519.h
+ $(CC) $(CFLAGS) -c $< \
+ -I .. \
+ -I ../externals/ed25519-donna \
+ -I ../../src \
+ -I ../../src/optional \
+ $$(pkg-config --cflags libsodium)
+
+%.out: %.o ed25519.o utils.o
+ $(CC) $(CFLAGS) -o $@ $^ \
+ $$(pkg-config --libs libsodium)
+
+ed25519.o: ../externals/ed25519-donna/ed25519.c \
+ $(wildcard ../externals/ed25519-donna/*.h)
+ $(CC) $(CFLAGS) -c $< \
+ -I ../../src \
+ -I ../../src/optional \
+ $$(pkg-config --cflags libsodium) \
+ -DED25519_CUSTOMHASH \
+ -DED25519_TEST \
+ -DED25519_NO_INLINE_ASM \
+ -DED25519_FORCE_32BIT
+
+vector_to_header.out: vector_to_header.c
+ $(CC) $(CFLAGS) $< -o $@
+
+chacha20.all.vec : chacha20.vec vectors/chacha20
+poly1305.all.vec : poly1305.vec vectors/poly1305
+x25519.all.vec : x25519.vec vectors/x25519
+x25519_pk.all.vec : x25519_pk.vec
+hchacha20.all.vec : hchacha20.vec
+xchacha20.all.vec : xchacha20.vec
+ietf_chacha20.all.vec : ietf_chacha20.vec
+aead_ietf.all.vec : aead_ietf.vec
+aead_8439.all.vec : aead_8439.vec
+blake2b.all.vec : blake2b.vec vectors/blake2b
+sha512.all.vec : sha512.vec
+sha512_hmac.all.vec : sha512_hmac.vec vectors/sha512_hmac
+sha512_hkdf.all.vec : sha512_hkdf.vec
+argon2.all.vec : argon2.vec vectors/argon2
+edDSA.all.vec : edDSA.vec
+edDSA_pk.all.vec : edDSA_pk.vec
+ed_25519.all.vec : ed_25519.vec
+ed_25519_pk.all.vec : ed_25519_pk.vec
+ed_25519_check.all.vec: vectors/ed_25519_check
+ed_25519ph.all.vec : vectors/ed_25519ph
+elligator_dir.all.vec : elligator_dir.vec vectors/elligator_dir
+elligator_inv.all.vec : elligator_inv.vec vectors/elligator_inv
+$(VEC2):
+ mkdir -p $(@D)
+ cat $^ > $@
+
+%.h.vec: %.all.vec vector_to_header.out
+ ./vector_to_header.out $(patsubst %.all.vec,%,$<) < $< > $@
+
+prelude.h.vec:
+ @echo "creating prelude.h.vec"
+ @echo "// Generated with hard coded official vectors, and" > $@
+ @echo "// random vectors with libsodium and ed25519-donna." >> $@
+ @echo "// Download Monocypher's git repository to regenerate." >> $@
+ @echo "#include <inttypes.h>" >> $@
+ @echo "#include <stddef.h>" >> $@
+ @echo "" >> $@
+
+$(VECTORS): prelude.h.vec $(HEADERS)
+ cat $^ > $@
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/gen/poly1305.c b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/poly1305.c
new file mode 100644
index 0000000..32ca1c3
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/poly1305.c
@@ -0,0 +1,74 @@
+// This file is dual-licensed. Choose whichever licence you want from
+// the two licences listed below.
+//
+// The first licence is a regular 2-clause BSD licence. The second licence
+// is the CC-0 from Creative Commons. It is intended to release Monocypher
+// to the public domain. The BSD licence serves as a fallback option.
+//
+// SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+//
+// ------------------------------------------------------------------------
+//
+// Copyright (c) 2017-2019, Loup Vaillant
+// All rights reserved.
+//
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// ------------------------------------------------------------------------
+//
+// Written in 2017-2019 by Loup Vaillant
+//
+// To the extent possible under law, the author(s) have dedicated all copyright
+// and related neighboring rights to this software to the public domain
+// worldwide. This software is distributed without any warranty.
+//
+// You should have received a copy of the CC0 Public Domain Dedication along
+// with this software. If not, see
+// <https://creativecommons.org/publicdomain/zero/1.0/>
+
+#include <sodium.h>
+#include "utils.h"
+
+static void test(size_t size)
+{
+ RANDOM_INPUT(key, 32);
+ RANDOM_INPUT(in , 32);
+ u8 tag[ 16];
+
+ crypto_onetimeauth(tag, in, size, key);
+
+ print_vector(key, 32);
+ print_vector(in , size);
+ print_vector(tag, 16);
+ printf("\n");
+}
+
+int main(void)
+{
+ SODIUM_INIT;
+ FOR (size, 0, 32) { test(size); }
+ return 0;
+}
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/gen/sha512.c b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/sha512.c
new file mode 100644
index 0000000..a9befea
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/sha512.c
@@ -0,0 +1,74 @@
+// This file is dual-licensed. Choose whichever licence you want from
+// the two licences listed below.
+//
+// The first licence is a regular 2-clause BSD licence. The second licence
+// is the CC-0 from Creative Commons. It is intended to release Monocypher
+// to the public domain. The BSD licence serves as a fallback option.
+//
+// SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+//
+// ------------------------------------------------------------------------
+//
+// Copyright (c) 2017-2019, Loup Vaillant
+// All rights reserved.
+//
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// ------------------------------------------------------------------------
+//
+// Written in 2017-2019 by Loup Vaillant
+//
+// To the extent possible under law, the author(s) have dedicated all copyright
+// and related neighboring rights to this software to the public domain
+// worldwide. This software is distributed without any warranty.
+//
+// You should have received a copy of the CC0 Public Domain Dedication along
+// with this software. If not, see
+// <https://creativecommons.org/publicdomain/zero/1.0/>
+
+#include <sodium.h>
+#include "utils.h"
+
+static void test(size_t size)
+{
+ RANDOM_INPUT(in , 256);
+ u8 hash[64];
+
+ crypto_hash_sha512(hash, in, size);
+
+ print_vector(in , size);
+ print_vector(hash, 64);
+ printf("\n");
+}
+
+int main(void)
+{
+ SODIUM_INIT;
+ FOR(size, 0, 256) {
+ test(size);
+ }
+ return 0;
+}
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/gen/sha512_hkdf.py b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/sha512_hkdf.py
new file mode 100644
index 0000000..1d696c0
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/sha512_hkdf.py
@@ -0,0 +1,109 @@
+#! /usr/bin/env python3
+
+# This file is dual-licensed. Choose whichever licence you want from
+# the two licences listed below.
+#
+# The first licence is a regular 2-clause BSD licence. The second licence
+# is the CC-0 from Creative Commons. It is intended to release Monocypher
+# to the public domain. The BSD licence serves as a fallback option.
+#
+# SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+#
+# ------------------------------------------------------------------------
+#
+# Copyright (c) 2023, Loup Vaillant
+# All rights reserved.
+#
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# ------------------------------------------------------------------------
+#
+# Written in 2023 by Loup Vaillant
+#
+# To the extent possible under law, the author(s) have dedicated all copyright
+# and related neighboring rights to this software to the public domain
+# worldwide. This software is distributed without any warranty.
+#
+# You should have received a copy of the CC0 Public Domain Dedication along
+# with this software. If not, see
+# <https://creativecommons.org/publicdomain/zero/1.0/>
+
+from binascii import hexlify
+from cryptography.hazmat.primitives.hashes import SHA512
+from cryptography.hazmat.primitives.kdf.hkdf import HKDF
+from random import randrange
+from random import seed
+
+seed(12345) # deterministic test vectors
+
+def rand_buf(size):
+ buf = bytearray(size)
+ for i in range(size):
+ buf[i] = randrange(0, 256)
+ return bytes(buf)
+
+def vectors(ikm_size, salt_size, info_size, okm_size):
+ ikm = rand_buf(ikm_size)
+ salt = rand_buf(salt_size)
+ info = rand_buf(info_size)
+ okm = HKDF(
+ algorithm = SHA512(),
+ length = okm_size,
+ salt = salt,
+ info = info,
+ ).derive(ikm)
+ print(hexlify(ikm ).decode() + ":")
+ print(hexlify(salt).decode() + ":")
+ print(hexlify(info).decode() + ":")
+ print(hexlify(okm ).decode() + ":")
+
+vectors(0, 0, 0, 0)
+vectors(0, 0, 0, 64)
+
+vectors(32, 16, 8, 63)
+vectors(32, 16, 8, 64)
+vectors(32, 16, 8, 65)
+vectors(32, 16, 8, 127)
+vectors(32, 16, 8, 128)
+vectors(32, 16, 8, 129)
+
+vectors(32, 16, 8, 128)
+
+vectors(127, 16, 8, 128)
+vectors(128, 16, 8, 128)
+vectors(129, 16, 8, 128)
+
+vectors(32, 127, 8, 128)
+vectors(32, 128, 8, 128)
+vectors(32, 129, 8, 128)
+
+vectors(32, 16, 127, 128)
+vectors(32, 16, 128, 128)
+vectors(32, 16, 129, 128)
+
+vectors(127, 127, 127, 127)
+vectors(128, 128, 128, 128)
+vectors(129, 129, 129, 129)
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/gen/sha512_hmac.c b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/sha512_hmac.c
new file mode 100644
index 0000000..8d53a2f
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/sha512_hmac.c
@@ -0,0 +1,79 @@
+// This file is dual-licensed. Choose whichever licence you want from
+// the two licences listed below.
+//
+// The first licence is a regular 2-clause BSD licence. The second licence
+// is the CC-0 from Creative Commons. It is intended to release Monocypher
+// to the public domain. The BSD licence serves as a fallback option.
+//
+// SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+//
+// ------------------------------------------------------------------------
+//
+// Copyright (c) 2017-2019, Loup Vaillant
+// All rights reserved.
+//
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// ------------------------------------------------------------------------
+//
+// Written in 2017-2019 by Loup Vaillant
+//
+// To the extent possible under law, the author(s) have dedicated all copyright
+// and related neighboring rights to this software to the public domain
+// worldwide. This software is distributed without any warranty.
+//
+// You should have received a copy of the CC0 Public Domain Dedication along
+// with this software. If not, see
+// <https://creativecommons.org/publicdomain/zero/1.0/>
+
+#include <sodium.h>
+#include "utils.h"
+
+static void test(size_t key_size, size_t msg_size)
+{
+ RANDOM_INPUT(key, 256);
+ RANDOM_INPUT(msg, 256);
+ u8 tag[64];
+
+ crypto_auth_hmacsha512_state ctx;
+ crypto_auth_hmacsha512_init (&ctx, key, key_size);
+ crypto_auth_hmacsha512_update(&ctx, msg, msg_size);
+ crypto_auth_hmacsha512_final (&ctx, tag);
+
+ print_vector(key, key_size);
+ print_vector(msg, msg_size);
+ print_vector(tag, 64);
+ printf("\n");
+}
+
+int main(void)
+{
+ SODIUM_INIT;
+ FOR (key_size, 0, 32) { test(key_size, 32); }
+ FOR (key_size, 120, 136) { test(key_size, 32); }
+ FOR (msg_size, 0, 256) { test(32, msg_size); }
+ return 0;
+}
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/gen/utils.c b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/utils.c
new file mode 100644
index 0000000..0ef5482
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/utils.c
@@ -0,0 +1,100 @@
+// This file is dual-licensed. Choose whichever licence you want from
+// the two licences listed below.
+//
+// The first licence is a regular 2-clause BSD licence. The second licence
+// is the CC-0 from Creative Commons. It is intended to release Monocypher
+// to the public domain. The BSD licence serves as a fallback option.
+//
+// SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+//
+// ------------------------------------------------------------------------
+//
+// Copyright (c) 2017-2019, 2023 Loup Vaillant
+// All rights reserved.
+//
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// ------------------------------------------------------------------------
+//
+// Written in 2017-2019, 2023 by Loup Vaillant
+//
+// To the extent possible under law, the author(s) have dedicated all copyright
+// and related neighboring rights to this software to the public domain
+// worldwide. This software is distributed without any warranty.
+//
+// You should have received a copy of the CC0 Public Domain Dedication along
+// with this software. If not, see
+// <https://creativecommons.org/publicdomain/zero/1.0/>
+
+#include "utils.h"
+#include <stdio.h>
+
+static void store64_le(u8 out[8], u64 in)
+{
+ out[0] = in & 0xff;
+ out[1] = (in >> 8) & 0xff;
+ out[2] = (in >> 16) & 0xff;
+ out[3] = (in >> 24) & 0xff;
+ out[4] = (in >> 32) & 0xff;
+ out[5] = (in >> 40) & 0xff;
+ out[6] = (in >> 48) & 0xff;
+ out[7] = (in >> 56) & 0xff;
+}
+
+// Must be seeded with a nonzero value.
+// Accessible from the outside so we can modify it
+u64 random_state = 12345;
+
+// Pseudo-random 64 bit number, based on xorshift*
+u64 rand64(void)
+{
+ random_state ^= random_state >> 12;
+ random_state ^= random_state << 25;
+ random_state ^= random_state >> 27;
+ return random_state * 0x2545F4914F6CDD1D; // magic constant
+}
+
+void p_random(u8 *stream, size_t size)
+{
+ FOR (i, 0, size) {
+ stream[i] = (u8)rand64();
+ }
+}
+
+void print_vector(const u8 *buf, size_t size)
+{
+ FOR (i, 0, size) {
+ printf("%x%x", buf[i] >> 4, buf[i] & 0x0f);
+ }
+ printf(":\n");
+}
+
+void print_number(u64 n)
+{
+ u8 buf[8];
+ store64_le(buf, n);
+ print_vector(buf, 8);
+}
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/gen/utils.h b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/utils.h
new file mode 100644
index 0000000..5704f66
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/utils.h
@@ -0,0 +1,78 @@
+// This file is dual-licensed. Choose whichever licence you want from
+// the two licences listed below.
+//
+// The first licence is a regular 2-clause BSD licence. The second licence
+// is the CC-0 from Creative Commons. It is intended to release Monocypher
+// to the public domain. The BSD licence serves as a fallback option.
+//
+// SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+//
+// ------------------------------------------------------------------------
+//
+// Copyright (c) 2017-2019, 2023 Loup Vaillant
+// All rights reserved.
+//
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// ------------------------------------------------------------------------
+//
+// Written in 2017-2019, 2023 by Loup Vaillant
+//
+// To the extent possible under law, the author(s) have dedicated all copyright
+// and related neighboring rights to this software to the public domain
+// worldwide. This software is distributed without any warranty.
+//
+// You should have received a copy of the CC0 Public Domain Dedication along
+// with this software. If not, see
+// <https://creativecommons.org/publicdomain/zero/1.0/>
+
+#ifndef UTILS_H
+#define UTILS_H
+
+#include <inttypes.h>
+#include <stddef.h>
+
+typedef uint8_t u8;
+typedef uint32_t u32;
+typedef uint64_t u64;
+
+#define FOR(i, start, end) for (size_t i = (start); i < (end); i++)
+#define SODIUM_INIT ASSERT(sodium_init() != -1)
+#define RANDOM_INPUT(name, size) u8 name[size]; p_random(name, size)
+#define ASSERT(condition) do { \
+ if (!(condition)) { \
+ fprintf(stderr, "Assert failure(%s, %d): %s\n", \
+ __FILE__, __LINE__, #condition); \
+ exit(1); \
+ } \
+ } while (0)
+
+u64 rand64(void); // Pseudo-random 64 bit number, based on xorshift*
+void p_random(u8 *stream, size_t size);
+void print_vector(const u8 *buf, size_t size);
+void print_number(u64 n);
+
+#endif // UTILS_H
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/gen/vector_to_header.c b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/vector_to_header.c
new file mode 100644
index 0000000..5d5aa1f
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/vector_to_header.c
@@ -0,0 +1,122 @@
+// This file is dual-licensed. Choose whichever licence you want from
+// the two licences listed below.
+//
+// The first licence is a regular 2-clause BSD licence. The second licence
+// is the CC-0 from Creative Commons. It is intended to release Monocypher
+// to the public domain. The BSD licence serves as a fallback option.
+//
+// SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+//
+// ------------------------------------------------------------------------
+//
+// Copyright (c) 2017-2020, 2023 Loup Vaillant
+// All rights reserved.
+//
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// ------------------------------------------------------------------------
+//
+// Written in 2017-2020, 2023 by Loup Vaillant
+//
+// To the extent possible under law, the author(s) have dedicated all copyright
+// and related neighboring rights to this software to the public domain
+// worldwide. This software is distributed without any warranty.
+//
+// You should have received a copy of the CC0 Public Domain Dedication along
+// with this software. If not, see
+// <https://creativecommons.org/publicdomain/zero/1.0/>
+
+// Transforms a test vector file (from stdin) into a C header.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stddef.h>
+#include <assert.h>
+
+#define FOR(i, start, end) for (size_t i = (start); i < (end); i++)
+#define CHECK(cond, msg) do { if (!(cond)) { panic(msg); } } while (0)
+
+static void panic(const char *msg)
+{
+ fprintf(stderr, "%s\n", msg);
+ exit(1);
+}
+
+static int is_digit(int c)
+{
+ return
+ (c >= '0' && c <= '9') ||
+ (c >= 'a' && c <= 'f') ||
+ (c >= 'A' && c <= 'F');
+}
+
+static int whitespace(int c)
+{
+ // Skip whitespace
+ while (c == '\n') {
+ c = getchar();
+ }
+ // Skip comment
+ if (c == '#') {
+ while (c != EOF && c != '\n') {
+ c = getchar();
+ }
+ return whitespace(getchar());
+ }
+ CHECK(is_digit(c) || c == ':' || c == EOF, "Illegal character");
+ return c; // first digit
+}
+
+int main(int argc, char** argv)
+{
+ CHECK(argc == 2, "Wrong use of vector transformer. Give one argument");
+
+ char *prefix = argv[1];
+ size_t nb_vec = 0;
+
+ printf("static const char *%s_vectors[]={\n", prefix);
+
+ int c = whitespace(getchar());
+ while (c != EOF) {
+ printf(" \"");
+ unsigned parity = 0;
+ while (c != ':' && c != EOF) {
+ parity = ~parity;
+ CHECK(is_digit(c), "Not a digit");
+ printf("%c", (char)c);
+ c = getchar();
+ }
+ CHECK(parity == 0, "Odd number of digits");
+ printf("\",\n");
+ c = whitespace(getchar());
+ nb_vec++;
+ }
+ printf("};\n");
+ printf("static size_t nb_%s_vectors=%zu;\n", prefix, nb_vec);
+
+ return 0;
+}
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/gen/vectors/argon2 b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/vectors/argon2
new file mode 100644
index 0000000..c111670
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/vectors/argon2
@@ -0,0 +1,76 @@
+# Parameters are in the following order:
+#
+# - Algorithm (0 = Argon2d, 1 = Argon2i, 2 -> Argon2id)
+# - Memory (number of KiB)
+# - Time (number of iterations)
+# - Parallelism (number of lanes)
+# - Password
+# - Salt
+# - Key
+# - Additional data
+# - Digest
+
+# This one is modified from the RFC to only take one lane,
+# from back when Monocypher only supported one lane.
+0100000000000000:
+0800000000000000:
+0300000000000000:
+0100000000000000:
+0101010101010101010101010101010101010101010101010101010101010101:
+02020202020202020202020202020202:
+0303030303030303:
+040404040404040404040404:
+afe519be3ab0e92375df221dfb17347080c7000b1be85f9ee39978bf11e7cc3a:
+
+#
+# From RFC 9106 (Argon2d)
+#
+0000000000000000:
+2000000000000000:
+0300000000000000:
+0400000000000000:
+0101010101010101010101010101010101010101010101010101010101010101:
+02020202020202020202020202020202:
+0303030303030303:
+040404040404040404040404:
+512b391b6f1162975371d30919734294f868e3be3984f3c1a13a4db9fabe4acb:
+
+#
+# From RFC 9106 (Argon2i)
+#
+0100000000000000:
+2000000000000000:
+0300000000000000:
+0400000000000000:
+0101010101010101010101010101010101010101010101010101010101010101:
+02020202020202020202020202020202:
+0303030303030303:
+040404040404040404040404:
+c814d9d1dc7f37aa13f0d77f2494bda1c8de6b016dd388d29952a4c4672b6ce8:
+
+#
+# From RFC 9106 (Argon2id)
+#
+0200000000000000:
+2000000000000000:
+0300000000000000:
+0400000000000000:
+0101010101010101010101010101010101010101010101010101010101010101:
+02020202020202020202020202020202:
+0303030303030303:
+040404040404040404040404:
+0d640df58d78766c08c037a34a8b53c9d01ef0452d75b65eb52520e96b01e659:
+
+#
+# This one was modified from the RFC (Argon2d) to 2 lanes,
+# which is enough to trigger the reference set error
+#
+0000000000000000:
+2000000000000000:
+0300000000000000:
+0200000000000000:
+0101010101010101010101010101010101010101010101010101010101010101:
+02020202020202020202020202020202:
+0303030303030303:
+040404040404040404040404:
+c53c3e988d88e8c37b322e3302d273f4847eb058bf06449f647ea6396f14e87c:
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/gen/vectors/blake2b b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/vectors/blake2b
new file mode 100644
index 0000000..d57c0d3
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/vectors/blake2b
@@ -0,0 +1,1028 @@
+#
+# Official BLAKE2b test vectors, from
+# https://github.com/BLAKE2/BLAKE2/blob/master/testvectors/blake2b-kat.txt
+#
+
+:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+10ebb67700b1868efb4417987acf4690ae9d972fb7a590c2f02871799aaa4786b5e996e8f0f4eb981fc214b005f42d2ff4233499391653df7aefcbc13fc51568:
+
+00:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+961f6dd1e4dd30f63901690c512e78e4b45e4742ed197c3c5e45c549fd25f2e4187b0bc9fe30492b16b0d0bc4ef9b0f34c7003fac09a5ef1532e69430234cebd:
+
+0001:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+da2cfbe2d8409a0f38026113884f84b50156371ae304c4430173d08a99d9fb1b983164a3770706d537f49e0c916d9f32b95cc37a95b99d857436f0232c88a965:
+
+000102:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+33d0825dddf7ada99b0e7e307104ad07ca9cfd9692214f1561356315e784f3e5a17e364ae9dbb14cb2036df932b77f4b292761365fb328de7afdc6d8998f5fc1:
+
+00010203:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+beaa5a3d08f3807143cf621d95cd690514d0b49efff9c91d24b59241ec0eefa5f60196d407048bba8d2146828ebcb0488d8842fd56bb4f6df8e19c4b4daab8ac:
+
+0001020304:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+098084b51fd13deae5f4320de94a688ee07baea2800486689a8636117b46c1f4c1f6af7f74ae7c857600456a58a3af251dc4723a64cc7c0a5ab6d9cac91c20bb:
+
+000102030405:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+6044540d560853eb1c57df0077dd381094781cdb9073e5b1b3d3f6c7829e12066bbaca96d989a690de72ca3133a83652ba284a6d62942b271ffa2620c9e75b1f:
+
+00010203040506:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+7a8cfe9b90f75f7ecb3acc053aaed6193112b6f6a4aeeb3f65d3de541942deb9e2228152a3c4bbbe72fc3b12629528cfbb09fe630f0474339f54abf453e2ed52:
+
+0001020304050607:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+380beaf6ea7cc9365e270ef0e6f3a64fb902acae51dd5512f84259ad2c91f4bc4108db73192a5bbfb0cbcf71e46c3e21aee1c5e860dc96e8eb0b7b8426e6abe9:
+
+000102030405060708:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+60fe3c4535e1b59d9a61ea8500bfac41a69dffb1ceadd9aca323e9a625b64da5763bad7226da02b9c8c4f1a5de140ac5a6c1124e4f718ce0b28ea47393aa6637:
+
+00010203040506070809:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+4fe181f54ad63a2983feaaf77d1e7235c2beb17fa328b6d9505bda327df19fc37f02c4b6f0368ce23147313a8e5738b5fa2a95b29de1c7f8264eb77b69f585cd:
+
+000102030405060708090a:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+f228773ce3f3a42b5f144d63237a72d99693adb8837d0e112a8a0f8ffff2c362857ac49c11ec740d1500749dac9b1f4548108bf3155794dcc9e4082849e2b85b:
+
+000102030405060708090a0b:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+962452a8455cc56c8511317e3b1f3b2c37df75f588e94325fdd77070359cf63a9ae6e930936fdf8e1e08ffca440cfb72c28f06d89a2151d1c46cd5b268ef8563:
+
+000102030405060708090a0b0c:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+43d44bfa18768c59896bf7ed1765cb2d14af8c260266039099b25a603e4ddc5039d6ef3a91847d1088d401c0c7e847781a8a590d33a3c6cb4df0fab1c2f22355:
+
+000102030405060708090a0b0c0d:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+dcffa9d58c2a4ca2cdbb0c7aa4c4c1d45165190089f4e983bb1c2cab4aaeff1fa2b5ee516fecd780540240bf37e56c8bcca7fab980e1e61c9400d8a9a5b14ac6:
+
+000102030405060708090a0b0c0d0e:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+6fbf31b45ab0c0b8dad1c0f5f4061379912dde5aa922099a030b725c73346c524291adef89d2f6fd8dfcda6d07dad811a9314536c2915ed45da34947e83de34e:
+
+000102030405060708090a0b0c0d0e0f:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+a0c65bddde8adef57282b04b11e7bc8aab105b99231b750c021f4a735cb1bcfab87553bba3abb0c3e64a0b6955285185a0bd35fb8cfde557329bebb1f629ee93:
+
+000102030405060708090a0b0c0d0e0f10:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+f99d815550558e81eca2f96718aed10d86f3f1cfb675cce06b0eff02f617c5a42c5aa760270f2679da2677c5aeb94f1142277f21c7f79f3c4f0cce4ed8ee62b1:
+
+000102030405060708090a0b0c0d0e0f1011:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+95391da8fc7b917a2044b3d6f5374e1ca072b41454d572c7356c05fd4bc1e0f40b8bb8b4a9f6bce9be2c4623c399b0dca0dab05cb7281b71a21b0ebcd9e55670:
+
+000102030405060708090a0b0c0d0e0f101112:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+04b9cd3d20d221c09ac86913d3dc63041989a9a1e694f1e639a3ba7e451840f750c2fc191d56ad61f2e7936bc0ac8e094b60caeed878c18799045402d61ceaf9:
+
+000102030405060708090a0b0c0d0e0f10111213:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+ec0e0ef707e4ed6c0c66f9e089e4954b058030d2dd86398fe84059631f9ee591d9d77375355149178c0cf8f8e7c49ed2a5e4f95488a2247067c208510fadc44c:
+
+000102030405060708090a0b0c0d0e0f1011121314:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+9a37cce273b79c09913677510eaf7688e89b3314d3532fd2764c39de022a2945b5710d13517af8ddc0316624e73bec1ce67df15228302036f330ab0cb4d218dd:
+
+000102030405060708090a0b0c0d0e0f101112131415:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+4cf9bb8fb3d4de8b38b2f262d3c40f46dfe747e8fc0a414c193d9fcf753106ce47a18f172f12e8a2f1c26726545358e5ee28c9e2213a8787aafbc516d2343152:
+
+000102030405060708090a0b0c0d0e0f10111213141516:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+64e0c63af9c808fd893137129867fd91939d53f2af04be4fa268006100069b2d69daa5c5d8ed7fddcb2a70eeecdf2b105dd46a1e3b7311728f639ab489326bc9:
+
+000102030405060708090a0b0c0d0e0f1011121314151617:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+5e9c93158d659b2def06b0c3c7565045542662d6eee8a96a89b78ade09fe8b3dcc096d4fe48815d88d8f82620156602af541955e1f6ca30dce14e254c326b88f:
+
+000102030405060708090a0b0c0d0e0f101112131415161718:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+7775dff889458dd11aef417276853e21335eb88e4dec9cfb4e9edb49820088551a2ca60339f12066101169f0dfe84b098fddb148d9da6b3d613df263889ad64b:
+
+000102030405060708090a0b0c0d0e0f10111213141516171819:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+f0d2805afbb91f743951351a6d024f9353a23c7ce1fc2b051b3a8b968c233f46f50f806ecb1568ffaa0b60661e334b21dde04f8fa155ac740eeb42e20b60d764:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+86a2af316e7d7754201b942e275364ac12ea8962ab5bd8d7fb276dc5fbffc8f9a28cae4e4867df6780d9b72524160927c855da5b6078e0b554aa91e31cb9ca1d:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+10bdf0caa0802705e706369baf8a3f79d72c0a03a80675a7bbb00be3a45e516424d1ee88efb56f6d5777545ae6e27765c3a8f5e493fc308915638933a1dfee55:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+b01781092b1748459e2e4ec178696627bf4ebafebba774ecf018b79a68aeb84917bf0b84bb79d17b743151144cd66b7b33a4b9e52c76c4e112050ff5385b7f0b:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+c6dbc61dec6eaeac81e3d5f755203c8e220551534a0b2fd105a91889945a638550204f44093dd998c076205dffad703a0e5cd3c7f438a7e634cd59fededb539e:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+eba51acffb4cea31db4b8d87e9bf7dd48fe97b0253ae67aa580f9ac4a9d941f2bea518ee286818cc9f633f2a3b9fb68e594b48cdd6d515bf1d52ba6c85a203a7:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+86221f3ada52037b72224f105d7999231c5e5534d03da9d9c0a12acb68460cd375daf8e24386286f9668f72326dbf99ba094392437d398e95bb8161d717f8991:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+5595e05c13a7ec4dc8f41fb70cb50a71bce17c024ff6de7af618d0cc4e9c32d9570d6d3ea45b86525491030c0d8f2b1836d5778c1ce735c17707df364d054347:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+ce0f4f6aca89590a37fe034dd74dd5fa65eb1cbd0a41508aaddc09351a3cea6d18cb2189c54b700c009f4cbf0521c7ea01be61c5ae09cb54f27bc1b44d658c82:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+7ee80b06a215a3bca970c77cda8761822bc103d44fa4b33f4d07dcb997e36d55298bceae12241b3fa07fa63be5576068da387b8d5859aeab701369848b176d42:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+940a84b6a84d109aab208c024c6ce9647676ba0aaa11f86dbb7018f9fd2220a6d901a9027f9abcf935372727cbf09ebd61a2a2eeb87653e8ecad1bab85dc8327:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021222324:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+2020b78264a82d9f4151141adba8d44bf20c5ec062eee9b595a11f9e84901bf148f298e0c9f8777dcdbc7cc4670aac356cc2ad8ccb1629f16f6a76bcefbee760:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+d1b897b0e075ba68ab572adf9d9c436663e43eb3d8e62d92fc49c9be214e6f27873fe215a65170e6bea902408a25b49506f47babd07cecf7113ec10c5dd31252:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223242526:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+b14d0c62abfa469a357177e594c10c194243ed2025ab8aa5ad2fa41ad318e0ff48cd5e60bec07b13634a711d2326e488a985f31e31153399e73088efc86a5c55:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021222324252627:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+4169c5cc808d2697dc2a82430dc23e3cd356dc70a94566810502b8d655b39abf9e7f902fe717e0389219859e1945df1af6ada42e4ccda55a197b7100a30c30a1:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+258a4edb113d66c839c8b1c91f15f35ade609f11cd7f8681a4045b9fef7b0b24c82cda06a5f2067b368825e3914e53d6948ede92efd6e8387fa2e537239b5bee:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223242526272829:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+79d2d8696d30f30fb34657761171a11e6c3f1e64cbe7bebee159cb95bfaf812b4f411e2f26d9c421dc2c284a3342d823ec293849e42d1e46b0a4ac1e3c86abaa:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+8b9436010dc5dee992ae38aea97f2cd63b946d94fedd2ec9671dcde3bd4ce9564d555c66c15bb2b900df72edb6b891ebcadfeff63c9ea4036a998be7973981e7:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+c8f68e696ed28242bf997f5b3b34959508e42d613810f1e2a435c96ed2ff560c7022f361a9234b9837feee90bf47922ee0fd5f8ddf823718d86d1e16c6090071:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+b02d3eee4860d5868b2c39ce39bfe81011290564dd678c85e8783f29302dfc1399ba95b6b53cd9ebbf400cca1db0ab67e19a325f2d115812d25d00978ad1bca4:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+7693ea73af3ac4dad21ca0d8da85b3118a7d1c6024cfaf557699868217bc0c2f44a199bc6c0edd519798ba05bd5b1b4484346a47c2cadf6bf30b785cc88b2baf:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+a0e5c1c0031c02e48b7f09a5e896ee9aef2f17fc9e18e997d7f6cac7ae316422c2b1e77984e5f3a73cb45deed5d3f84600105e6ee38f2d090c7d0442ea34c46d:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+41daa6adcfdb69f1440c37b596440165c15ada596813e2e22f060fcd551f24dee8e04ba6890387886ceec4a7a0d7fc6b44506392ec3822c0d8c1acfc7d5aebe8:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f30:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+14d4d40d5984d84c5cf7523b7798b254e275a3a8cc0a1bd06ebc0bee726856acc3cbf516ff667cda2058ad5c3412254460a82c92187041363cc77a4dc215e487:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+d0e7a1e2b9a447fee83e2277e9ff8010c2f375ae12fa7aaa8ca5a6317868a26a367a0b69fbc1cf32a55d34eb370663016f3d2110230eba754028a56f54acf57c:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+e771aa8db5a3e043e8178f39a0857ba04a3f18e4aa05743cf8d222b0b095825350ba422f63382a23d92e4149074e816a36c1cd28284d146267940b31f8818ea2:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f30313233:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+feb4fd6f9e87a56bef398b3284d2bda5b5b0e166583a66b61e538457ff0584872c21a32962b9928ffab58de4af2edd4e15d8b35570523207ff4e2a5aa7754caa:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+462f17bf005fb1c1b9e671779f665209ec2873e3e411f98dabf240a1d5ec3f95ce6796b6fc23fe171903b502023467dec7273ff74879b92967a2a43a5a183d33:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+d3338193b64553dbd38d144bea71c5915bb110e2d88180dbc5db364fd6171df317fc7268831b5aef75e4342b2fad8797ba39eddcef80e6ec08159350b1ad696d:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f30313233343536:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+e1590d585a3d39f7cb599abd479070966409a6846d4377acf4471d065d5db94129cc9be92573b05ed226be1e9b7cb0cabe87918589f80dadd4ef5ef25a93d28e:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+f8f3726ac5a26cc80132493a6fedcb0e60760c09cfc84cad178175986819665e76842d7b9fedf76dddebf5d3f56faaad4477587af21606d396ae570d8e719af2:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+30186055c07949948183c850e9a756cc09937e247d9d928e869e20bafc3cd9721719d34e04a0899b92c736084550186886efba2e790d8be6ebf040b209c439a4:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f30313233343536373839:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+f3c4276cb863637712c241c444c5cc1e3554e0fddb174d035819dd83eb700b4ce88df3ab3841ba02085e1a99b4e17310c5341075c0458ba376c95a6818fbb3e2:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+0aa007c4dd9d5832393040a1583c930bca7dc5e77ea53add7e2b3f7c8e231368043520d4a3ef53c969b6bbfd025946f632bd7f765d53c21003b8f983f75e2a6a:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+08e9464720533b23a04ec24f7ae8c103145f765387d738777d3d343477fd1c58db052142cab754ea674378e18766c53542f71970171cc4f81694246b717d7564:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+d37ff7ad297993e7ec21e0f1b4b5ae719cdc83c5db687527f27516cbffa822888a6810ee5c1ca7bfe3321119be1ab7bfa0a502671c8329494df7ad6f522d440f:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+dd9042f6e464dcf86b1262f6accfafbd8cfd902ed3ed89abf78ffa482dbdeeb6969842394c9a1168ae3d481a017842f660002d42447c6b22f7b72f21aae021c9:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+bd965bf31e87d70327536f2a341cebc4768eca275fa05ef98f7f1b71a0351298de006fba73fe6733ed01d75801b4a928e54231b38e38c562b2e33ea1284992fa:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+65676d800617972fbd87e4b9514e1c67402b7a331096d3bfac22f1abb95374abc942f16e9ab0ead33b87c91968a6e509e119ff07787b3ef483e1dcdccf6e3022:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f40:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+939fa189699c5d2c81ddd1ffc1fa207c970b6a3685bb29ce1d3e99d42f2f7442da53e95a72907314f4588399a3ff5b0a92beb3f6be2694f9f86ecf2952d5b41c:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f4041:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+c516541701863f91005f314108ceece3c643e04fc8c42fd2ff556220e616aaa6a48aeb97a84bad74782e8dff96a1a2fa949339d722edcaa32b57067041df88cc:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+987fd6e0d6857c553eaebb3d34970a2c2f6e89a3548f492521722b80a1c21a153892346d2cba6444212d56da9a26e324dccbc0dcde85d4d2ee4399eec5a64e8f:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f40414243:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+ae56deb1c2328d9c4017706bce6e99d41349053ba9d336d677c4c27d9fd50ae6aee17e853154e1f4fe7672346da2eaa31eea53fcf24a22804f11d03da6abfc2b:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f4041424344:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+49d6a608c9bde4491870498572ac31aac3fa40938b38a7818f72383eb040ad39532bc06571e13d767e6945ab77c0bdc3b0284253343f9f6c1244ebf2ff0df866:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+da582ad8c5370b4469af862aa6467a2293b2b28bd80ae0e91f425ad3d47249fdf98825cc86f14028c3308c9804c78bfeeeee461444ce243687e1a50522456a1d:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f40414243444546:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+d5266aa3331194aef852eed86d7b5b2633a0af1c735906f2e13279f14931a9fc3b0eac5ce9245273bd1aa92905abe16278ef7efd47694789a7283b77da3c70f8:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f4041424344454647:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+2962734c28252186a9a1111c732ad4de4506d4b4480916303eb7991d659ccda07a9911914bc75c418ab7a4541757ad054796e26797feaf36e9f6ad43f14b35a4:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+e8b79ec5d06e111bdfafd71e9f5760f00ac8ac5d8bf768f9ff6f08b8f026096b1cc3a4c973333019f1e3553e77da3f98cb9f542e0a90e5f8a940cc58e59844b3:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f40414243444546474849:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+dfb320c44f9d41d1efdcc015f08dd5539e526e39c87d509ae6812a969e5431bf4fa7d91ffd03b981e0d544cf72d7b1c0374f8801482e6dea2ef903877eba675e:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+d88675118fdb55a5fb365ac2af1d217bf526ce1ee9c94b2f0090b2c58a06ca58187d7fe57c7bed9d26fca067b4110eefcd9a0a345de872abe20de368001b0745:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+b893f2fc41f7b0dd6e2f6aa2e0370c0cff7df09e3acfcc0e920b6e6fad0ef747c40668417d342b80d2351e8c175f20897a062e9765e6c67b539b6ba8b9170545:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+6c67ec5697accd235c59b486d7b70baeedcbd4aa64ebd4eef3c7eac189561a726250aec4d48cadcafbbe2ce3c16ce2d691a8cce06e8879556d4483ed7165c063:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+f1aa2b044f8f0c638a3f362e677b5d891d6fd2ab0765f6ee1e4987de057ead357883d9b405b9d609eea1b869d97fb16d9b51017c553f3b93c0a1e0f1296fedcd:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+cbaa259572d4aebfc1917acddc582b9f8dfaa928a198ca7acd0f2aa76a134a90252e6298a65b08186a350d5b7626699f8cb721a3ea5921b753ae3a2dce24ba3a:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+fa1549c9796cd4d303dcf452c1fbd5744fd9b9b47003d920b92de34839d07ef2a29ded68f6fc9e6c45e071a2e48bd50c5084e96b657dd0404045a1ddefe282ed:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f50:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+5cf2ac897ab444dcb5c8d87c495dbdb34e1838b6b629427caa51702ad0f9688525f13bec503a3c3a2c80a65e0b5715e8afab00ffa56ec455a49a1ad30aa24fcd:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f5051:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+9aaf80207bace17bb7ab145757d5696bde32406ef22b44292ef65d4519c3bb2ad41a59b62cc3e94b6fa96d32a7faadae28af7d35097219aa3fd8cda31e40c275:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+af88b163402c86745cb650c2988fb95211b94b03ef290eed9662034241fd51cf398f8073e369354c43eae1052f9b63b08191caa138aa54fea889cc7024236897:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f50515253:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+48fa7d64e1ceee27b9864db5ada4b53d00c9bc7626555813d3cd6730ab3cc06ff342d727905e33171bde6e8476e77fb1720861e94b73a2c538d254746285f430:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f5051525354:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+0e6fd97a85e904f87bfe85bbeb34f69e1f18105cf4ed4f87aec36c6e8b5f68bd2a6f3dc8a9ecb2b61db4eedb6b2ea10bf9cb0251fb0f8b344abf7f366b6de5ab:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+06622da5787176287fdc8fed440bad187d830099c94e6d04c8e9c954cda70c8bb9e1fc4a6d0baa831b9b78ef6648681a4867a11da93ee36e5e6a37d87fc63f6f:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f50515253545556:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+1da6772b58fabf9c61f68d412c82f182c0236d7d575ef0b58dd22458d643cd1dfc93b03871c316d8430d312995d4197f0874c99172ba004a01ee295abac24e46:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f5051525354555657:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+3cd2d9320b7b1d5fb9aab951a76023fa667be14a9124e394513918a3f44096ae4904ba0ffc150b63bc7ab1eeb9a6e257e5c8f000a70394a5afd842715de15f29:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+04cdc14f7434e0b4be70cb41db4c779a88eaef6accebcb41f2d42fffe7f32a8e281b5c103a27021d0d08362250753cdf70292195a53a48728ceb5844c2d98bab:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f50515253545556575859:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+9071b7a8a075d0095b8fb3ae5113785735ab98e2b52faf91d5b89e44aac5b5d4ebbf91223b0ff4c71905da55342e64655d6ef8c89a4768c3f93a6dc0366b5bc8:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+ebb30240dd96c7bc8d0abe49aa4edcbb4afdc51ff9aaf720d3f9e7fbb0f9c6d6571350501769fc4ebd0b2141247ff400d4fd4be414edf37757bb90a32ac5c65a:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+8532c58bf3c8015d9d1cbe00eef1f5082f8f3632fbe9f1ed4f9dfb1fa79e8283066d77c44c4af943d76b300364aecbd0648c8a8939bd204123f4b56260422dec:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+fe9846d64f7c7708696f840e2d76cb4408b6595c2f81ec6a28a7f2f20cb88cfe6ac0b9e9b8244f08bd7095c350c1d0842f64fb01bb7f532dfcd47371b0aeeb79:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+28f17ea6fb6c42092dc264257e29746321fb5bdaea9873c2a7fa9d8f53818e899e161bc77dfe8090afd82bf2266c5c1bc930a8d1547624439e662ef695f26f24:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+ec6b7d7f030d4850acae3cb615c21dd25206d63e84d1db8d957370737ba0e98467ea0ce274c66199901eaec18a08525715f53bfdb0aacb613d342ebdceeddc3b:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+b403d3691c03b0d3418df327d5860d34bbfcc4519bfbce36bf33b208385fadb9186bc78a76c489d89fd57e7dc75412d23bcd1dae8470ce9274754bb8585b13c5:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f60:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+31fc79738b8772b3f55cd8178813b3b52d0db5a419d30ba9495c4b9da0219fac6df8e7c23a811551a62b827f256ecdb8124ac8a6792ccfecc3b3012722e94463:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f6061:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+bb2039ec287091bcc9642fc90049e73732e02e577e2862b32216ae9bedcd730c4c284ef3968c368b7d37584f97bd4b4dc6ef6127acfe2e6ae2509124e66c8af4:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+f53d68d13f45edfcb9bd415e2831e938350d5380d3432278fc1c0c381fcb7c65c82dafe051d8c8b0d44e0974a0e59ec7bf7ed0459f86e96f329fc79752510fd3:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f60616263:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+8d568c7984f0ecdf7640fbc483b5d8c9f86634f6f43291841b309a350ab9c1137d24066b09da9944bac54d5bb6580d836047aac74ab724b887ebf93d4b32eca9:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f6061626364:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+c0b65ce5a96ff774c456cac3b5f2c4cd359b4ff53ef93a3da0778be4900d1e8da1601e769e8f1b02d2a2f8c5b9fa10b44f1c186985468feeb008730283a6657d:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+4900bba6f5fb103ece8ec96ada13a5c3c85488e05551da6b6b33d988e611ec0fe2e3c2aa48ea6ae8986a3a231b223c5d27cec2eadde91ce07981ee652862d1e4:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f60616263646566:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+c7f5c37c7285f927f76443414d4357ff789647d7a005a5a787e03c346b57f49f21b64fa9cf4b7e45573e23049017567121a9c3d4b2b73ec5e9413577525db45a:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f6061626364656667:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+ec7096330736fdb2d64b5653e7475da746c23a4613a82687a28062d3236364284ac01720ffb406cfe265c0df626a188c9e5963ace5d3d5bb363e32c38c2190a6:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+82e744c75f4649ec52b80771a77d475a3bc091989556960e276a5f9ead92a03f718742cdcfeaee5cb85c44af198adc43a4a428f5f0c2ddb0be36059f06d7df73:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f60616263646566676869:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+2834b7a7170f1f5b68559ab78c1050ec21c919740b784a9072f6e5d69f828d70c919c5039fb148e39e2c8a52118378b064ca8d5001cd10a5478387b966715ed6:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+16b4ada883f72f853bb7ef253efcab0c3e2161687ad61543a0d2824f91c1f81347d86be709b16996e17f2dd486927b0288ad38d13063c4a9672c39397d3789b6:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+78d048f3a69d8b54ae0ed63a573ae350d89f7c6cf1f3688930de899afa037697629b314e5cd303aa62feea72a25bf42b304b6c6bcb27fae21c16d925e1fbdac3:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+0f746a48749287ada77a82961f05a4da4abdb7d77b1220f836d09ec814359c0ec0239b8c7b9ff9e02f569d1b301ef67c4612d1de4f730f81c12c40cc063c5caa:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+f0fc859d3bd195fbdc2d591e4cdac15179ec0f1dc821c11df1f0c1d26e6260aaa65b79fafacafd7d3ad61e600f250905f5878c87452897647a35b995bcadc3a3:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+2620f687e8625f6a412460b42e2cef67634208ce10a0cbd4dff7044a41b7880077e9f8dc3b8d1216d3376a21e015b58fb279b521d83f9388c7382c8505590b9b:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+227e3aed8d2cb10b918fcb04f9de3e6d0a57e08476d93759cd7b2ed54a1cbf0239c528fb04bbf288253e601d3bc38b21794afef90b17094a182cac557745e75f:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f70:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+1a929901b09c25f27d6b35be7b2f1c4745131fdebca7f3e2451926720434e0db6e74fd693ad29b777dc3355c592a361c4873b01133a57c2e3b7075cbdb86f4fc:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f7071:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+5fd7968bc2fe34f220b5e3dc5af9571742d73b7d60819f2888b629072b96a9d8ab2d91b82d0a9aaba61bbd39958132fcc4257023d1eca591b3054e2dc81c8200:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+dfcce8cf32870cc6a503eadafc87fd6f78918b9b4d0737db6810be996b5497e7e5cc80e312f61e71ff3e9624436073156403f735f56b0b01845c18f6caf772e6:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f70717273:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+02f7ef3a9ce0fff960f67032b296efca3061f4934d690749f2d01c35c81c14f39a67fa350bc8a0359bf1724bffc3bca6d7c7bba4791fd522a3ad353c02ec5aa8:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f7071727374:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+64be5c6aba65d594844ae78bb022e5bebe127fd6b6ffa5a13703855ab63b624dcd1a363f99203f632ec386f3ea767fc992e8ed9686586aa27555a8599d5b808f:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+f78585505c4eaa54a8b5be70a61e735e0ff97af944ddb3001e35d86c4e2199d976104b6ae31750a36a726ed285064f5981b503889fef822fcdc2898dddb7889a:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f70717273747576:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+e4b5566033869572edfd87479a5bb73c80e8759b91232879d96b1dda36c012076ee5a2ed7ae2de63ef8406a06aea82c188031b560beafb583fb3de9e57952a7e:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f7071727374757677:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+e1b3e7ed867f6c9484a2a97f7715f25e25294e992e41f6a7c161ffc2adc6daaeb7113102d5e6090287fe6ad94ce5d6b739c6ca240b05c76fb73f25dd024bf935:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+85fd085fdc12a080983df07bd7012b0d402a0f4043fcb2775adf0bad174f9b08d1676e476985785c0a5dcc41dbff6d95ef4d66a3fbdc4a74b82ba52da0512b74:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f70717273747576777879:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+aed8fa764b0fbff821e05233d2f7b0900ec44d826f95e93c343c1bc3ba5a24374b1d616e7e7aba453a0ada5e4fab5382409e0d42ce9c2bc7fb39a99c340c20f0:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+7ba3b2e297233522eeb343bd3ebcfd835a04007735e87f0ca300cbee6d416565162171581e4020ff4cf176450f1291ea2285cb9ebffe4c56660627685145051c:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+de748bcf89ec88084721e16b85f30adb1a6134d664b5843569babc5bbd1a15ca9b61803c901a4fef32965a1749c9f3a4e243e173939dc5a8dc495c671ab52145:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+aaf4d2bdf200a919706d9842dce16c98140d34bc433df320aba9bd429e549aa7a3397652a4d768277786cf993cde2338673ed2e6b66c961fefb82cd20c93338f:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+c408218968b788bf864f0997e6bc4c3dba68b276e2125a4843296052ff93bf5767b8cdce7131f0876430c1165fec6c4f47adaa4fd8bcfacef463b5d3d0fa61a0:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+76d2d819c92bce55fa8e092ab1bf9b9eab237a25267986cacf2b8ee14d214d730dc9a5aa2d7b596e86a1fd8fa0804c77402d2fcd45083688b218b1cdfa0dcbcb:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+72065ee4dd91c2d8509fa1fc28a37c7fc9fa7d5b3f8ad3d0d7a25626b57b1b44788d4caf806290425f9890a3a2a35a905ab4b37acfd0da6e4517b2525c9651e4:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f80:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+64475dfe7600d7171bea0b394e27c9b00d8e74dd1e416a79473682ad3dfdbb706631558055cfc8a40e07bd015a4540dcdea15883cbbf31412df1de1cd4152b91:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f8081:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+12cd1674a4488a5d7c2b3160d2e2c4b58371bedad793418d6f19c6ee385d70b3e06739369d4df910edb0b0a54cbff43d54544cd37ab3a06cfa0a3ddac8b66c89:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+60756966479dedc6dd4bcff8ea7d1d4ce4d4af2e7b097e32e3763518441147cc12b3c0ee6d2ecabf1198cec92e86a3616fba4f4e872f5825330adbb4c1dee444:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f80818283:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+a7803bcb71bc1d0f4383dde1e0612e04f872b715ad30815c2249cf34abb8b024915cb2fc9f4e7cc4c8cfd45be2d5a91eab0941c7d270e2da4ca4a9f7ac68663a:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f8081828384:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+b84ef6a7229a34a750d9a98ee2529871816b87fbe3bc45b45fa5ae82d5141540211165c3c5d7a7476ba5a4aa06d66476f0d9dc49a3f1ee72c3acabd498967414:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+fae4b6d8efc3f8c8e64d001dabec3a21f544e82714745251b2b4b393f2f43e0da3d403c64db95a2cb6e23ebb7b9e94cdd5ddac54f07c4a61bd3cb10aa6f93b49:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f80818283848586:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+34f7286605a122369540141ded79b8957255da2d4155abbf5a8dbb89c8eb7ede8eeef1daa46dc29d751d045dc3b1d658bb64b80ff8589eddb3824b13da235a6b:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f8081828384858687:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+3b3b48434be27b9eababba43bf6b35f14b30f6a88dc2e750c358470d6b3aa3c18e47db4017fa55106d8252f016371a00f5f8b070b74ba5f23cffc5511c9f09f0:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+ba289ebd6562c48c3e10a8ad6ce02e73433d1e93d7c9279d4d60a7e879ee11f441a000f48ed9f7c4ed87a45136d7dccdca482109c78a51062b3ba4044ada2469:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f80818283848586878889:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+022939e2386c5a37049856c850a2bb10a13dfea4212b4c732a8840a9ffa5faf54875c5448816b2785a007da8a8d2bc7d71a54e4e6571f10b600cbdb25d13ede3:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+e6fec19d89ce8717b1a087024670fe026f6c7cbda11caef959bb2d351bf856f8055d1c0ebdaaa9d1b17886fc2c562b5e99642fc064710c0d3488a02b5ed7f6fd:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+94c96f02a8f576aca32ba61c2b206f907285d9299b83ac175c209a8d43d53bfe683dd1d83e7549cb906c28f59ab7c46f8751366a28c39dd5fe2693c9019666c8:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+31a0cd215ebd2cb61de5b9edc91e6195e31c59a5648d5c9f737e125b2605708f2e325ab3381c8dce1a3e958886f1ecdc60318f882cfe20a24191352e617b0f21:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+91ab504a522dce78779f4c6c6ba2e6b6db5565c76d3e7e7c920caf7f757ef9db7c8fcf10e57f03379ea9bf75eb59895d96e149800b6aae01db778bb90afbc989:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+d85cabc6bd5b1a01a5afd8c6734740da9fd1c1acc6db29bfc8a2e5b668b028b6b3154bfb8703fa3180251d589ad38040ceb707c4bad1b5343cb426b61eaa49c1:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+d62efbec2ca9c1f8bd66ce8b3f6a898cb3f7566ba6568c618ad1feb2b65b76c3ce1dd20f7395372faf28427f61c9278049cf0140df434f5633048c86b81e0399:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f90:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+7c8fdc6175439e2c3db15bafa7fb06143a6a23bc90f449e79deef73c3d492a671715c193b6fea9f036050b946069856b897e08c00768f5ee5ddcf70b7cd6d0e0:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f9091:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+58602ee7468e6bc9df21bd51b23c005f72d6cb013f0a1b48cbec5eca299299f97f09f54a9a01483eaeb315a6478bad37ba47ca1347c7c8fc9e6695592c91d723:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+27f5b79ed256b050993d793496edf4807c1d85a7b0a67c9c4fa99860750b0ae66989670a8ffd7856d7ce411599e58c4d77b232a62bef64d15275be46a68235ff:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f90919293:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+3957a976b9f1887bf004a8dca942c92d2b37ea52600f25e0c9bc5707d0279c00c6e85a839b0d2d8eb59c51d94788ebe62474a791cadf52cccf20f5070b6573fc:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f9091929394:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+eaa2376d55380bf772ecca9cb0aa4668c95c707162fa86d518c8ce0ca9bf7362b9f2a0adc3ff59922df921b94567e81e452f6c1a07fc817cebe99604b3505d38:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+c1e2c78b6b2734e2480ec550434cb5d613111adcc21d475545c3b1b7e6ff12444476e5c055132e2229dc0f807044bb919b1a5662dd38a9ee65e243a3911aed1a:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f90919293949596:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+8ab48713389dd0fcf9f965d3ce66b1e559a1f8c58741d67683cd971354f452e62d0207a65e436c5d5d8f8ee71c6abfe50e669004c302b31a7ea8311d4a916051:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f9091929394959697:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+24ce0addaa4c65038bd1b1c0f1452a0b128777aabc94a29df2fd6c7e2f85f8ab9ac7eff516b0e0a825c84a24cfe492eaad0a6308e46dd42fe8333ab971bb30ca:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+5154f929ee03045b6b0c0004fa778edee1d139893267cc84825ad7b36c63de32798e4a166d24686561354f63b00709a1364b3c241de3febf0754045897467cd4:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f90919293949596979899:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+e74e907920fd87bd5ad636dd11085e50ee70459c443e1ce5809af2bc2eba39f9e6d7128e0e3712c316da06f4705d78a4838e28121d4344a2c79c5e0db307a677:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+bf91a22334bac20f3fd80663b3cd06c4e8802f30e6b59f90d3035cc9798a217ed5a31abbda7fa6842827bdf2a7a1c21f6fcfccbb54c6c52926f32da816269be1:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+d9d5c74be5121b0bd742f26bffb8c89f89171f3f934913492b0903c271bbe2b3395ef259669bef43b57f7fcc3027db01823f6baee66e4f9fead4d6726c741fce:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+50c8b8cf34cd879f80e2faab3230b0c0e1cc3e9dcadeb1b9d97ab923415dd9a1fe38addd5c11756c67990b256e95ad6d8f9fedce10bf1c90679cde0ecf1be347:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+0a386e7cd5dd9b77a035e09fe6fee2c8ce61b5383c87ea43205059c5e4cd4f4408319bb0a82360f6a58e6c9ce3f487c446063bf813bc6ba535e17fc1826cfc91:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+1f1459cb6b61cbac5f0efe8fc487538f42548987fcd56221cfa7beb22504769e792c45adfb1d6b3d60d7b749c8a75b0bdf14e8ea721b95dca538ca6e25711209:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+e58b3836b7d8fedbb50ca5725c6571e74c0785e97821dab8b6298c10e4c079d4a6cdf22f0fedb55032925c16748115f01a105e77e00cee3d07924dc0d8f90659:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+b929cc6505f020158672deda56d0db081a2ee34c00c1100029bdf8ea98034fa4bf3e8655ec697fe36f40553c5bb46801644a627d3342f4fc92b61f03290fb381:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+72d353994b49d3e03153929a1e4d4f188ee58ab9e72ee8e512f29bc773913819ce057ddd7002c0433ee0a16114e3d156dd2c4a7e80ee53378b8670f23e33ef56:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+c70ef9bfd775d408176737a0736d68517ce1aaad7e81a93c8c1ed967ea214f56c8a377b1763e676615b60f3988241eae6eab9685a5124929d28188f29eab06f7:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+c230f0802679cb33822ef8b3b21bf7a9a28942092901d7dac3760300831026cf354c9232df3e084d9903130c601f63c1f4a4a4b8106e468cd443bbe5a734f45f:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+6f43094cafb5ebf1f7a4937ec50f56a4c9da303cbb55ac1f27f1f1976cd96beda9464f0e7b9c54620b8a9fba983164b8be3578425a024f5fe199c36356b88972:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+3745273f4c38225db2337381871a0c6aafd3af9b018c88aa02025850a5dc3a42a1a3e03e56cbf1b0876d63a441f1d2856a39b8801eb5af325201c415d65e97fe:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+c50c44cca3ec3edaae779a7e179450ebdda2f97067c690aa6c5a4ac7c30139bb27c0df4db3220e63cb110d64f37ffe078db72653e2daacf93ae3f0a2d1a7eb2e:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+8aef263e385cbc61e19b28914243262af5afe8726af3ce39a79c27028cf3ecd3f8d2dfd9cfc9ad91b58f6f20778fd5f02894a3d91c7d57d1e4b866a7f364b6be:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+28696141de6e2d9bcb3235578a66166c1448d3e905a1b482d423be4bc5369bc8c74dae0acc9cc123e1d8ddce9f97917e8c019c552da32d39d2219b9abf0fa8c8:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+2fb9eb2085830181903a9dafe3db428ee15be7662224efd643371fb25646aee716e531eca69b2bdc8233f1a8081fa43da1500302975a77f42fa592136710e9dc:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aa:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+66f9a7143f7a3314a669bf2e24bbb35014261d639f495b6c9c1f104fe8e320aca60d4550d69d52edbd5a3cdeb4014ae65b1d87aa770b69ae5c15f4330b0b0ad8:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaab:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+f4c4dd1d594c3565e3e25ca43dad82f62abea4835ed4cd811bcd975e46279828d44d4c62c3679f1b7f7b9dd4571d7b49557347b8c5460cbdc1bef690fb2a08c0:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabac:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+8f1dc9649c3a84551f8f6e91cac68242a43b1f8f328ee92280257387fa7559aa6db12e4aeadc2d26099178749c6864b357f3f83b2fb3efa8d2a8db056bed6bcc:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacad:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+3139c1a7f97afd1675d460ebbc07f2728aa150df849624511ee04b743ba0a833092f18c12dc91b4dd243f333402f59fe28abdbbbae301e7b659c7a26d5c0f979:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadae:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+06f94a2996158a819fe34c40de3cf0379fd9fb85b3e363ba3926a0e7d960e3f4c2e0c70c7ce0ccb2a64fc29869f6e7ab12bd4d3f14fce943279027e785fb5c29:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+c29c399ef3eee8961e87565c1ce263925fc3d0ce267d13e48dd9e732ee67b0f69fad56401b0f10fcaac119201046cca28c5b14abdea3212ae65562f7f138db3d:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+4cec4c9df52eef05c3f6faaa9791bc7445937183224ecc37a1e58d0132d35617531d7e795f52af7b1eb9d147de1292d345fe341823f8e6bc1e5badca5c656108:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+898bfbae93b3e18d00697eab7d9704fa36ec339d076131cefdf30edbe8d9cc81c3a80b129659b163a323bab9793d4feed92d54dae966c77529764a09be88db45:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+ee9bd0469d3aaf4f14035be48a2c3b84d9b4b1fff1d945e1f1c1d38980a951be197b25fe22c731f20aeacc930ba9c4a1f4762227617ad350fdabb4e80273a0f4:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+3d4d3113300581cd96acbf091c3d0f3c310138cd6979e6026cde623e2dd1b24d4a8638bed1073344783ad0649cc6305ccec04beb49f31c633088a99b65130267:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+95c0591ad91f921ac7be6d9ce37e0663ed8011c1cfd6d0162a5572e94368bac02024485e6a39854aa46fe38e97d6c6b1947cd272d86b06bb5b2f78b9b68d559d:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+227b79ded368153bf46c0a3ca978bfdbef31f3024a5665842468490b0ff748ae04e7832ed4c9f49de9b1706709d623e5c8c15e3caecae8d5e433430ff72f20eb:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+5d34f3952f0105eef88ae8b64c6ce95ebfade0e02c69b08762a8712d2e4911ad3f941fc4034dc9b2e479fdbcd279b902faf5d838bb2e0c6495d372b5b7029813:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+7f939bf8353abce49e77f14f3750af20b7b03902e1a1e7fb6aaf76d0259cd401a83190f15640e74f3e6c5a90e839c7821f6474757f75c7bf9002084ddc7a62dc:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+062b61a2f9a33a71d7d0a06119644c70b0716a504de7e5e1be49bd7b86e7ed6817714f9f0fc313d06129597e9a2235ec8521de36f7290a90ccfc1ffa6d0aee29:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+f29e01eeae64311eb7f1c6422f946bf7bea36379523e7b2bbaba7d1d34a22d5ea5f1c5a09d5ce1fe682cced9a4798d1a05b46cd72dff5c1b355440b2a2d476bc:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9ba:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+ec38cd3bbab3ef35d7cb6d5c914298351d8a9dc97fcee051a8a02f58e3ed6184d0b7810a5615411ab1b95209c3c810114fdeb22452084e77f3f847c6dbaafe16:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babb:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+c2aef5e0ca43e82641565b8cb943aa8ba53550caef793b6532fafad94b816082f0113a3ea2f63608ab40437ecc0f0229cb8fa224dcf1c478a67d9b64162b92d1:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbc:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+15f534efff7105cd1c254d074e27d5898b89313b7d366dc2d7d87113fa7d53aae13f6dba487ad8103d5e854c91fdb6e1e74b2ef6d1431769c30767dde067a35c:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbd:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+89acbca0b169897a0a2714c2df8c95b5b79cb69390142b7d6018bb3e3076b099b79a964152a9d912b1b86412b7e372e9cecad7f25d4cbab8a317be36492a67d7:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbe:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+e3c0739190ed849c9c962fd9dbb55e207e624fcac1eb417691515499eea8d8267b7e8f1287a63633af5011fde8c4ddf55bfdf722edf88831414f2cfaed59cb9a:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebf:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+8d6cf87c08380d2d1506eee46fd4222d21d8c04e585fbfd08269c98f702833a156326a0724656400ee09351d57b440175e2a5de93cc5f80db6daf83576cf75fa:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+da24bede383666d563eeed37f6319baf20d5c75d1635a6ba5ef4cfa1ac95487e96f8c08af600aab87c986ebad49fc70a58b4890b9c876e091016daf49e1d322e:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+f9d1d1b1e87ea7ae753a029750cc1cf3d0157d41805e245c5617bb934e732f0ae3180b78e05bfe76c7c3051e3e3ac78b9b50c05142657e1e03215d6ec7bfd0fc:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+11b7bc1668032048aa43343de476395e814bbbc223678db951a1b03a021efac948cfbe215f97fe9a72a2f6bc039e3956bfa417c1a9f10d6d7ba5d3d32ff323e5:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+b8d9000e4fc2b066edb91afee8e7eb0f24e3a201db8b6793c0608581e628ed0bcc4e5aa6787992a4bcc44e288093e63ee83abd0bc3ec6d0934a674a4da13838a:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+ce325e294f9b6719d6b61278276ae06a2564c03bb0b783fafe785bdf89c7d5acd83e78756d301b445699024eaeb77b54d477336ec2a4f332f2b3f88765ddb0c3:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+29acc30e9603ae2fccf90bf97e6cc463ebe28c1b2f9b4b765e70537c25c702a29dcbfbf14c99c54345ba2b51f17b77b5f15db92bbad8fa95c471f5d070a137cc:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+3379cbaae562a87b4c0425550ffdd6bfe1203f0d666cc7ea095be407a5dfe61ee91441cd5154b3e53b4f5fb31ad4c7a9ad5c7af4ae679aa51a54003a54ca6b2d:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+3095a349d245708c7cf550118703d7302c27b60af5d4e67fc978f8a4e60953c7a04f92fcf41aee64321ccb707a895851552b1e37b00bc5e6b72fa5bcef9e3fff:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+07262d738b09321f4dbccec4bb26f48cb0f0ed246ce0b31b9a6e7bc683049f1f3e5545f28ce932dd985c5ab0f43bd6de0770560af329065ed2e49d34624c2cbb:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+b6405eca8ee3316c87061cc6ec18dba53e6c250c63ba1f3bae9e55dd3498036af08cd272aa24d713c6020d77ab2f3919af1a32f307420618ab97e73953994fb4:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9ca:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+7ee682f63148ee45f6e5315da81e5c6e557c2c34641fc509c7a5701088c38a74756168e2cd8d351e88fd1a451f360a01f5b2580f9b5a2e8cfc138f3dd59a3ffc:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacb:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+1d263c179d6b268f6fa016f3a4f29e943891125ed8593c81256059f5a7b44af2dcb2030d175c00e62ecaf7ee96682aa07ab20a611024a28532b1c25b86657902:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcc:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+106d132cbdb4cd2597812846e2bc1bf732fec5f0a5f65dbb39ec4e6dc64ab2ce6d24630d0f15a805c3540025d84afa98e36703c3dbee713e72dde8465bc1be7e:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccd:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+0e79968226650667a8d862ea8da4891af56a4e3a8b6d1750e394f0dea76d640d85077bcec2cc86886e506751b4f6a5838f7f0b5fef765d9dc90dcdcbaf079f08:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdce:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+521156a82ab0c4e566e5844d5e31ad9aaf144bbd5a464fdca34dbd5717e8ff711d3ffebbfa085d67fe996a34f6d3e4e60b1396bf4b1610c263bdbb834d560816:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecf:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+1aba88befc55bc25efbce02db8b9933e46f57661baeabeb21cc2574d2a518a3cba5dc5a38e49713440b25f9c744e75f6b85c9d8f4681f676160f6105357b8406:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+5a9949fcb2c473cda968ac1b5d08566dc2d816d960f57e63b898fa701cf8ebd3f59b124d95bfbbedc5f1cf0e17d5eaed0c02c50b69d8a402cabcca4433b51fd4:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+b0cead09807c672af2eb2b0f06dde46cf5370e15a4096b1a7d7cbb36ec31c205fbefca00b7a4162fa89fb4fb3eb78d79770c23f44e7206664ce3cd931c291e5d:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+bb6664931ec97044e45b2ae420ae1c551a8874bc937d08e969399c3964ebdba8346cdd5d09caafe4c28ba7ec788191ceca65ddd6f95f18583e040d0f30d0364d:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+65bc770a5faa3792369803683e844b0be7ee96f29f6d6a35568006bd5590f9a4ef639b7a8061c7b0424b66b60ac34af3119905f33a9d8c3ae18382ca9b689900:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+ea9b4dca333336aaf839a45c6eaa48b8cb4c7ddabffea4f643d6357ea6628a480a5b45f2b052c1b07d1fedca918b6f1139d80f74c24510dcbaa4be70eacc1b06:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+e6342fb4a780ad975d0e24bce149989b91d360557e87994f6b457b895575cc02d0c15bad3ce7577f4c63927ff13f3e381ff7e72bdbe745324844a9d27e3f1c01:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+3e209c9b33e8e461178ab46b1c64b49a07fb745f1c8bc95fbfb94c6b87c69516651b264ef980937fad41238b91ddc011a5dd777c7efd4494b4b6ecd3a9c22ac0:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+fd6a3d5b1875d80486d6e69694a56dbb04a99a4d051f15db2689776ba1c4882e6d462a603b7015dc9f4b7450f05394303b8652cfb404a266962c41bae6e18a94:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+951e27517e6bad9e4195fc8671dee3e7e9be69cee1422cb9fecfce0dba875f7b310b93ee3a3d558f941f635f668ff832d2c1d033c5e2f0997e4c66f147344e02:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+8eba2f874f1ae84041903c7c4253c82292530fc8509550bfdc34c95c7e2889d5650b0ad8cb988e5c4894cb87fbfbb19612ea93ccc4c5cad17158b9763464b492:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9da:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+16f712eaa1b7c6354719a8e7dbdfaf55e4063a4d277d947550019b38dfb564830911057d50506136e2394c3b28945cc964967d54e3000c2181626cfb9b73efd2:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadb:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+c39639e7d5c7fb8cdd0fd3e6a52096039437122f21c78f1679cea9d78a734c56ecbeb28654b4f18e342c331f6f7229ec4b4bc281b2d80a6eb50043f31796c88c:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdc:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+72d081af99f8a173dcc9a0ac4eb3557405639a29084b54a40172912a2f8a395129d5536f0918e902f9e8fa6000995f4168ddc5f893011be6a0dbc9b8a1a3f5bb:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdd:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+c11aa81e5efd24d5fc27ee586cfd8847fbb0e27601ccece5ecca0198e3c7765393bb74457c7e7a27eb9170350e1fb53857177506be3e762cc0f14d8c3afe9077:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcddde:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+c28f2150b452e6c0c424bcde6f8d72007f9310fed7f2f87de0dbb64f4479d6c1441ba66f44b2accee61609177ed340128b407ecec7c64bbe50d63d22d8627727:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedf:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+f63d88122877ec30b8c8b00d22e89000a966426112bd44166e2f525b769ccbe9b286d437a0129130dde1a86c43e04bedb594e671d98283afe64ce331de9828fd:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+348b0532880b88a6614a8d7408c3f913357fbb60e995c60205be9139e74998aede7f4581e42f6b52698f7fa1219708c14498067fd1e09502de83a77dd281150c:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+5133dc8bef725359dff59792d85eaf75b7e1dcd1978b01c35b1b85fcebc63388ad99a17b6346a217dc1a9622ebd122ecf6913c4d31a6b52a695b86af00d741a0:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+2753c4c0e98ecad806e88780ec27fccd0f5c1ab547f9e4bf1659d192c23aa2cc971b58b6802580baef8adc3b776ef7086b2545c2987f348ee3719cdef258c403:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+b1663573ce4b9d8caefc865012f3e39714b9898a5da6ce17c25a6a47931a9ddb9bbe98adaa553beed436e89578455416c2a52a525cf2862b8d1d49a2531b7391:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+64f58bd6bfc856f5e873b2a2956ea0eda0d6db0da39c8c7fc67c9f9feefcff3072cdf9e6ea37f69a44f0c61aa0da3693c2db5b54960c0281a088151db42b11e8:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+0764c7be28125d9065c4b98a69d60aede703547c66a12e17e1c618994132f5ef82482c1e3fe3146cc65376cc109f0138ed9a80e49f1f3c7d610d2f2432f20605:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+f748784398a2ff03ebeb07e155e66116a839741a336e32da71ec696001f0ad1b25cd48c69cfca7265eca1dd71904a0ce748ac4124f3571076dfa7116a9cf00e9:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+3f0dbc0186bceb6b785ba78d2a2a013c910be157bdaffae81bb6663b1a73722f7f1228795f3ecada87cf6ef0078474af73f31eca0cc200ed975b6893f761cb6d:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+d4762cd4599876ca75b2b8fe249944dbd27ace741fdab93616cbc6e425460feb51d4e7adcc38180e7fc47c89024a7f56191adb878dfde4ead62223f5a2610efe:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+cd36b3d5b4c91b90fcbba79513cfee1907d8645a162afd0cd4cf4192d4a5f4c892183a8eacdb2b6b6a9d9aa8c11ac1b261b380dbee24ca468f1bfd043c58eefe:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9ea:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+98593452281661a53c48a9d8cd790826c1a1ce567738053d0bee4a91a3d5bd92eefdbabebe3204f2031ca5f781bda99ef5d8ae56e5b04a9e1ecd21b0eb05d3e1:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaeb:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+771f57dd2775ccdab55921d3e8e30ccf484d61fe1c1b9c2ae819d0fb2a12fab9be70c4a7a138da84e8280435daade5bbe66af0836a154f817fb17f3397e725a3:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebec:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+c60897c6f828e21f16fbb5f15b323f87b6c8955eabf1d38061f707f608abdd993fac3070633e286cf8339ce295dd352df4b4b40b2f29da1dd50b3a05d079e6bb:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebeced:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+8210cd2c2d3b135c2cf07fa0d1433cd771f325d075c6469d9c7f1ba0943cd4ab09808cabf4acb9ce5bb88b498929b4b847f681ad2c490d042db2aec94214b06b:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedee:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+1d4edfffd8fd80f7e4107840fa3aa31e32598491e4af7013c197a65b7f36dd3ac4b478456111cd4309d9243510782fa31b7c4c95fa951520d020eb7e5c36e4ef:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeef:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+af8e6e91fab46ce4873e1a50a8ef448cc29121f7f74deef34a71ef89cc00d9274bc6c2454bbb3230d8b2ec94c62b1dec85f3593bfa30ea6f7a44d7c09465a253:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+29fd384ed4906f2d13aa9fe7af905990938bed807f1832454a372ab412eea1f5625a1fcc9ac8343b7c67c5aba6e0b1cc4644654913692c6b39eb9187ceacd3ec:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+a268c7885d9874a51c44dffed8ea53e94f78456e0b2ed99ff5a3924760813826d960a15edbedbb5de5226ba4b074e71b05c55b9756bb79e55c02754c2c7b6c8a:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+0cf8545488d56a86817cd7ecb10f7116b7ea530a45b6ea497b6c72c997e09e3d0da8698f46bb006fc977c2cd3d1177463ac9057fdd1662c85d0c126443c10473:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+b39614268fdd8781515e2cfebf89b4d5402bab10c226e6344e6b9ae000fb0d6c79cb2f3ec80e80eaeb1980d2f8698916bd2e9f747236655116649cd3ca23a837:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+74bef092fc6f1e5dba3663a3fb003b2a5ba257496536d99f62b9d73f8f9eb3ce9ff3eec709eb883655ec9eb896b9128f2afc89cf7d1ab58a72f4a3bf034d2b4a:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+3a988d38d75611f3ef38b8774980b33e573b6c57bee0469ba5eed9b44f29945e7347967fba2c162e1c3be7f310f2f75ee2381e7bfd6b3f0baea8d95dfb1dafb1:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+58aedfce6f67ddc85a28c992f1c0bd0969f041e66f1ee88020a125cbfcfebcd61709c9c4eba192c15e69f020d462486019fa8dea0cd7a42921a19d2fe546d43d:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+9347bd291473e6b4e368437b8e561e065f649a6d8ada479ad09b1999a8f26b91cf6120fd3bfe014e83f23acfa4c0ad7b3712b2c3c0733270663112ccd9285cd9:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+b32163e7c5dbb5f51fdc11d2eac875efbbcb7e7699090a7e7ff8a8d50795af5d74d9ff98543ef8cdf89ac13d0485278756e0ef00c817745661e1d59fe38e7537:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+1085d78307b1c4b008c57a2e7e5b234658a0a82e4ff1e4aaac72b312fda0fe27d233bc5b10e9cc17fdc7697b540c7d95eb215a19a1a0e20e1abfa126efd568c7:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fa:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+4e5c734c7dde011d83eac2b7347b373594f92d7091b9ca34cb9c6f39bdf5a8d2f134379e16d822f6522170ccf2ddd55c84b9e6c64fc927ac4cf8dfb2a17701f2:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafb:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+695d83bd990a1117b3d0ce06cc888027d12a054c2677fd82f0d4fbfc93575523e7991a5e35a3752e9b70ce62992e268a877744cdd435f5f130869c9a2074b338:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfc:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+a6213743568e3b3158b9184301f3690847554c68457cb40fc9a4b8cfd8d4a118c301a07737aeda0f929c68913c5f51c80394f53bff1c3e83b2e40ca97eba9e15:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfd:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+d444bfa2362a96df213d070e33fa841f51334e4e76866b8139e8af3bb3398be2dfaddcbc56b9146de9f68118dc5829e74b0c28d7711907b121f9161cb92b69a9:
+
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe:
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f:
+142709d62e28fcccd0af97fad0f8465b971e82201dc51070faa0372aa43e92484be1c1e73ba10906d5d1853db6a4106e0a7bf9800d373d6dee2d46d62ef2a461:
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/gen/vectors/chacha20 b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/vectors/chacha20
new file mode 100644
index 0000000..34b2fb9
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/vectors/chacha20
@@ -0,0 +1,36 @@
+# RFC 8439
+# Test Vector #1:
+# ==============
+0000000000000000000000000000000000000000000000000000000000000000:
+0000000000000000:
+00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:
+0000000000000000:
+76b8e0ada0f13d90405d6ae55386bd28bdd219b8a08ded1aa836efcc8b770dc7da41597c5157488d7724e03fb8d84a376a43b8f41518a11cc387b669b2ee6586:
+
+# Same, key slightly modified
+0000000000000000000000000000000000000000000000000000000000000001:
+0000000000000000:
+00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:
+0000000000000000:
+4540f05a9f1fb296d7736e7b208e3c96eb4fe1834688d2604f450952ed432d41bbe2a0b6ea7566d2a5d1e7e20d42af2c53d792b1c43fea817e9ad275ae546963:
+
+# Same, nonce slightly modified
+0000000000000000000000000000000000000000000000000000000000000000:
+0000000000000001:
+000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:
+0000000000000000:
+de9cba7bf3d69ef5e786dc63973f653a0b49e015adbff7134fcb7df137821031e85a050278a7084527214f73efc7fa5b5277062eb7a0433e445f41e3:
+
+# Same, nonce MSB modified
+0000000000000000000000000000000000000000000000000000000000000000:
+0100000000000000:
+00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:
+0000000000000000:
+ef3fdfd6c61578fbf5cf35bd3dd33b8009631634d21e42ac33960bd138e50d32111e4caf237ee53ca8ad6426194a88545ddc497a0b466e7d6bbdb0041b2f586b:
+
+# Don't remember where this one comes from
+000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f:
+0001020304050607:
+00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:
+0000000000000000:
+f798a189f195e66982105ffb640bb7757f579da31602fc93ec01ac56f85ac3c134a4547b733b46413042c9440049176905d3be59ea1c53f15916155c2be8241a38008b9a26bc35941e2444177c8ade6689de95264986d95889fb60e84629c9bd9a5acb1cc118be563eb9b3a4a472f82e09a7e778492b562ef7130e88dfe031c79db9d4f7c7a899151b9a475032b63fc385245fe054e3dd5a97a5f576fe064025d3ce042c566ab2c507b138db853e3d6959660996546cc9c4a6eafdc777c040d70eaf46f76dad3979e5c5360c3317166a1c894c94a371876a94df7628fe4eaaf2ccb27d5aaae0ad7ad0f9d4b6ad3b54098746d4524d38407a6deb3ab78fab78c9:
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/gen/vectors/ed_25519_check b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/vectors/ed_25519_check
new file mode 100644
index 0000000..42e4b47
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/vectors/ed_25519_check
@@ -0,0 +1,1981 @@
+# Daniel Bleichenbacher test vectors from Wycheproof:
+# https://github.com/google/wycheproof/blob/master/testvectors/eddsa_test.json
+#
+# Notes:
+#
+# - SignatureMalleability: EdDSA signatures are non-malleable, if
+# implemented accordingly. Failing to check the range of S allows to
+# modify signatures. See RFC 8032, Section 5.2.7 and Section 8.4.
+
+# valid
+7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa:
+:
+d4fbdb52bfa726b44d1786a8c0d171c3e62ca83c9e5bbe63de0bb2483f8fd6cc1429ab72cafc41ab56af02ff8fcc43b99bfe4c7ae940f60f38ebaa9d311c4007:
+00:
+
+# valid
+7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa:
+78:
+d80737358ede548acb173ef7e0399f83392fe8125b2ce877de7975d8b726ef5b1e76632280ee38afad12125ea44b961bf92f1178c9fa819d020869975bcbe109:
+00:
+
+# valid
+7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa:
+54657374:
+7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab07a9155711ecfaf7f99f277bad0c6ae7e39d4eef676573336a5c51eb6f946b30d:
+00:
+
+# valid
+7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa:
+48656c6c6f:
+1c1ad976cbaae3b31dee07971cf92c928ce2091a85f5899f5e11ecec90fc9f8e93df18c5037ec9b29c07195ad284e63d548cd0a6fe358cc775bd6c1608d2c905:
+00:
+
+# valid
+7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa:
+313233343030:
+657c1492402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c2bf0cf5b3a289976458a1be6277a5055545253b45b07dcc1abd96c8b989c00f301:
+00:
+
+# valid
+7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa:
+000000000000000000000000:
+d46543bfb892f84ec124dcdfc847034c19363bf3fc2fa89b1267833a14856e52e60736918783f950b6f1dd8d40dc343247cd43ce054c2d68ef974f7ed0f3c60f:
+00:
+
+# valid
+7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa:
+6161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161:
+879350045543bc14ed2c08939b68c30d22251d83e018cacbaf0c9d7a48db577e80bdf76ce99e5926762bc13b7b3483260a5ef63d07e34b58eb9c14621ac92f00:
+00:
+
+# valid
+7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa:
+202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f60:
+7bdc3f9919a05f1d5db4a3ada896094f6871c1f37afc75db82ec3147d84d6f237b7e5ecc26b59cfea0c7eaf1052dc427b0f724615be9c3d3e01356c65b9b5109:
+00:
+
+# valid
+7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa:
+ffffffffffffffffffffffffffffffff:
+5dbd7360e55aa38e855d6ad48c34bd35b7871628508906861a7c4776765ed7d1e13d910faabd689ec8618b78295c8ab8f0e19c8b4b43eb8685778499e943ae04:
+00:
+
+# special values for r and s
+# invalid
+7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa:
+3f:
+00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:
+ff:
+
+# special values for r and s
+# invalid
+7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa:
+3f:
+00000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000:
+ff:
+
+# special values for r and s
+# invalid
+7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa:
+3f:
+0000000000000000000000000000000000000000000000000000000000000000ecd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010:
+ff:
+
+# special values for r and s
+# invalid
+7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa:
+3f:
+0000000000000000000000000000000000000000000000000000000000000000edd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010:
+ff:
+
+# special values for r and s
+# invalid
+7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa:
+3f:
+0000000000000000000000000000000000000000000000000000000000000000edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+ff:
+
+# special values for r and s
+# invalid
+7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa:
+3f:
+01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:
+ff:
+
+# special values for r and s
+# invalid
+7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa:
+3f:
+01000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000:
+ff:
+
+# special values for r and s
+# invalid
+7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa:
+3f:
+0100000000000000000000000000000000000000000000000000000000000000ecd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010:
+ff:
+
+# special values for r and s
+# invalid
+7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa:
+3f:
+0100000000000000000000000000000000000000000000000000000000000000edd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010:
+ff:
+
+# special values for r and s
+# invalid
+7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa:
+3f:
+0100000000000000000000000000000000000000000000000000000000000000edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+ff:
+
+# special values for r and s
+# invalid
+7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa:
+3f:
+edd3f55c1a631258d69cf7a2def9de14000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000:
+ff:
+
+# special values for r and s
+# invalid
+7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa:
+3f:
+edd3f55c1a631258d69cf7a2def9de14000000000000000000000000000000100100000000000000000000000000000000000000000000000000000000000000:
+ff:
+
+# special values for r and s
+# invalid
+7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa:
+3f:
+edd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010ecd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010:
+ff:
+
+# special values for r and s
+# invalid
+7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa:
+3f:
+edd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010edd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010:
+ff:
+
+# special values for r and s
+# invalid
+7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa:
+3f:
+edd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+ff:
+
+# special values for r and s
+# invalid
+7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa:
+3f:
+edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000:
+ff:
+
+# special values for r and s
+# invalid
+7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa:
+3f:
+edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0100000000000000000000000000000000000000000000000000000000000000:
+ff:
+
+# special values for r and s
+# invalid
+7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa:
+3f:
+edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fecd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010:
+ff:
+
+# special values for r and s
+# invalid
+7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa:
+3f:
+edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fedd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010:
+ff:
+
+# special values for r and s
+# invalid
+7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa:
+3f:
+edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fedffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+ff:
+
+# modified bit 0 in R
+# invalid
+7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa:
+313233343030:
+647c1492402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c2b1d125e5538f38afbcc1c84e489521083041d24bc6240767029da063271a1ff0c:
+ff:
+
+# modified bit 1 in R
+# invalid
+7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa:
+313233343030:
+677c1492402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c2bc108ca4b87a49c9ed2cf383aecad8f54a962b2899da891e12004d7993a627e01:
+ff:
+
+# modified bit 2 in R
+# invalid
+7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa:
+313233343030:
+617c1492402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c2b9ce23fc6213ed5b87912e9bbf92f5e2c780eae26d15c50a112d1e97d2ea33c06:
+ff:
+
+# modified bit 7 in R
+# invalid
+7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa:
+313233343030:
+e57c1492402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c2bbb3eb51cd98dddb235a5f46f2bded6af184a58d09cce928bda43f41d69118a03:
+ff:
+
+# modified bit 8 in R
+# invalid
+7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa:
+313233343030:
+657d1492402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c2bcd237dda9a116501f67a5705a854b9adc304f34720803a91b324f2c13e0f5a09:
+ff:
+
+# modified bit 16 in R
+# invalid
+7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa:
+313233343030:
+657c1592402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c2b6b167bbdc0d881cc04d28905552c1876f3709851abc5007376940cc8a435c300:
+ff:
+
+# modified bit 31 in R
+# invalid
+7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa:
+313233343030:
+657c1412402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c2b7fd2ac7da14afffcceeb13f2a0d6b887941cb1a5eb57a52f3cb131a16cce7b0e:
+ff:
+
+# modified bit 32 in R
+# invalid
+7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa:
+313233343030:
+657c1492412ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c2b7373ba13ebbef99cd2a8ead55ce735c987d85a35320925a8e871702dc7c5c40d:
+ff:
+
+# modified bit 63 in R
+# invalid
+7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa:
+313233343030:
+657c1492402ab54e03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c2bd35bd331c03f0855504ca1cab87b83c36a028425a3cf007ede4f4254c261cb00:
+ff:
+
+# modified bit 64 in R
+# invalid
+7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa:
+313233343030:
+657c1492402ab5ce02e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c2bcb35101f73cf467deac8c1a03b6c3dc35af544132734b7e57ab20c89b2e4750d:
+ff:
+
+# modified bit 97 in R
+# invalid
+7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa:
+313233343030:
+657c1492402ab5ce03e2c3a7f2384d051b9cf3570f1207fc78c1bcc98c281c2bb58d2e8878290bff8d3355fdd4ea381924ee578752354eb6dee678ab4011c301:
+ff:
+
+# modified bit 127 in R
+# invalid
+7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa:
+313233343030:
+657c1492402ab5ce03e2c3a7f0384d851b9cf3570f1207fc78c1bcc98c281c2bb978c866187ffb1cc7b29a0b4045aefc08768df65717194ff0c6e63f4dea0d02:
+ff:
+
+# modified bit 240 in R
+# invalid
+7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa:
+313233343030:
+657c1492402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281d2b0576ecf8eaf675f00f3dfbe19f75b83b7607a6c96414f6821af920a2498d0305:
+ff:
+
+# modified bit 247 in R
+# invalid
+7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa:
+313233343030:
+657c1492402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c289c2be5241a345c7b5428054c74b7c382fa10d4a5f1e8f8b79a71d3fdea2254f1ff0e:
+ff:
+
+# modified bit 248 in R
+# invalid
+7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa:
+313233343030:
+657c1492402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c2a63950c85cd6dc96364e768de50ff7732b538f8a0b1615d799190ab600849230e:
+ff:
+
+# modified bit 253 in R
+# invalid
+7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa:
+313233343030:
+657c1492402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c0b543bd3da0a56a8c9c152f59c9fec12f31fa66434d48b817b30d90cb4efa8b501:
+ff:
+
+# modified bit 254 in R
+# invalid
+7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa:
+313233343030:
+657c1492402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c6b8da07efd07a6dafb015ed6a32fe136319a972ffbc341f3a0beae97ccf8136505:
+ff:
+
+# modified bit 255 in R
+# invalid
+7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa:
+313233343030:
+657c1492402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281cab227aedf259f910f0f3a759a335062665217925d019173b88917eae294f75d40f:
+ff:
+
+# R==0
+# invalid
+7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa:
+313233343030:
+0000000000000000000000000000000000000000000000000000000000000000e0b8e7770d51c7a36375d006c5bffd6af43ff54aaf47e4330dc118c71d61ec02:
+ff:
+
+# invalid R
+# invalid
+7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa:
+313233343030:
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff463a1908382e7eb7693acef9884f7cf931a215e0791876be22c631a59881fd0e:
+ff:
+
+# all bits flipped in R
+# invalid
+7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa:
+313233343030:
+9a83eb6dbfd54a31fc1d3c580fc7b2fae4630ca8f0edf803873e433673d7e3d40e94254586cb6188c5386c3febed477cb9a6cb29e3979adc4cb27cf5278fb70a:
+ff:
+
+# checking malleability
+# invalid
+# SignatureMalleability
+7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa:
+54657374:
+7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab067654bce3832c2d76f8f6f5dafc08d9339d4eef676573336a5c51eb6f946b31d:
+ff:
+
+# checking malleability
+# invalid
+# SignatureMalleability
+7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa:
+54657374:
+7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab05439412b5395d42f462c67008eba6ca839d4eef676573336a5c51eb6f946b32d:
+ff:
+
+# checking malleability
+# invalid
+# SignatureMalleability
+7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa:
+54657374:
+7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab02ee12ce5875bf9dff26556464bae2ad239d4eef676573336a5c51eb6f946b34d:
+ff:
+
+# checking malleability
+# invalid
+# SignatureMalleability
+7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa:
+54657374:
+7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab0e2300459f1e742404cd934d2c595a6253ad4eef676573336a5c51eb6f946b38d:
+ff:
+
+# checking malleability
+# invalid
+# SignatureMalleability
+7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa:
+54657374:
+7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab07a9155711ecfaf7f99f277bad0c6ae7e39d4eef676573336a5c51eb6f946b32d:
+ff:
+
+# checking malleability
+# invalid
+# SignatureMalleability
+7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa:
+54657374:
+7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab07a9155711ecfaf7f99f277bad0c6ae7e39d4eef676573336a5c51eb6f946b34d:
+ff:
+
+# checking malleability
+# invalid
+# SignatureMalleability
+7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa:
+54657374:
+7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab07a9155711ecfaf7f99f277bad0c6ae7e39d4eef676573336a5c51eb6f946b38d:
+ff:
+
+# checking malleability
+# invalid
+# SignatureMalleability
+7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa:
+54657374:
+7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab0679155711ecfaf7f99f277bad0c6ae7e39d4eef676573336a5c51eb6f946b38d:
+ff:
+
+# valid
+a12c2beb77265f2aac953b5009349d94155a03ada416aad451319480e983ca4c:
+:
+5056325d2ab440bf30bbf0f7173199aa8b4e6fbc091cf3eb6bc6cf87cd73d992ffc216c85e4ab5b8a0bbc7e9a6e9f8d33b7f6e5ac0ffdc22d9fcaf784af84302:
+00:
+
+# valid
+a12c2beb77265f2aac953b5009349d94155a03ada416aad451319480e983ca4c:
+78:
+481fafbf4364d7b682475282f517a3ac0538c9a6b6a562e99a3d8e5afb4f90a559b056b9f07af023905753b02d95eb329a35c77f154b79abbcd291615ce42f02:
+00:
+
+# valid
+a12c2beb77265f2aac953b5009349d94155a03ada416aad451319480e983ca4c:
+54657374:
+8a9bb4c465a3863abc9fd0dd35d80bb28f7d33d37d74679802d63f82b20da114b8d765a1206b3e9ad7cf2b2d8d778bb8651f1fa992db293c0039eacb6161480f:
+00:
+
+# valid
+a12c2beb77265f2aac953b5009349d94155a03ada416aad451319480e983ca4c:
+48656c6c6f:
+d839c20abfda1fd429531831c64f813f84b913e9928540310cf060b44c3dbf9457d44a7721fdc0d67724ff81cb450dd39b10cfb65db15dda4b8bf09d26bd3801:
+00:
+
+# valid
+a12c2beb77265f2aac953b5009349d94155a03ada416aad451319480e983ca4c:
+313233343030:
+9bbb1052dcfa8ad2715c2eb716ae4f1902dea353d42ee09fd4c0b4fcb8b52b5219e2200016e1199d0061891c263e31b0bc3b55673c19610c4e0fa5408004160b:
+00:
+
+# valid
+a12c2beb77265f2aac953b5009349d94155a03ada416aad451319480e983ca4c:
+000000000000000000000000:
+f63b5c0667c7897fc283296416f7f60e84bbde9cbd832e56be463ed9f568069702b17a2f7c341ebf590706a6388ac76ac613c1675ec0f2c7118f2573422a500b:
+00:
+
+# valid
+a12c2beb77265f2aac953b5009349d94155a03ada416aad451319480e983ca4c:
+6161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161:
+1bc44d7001e6b5b9090fef34b2ca480f9786bbefa7d279353e5881e8dfb91b803ccd46500e270ef0109bfd741037558832120bc2a4f20fbe7b5fb3c3aaf23e08:
+00:
+
+# valid
+a12c2beb77265f2aac953b5009349d94155a03ada416aad451319480e983ca4c:
+202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f60:
+ea8e22143b02372e76e99aece3ed36aec529768a27e2bb49bdc135d44378061e1f62d1ac518f33ebf37b2ee8cc6dde68a4bd7d4a2f4d6cb77f015f71ca9fc30d:
+00:
+
+# valid
+a12c2beb77265f2aac953b5009349d94155a03ada416aad451319480e983ca4c:
+ffffffffffffffffffffffffffffffff:
+8acd679e1a914fc45d5fa83d3021f0509c805c8d271df54e52f43cfbd00cb6222bf81d58fe1de2de378df67ee9f453786626961fe50a9b05f12b6f0899ebdd0a:
+00:
+
+# draft-josefsson-eddsa-ed25519-02: Test 1
+# valid
+d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a:
+:
+e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b:
+00:
+
+# draft-josefsson-eddsa-ed25519-02: Test 2
+# valid
+3d4017c3e843895a92b70aa74d1b7ebc9c982ccf2ec4968cc0cd55f12af4660c:
+72:
+92a009a9f0d4cab8720e820b5f642540a2b27b5416503f8fb3762223ebdb69da085ac1e43e15996e458f3613d0f11d8c387b2eaeb4302aeeb00d291612bb0c00:
+00:
+
+# draft-josefsson-eddsa-ed25519-02: Test 3
+# valid
+fc51cd8e6218a1a38da47ed00230f0580816ed13ba3303ac5deb911548908025:
+af82:
+6291d657deec24024827e69c3abe01a30ce548a284743a445e3680d7db5ac3ac18ff9b538d16f290ae67f760984dc6594a7c15e9716ed28dc027beceea1ec40a:
+00:
+
+# draft-josefsson-eddsa-ed25519-02: Test 1024
+# valid
+278117fc144c72340f67d0f2316e8386ceffbf2b2428c9c51fef7c597f1d426e:
+08b8b2b733424243760fe426a4b54908632110a66c2f6591eabd3345e3e4eb98fa6e264bf09efe12ee50f8f54e9f77b1e355f6c50544e23fb1433ddf73be84d879de7c0046dc4996d9e773f4bc9efe5738829adb26c81b37c93a1b270b20329d658675fc6ea534e0810a4432826bf58c941efb65d57a338bbd2e26640f89ffbc1a858efcb8550ee3a5e1998bd177e93a7363c344fe6b199ee5d02e82d522c4feba15452f80288a821a579116ec6dad2b3b310da903401aa62100ab5d1a36553e06203b33890cc9b832f79ef80560ccb9a39ce767967ed628c6ad573cb116dbefefd75499da96bd68a8a97b928a8bbc103b6621fcde2beca1231d206be6cd9ec7aff6f6c94fcd7204ed3455c68c83f4a41da4af2b74ef5c53f1d8ac70bdcb7ed185ce81bd84359d44254d95629e9855a94a7c1958d1f8ada5d0532ed8a5aa3fb2d17ba70eb6248e594e1a2297acbbb39d502f1a8c6eb6f1ce22b3de1a1f40cc24554119a831a9aad6079cad88425de6bde1a9187ebb6092cf67bf2b13fd65f27088d78b7e883c8759d2c4f5c65adb7553878ad575f9fad878e80a0c9ba63bcbcc2732e69485bbc9c90bfbd62481d9089beccf80cfe2df16a2cf65bd92dd597b0707e0917af48bbb75fed413d238f5555a7a569d80c3414a8d0859dc65a46128bab27af87a71314f318c782b23ebfe808b82b0ce26401d2e22f04d83d1255dc51addd3b75a2b1ae0784504df543af8969be3ea7082ff7fc9888c144da2af58429ec96031dbcad3dad9af0dcbaaaf268cb8fcffead94f3c7ca495e056a9b47acdb751fb73e666c6c655ade8297297d07ad1ba5e43f1bca32301651339e22904cc8c42f58c30c04aafdb038dda0847dd988dcda6f3bfd15c4b4c4525004aa06eeff8ca61783aacec57fb3d1f92b0fe2fd1a85f6724517b65e614ad6808d6f6ee34dff7310fdc82aebfd904b01e1dc54b2927094b2db68d6f903b68401adebf5a7e08d78ff4ef5d63653a65040cf9bfd4aca7984a74d37145986780fc0b16ac451649de6188a7dbdf191f64b5fc5e2ab47b57f7f7276cd419c17a3ca8e1b939ae49e488acba6b965610b5480109c8b17b80e1b7b750dfc7598d5d5011fd2dcc5600a32ef5b52a1ecc820e308aa342721aac0943bf6686b64b2579376504ccc493d97e6aed3fb0f9cd71a43dd497f01f17c0e2cb3797aa2a2f256656168e6c496afc5fb93246f6b1116398a346f1a641f3b041e989f7914f90cc2c7fff357876e506b50d334ba77c225bc307ba537152f3f1610e4eafe595f6d9d90d11faa933a15ef1369546868a7f3a45a96768d40fd9d03412c091c6315cf4fde7cb68606937380db2eaaa707b4c4185c32eddcdd306705e4dc1ffc872eeee475a64dfac86aba41c0618983f8741c5ef68d3a101e8a3b8cac60c905c15fc910840b94c00a0b9d0:
+0aab4c900501b3e24d7cdf4663326a3a87df5e4843b2cbdb67cbf6e460fec350aa5371b1508f9f4528ecea23c436d94b5e8fcd4f681e30a6ac00a9704a188a03:
+00:
+
+# Random test failure 1
+# valid
+8fd659b77b558ed93882c1157438450ac86ec62d421d568e98ee236f3810295a:
+b0729a713593a92e46b56eaa66b9e435f7a09a8e7de03b078f6f282285276635f301e7aaafe42187c45d6f5b13f9f16b11195cc125c05b90d24dfe4c:
+7db17557ac470c0eda4eedaabce99197ab62565653cf911f632ee8be0e5ffcfc88fb94276b42e0798fd3aa2f0318be7fc6a29fae75f70c3dcdc414a0ad866601:
+00:
+
+# Random test failure 2
+# valid
+2a606bf67ac770c607038b004101b325edb569efd3413d2d1f2c3e6b4e6e3082:
+a8546e50ba31cae3234310d32672447be213fad91a227a19669c53d309b959782b0e6b71f8791fdb470043b58122003157d2d96a43a6cbd7d3a8d86bf4c97391883e268d50af80e1e6e12939c2bd50ca746cdadfad4edf1bda875299740724148efb1ebe73fb60088cda890317658627a5f7ab5a0c075d9d8f3f97b6492b35519e50ff6b38377432a7081f9176bb1c29a862deac1336ca20b097a47829cec10a6a7cec178eda2d12f6dc6c87f910454af0123555ba184e68804d9cced60fd5c8c90943e56599c8f0ba59a38491ba5e5a53460682474c07e40ca142983314fd762856bb1093f359da6eb0a756bd93a3160c10dd8feea6b97e7c6a17cb54bd5d7649c05c66d7bdee056671dfdaf689fa3945bb8e29a429f4bd5d355dce9687b06f01d5e33e3999f0e8:
+67d84d4c3945aaf06e06d524be63acbfb5dbb1988c4aea96a5ee9f7a9b9eecc29df4f66b8aa1d9e8607a58fb1ef0c2ad69aac005b4f58e34103344a9c8871a09:
+00:
+
+# Random test failure 24
+# valid
+2a606bf67ac770c607038b004101b325edb569efd3413d2d1f2c3e6b4e6e3082:
+b477b0480bb84642608b908d29a51cf2fce63f24ee95:
+28fafbb62b4d688fa79e1ac92851f46e319b161f801d4dc09acc21fdd6780a2c4292b8c1003c61c2bcebe7f3f88ccc4bb26d407387c5f27cb8c94cf6ce810405:
+00:
+
+# Random test failure 3
+# valid
+c9c946cbc5544ac74eef491f07c5881c16faf7ec31ce4aa91bb60ae7b4539051:
+cd2212eddb0706f62c995cef958634f0cb7793444cbf4d30e81c27c41ebea6cb02607510131f9c015692dfd521b148841e9a2d3564d20ac401f6cb8e40f520fe0cafbeaa88840b83013369d879f013463fe52a13267aa0c8c59c45cde9399cd1e6be8cc64cf48315ac2eb31a1c567a4fb7d601746d1f63b5ac020712adbbe07519bded6f:
+24087d47f3e20af51b9668ae0a88ce76586802d0ec75d8c0f28fc30962b5e1d1a1d509571a1624ed125a8df92a6e963728d6b5de99200b8e285f70feb6f05207:
+00:
+
+# Random test failure 20
+# valid
+c9c946cbc5544ac74eef491f07c5881c16faf7ec31ce4aa91bb60ae7b4539051:
+27d465bc632743522aefa23c:
+c2656951e2a0285585a51ff0eda7e9a23c2dfd2ffa273aee7808f4604e8f9a8c8ea49e9fce4eb2d8d75d36b7238fe6fc13b6c5d9427dd58f8c6615d033c0bd0f:
+00:
+
+# Random test failure 4
+# valid
+32ad026f693d0d2afe7f4388d91c4c964426fcb9e3665c3ebd8650009b815c8e:
+ec5c7cb078:
+d920d421a5956b69bfe1ba834c025e2babb6c7a6d78c97de1d9bb1116dfdd1185147b2887e34e15578172e150774275ea2aad9e02106f7e8ca1caa669a066f0c:
+00:
+
+# Random test failure 5
+# valid
+32ad026f693d0d2afe7f4388d91c4c964426fcb9e3665c3ebd8650009b815c8e:
+4668c6a76f0e482190a7175b9f3806a5fe4314a004fa69f988373f7a:
+4f62daf7f7c162038552ad7d306e195baa37ecf6ca7604142679d7d1128e1f8af52e4cb3545748c44ef1ff1c64e877e4f4d248259b7f6eb56e3ef72097dc8e0c:
+00:
+
+# Random test failure 8
+# valid
+32ad026f693d0d2afe7f4388d91c4c964426fcb9e3665c3ebd8650009b815c8e:
+5dc9bb87eb11621a93f92abe53515697d2611b2eef73:
+deecafb6f2ede73fec91a6f10e45b9c1c61c4b9bfbe6b6147e2de0b1df6938971f7896c3ab83851fb5d9e537037bff0fca0ccb4a3cc38f056f91f7d7a0557e08:
+00:
+
+# Random test failure 10
+# valid
+32ad026f693d0d2afe7f4388d91c4c964426fcb9e3665c3ebd8650009b815c8e:
+7dcfe60f881e1285676f35b68a1b2dbcdd7be6f719a288ababc28d36e3a42ac3010a1ca54b32760e74:
+7f8663cf98cbd39d5ff553f00bcf3d0d520605794f8866ce75714d77cc51e66c91818b657d7b0dae430a68353506edc4a714c345f5ddb5c8b958ba3d035f7a01:
+00:
+
+# Random test failure 12
+# valid
+32ad026f693d0d2afe7f4388d91c4c964426fcb9e3665c3ebd8650009b815c8e:
+58e456064dff471109def4ca27fa8310a1df32739655b624f27e6418d34b7f007173f3faa5:
+6aab49e5c0bc309b783378ee03ffda282f0185cdf94c847701ff307a6ee8d0865411c44e0a8206f6a5f606107451940c2593af790ce1860f4c14ab25b2deae08:
+00:
+
+# Random test failure 15
+# valid
+32ad026f693d0d2afe7f4388d91c4c964426fcb9e3665c3ebd8650009b815c8e:
+a1:
+1a74ed2cbdc7d8f3827014e8e6ecf8fd2698ac8f86833acccdd400df710fe0d6b0543c9cfa00d52bf024ab7ce0d91981944097233ec134d5c7abbd44bfd32d0d:
+00:
+
+# Random test failure 19
+# valid
+32ad026f693d0d2afe7f4388d91c4c964426fcb9e3665c3ebd8650009b815c8e:
+11cb1eafa4c42a8402c4193c4696f7b2e6d4585e4b42dcf1a8b67a80b2da80bc9d4b649fb2f35eaf1f56c426fd0b:
+14ceb2eaf4688d995d482f44852d71ad878cd7c77b41e60b0065fd01a59b054ee74759224187dbde9e59a763a70277c960892ef89fba997aba2576b2c54ba608:
+00:
+
+# Random test failure 25
+# valid
+32ad026f693d0d2afe7f4388d91c4c964426fcb9e3665c3ebd8650009b815c8e:
+aa365b442d12b7f3c925:
+83c40ce13d483cc58ff65844875862d93df4bd367af77efa469ec06a8ed9e6d7905a04879535708ddf225567a815c9b941d405c98e918fd0c151165cea7fb101:
+00:
+
+# Random test failure 28
+# valid
+32ad026f693d0d2afe7f4388d91c4c964426fcb9e3665c3ebd8650009b815c8e:
+475f:
+71a4a06a34075f2fd47bc3abf4714d46db7e97b08cb6180d3f1539ac50b18ce51f8af8ae95ed21d4fa0daab7235925631ecea1fd9d0d8a2ba7a7583fd04b900c:
+00:
+
+# Random test failure 6
+# valid
+c29ec1894e06d27b4e40486b4fa5063d66a746c7f9c323b12203c03b72b8b78a:
+0f325ffd87e58131ffa23c05ea4579513b287fdba87b44:
+6669acf94667c5b541afe5307bde9476b13ae7e0e6058a772101ac8eb0a94331428eb4db0a2c68a9b6c1763b8624dab259b0876cdcfaeacc17b21a18e3fc010a:
+00:
+
+# Random test failure 21
+# valid
+c29ec1894e06d27b4e40486b4fa5063d66a746c7f9c323b12203c03b72b8b78a:
+5ffa:
+931e5152fcef078c22cc5d6a3a65f06e396289f6f5f2d1efa6340254a53526ef5dc6874eeddf35c3f50991c53cd02bf06313e37d93ee1f7022128ffa3b8f300b:
+00:
+
+# Random test failure 7
+# valid
+cfda5b899e35764c5229e59295fe1222b7ddce176643697c29e46ecbba10cf10:
+ec5c7cb078:
+30490c28f806298225df62103521dcee047153912c33ab8ab8bbdd1ffabd70fd4fdb360f05be535b067d1cf4e78c2cb432206bf280aab3bd21aaa1cb894c5b06:
+00:
+
+# Random test failure 9
+# valid
+cfda5b899e35764c5229e59295fe1222b7ddce176643697c29e46ecbba10cf10:
+67484059b2490b1a0a4f8dee77979e26:
+4cd4f77ed473a6647387f3163541c67a1708a3c3bd1673247cb87f0cb68b3c56f04bfa72970c8a483efe659c87009ab4020b590b6641316b3deddb5450544e02:
+00:
+
+# Random test failure 11
+# valid
+cfda5b899e35764c5229e59295fe1222b7ddce176643697c29e46ecbba10cf10:
+a020a4381dc9141f47ee508871ab7a8b5a3648727c4281ae9932376f23a8e1bcda0626b7129197d864178631ec89c4332dbb18:
+1e41a24fe732bd7cab14c2a2f5134ee8c87fcbd2e987e60957ed9239e5c32404d56977e1b4282871896cb10625a1937468e4dc266e16a9c1b8e9891177eca802:
+00:
+
+# Random test failure 14
+# valid
+cfda5b899e35764c5229e59295fe1222b7ddce176643697c29e46ecbba10cf10:
+a25176b3afea318b2ec11ddacb10caf7179c0b3f8eabbfa2895581138d3c1e0e:
+2a833aadecd9f28235cb5896bf3781521dc71f28af2e91dbe1735a61dce3e31ac15ca24b3fc47817a59d386bbbb2ce60a6adc0a2703bb2bdea8f70f91051f706:
+00:
+
+# Random test failure 18
+# valid
+cfda5b899e35764c5229e59295fe1222b7ddce176643697c29e46ecbba10cf10:
+a9e6d94870a67a9fe1cf13b1e6f9150cdd407bf6480ec841ea586ae3935e9787163cf419c1:
+c97e3190f83bae7729ba473ad46b420b8aad735f0808ea42c0f898ccfe6addd4fd9d9fa3355d5e67ee21ab7e1f805cd07f1fce980e307f4d7ad36cc924eef00c:
+00:
+
+# Random test failure 13
+# valid
+529919c9c780985a841c42ba6c180ff2d67a276ccfbe281080e47ab71a758f56:
+e1cbf2d86827825613fb7a85811d:
+01abfa4d6bbc726b196928ec84fd03f0c953a4fa2b228249562ff1442a4f63a7150b064f3712b51c2af768d2c2711a71aabf8d186833e941a0301b82f0502905:
+00:
+
+# Random test failure 22
+# valid
+529919c9c780985a841c42ba6c180ff2d67a276ccfbe281080e47ab71a758f56:
+25:
+e4ae21f7a8f4b3b325c161a8c6e53e2edd7005b9c2f8a2e3b0ac4ba94aa80be6f2ee22ac8d4a96b9a3eb73a825e7bb5aff4a3393bf5b4a38119e9c9b1b041106:
+00:
+
+# Random test failure 16
+# valid
+2252b3d57c74cbf8bc460dc2e082847926bc022f09ab6ae95756362bfd1167c1:
+975ef941710071a9e1e6325a0c860becd7c695b5117c3107b686e330e5:
+af0fd9dda7e03e12313410d8d8844ebb6fe6b7f65141f22d7bcba5695a25414a9e54326fb44d59fb14707899a8aae70857b23d4080d7ab2c396ef3a36d45ce02:
+00:
+
+# Random test failure 23
+# valid
+2252b3d57c74cbf8bc460dc2e082847926bc022f09ab6ae95756362bfd1167c1:
+80fdd6218f29c8c8f6bd820945f9b0854e3a8824:
+e097e0bd0370bff5bde359175a11b728ee9639095d5df8eda496395565616edfe079977f7d4dc8c75d6113a83d6a55e6e1676408c0967a2906339b43337dcb01:
+00:
+
+# Random test failure 17
+# valid
+c0a773110f975de3732355bb7ec7f0c41c091c0252966070205516693b992a4a:
+:
+0280427e713378f49d478df6373c6cac847b622b567daa2376c839e7ac10e22c380ab0fa8617c9dcfe76c4d9db5459b21dc1413726e46cc8f387d359e344f407:
+00:
+
+# Random test failure 26
+# valid
+54cda623245759ad6d43e620a606908befc633d60792bc7798447a0ef38e7311:
+27e792b28b2f1702:
+14d9b497c19b91d43481c55bb6f5056de252d9ecb637575c807e58e9b4c5eac8b284089d97e2192dc242014363208e2c9a3435edf8928fb1d893553e9be4c703:
+00:
+
+# Random test failure 27
+# valid
+2362bac514d5fad33802642e979a1e82de6eb6f1bcbf6a5b304f2bb02b9e57fe:
+eef3bb0f617c17d0420c115c21c28e3762edc7b7fb048529b84a9c2bc6:
+242ddb3a5d938d07af690b1b0ef0fa75842c5f9549bf39c8750f75614c712e7cbaf2e37cc0799db38b858d41aec5b9dd2fca6a3c8e082c10408e2cf3932b9d08:
+00:
+
+# Test case for overflow in signature generation
+# valid
+037b55b427dc8daa0f80fcebaf0846902309f8a6cf18b465c0ce9b6539629ac8:
+01234567:
+c964e100033ce8888b23466677da4f4aea29923f642ae508f9d0888d788150636ab9b2c3765e91bbb05153801114d9e52dc700df377212222bb766be4b8c020d:
+00:
+
+# Test case for overflow in signature generation
+# valid
+9c0007698f177998a7666c7cf7973e2b88e9c4946e33804a7bbe8968d2394b2e:
+9399a6db9433d2a28d2b0c11c8794ab7d108c95b:
+176065c6d64a136a2227687d77f61f3fca3b16122c966276fd9a8b14a1a2cea4c33b3533d11101717016684e3810efbea63bb23773f7cc480174199abd734f08:
+00:
+
+# Test case for overflow in signature generation
+# valid
+ed3a6f9721dc9729c1f76635bcf080d7036e1c2f0228654ccbbe1e738c17b963:
+7af783afbbd44c1833ab7237ecaf63b94ffdd003:
+7ca69331eec8610d38f00e2cdbd46966cb359dcde98a257ac6f362cc00c8f4fe85c02285fe4d66e31a44cadb2bf474e1a7957609eb4fe95a71473fe6699aa70d:
+00:
+
+# Test case for overflow in signature generation
+# valid
+4abfb535313705a6570018440cdec1a3ae33e51f352112fa6acbd0c6bc3ea859:
+321b5f663c19e30ee7bbb85e48ecf44db9d3f512:
+f296715e855d8aecccba782b670163dedc4458fe4eb509a856bcac450920fd2e95a3a3eb212d2d9ccaf948c39ae46a2548af125f8e2ad9b77bd18f92d59f9200:
+00:
+
+# Test case for overflow in signature generation
+# valid
+4f2162e6bf03a712db0efa418b7e7006e23871d9d7ec555a313885c4afd96385:
+c48890e92aeeb3af04858a8dc1d34f16a4347b91:
+367d07253a9d5a77d054b9c1a82d3c0a448a51905343320b3559325ef41839608aa45564978da1b2968c556cfb23b0c98a9be83e594d5e769d69d1156e1b1506:
+00:
+
+# regression test for arithmetic error
+# valid
+0717d75ce27ea181ed5a30e6456c649b5cf453a6b4c12cd3f9fd16b31e0c25cd:
+26d5f0631f49106db58c4cfc903691134811b33c:
+9588e02bc815649d359ce710cdc69814556dd8c8bab1c468f40a49ebefb7f0de7ed49725edfd1b708fa1bad277c35d6c1b9c5ec25990997645780f9203d7dd08:
+00:
+
+# regression test for arithmetic error
+# valid
+db5b9eab7e84e5a13505865fa711c9c896c898609fc11fc9bc1e55028f9496df:
+2a71f064af982a3a1103a75cef898732d7881981:
+2217a0be57dd0d6c0090641496bcb65e37213f02a0df50aff0368ee2808e1376504f37b37494132dfc4d4887f58b9e86eff924040db3925ee4f8e1428c4c500e:
+00:
+
+# regression test for arithmetic error
+# valid
+7bac18f6d2625d3915f233434cda38a577247a7332a5170b37142a34644145e0:
+bf26796cef4ddafcf5033c8d105057db0210b6ad:
+1fda6dd4519fdbefb515bfa39e8e5911f4a0a8aa65f40ef0c542b8b34b87f9c249dc57f320718ff457ed5915c4d0fc352affc1287724d3f3a9de1ff777a02e01:
+00:
+
+# regression test for arithmetic error
+# valid
+38ead304624abebf3e2b31e20e5629531e3fc659008887c9106f5e55adbbc62a:
+ae03da6997e40cea67935020152d3a9a365cc055:
+068eafdc2f36b97f9bae7fbda88b530d16b0e35054d3a351e3a4c914b22854c711505e49682e1a447e10a69e3b04d0759c859897b64f71137acf355b63faf100:
+00:
+
+# regression test for arithmetic error
+# valid
+e9bc95049af7e4817b17c402269ba5e767b7348757ac8002fec9e08390c0a9cf:
+489d473f7fb83c7f6823baf65482517bccd8f4ea:
+43670abc9f09a8a415e76f4a21c6a46156f066b5a37b3c1e867cf67248c7b927e8d13a763e37abf936f5f27f7a8aa290539d21f740efd26b65fd5ad27085f400:
+00:
+
+# regression test for arithmetic error
+# valid
+ee8155ca4e8fe7bc5bca5992044eab7f8c3c6a13db1176f42f46c29da5b064f4:
+1b704d6692d60a07ad1e1d047b65e105a80d3459:
+56388f2228893b14ce4f2a5e0cc626591061de3a57c50a5ecab7b9d5bb2caeea191560a1cf2344c75fdb4a085444aa68d727b39f498169eaa82cf64a31f59803:
+00:
+
+# regression test for arithmetic error
+# valid
+db507bfcc9576393f7157bb360532b05c5fcf2e764b690cc6698a4a30d349095:
+dc87030862c4c32f56261e93a367caf458c6be27:
+553e5845fc480a577da6544e602caadaa00ae3e5aa3dce9ef332b1541b6d5f21bdf1d01e98baf80b8435f9932f89b3eb70f02da24787aac8e77279e797d0bd0b:
+00:
+
+# regression test for arithmetic error
+# valid
+994eaf03309d6ad9d95a656bc1744e2886f029023a3750b34f35086b3c7227f8:
+7f41ef68508343ef18813cb2fb332445ec6480cd:
+bc10f88081b7be1f2505b6e76c5c82e358cf21ec11b7df1f334fb587bada465b53d9f7b4d4fec964432ee91ead1bc32ed3c82f2167da1c834a37515df7fe130e:
+00:
+
+# regression test for arithmetic error
+# valid
+127d37e406e0d83e4b55a09e21e8f50fb88af47e4a43f018cdebffc1948757f0:
+e1ce107971534bc46a42ac609a1a37b4ca65791d:
+00c11e76b5866b7c37528b0670188c1a0473fb93c33b72ae604a8865a7d6e094ff722e8ede3cb18389685ff3c4086c29006047466f81e71a329711e0b9294709:
+00:
+
+# regression test for arithmetic error
+# valid
+d83ba84edfb4bec49f29be31d80a64b7c0b5a502438cdb1d0dd1e0e3e55786de:
+869a827397c585cf35acf88a8728833ab1c8c81e:
+0a6f0ac47ea136cb3ff00f7a96638e4984048999ee2da0af6e5c86bffb0e70bb97406b6ad5a4b764f7c99ebb6ec0fd434b8efe253b0423ef876c037998e8ab07:
+00:
+
+# regression test for arithmetic error
+# valid
+d3c9aa2f3d6ef217a166e8ae403ed436c37facbbe3beceb78df6eb439f8fa04a:
+619d8c4f2c93104be01cd574a385ceca08c33a9e:
+b7cbb942a6661e2312f79548224f3e44f5841c6e880c68340756a00ce94a914e8404858265985e6bb97ef01d2d7e5e41340309606bfc43c8c6a8f925126b3d09:
+00:
+
+# regression test for arithmetic error
+# valid
+d53280367c1c0b95ac4112218b92c6a71c51fb6312ce668de196c7d52a136155:
+5257a0bae8326d259a6ce97420c65e6c2794afe2:
+27a4f24009e579173ff3064a6eff2a4d20224f8f85fdec982a9cf2e6a3b51537348a1d7851a3a932128a923a393ea84e6b35eb3473c32dceb9d7e9cab03a0f0d:
+00:
+
+# regression test for arithmetic error
+# valid
+94ac2336ba97a476fb4c9f2b5563e4167ca292c6e99e422350a911ae3172c315:
+5acb6afc9b368f7acac0e71f6a4831c72d628405:
+985b605fe3f449f68081197a68c714da0bfbf6ac2ab9abb0508b6384ea4999cb8d79af98e86f589409e8d2609a8f8bd7e80aaa8d92a84e7737fbe8dcef41920a:
+00:
+
+# regression test for arithmetic error
+# valid
+e1e7316d231f7f275bdf403360304da1509fdf1af1fd25ca214eaac0a289398f:
+3c87b3453277b353941591fc7eaa7dd37604b42a:
+1c8fbda3d39e2b441f06da6071c13115cb4115c7c3341704cf6513324d4cf1ef4a1dd7678a048b0dde84e48994d080befcd70854079d44b6a0b0f9fa002d130c:
+00:
+
+# regression test for arithmetic error
+# valid
+fffbeea71215efaf9888fec2cc68edb3703ff11a66fd629b53cbda5eabc18750:
+0a68e27ef6847bfd9e398b328a0ded3679d4649d:
+59097233eb141ed948b4f3c28a9496b9a7eca77454ecfe7e46737d1449a0b76b15aacf77cf48af27a668aa4434cfa26c504d75a2bcc4feac46465446234c0508:
+00:
+
+# regression test for arithmetic error
+# valid
+19ccc0527599cb032e0b4c4d74e60f13901768a99df041c3bc1bf6c0ef271169:
+4e9bef60737c7d4dd10bd52567e1473a36d3573d:
+519105608508fe2f1b6da4cc8b23e39798b1d18d25972beed0404cec722e01ba1b6a0f85e99e092cca8076b101b60d4ac5035684357f4d0daacdc642da742a06:
+00:
+
+# regression test for arithmetic error
+# valid
+0e726e27047563aa0a1a9c2e085d8d26af2acba129d0869c65031e3e6cac329a:
+cc82b3163efda3ba7e9240e765112caa69113694:
+d8b03ee579e73f16477527fc9dc37a72eaac0748a733772c483ba013944f01ef64fb4ec5e3a95021dc22f4ae282baff6e9b9cc8433c6b6710d82e7397d72ef04:
+00:
+
+# regression test for arithmetic error
+# valid
+e77717b54a2b5e5bce5bccb8f0c5fdb5fd7df77ac254020fc9120dc0d4df4178:
+923a5c9e7b5635bb6c32c5a408a4a15b652450eb:
+26da61fdfd38e6d01792813f27840c8b4766b0faaed39d0ee898cb450d94a5d5f57e58b6a003d7f9b56b20561954c6edcf66492d116b8b5e91f205a3a6449d0b:
+00:
+
+# regression test for arithmetic error
+# valid
+6220972d3f7d150b36790d7d522384876d64d640cd9913186815e1629582ed36:
+6f2f0245de4587062979d0422d349f93ccdc3af2:
+4adeaff7a58c5010a5a067feea0ae504d37b0c6a76c6c153e222f13409dff2df0fab69bc5059b97d925dc1b89e9851d7c627cb82d65585f9fd976124553f8902:
+00:
+
+# regression test for arithmetic error
+# valid
+7b64a28c50ec7678a90e3e1a21522e30ac9db7b5215aea2bfb33bea037eab987:
+6e911edb27a170b983d4dee1110554f804330f41:
+4204d620cde0c3008c0b2901f5d6b44f88f0e3cb4f4d62252bf6f3cb37c1fb150a9ccb296afe5e7c75f65b5c8edd13dc4910ffe1e1265b3707c59042cf9a5902:
+00:
+
+# regression test for arithmetic error
+# valid
+724452210a9e4c994819229bf12bf84e95768a3a97c08d8d8f5f939a4cad34c5:
+b8cf807eea809aaf739aa091f3b7a3f2fd39fb51:
+f8a69d3fd8c2ff0a9dec41e4c6b43675ce08366a35e220b1185ffc246c339e22c20ac661e866f52054015efd04f42eca2adcee6834c4df923b4a62576e4dff0e:
+00:
+
+# regression test for arithmetic error
+# valid
+bad265b294ed2f422cb6a141694086238fbfe987571aa765d8b4f3a24105aa01:
+01a2b5f7fee813b4e9bd7fc25137648004795010:
+61792c9442bc6338ac41fd42a40bee9b02ec1836503d60ff725128c63d72808880c36e6190b7da525cbee5d12900aa043547dd14a2709ef9e49d628f37f6b70c:
+00:
+
+# regression test for arithmetic error
+# valid
+0aaee4b723db9b51ba7d22eb23eb8a76a5ac02f4fc9dd06f77bea42e1d37ec5a:
+0fbf5d47cb5d498feace8f98f1896208da38a885:
+fa3cd41e3a8c00b19eecd404a63c3cb787cd30de0dfc936966cff2117f5aff18db6bef80fcfd8856f3fb2e9c3dc47593e9471103032af918feee638a33d40505:
+00:
+
+# regression test for arithmetic error
+# valid
+812344af15a91ba83c2c91e96f1727ac0f3c4c41385b9fa84efa399ada5168be:
+36e67c1939750bffb3e4ba6cb85562612275e862:
+97fbbcd7a1d0eb42d2f8c42448ef35a2c2472740556b645547865330d6c57068af377fced08aaf810c08cd3c43d296f1975710312e9334c98b485f831efa4103:
+00:
+
+# regression test for arithmetic error
+# valid
+0ee5cb5597fbdf8dccc48b01485e39b33aa133b52d30d23740277267cfec3e3e:
+13945c894c1d3fe8562e8b20e5f0efaa26ade8e3:
+d7dbaa337ffd2a5fd8d5fd8ad5aeccc0c0f83795c2c59fe62a40b87903b1ae62ed748a8df5af4d32f9f822a65d0e498b6f40eaf369a9342a1164ee7d08b58103:
+00:
+
+# regression test for arithmetic error
+# valid
+9fba1de92b60b5b4703089763d0d6f9125e4dd7efae41f08a22882aef96892c4:
+4de142af4b8402f80a47fa812df84f42e283cee7:
+09a2ed303a2fa7027a1dd7c3b0d25121eeed2b644a2fbc17aa0c8aea4524071ede7e7dd7a536d5497f8165d29e4e1b63200f74bbae39fbbbccb29889c62c1f09:
+00:
+
+# regression test for arithmetic error
+# valid
+7582ab1b52e1316e5c13671f43b39ca36b28133cd0832831bcddd0b0f23398cb:
+563357f41b8b23b1d83f19f5667177a67da20b18:
+e6884a6e6b2e60a0b5862251c001e7c79d581d777d6fc11d218d0aecd79f26a30e2ca22cc7c4674f8b72655bc4ee5cb5494ca07c05177656142ac55cc9d33e02:
+00:
+
+# regression test for arithmetic error
+# valid
+dd2d678bae222f3fb6e8278f08cc9e1a66339c926c29ac0a16f9717f5ee18cd8:
+931bbf9c877a6571cf7d4609fc3eb867edd43f51:
+6124c206d864507ea5d984b363b4cf583314db6856a45ded5e61eebff4d5e337e0b4c82b445ae2e52d549d2d961eace2ea01f81158e09a9686baa040db65ad08:
+00:
+
+# regression test for arithmetic error
+# valid
+ccbe7cb2e4bc215cee2f885e1d22f7e0d582b2bbbd782c104e548b152d26fc69:
+44530b0b34f598767a7b875b0caee3c7b9c502d1:
+cfbd450a2c83cb8436c348822fe3ee347d4ee937b7f2ea11ed755cc52852407c9eec2c1fa30d2f9aef90e89b2cc3bcef2b1b9ca59f712110d19894a9cf6a2802:
+00:
+
+
+##########################################
+# Zebra low order & non-canonical points #
+##########################################
+
+# Credits to Henry de Valence for the whole idea:
+# https://hdevalence.ca/blog/2020-10-04-its-25519am
+#
+# To facilitate compatibility in consensus algorithms, Monocypher
+# chooses the maximally permissive (yet still secure) option, used in
+# the ed25519-zebra library.
+#
+# - Low order and non-canonical public keys are accepted.
+# - Low order and non-canonical R are accepted.
+# - Low order components are ignored (batch equation).
+# - (Non-canonical S is still rejected, to avoid malleability problems.)
+#
+#
+# To test this, we test that we do accept all signatures where:
+#
+# - A has low order
+# - R has low order
+# - S is zero
+#
+# Such a signature R || S, with public key A, should verify any message.
+# So we just test every possible combination of A and R. S stays null of
+# course, and we arbitrarily use the empty message.
+#
+# Curve25519 has 8 low-order points:
+#
+# - 0100000000000000000000000000000000000000000000000000000000000000
+# - 26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05
+# - 0000000000000000000000000000000000000000000000000000000000000000
+# - c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a
+# - ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f
+# - c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa
+# - 0000000000000000000000000000000000000000000000000000000000000080
+# - 26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85
+#
+# So this should mean 8*8 possibilities for A and R, meaning 64 tests.
+# But that's not enough. We want to make sure that we accept
+# non-canonical representations as well. And those can happen on a point
+# (x, y) whenever at least one of the following holds:
+#
+# - The y coordinate is between 0 and 18.
+# - The x coordinate is 0.
+#
+# Small y coordinates can have an additional representation (modulo p)
+# that still fit in 255 bits. Null x coordinates can be negated by the
+# parity bit without affecting its value (0 = -0). When we do either
+# (or both) of those things, we get a non-canonical representation of
+# the same point. The low-order points of Curve25519 have 6:
+#
+# - 0100000000000000000000000000000000000000000000000000000000000080
+# - eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f
+# - eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+# - edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f
+# - ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+# - edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+#
+# This means 8 + 6 = 14 possibilities for A and R, and a total of 196
+# combinations, which should all be accepted.
+
+# First though, let's test that the code that checks for malleability
+# doesn't have an off-by-one error and mistakenly accepts an S that is
+# exactly the order of the curve (instead of being zero).
+0000000000000000000000000000000000000000000000000000000000000000:
+:
+0000000000000000000000000000000000000000000000000000000000000000edd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010:
+ff:
+
+# And now the long awaited 196 Zebra tests:
+0100000000000000000000000000000000000000000000000000000000000000:
+:
+01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+0100000000000000000000000000000000000000000000000000000000000000:
+:
+26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc050000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+0100000000000000000000000000000000000000000000000000000000000000:
+:
+00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+0100000000000000000000000000000000000000000000000000000000000000:
+:
+c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+0100000000000000000000000000000000000000000000000000000000000000:
+:
+ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+0100000000000000000000000000000000000000000000000000000000000000:
+:
+c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+0100000000000000000000000000000000000000000000000000000000000000:
+:
+00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+0100000000000000000000000000000000000000000000000000000000000000:
+:
+26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc850000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+0100000000000000000000000000000000000000000000000000000000000000:
+:
+01000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+0100000000000000000000000000000000000000000000000000000000000000:
+:
+eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+0100000000000000000000000000000000000000000000000000000000000000:
+:
+eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+0100000000000000000000000000000000000000000000000000000000000000:
+:
+edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+0100000000000000000000000000000000000000000000000000000000000000:
+:
+ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+0100000000000000000000000000000000000000000000000000000000000000:
+:
+edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05:
+:
+01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05:
+:
+26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc050000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05:
+:
+00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05:
+:
+c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05:
+:
+ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05:
+:
+c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05:
+:
+00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05:
+:
+26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc850000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05:
+:
+01000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05:
+:
+eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05:
+:
+eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05:
+:
+edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05:
+:
+ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05:
+:
+edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+0000000000000000000000000000000000000000000000000000000000000000:
+:
+01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+0000000000000000000000000000000000000000000000000000000000000000:
+:
+26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc050000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+0000000000000000000000000000000000000000000000000000000000000000:
+:
+00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+0000000000000000000000000000000000000000000000000000000000000000:
+:
+c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+0000000000000000000000000000000000000000000000000000000000000000:
+:
+ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+0000000000000000000000000000000000000000000000000000000000000000:
+:
+c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+0000000000000000000000000000000000000000000000000000000000000000:
+:
+00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+0000000000000000000000000000000000000000000000000000000000000000:
+:
+26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc850000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+0000000000000000000000000000000000000000000000000000000000000000:
+:
+01000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+0000000000000000000000000000000000000000000000000000000000000000:
+:
+eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+0000000000000000000000000000000000000000000000000000000000000000:
+:
+eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+0000000000000000000000000000000000000000000000000000000000000000:
+:
+edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+0000000000000000000000000000000000000000000000000000000000000000:
+:
+ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+0000000000000000000000000000000000000000000000000000000000000000:
+:
+edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a:
+:
+01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a:
+:
+26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc050000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a:
+:
+00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a:
+:
+c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a:
+:
+ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a:
+:
+c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a:
+:
+00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a:
+:
+26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc850000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a:
+:
+01000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a:
+:
+eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a:
+:
+eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a:
+:
+edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a:
+:
+ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a:
+:
+edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+:
+01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+:
+26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc050000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+:
+00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+:
+c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+:
+ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+:
+c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+:
+00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+:
+26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc850000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+:
+01000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+:
+eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+:
+eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+:
+edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+:
+ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+:
+edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa:
+:
+01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa:
+:
+26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc050000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa:
+:
+00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa:
+:
+c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa:
+:
+ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa:
+:
+c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa:
+:
+00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa:
+:
+26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc850000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa:
+:
+01000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa:
+:
+eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa:
+:
+eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa:
+:
+edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa:
+:
+ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa:
+:
+edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+0000000000000000000000000000000000000000000000000000000000000080:
+:
+01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+0000000000000000000000000000000000000000000000000000000000000080:
+:
+26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc050000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+0000000000000000000000000000000000000000000000000000000000000080:
+:
+00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+0000000000000000000000000000000000000000000000000000000000000080:
+:
+c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+0000000000000000000000000000000000000000000000000000000000000080:
+:
+ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+0000000000000000000000000000000000000000000000000000000000000080:
+:
+c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+0000000000000000000000000000000000000000000000000000000000000080:
+:
+00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+0000000000000000000000000000000000000000000000000000000000000080:
+:
+26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc850000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+0000000000000000000000000000000000000000000000000000000000000080:
+:
+01000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+0000000000000000000000000000000000000000000000000000000000000080:
+:
+eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+0000000000000000000000000000000000000000000000000000000000000080:
+:
+eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+0000000000000000000000000000000000000000000000000000000000000080:
+:
+edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+0000000000000000000000000000000000000000000000000000000000000080:
+:
+ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+0000000000000000000000000000000000000000000000000000000000000080:
+:
+edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85:
+:
+01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85:
+:
+26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc050000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85:
+:
+00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85:
+:
+c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85:
+:
+ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85:
+:
+c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85:
+:
+00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85:
+:
+26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc850000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85:
+:
+01000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85:
+:
+eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85:
+:
+eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85:
+:
+edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85:
+:
+ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85:
+:
+edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+0100000000000000000000000000000000000000000000000000000000000080:
+:
+01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+0100000000000000000000000000000000000000000000000000000000000080:
+:
+26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc050000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+0100000000000000000000000000000000000000000000000000000000000080:
+:
+00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+0100000000000000000000000000000000000000000000000000000000000080:
+:
+c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+0100000000000000000000000000000000000000000000000000000000000080:
+:
+ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+0100000000000000000000000000000000000000000000000000000000000080:
+:
+c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+0100000000000000000000000000000000000000000000000000000000000080:
+:
+00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+0100000000000000000000000000000000000000000000000000000000000080:
+:
+26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc850000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+0100000000000000000000000000000000000000000000000000000000000080:
+:
+01000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+0100000000000000000000000000000000000000000000000000000000000080:
+:
+eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+0100000000000000000000000000000000000000000000000000000000000080:
+:
+eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+0100000000000000000000000000000000000000000000000000000000000080:
+:
+edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+0100000000000000000000000000000000000000000000000000000000000080:
+:
+ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+0100000000000000000000000000000000000000000000000000000000000080:
+:
+edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+:
+01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+:
+26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc050000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+:
+00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+:
+c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+:
+ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+:
+c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+:
+00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+:
+26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc850000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+:
+01000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+:
+eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+:
+eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+:
+edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+:
+ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+:
+edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff:
+:
+01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff:
+:
+26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc050000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff:
+:
+00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff:
+:
+c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff:
+:
+ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff:
+:
+c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff:
+:
+00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff:
+:
+26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc850000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff:
+:
+01000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff:
+:
+eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff:
+:
+eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff:
+:
+edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff:
+:
+ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff:
+:
+edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+:
+01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+:
+26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc050000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+:
+00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+:
+c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+:
+ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+:
+c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+:
+00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+:
+26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc850000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+:
+01000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+:
+eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+:
+eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+:
+edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+:
+ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+:
+edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff:
+:
+01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff:
+:
+26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc050000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff:
+:
+00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff:
+:
+c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff:
+:
+ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff:
+:
+c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff:
+:
+00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff:
+:
+26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc850000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff:
+:
+01000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff:
+:
+eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff:
+:
+eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff:
+:
+edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff:
+:
+ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff:
+:
+edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff:
+:
+01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff:
+:
+26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc050000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff:
+:
+00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff:
+:
+c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff:
+:
+ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff:
+:
+c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff:
+:
+00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff:
+:
+26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc850000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff:
+:
+01000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff:
+:
+eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff:
+:
+eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff:
+:
+edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff:
+:
+ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000:
+00:
+
+edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff:
+:
+edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000:
+00:
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/gen/vectors/ed_25519ph b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/vectors/ed_25519ph
new file mode 100644
index 0000000..da317a5
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/vectors/ed_25519ph
@@ -0,0 +1,11 @@
+# From RFC 8032
+833fe62409237b9d62ec77587520911e9a759cec1d19755b7da901b96dca3d42:
+ec172b93ad5e563bf4932c70e1245034c35467ef2efd4d64ebf819683467e2bf:
+616263:
+98a70222f0b8121aa9d30f813d683f809e462b469c7ff87639499bb94e6dae4131f85042463c2a355a2003d062adf5aaa10b8c61e636062aaad11c2a26083406:
+
+# Test vector of unknown origin, generated with Bouncy Castle
+17A4AB24CACC54F1ED6AADBDBE0B22328C4F4F9747F75DCEC653796963367476:
+b73f21f54921d332fcb8a32292c65bdafc91358d5383a3145e9aea57c9381440:
+0000000000000000000000000000000000000000000000000000000000000000:
+a8dd09bd36d6588a4535a3e258cd5bb75cef484f8f66bd7631b45bee89fddf03933ea8ea1c2b5636d133b7c5bb63f1ca55251b963cf3c9c13fe43bd773cc8600:
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/gen/vectors/elligator_dir b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/vectors/elligator_dir
new file mode 100644
index 0000000..5080532
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/vectors/elligator_dir
@@ -0,0 +1,115 @@
+d3c41ec20dbe9fc33ccc14823d898066f433a892994ffbcc921e9f5ace519d02:
+170a436471aaa00d817436197fde47fa3320aa040b48d1d2a9f155e15ce3975e:
+
+e03a05ebde6ca000cdc5c539bf48a1d08222483b87693046e00a411a8d93dd34:
+b8e22e654ae391c44be4760a30d13950651d454c7ec71f0bdf7c5669bb22b564:
+
+ec3afb86e23aff9a05c54b4274abb5daf77ad956b5a4a38caf7529866e5f5a3e:
+c1f0588b07c7624ff31b1465354d7a55eee0ce4302f4d91fa88236cfd808501f:
+
+4bdb87edb62cc3b3bf55ff767ac7e3c801c7954d2b5c03d3a26811dd6a8ad929:
+9208e81f3ae66b2cae22b4e0f25ca380ad211a5d44284dc1b741401f0decf964:
+
+b41d9ff0d16193a77fb6d68f5fe9d2dc3f8c722a4511ec3e95a184db3aebe617:
+e5bd8597bf26ef88a9e759495fa74288822ffc2ab77dc344d7641b8fb543fc56:
+
+9a8871e5d563da6919f1f24a91c2cad92ed02412ab1aa8b321d1a84459bb8e2a:
+68df2c7c319d39ea9c0fa1e53da178cb5668989f2657f6d25bdda489da83ea16:
+
+82a4c02a4d8041d5f8899c126bd3889fcff3d5cd63ee8e70bbd64b585fade926:
+bb963159d8ecc37772b0cf00d9ca0ed37a76d9b306a6f8f64ebefc8f861d5f5b:
+
+02712da5a7ed5c4ad4117eff95b84cad5b76e67f7dfbcab69215295a7aac4228:
+d7c1d9ee82b24eac542594a44c6f6653c9a8e19918d612f27f99351b30b8d864:
+
+140b05608cf89a4c4cb822f59ba8b25b300e9a36108d21e5c26a03240b5b2a31:
+058070e8efd599be224ba79dc4ee86823c41c14d89e651a7cd968293753f151a:
+
+ab98be98602474dedc91d15346bcb65bb833dd75518871f70bd26e5bfe712931:
+215524de571c221e08edb912dbe9d9c386d971e4239835ad155de6fa1ff82f28:
+
+538155639021f156812c473ed3abff75063fc4bc5e1e78ecf7f1f7fed8594a33:
+d47e10faef70170b6a3ba0ae4727ba6cb86f16f29a7e7747084310a0f466933f:
+
+d261f7d0d6ce68b6d698c4c61d54ec301dfc94e99b5f47df34a3def8e6568233:
+ce674898f882e57c6cdb41a58171cd75233a082def385ef326e35e99e1c1102d:
+
+6cbb36ab7acb90459bd526f6177bc20c49cdcecb156a14a1f65924c7c219211f:
+119a846d3fd2387621eb3e22bfa95eb7ee3abfda1cf5466ba9401ba08de0152b:
+
+664498366a736b04bc592cf18b8ac7bf94b7fcb985d4b77252844e2eeeb4811f:
+64a92a41815b38eb01e4f6e9aee7e34fa2f8d221e9da0502af542c3c203d262a:
+
+11bef745f0f627555fa65787043ea5231e057fc3bb2afc1903b13f88b494cb00:
+94ce42fb8d978dae1d353ad166b2b5ed24b6967bc0ea90f792f49b841952b844:
+
+dbe6aa62ba71ccef606f3cea913ee21b1c98f46c1a9b4ee33c843cba7cea4127:
+2a3bf5765ba945c5c7df871cecfc7374e0b655260f5eb0553e5901442cfca879:
+
+a8b34d537d591177ed521aaacb4d0917eb6d49b60353d9044d4c6d5fc09fb20d:
+d9fb40edd0f4532024fbdfd74fefe50739820085d0d9f6d9c5e9e9523a05b37d:
+
+c5cc85bd95d812d739c704e80c03416f75ae5f6ff01c929548feee5e599cd907:
+a9b74c3c12e4efb31a1d26c7677773bf223d8cb120bd552a8b6f92eadd35ed48:
+
+949523d0fa2e180612d9a776c655d08e0b16d37dff8457218e3d31eba4531413:
+1bc05bdc88c88eba38270af970abff204cfa8b07bd7fa78ea4ab5c04d1ab317c:
+
+2430a2b8a95d2f415f2f2a2a9257ff03a305ad9f2ecdd84ba0aa6760e4b1bf1d:
+7e73a15142ab131d176716129e69161b33c34ca2464b79703f47ba4cf0dcf92d:
+
+ec76eba0794f9a6215194d5c1bbd6b17502ec6b80d9af029d36c30a705e2291a:
+5563bf02a1878455a049ea1bc3c608f69f215aaac8a678977626daa451e14112:
+
+f9ce1ac470f31bbf3010c779b0a8419634052b28bd8e9ad1f07547d70f609313:
+bacf5302a799ac7f459139f6379efa3083457679dd3d2de7431aa1c7d958c725:
+
+e87526cc0db1adad5d496e25949461c13bc0573e4cccf2e76c2eb535ce40223e:
+b1acbbf9410113a467ae0d3731894cc67a131208af70e2f16758a4be0bb6706c:
+
+7a48adebb692fdb8e5a2176389f3f0bcbdc1956b0d57acac4a8eda87b577e618:
+22997bed0e3c6023e73fb371e6d3c5c3661a87c6f3f787ba6054e699aef5aa64:
+
+
+
+e73507d38bae63992b3f57aac48c0abc14509589288457995a2b4ca3490aa207:
+1e8afffed6bf53fe271ad572473262ded8faec68e5e67ef45ebb82eeba52604f:
+
+95a16019041dbefed9832048ede11928d90365f24a38aa7aef1b97e23954101b:
+794f05ba3e3a72958022468c88981e0be5782be1e1145ce2c3c6fde16ded5363:
+
+f6ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3f:
+9cdb525555555555555555555555555555555555555555555555555555555555:
+
+f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3f:
+9cdb525555555555555555555555555555555555555555555555555555555555:
+
+e4e4c4054fe35a75d9c0f679ad8770d8227e68e4c1e68ce67ee88e6be251a207:
+2fd05944d079627cac0b3c292f72d41b1902b31c48457f42ab35dd10fc4eb013:
+
+48b3753cff3a6d990163e6b60da1e4e5d6a2df78c16c96a52d4fb01ea4ecf70e:
+803e8e870b922ae41883e7b41b534ea191c1eca3f657336ab652b7c683ac0176:
+
+81ac001b08d6577bd91ce991c4c45c46bc84d5465fc9139bf17042ae7313181f:
+eb0f19204beb1f397a0e8b8aeaf70fba944f4707a86d0edf4bf58cb289d6110e:
+
+7afb217bd1eceeac1e133aaa9edb441fa88ea3ae0eaa06cb9911b6d218570f12:
+5e5e130e90024e8378c8f61c7033462c1f2bead4bbfc05d1bbd592d34c620759:
+
+4a70a7e992b43e0b18578e892e954c40a51abdb5a85d300c32f391c45d6ef41b:
+dbd60ec2c1c945a5c53017a0c74e38625514307da10a65aa2523e8d3eba2cb35:
+
+043ddcf4214f24ea6ef6b181071f299aa254a4606ab6a058e0c6fb5598218d37:
+6a2ec7cf38c7b8c76a3e40e5ec25ea7b0f82215b27b31bf3fa2bebfe585ee44b:
+
+1deb473f7d04c152e7e857736715dc7b788aca39a3c96a878019e8999c815c17:
+94d5d8b30212b061affa45fa95a27dd48ad053c9e80d3a066b821affdcbf6970:
+
+23dbfbde05e6c71f118afc0dedb5b9f8dea398b2d764bca68dfc023a9821931d:
+468c7bdac19ed43aa625677d8416337c2b4f48b950755b2b5e7d664b3b3f4d03:
+
+389e38a072cf1b413bb1517c3fe83abebb1cdf3a218abb1b0c01da64c24f592e:
+6d15f8b3b5acf7be2fe9408fd1930f20c56da37f150485ef0e6243d406eb3f60:
+
+d19cfb8cb3940aba546f0be57895e2cc869fe55aab069c5abcf9e7ba6444a806:
+12524580b61c9f88f4f1cd24042002b0df4bc3feb242555bf276f96453c15826:
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/gen/vectors/elligator_inv b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/vectors/elligator_inv
new file mode 100644
index 0000000..efffd5a
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/vectors/elligator_inv
@@ -0,0 +1,22 @@
+#
+# Elligator inverse map
+#
+# - Point
+# - Tweak
+# - status (00 = success, ff = failure)
+#
+
+e6f66fdf6e230c603c5e6e59a254ea1476a13eb9511b9549846781e12e52230a:
+00:
+ff:
+:
+
+46951964003c940878063ccfd0348af42150ca16d2646f2c5856e8338377d800:
+00:
+00:
+2820b6b241e0f68a6c4a7fee3d978228ef3ae45533cd410aa91a415331d8612d:
+
+46951964003c940878063ccfd0348af42150ca16d2646f2c5856e8338377d800:
+01:
+00:
+3cfb87c46c0b4575ca8175e0ed1c0ae9dae79db78df86997c4847b9f20b27718:
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/gen/vectors/poly1305 b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/vectors/poly1305
new file mode 100644
index 0000000..345f25a
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/vectors/poly1305
@@ -0,0 +1,105 @@
+#
+# Empty messages (inspired from RFC 8439)
+#
+0000000000000000000000000000000000000000000000000000000000000000:
+:
+00000000000000000000000000000000:
+
+36e5f6b5c5e06070f0efca96227a863e00000000000000000000000000000000:
+:
+00000000000000000000000000000000:
+
+0000000000000000000000000000000036e5f6b5c5e06070f0efca96227a863e:
+:
+36e5f6b5c5e06070f0efca96227a863e:
+
+79207375626d697373696f6e20746f2036e5f6b5c5e06070f0efca96227a863e:
+:
+36e5f6b5c5e06070f0efca96227a863e:
+
+#
+# No idea where I got this one from.
+# The key looks random, and the message reads
+# "Cryptographic Forum Research Group"
+#
+85d6be7857556d337f4452fe42d506a80103808afb0db2fd4abff6af4149f51b:
+43727970746f6772617068696320466f72756d2052657365617263682047726f7570:
+a8061dc1305136c6c22b8baf0c0127a9:
+
+
+##################################
+### Test vectors from RFC 8439 ###
+##################################
+
+# Notice how, in test vector #2, r is equal to zero. The part of the
+# Poly1305 algorithm where the accumulator is multiplied by r means
+# that with r equal zero, the tag will be equal to s regardless of the
+# content of the text. Fortunately, all the proposed methods of
+# generating r are such that getting this particular weak key is very
+# unlikely.
+
+# Test Vector #1:
+# ==============
+0000000000000000000000000000000000000000000000000000000000000000:
+00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:
+00000000000000000000000000000000:
+
+# Test Vector #2:
+# ==============
+0000000000000000000000000000000036e5f6b5c5e06070f0efca96227a863e:
+416e79207375626d697373696f6e20746f20746865204945544620696e74656e6465642062792074686520436f6e7472696275746f7220666f72207075626c69636174696f6e20617320616c6c206f722070617274206f6620616e204945544620496e7465726e65742d4472616674206f722052464320616e6420616e792073746174656d656e74206d6164652077697468696e2074686520636f6e74657874206f6620616e204945544620616374697669747920697320636f6e7369646572656420616e20224945544620436f6e747269627574696f6e222e20537563682073746174656d656e747320696e636c756465206f72616c2073746174656d656e747320696e20494554462073657373696f6e732c2061732077656c6c206173207772697474656e20616e6420656c656374726f6e696320636f6d6d756e69636174696f6e73206d61646520617420616e792074696d65206f7220706c6163652c207768696368206172652061646472657373656420746f:
+36e5f6b5c5e06070f0efca96227a863e:
+
+# Test Vector #3:
+# ==============
+36e5f6b5c5e06070f0efca96227a863e00000000000000000000000000000000:
+416e79207375626d697373696f6e20746f20746865204945544620696e74656e6465642062792074686520436f6e7472696275746f7220666f72207075626c69636174696f6e20617320616c6c206f722070617274206f6620616e204945544620496e7465726e65742d4472616674206f722052464320616e6420616e792073746174656d656e74206d6164652077697468696e2074686520636f6e74657874206f6620616e204945544620616374697669747920697320636f6e7369646572656420616e20224945544620436f6e747269627574696f6e222e20537563682073746174656d656e747320696e636c756465206f72616c2073746174656d656e747320696e20494554462073657373696f6e732c2061732077656c6c206173207772697474656e20616e6420656c656374726f6e696320636f6d6d756e69636174696f6e73206d61646520617420616e792074696d65206f7220706c6163652c207768696368206172652061646472657373656420746f:
+f3477e7cd95417af89a6b8794c310cf0:
+
+# Test Vector #4:
+# ==============
+1c9240a5eb55d38af333888604f6b5f0473917c1402b80099dca5cbc207075c0:
+2754776173206272696c6c69672c20616e642074686520736c6974687920746f7665730a446964206779726520616e642067696d626c6520696e2074686520776162653a0a416c6c206d696d737920776572652074686520626f726f676f7665732c0a416e6420746865206d6f6d65207261746873206f757467726162652e:
+4541669a7eaaee61e708dc7cbcc5eb62:
+
+# Test Vector #5: If one uses 130-bit partial reduction, does the code
+# handle the case where partially reduced final result is not fully
+# reduced?
+0200000000000000000000000000000000000000000000000000000000000000:
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF:
+03000000000000000000000000000000:
+
+# Test Vector #6: What happens if addition of s overflows modulo 2^128?
+02000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF:
+02000000000000000000000000000000:
+03000000000000000000000000000000:
+
+# Test Vector #7: What happens if data limb is all ones and there is
+# carry from lower limb?
+0100000000000000000000000000000000000000000000000000000000000000:
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF11000000000000000000000000000000:
+05000000000000000000000000000000:
+
+# Test Vector #8: What happens if final result from polynomial part is
+# exactly 2^130-5?
+0100000000000000000000000000000000000000000000000000000000000000:
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFEFEFEFEFEFEFEFEFEFEFEFEFEFEFE01010101010101010101010101010101:
+00000000000000000000000000000000:
+
+# Test Vector #9: What happens if final result from polynomial part is
+# exactly 2^130-6?
+0200000000000000000000000000000000000000000000000000000000000000:
+FDFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF:
+FAFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF:
+
+# Test Vector #10: What happens if 5*H+L-type reduction produces
+# 131-bit intermediate result?
+0100000000000000040000000000000000000000000000000000000000000000:
+E33594D7505E43B900000000000000003394D7505E4379CD01000000000000000000000000000000000000000000000001000000000000000000000000000000:
+14000000000000005500000000000000:
+
+# Test Vector #11: What happens if 5*H+L-type reduction produces
+# 131-bit final result?
+0100000000000000040000000000000000000000000000000000000000000000:
+E33594D7505E43B900000000000000003394D7505E4379CD010000000000000000000000000000000000000000000000:
+13000000000000000000000000000000:
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/gen/vectors/sha512_hmac b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/vectors/sha512_hmac
new file mode 100644
index 0000000..53f742c
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/vectors/sha512_hmac
@@ -0,0 +1,155 @@
+0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b:
+4869205468657265:
+87aa7cdea5ef619d4ff0b4241a1d6cb02379f4e2ce4ec2787ad0b30545e17cdedaa833b7d6b8a702038b274eaea3f4e4be9d914eeb61f1702e696c203a126854:
+
+4a656665:
+7768617420646f2079612077616e7420666f72206e6f7468696e673f:
+164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea2505549758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737:
+
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd:
+fa73b0089d56a284efb0f0756c890be9b1b5dbdd8ee81a3655f83e33b2279d39bf3e848279a722c806b485a47e67c807b946a337bee8942674278859e13292fb:
+
+0102030405060708090a0b0c0d0e0f10111213141516171819:
+cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd:
+b0ba465637458c6990e5a8c5f61d4af7e576d97ff94b872de76f8050361ee3dba91ca5c11aa25eb4d679275cc5788063a5f19741120c4f2de2adebeb10a298dd:
+
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:
+54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a65204b6579202d2048617368204b6579204669727374:
+80b24263c7c1a3ebb71493c1dd7be8b49b46d1f41b4aeec1121b013783f8f3526b56d037e05f2598bd0fd2215d6a1e5295e64f73f63f0aec8b915a985d786598:
+
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:
+5468697320697320612074657374207573696e672061206c6172676572207468616e20626c6f636b2d73697a65206b657920616e642061206c6172676572207468616e20626c6f636b2d73697a6520646174612e20546865206b6579206e6565647320746f20626520686173686564206265666f7265206265696e6720757365642062792074686520484d414320616c676f726974686d2e:
+e37b6a775dc87dbaa4dfa9f96e5e3ffddebd71f8867289865df5a32d20cdc944b6022cac3c4982b10d5eeb55c3e4de15134676fb6de0446065c97440fa8c6a58:
+
+5365244bb43f23f18dfc86c09d62db4741138bec1fbddc282d295e0a098eb5c3e37bd6f4cc16d5ce7d77b1d474a1eb4db313cc0c24e48992ac125196549df9a8:
+:
+d0a556bd1afa8df1ebf9e3ee683a8a2450a7c83eba2daf2e2ff2f953f0cd64da216e67134cf55578b205c8a1e241ba1369516a5ef4298b9c1d31e9d59fc04fe4:
+
+00698977f7102c67b594166919aa99dc3e58c7b6697a6422e238d04d2f57b2c74e4e84f5c4c6b792952df72f1c09244802f0bcf8752efb90e836110703bfa21c:
+01:
+4d1609cc2c2f1ab5ddc35815ae1b5dc046f226bde17ec37a4c89ec46fbd31af2aeb810b196dffdd11924d3772bef26a7a542e0a1673b76b915d41cbd3df0f6a6:
+
+ed6dc65dbeaadbdaab530a0d35f19f78a7bd93e698546c82751bf650c2a44fc8529033d088febeed288fb4c8132a59df0207687640c76dcdb270ac3af5f042f1:
+a78f:
+0757b27e120559d64cd3d6e3cb40d497845375815181bd9b4e74f2189d09d01a1b3ead53701380d988958ed22bc379ace9d47cbcac1d49bfa7e14f1f44804c30:
+
+463c5e696da0ec0d784388be775d1d91d94746aa8d3d2c209f56ac95ea54e7288329f9fb40be4eef35547e64c61dc51a4a1f3380a2b96420f088655ea9d85b97:
+e956c1:
+ac4b1509391814ae5cb5a123e7a060601575c11d81b563bdc52febe6bb2c747b85eeddcb6748c98147a46a1cc9be6776d1a8e82ae4896b9c18da2ff351c56795:
+
+4bc0d32e945cfdafd20d39be3820f9649727cbda5ab5859953a322cbde1ab7a514d7dcd14ba90905e70919bb86b85cfeaa375ee2ce2703711b938c8f4ab5f178:
+b2aa48b3:
+c4ecdbd2efb17640ce6707e2e9d0ee5bfb98b91584bc86ab386437eaa37b0f2eb70500361105416c0dcecff389dc94c723fcff18cb801740962312007a195a23:
+
+aca47f6350941a0efd8c3bac9064a554be337cde7d192f6fbf86d1b4db09b36531165cbae0a634206f71fa400df33352fff60e1fba4009ac6671cd37312bdd98:
+bc993b1db0:
+89af2f5746cab89fda6993e00f1bf0cc70a77188945bb7b5409b536aec5533ad501db6ecfa3e516b580b7df9c8eadb3cf556ccc01668be984335bd5a6255d566:
+
+b3ecae6f25c2f699f158b3ffcd0a7a575583e4c9cb56b5c22ef4273cde6c6734e84d7400749c17e47e8cfccafaf8b50c65eb47dfeb273d5d30a1181e37b27ad0:
+f0361d58291e:
+4037a57aa279b5a07abe9389dcf508be9495a8257dcb3feba3f0801cd57574c30bfddc6df5df6567cd572c4e82735fd4e67b65e85b030f183a7f4457fb7d2c3d:
+
+70ff24a252d65183bdc6b7c88751f850821141a61246727c3240b4f96088ae3278767a822b65735a28ccebe4c874bcb2c942882cb23f9dd87fe08fbaad5ae72f:
+e18da3ebf0ffa4:
+878d488754bc796c70e11d5db77acda2e1796d86146e27d862586740c4d488ed12239e6fb4ab2925afc88168609edc048f8572536fae96e149d73d230b18db66:
+
+dd4e05933d09711ee88cb4c1ceb3600b2b33808bc08d499387b331d9c7af49bc65b55172cf8083385a940e4b864b7b4b73ddf3bd513a6cbcac73878a879b4d06:
+66948029351432c3:
+9968a16eff2b4eeecb2f9d11fcb105e8d8ca59ed4e69131c9de599cd8155fa4f33def1195a6b452263aad9265e16d4951841d7cd33c74c475da04497c02922ea:
+
+fbd32caf8984fc4376d10daa7288db8e6e74464bdd94b448adab4497b319e9a6dcce542f82a7ff2e775d12477c880e460a9eab8efc49fcfc8c5476cb4b08954a:
+38a2586a2883953cc4:
+e0c69bd034cdec5b48150fdf3a4383456a7626d4405df52dc6c2bc8fe93bd87e369e06a781ed80ba8b1fe1146c4df82b6a514412358b31b77b9b79c7a91ec9e4:
+
+fd4c3f6b2137513616c28ed4d8638f867ad0b97188b73fc9b36f3d52b82d72a49b9dc1b8b25397eb448054a8d38d838e7a88b4df9c263aea1b968771d5ac5756:
+86b4e61b3b7d650044ad:
+29345d7da44e2f228e8d502e29fb655da3676a481f9947c8482502ce070b3da5065589d84c02a05cd774b4bd5a15b668c59bafc192695aec43e5df3a82301745:
+
+f95baea535f477d22b405c67d927f59a9e042c46297a1681bcc16fdbe1b2cd59675a221351a78075981e7eb4998066768801cbd7a85231114d7f27f9bdf24899:
+5a34dee4e0982d458efffb:
+63867bb3e82bd4a5f715b3dd67ba3625666e458c5e3d75804709f80b6dde6f774ea223ba9e2536c60ab636dd12d07b217234a490ea9cae4fe673215d33f8c57a:
+
+4d76ae95a123207e01c6d22d8b587e63ba682963e50961afff531160a9b9aac6c772c5e8bf918ddecbeb56455ea64710e51ac21e3bb9af4b24eaa8535b3c2924:
+2c31f2d986f68a6d6a96c4b0:
+9d4f9549ac134a6f60f17fd0fbc80f55426afa73cdaf84a806d98dfffc94263178116f76aadca95a9243a9128f5f66d3e7f33e72603d4b35ab90ab7d1e870ad7:
+
+0da7fa1f5d217951e3e343cda81f232deb71764eb49e8510bc28dba8eb62afa2a98b6f0536adb10250c74878fe649f47bbafdf3f722fa150f66e83f65f606ab0:
+83511de190663c9c4229ace901:
+11bd76ba2fd5684e3faadd44abc05d32661472ae4c75fd69e62e47a2d462e483ab5fd374070e648017250934d486fed55e68f4338547fb5dc54d4bed894c1c2f:
+
+cec9e9f25ed9a017004a7882b1e44e8bd8fa3203c50cb6058455ed4f2a036788d46fcd328327d0d86b1abae69f7bbb96e3d66373ec8bd45075890879a83f4d33:
+80dcd8ba66f98b51094144e9b8bd:
+c69f1787bf7804bfffd9da7e62f58c1c9f599ccae2ed4fc6abda1be48620afc797d59d4adb396e1fa5d18b8c1aa1c7c15218a9f9e3aab226119adad742641089:
+
+bbe25649ecdf54ae0028fb923cc8c28ec00e10e2d44214590781238a143b75d54efb037eb9f53082a8ab3d8876daf4dbdc2483c4ba222797fe20da3b7730368b:
+33f630088c0d24cda98caff1a3afc7:
+c803ca833e851418a3d9ed764f8c83f481060141eb1b2bf64d7ee7991b041c48bfc747bce13d69722f63944085cef8e7a166270530fe31a2a525a99b8a75f1b1:
+
+f5e2b9e2313f4f807cb3a924a7d4943fc3fb475d8f1a1b40ce09a37770f621af8977729cadf986c98c75f08a4fab4280538e09e7e51e87a8d62c03411bdb8d24:
+74ef623c83275ae99745bff7e6142afa:
+471055f7a2d44758e7d7837db85c33626b8306760eb45e18d4ba8dfbcd0d4279fcf8b539ef7b165eeabf5457ee2c41e52d07e9121da02c988f08162f86bdf208:
+
+8e323d5fb4752d92a6d905c512b287d07b21ae50002d026ff0388e1593bde9998dd02321e200d148f5fa2e824b37e9f5a77441794b840bedd552d1051c1ddd8c:
+4daa229b009b8984354c2ec3e7973e0042:
+93a2137cc84e2fa1439d7c239767b3ce653d634c58a4590eb61af9d3ef986445220aff3554de45a1b0933fa06d3d64460418910977d8d9ddb2eb04963c816841:
+
+465bc1ab2125cca29729d01df044e393b0677defdd939280a3aa141224efa06457e623056d02f6c36eca3dfc4a7476dd36b97d0c2d60c7672129189e73b6af8f:
+dd84599b47ba9ae9f2ad0c8eac678485433eb6b1dfb7c998:
+9fff43a83c71833211f9d60eeef4166965c41a37c76634b1bdf9c5291df75dc877668f2287bcf8108ea9e03d061a708db2db08687eda61fa97b1ca92dcf22b92:
+
+b90226798dff2ffb91d1ee4103f26397d0bf84c13c1ec717392c5fe1d4d0f4dc790236d759fa1be852e305da585a3dbde0d3912bea60d6b140c25645eb00943f:
+aa29c372f136993c65ace5e1d62078806eb787913bb35af33371056359d354b2:
+493a727536b07d434a7fc8df6b70989148a8d94cadb9761ad845ac5fde2068f9565e68607b531b0f307d7c17ce0a2ba69fb1ac1b0c716f93904eec75669e70b7:
+
+af1bb91775cb40c73983f119c927a2ce8f7b954a6274ecc1cd96019e5c417af4b094376194eae71c7f68f3345654d5d9f8198a697b41ae251e82308accd935bd:
+75ededdfa7f1df1dc144fb195b27e454640e3f897cb564222f05e8aab0c6024f90472afea6e7254ed25134ea43452a:
+b53d564086a745b10d88a48b50ed8b53f4c83fd12bf56a75108074de9b343cdf0668ce8b6a3d884ba2da5f4c957f1319e26c0813c99a4269c171ad80981013a2:
+
+513e0e7622eabcb6bfc81669dac903df46daea1240f32248bbf4fc61f1f9b13b2c3fe1bcc97540d30065be9eee41e51748bc42c16a8c8269fbe2b6f625c19228:
+81d8650937f50871a66af71605ea4fa9d6c5d7a375774c2280eb34aefcee8c0ef83345bc547e4de7cbea482369b25a93:
+9d942e4585742ba118bda6e132510af3b9297047d364f76b2a0d1fc803849b06ccac0eaa427934055c9d2e5a5da19cf17299ffdab65089580d10ff7207c9ed03:
+
+627c9a72247d07b0cec8346277468311c7401fc4cecaea8e22e13ece4b352c8f7a7eb1ba81ce348a08670438c97b8d9e883614d550f1ff16d636975c59988c2d:
+118e0468cbb52f93a3396ebfaa114881a98a4101f4ff912ced47ecfc73b27f52205b7a5d4f3899506f9e34ebf99460da7a:
+a186e08c7731d4bbb1d5342a105ef48f5353c5c542277de607831fcbbc8d0b9fd509c74bf9e352ee739792ee3cd6382f96e70adb589fdf1fb031d43eef1a595f:
+
+1e981d0cbbad5bea9480d836b4704bf3147663b6ea59e1e0a280fb45d9b85d445dc972159dde301c6f1e66681f95642dbb9a9218c00d0cd724cb02f3bcaea2ea:
+440dff390688c9fde31c17fdb61c1d13899f9544a986324c34d5eb07bef9a4436297f4a7fe16de5dd7b24e0c7c129051efe6f2dd0a21aec05c3e3c8f6fa30d9c0cbd60d840d14f0b2a928bc7189b9de4a6a731151d6b31e6a0ecae75095434737be8c3db11a6a697d0616c78b97041de:
+c52eb5d18e90687248342a84dc0241c680e992b88b1409275df7e347c99169a50cd780eb4726ad759e2a027fb091354e3d7c7aba8a21f8acd1d0e21236af5f98:
+
+ee8aea2a52eb7e0c1120ab736b1a825b12610063de9642c594766c020cb87314d8ac94b13072bfbf3c019b4aacb1d2695cdd7563a26f574e12559906784d853c:
+a3951f1d18135602fdadceeef5741c24ad22756160d0c55e51b788af952adaeb13e18c24c6b09672f405d7ec3d49b0bd86c7f8691b6f69af49175423215cf57d7c08a54ab0b0293e685c9aa250f1599d78193a00af822dec4b56fdb41f0343ab2cf85ea27bb2e650930f5e8ca836833903b053b3e06899b4012a6532978d90:
+d3678ca7c5c1aa21f12eccc21a1add0b3eb12ccd134033570468191e51b058c61f2a7d88f2ca6c652c29c65c491bf1f0252bc157bdd77436ff55204eac6dfb0d:
+
+ecd1861a12eaee48aef1d7ed278223b50d3416dbff81e976c56ecd4b1a1bc8892b584cbcc72370ff5e976a6af1790caa32f9ea912855914c0315979578fbf165:
+5779c56373a8e5db43bd65c0453ce23144230d43666d717a3b59d2e90f0e10732376831d7281cb23dd5566e5f8c627d00d39650139ceb87cd47e921d65d6c1cc7712ac4bd75bda8828e68abc968f4160ed91b28946c9d706b0360bbbdd65f47ef9983c50f2d09d05c3674c0943ea4af54c381089f9b846dd69ce908e0f6eaaaf:
+d377e4efc39f25ca751452e79dcb5661f8adcc06570bd3f710e03854e032286ca477e6a620647958fd31706463b542ddf617757875f349c61109358d04f6dc58:
+
+71aadbf330ea133b46c939d12e603896902e8df638597c98872dfb5aecd5161bc84095221de3222367012f45c6d70701e862ab000e782e91b505b21b4e212c38:
+e6d7b0280d2f7df83fd26562fcdea2597cf687a9c9fa194f655c44d3271b881f28adc436db8e0437ff4dc5d38356271c338829c3e2d9ba4ac1777c94886983d4b72c275bc00e4f7b06c5ce38a2fe549fe53761857f236da705fd03790b41cc6f759f41aa206feca7ba5486f4fc9d09f35c8e0887241291882010414ae41b8b384a715a409be13da17bfd60d3fbd4b8cb3cc7c26043807264a20b9a5c02725e742fff03e1806b38af357ebf8c79fc4c38b007bf0613286cf063e45482375475e6c426d4f70057cd92efcb2dfe86e45bdea399273a5e0f142221fae206800555c01b18533295f577e23a9a7a0aa072823002b9096501174d3bc4aac33e0dc600:
+0c1cbb2f196d3d1af5f982a330bf1d9accaada72cf6c254658cb32bfd8705481abd2e163a73338700f0d961ca02a31b600df04faf311cd06498557831102f80f:
+
+14d93759fc28f3319ab74b8167c974e800f032344dc2747ec0f4945061a47827:
+:
+68934dbe948d9a77a5e0a92ed98254fa3b6c93c8bf5eeaa912b7dfdf762b37192c5d8523bcab9ad71b09bf96d8454188d001c7f2077eb641199f5731b9f94669:
+
+9fa371f36fb273d514fd628cb938067a4bae32a19a1e045a7d6d7f6de3751cbf:
+311bbf722d322cd7a0710f480fc66518:
+16345f6a6ca6e78d4ccac30b48d76691d6442420efa113c15ef127b538b5b024018b7d2db4bc3ed3424251ab6b8b6c3cb108b0beda842dc3e68e63400287e5cd:
+
+6313f1526bc220f20dde1e64ced8597279586d1e15aad05ad591d841b369284f:
+f744fa3933e16d8bf524afaeb34c715653a9cfb01fa45fe1fb68e701fe1487ca:
+b88d1ba03e2799200a447550d18e310697a57974f513df77eb07bbe315ba5fef397eeb81ad9071680bcc6c70f6b252ade35b4a4040279ec01b86e40b98770e39:
+
+dd1e0bdbb6b60862176484f3669da531455f1cd714f999c29f08b851055fee8d72186d376c236f4e16cba7a25cba879fb2753deca4459aaebc6f6de625d99af330:
+:
+7e4f7d844b3ba0e025b66de7cc6227bc50d4e174930251bfff3df36c3900b5b76b00095a896d0f96842e37b6134df40760307699534d6670f138974ee1c58d94:
+
+432b311ebcfd46ecfcd3cc706ebd05c787dfbe1855fdcfce8d50c9a00f72b65a8d42acec335b4e07d544c92fd7b1d38543ac6e0fc04c26d88de8dd974af69e24d7:
+36b1fbe8f1335e7c0399c24730906420:
+2cfb688f30b10534da9377a4b3fbee1dec161cb288ac8b758793838b45ab953979dadf27817f477c9ebf23cfdcbacb60b81038e08bc4fc3180bd2a1ee805976a:
+
+17f720f09df5972af9b9c63e10043284608900d50b7955db3b4e2679cb4120be2c9b9e2aa1a5743eb519792822c326b4d890b5554d1cb0eb71081b7569a2f04df7:
+57167c2524a55289687b83a40d3a69bc90adc53ad247020b88897f9b95d1516d:
+4f70267b98fceb4f662901bd18fb4c81ac164281dd0ece43028a3c2a65ca213aedf1bd207f0939bd879bbe20fd09cdeb20246e6539766add08b3adc5143d2bd9:
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/gen/vectors/x25519 b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/vectors/x25519
new file mode 100644
index 0000000..4e2cb17
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/vectors/x25519
@@ -0,0 +1,3168 @@
+# X25519 test vectors
+
+
+# Random tests I don't quite remember come from
+a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4:
+e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c:
+c3da55379de9c6908e94ea4df28d084f32eccf03491c71f754b4075577a28552:
+
+4b66e9d4d1b4673c5ad22691957d6af5c11b6421e0ea01d42ca4169e7918ba0d:
+e5210f12786811d3f4b7959d0538ae2c31dbe7106fc03c3efc4cd549c715a493:
+95cbde9476e8907d7aade45cb4b873f88b595a68799fa152e6f8f7647aac7957:
+
+77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a:
+de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f:
+4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742:
+
+5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb:
+8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a:
+4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742:
+
+#
+# First iteration of the iterated scalarmult test
+#
+0900000000000000000000000000000000000000000000000000000000000000:
+0900000000000000000000000000000000000000000000000000000000000000:
+422c8e7a6227d7bca1350b3e2bb7279f7897b87bb6854b783c60e80311ae3079:
+
+
+# Daniel Bleichenbacher test vectors from Wycheproof:
+# https://github.com/google/wycheproof/blob/master/testvectors/x25519_test.json
+#
+# Notes:
+#
+# - LowOrderPublic: The curves and its twists contain some points of low
+# order. This test vector contains a public key with such a
+# point. While many libraries reject such public keys, doing so is not
+# a strict requirement according to RFC 7748.
+#
+# - NonCanonicalPublic: The public key is in non-canonical form. RFC
+# 7749, section 5 defines the value that this public key
+# represents. Section 7 of the same RFC recommends accepting such
+# keys. If a non-canonical key is accepted then it must follow the
+# RFC.
+#
+# - SmallPublicKey: The public key is insecure and does not belong to a
+# valid private key. Some libraries reject such keys.
+# (Note from Monocypher: we accept all keys).
+#
+# - Twist: Public keys are either points on a given curve or points on
+# its twist. The functions X25519 and X448 are defined for points on a
+# twist with the goal that the output of computations do not leak
+# private keys. Implementations may accept or reject points on a
+# twist. If a point multiplication is performed then it is important
+# that the result is correct, since otherwise attacks with invalid
+# keys are possible.
+#
+# - ZeroSharedSecret: Some libraries include a check that the shared
+# secret is not all-zero. This check is described in Section 6.1 of
+# RFC 7748.
+# (Note from Monocypher: we do not, user must check manually.)
+
+# normal case
+# valid
+c8a9d5a91091ad851c668b0736c1c9a02936c0d3ad62670858088047ba057475:
+504a36999f489cd2fdbc08baff3d88fa00569ba986cba22548ffde80f9806829:
+436a2c040cf45fea9b29a0cb81b1f41458f863d0d61b453d0a982720d6d61320:
+
+# public key on twist
+# acceptable: Twist
+d85d8c061a50804ac488ad774ac716c3f5ba714b2712e048491379a500211958:
+63aa40c6e38346c5caf23a6df0a5e6c80889a08647e551b3563449befcfc9733:
+279df67a7c4611db4708a0e8282b195e5ac0ed6f4b2f292c6fbd0acac30d1332:
+
+# public key on twist
+# acceptable: Twist
+c8b45bfd32e55325d9fd648cb302848039000b390e44d521e58aab3b29a6964b:
+0f83c36fded9d32fadf4efa3ae93a90bb5cfa66893bc412c43fa7287dbb99779:
+4bc7e01e7d83d6cf67632bf90033487a5fc29eba5328890ea7b1026d23b9a45f:
+
+# public key on twist
+# acceptable: Twist
+f876e34bcbe1f47fbc0fddfd7c1e1aa53d57bfe0f66d243067b424bb6210be51:
+0b8211a2b6049097f6871c6c052d3c5fc1ba17da9e32ae458403b05bb283092a:
+119d37ed4b109cbd6418b1f28dea83c836c844715cdf98a3a8c362191debd514:
+
+# public key on twist
+# acceptable: Twist
+006ac1f3a653a4cdb1d37bba94738f8b957a57beb24d646e994dc29a276aad45:
+343ac20a3b9c6a27b1008176509ad30735856ec1c8d8fcae13912d08d152f46c:
+cc4873aed3fcee4b3aaea7f0d20716b4276359081f634b7bea4b705bfc8a4d3e:
+
+# public key on twist
+# acceptable: Twist
+08da77b26d06dff9d9f7fd4c5b3769f8cdd5b30516a5ab806be324ff3eb69e60:
+fa695fc7be8d1be5bf704898f388c452bafdd3b8eae805f8681a8d15c2d4e142:
+b6f8e2fcb1affc79e2ff798319b2701139b95ad6dd07f05cbac78bd83edfd92e:
+
+# public key on twist
+# acceptable: Twist
+d03edde9f3e7b799045f9ac3793d4a9277dadeadc41bec0290f81f744f73775f:
+0200000000000000000000000000000000000000000000000000000000000000:
+b87a1722cc6c1e2feecb54e97abd5a22acc27616f78f6e315fd2b73d9f221e57:
+
+# public key on twist
+# acceptable: Twist
+e09d57a914e3c29036fd9a442ba526b5cdcdf28216153e636c10677acab6bd6a:
+0300000000000000000000000000000000000000000000000000000000000000:
+a29d8dad28d590cd3017aa97a4761f851bf1d3672b042a4256a45881e2ad9035:
+
+# public key on twist
+# acceptable: Twist
+e0ed78e6ee02f08bec1c15d66fbbe5b83ffc37ea14e1512cc1bd4b2ea6d8066f:
+ff00000000000000000000000000000000000000000000000000000000000000:
+e703bc8aa94b7d87ba34e2678353d12cdaaa1a97b5ca3e1b8c060c4636087f07:
+
+# public key on twist
+# acceptable: Twist
+a8a1a2ec9fa9915ae7aace6a37c68591d39e15995c4ef5ebd3561c02f72dda41:
+ffff000000000000000000000000000000000000000000000000000000000000:
+ff5cf041e924dbe1a64ac9bdba96bdcdfaf7d59d91c7e33e76ed0e4c8c836446:
+
+# public key on twist
+# acceptable: Twist
+a8c9df5820eb399d471dfa3215d96055b3c7d0f4ea49f8ab028d6a6e3194517b:
+0000010000000000000000000000000000000000000000000000000000000000:
+a92a96fa029960f9530e6fe37e2429cd113be4d8f3f4431f8546e6c76351475d:
+
+# public key on twist
+# acceptable: Twist
+d0d31c491cbd39271859b4a63a316826507b1db8c701709fd0ffe3eb21c4467c:
+ffffff0f00000000000000000000000000000000000000000000000000000000:
+9f8954868158ec62b6b586b8cae1d67d1b9f4c03d5b3ca0393cee71accc9ab65:
+
+# public key on twist
+# acceptable: Twist
+d053e7bf1902619cd61c9c739e09d54c4147f46d190720966f7de1d9cffbbd4e:
+ffffffff00000000000000000000000000000000000000000000000000000000:
+6cbf1dc9af97bc148513a18be4a257de1a3b065584df94e8b43c1ab89720b110:
+
+# public key on twist
+# acceptable: Twist
+a021d75009a4596e5a33f12921c10f3670933bc80dde3bba22881b6120582144:
+0000000000001000000000000000000000000000000000000000000000000000:
+38284b7086095a9406028c1f800c071ea106039ad7a1d7f82fe00906fd90594b:
+
+# public key on twist
+# acceptable: Twist
+a89c6687f99bd569a01fd8bd438236160d15ce2c57c1d71ebaa3f2da88233863:
+0000000000000001000000000000000000000000000000000000000000000000:
+c721041df0244071794a8db06b9f7eaeec690c257265343666f4416f4166840f:
+
+# public key on twist
+# acceptable: Twist
+68964bca51465bf0f5ba524b1482ceff0e960a1ed9f48dcc30f1608d0e501a50:
+ffffffffffffffff000000000000000000000000000000000000000000000000:
+25ff9a6631b143dbdbdc207b38e38f832ae079a52a618c534322e77345fd9049:
+
+# public key on twist
+# acceptable: Twist
+a8e56bb13a9f2b33b8e6750b4a6e6621dc26ae8c5c624a0992c8f0d5b910f170:
+0000000000000000000000000000000000000000000000000100000000000000:
+f294e7922c6cea587aefe72911630d50f2456a2ba7f21207d57f1ecce04f6213:
+
+# public key on twist
+# acceptable: Twist
+e045f55c159451e97814d747050fd7769bd478434a01876a56e553f66384a74c:
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000:
+ff4715bd8cf847b77c244ce2d9b008b19efaa8e845feb85ce4889b5b2c6a4b4d:
+
+# public key on twist
+# acceptable: Twist
+105d621e1ef339c3d99245cfb77cd3a5bd0c4427a0e4d8752c3b51f045889b4f:
+ffffff030000f8ffff1f0000c0ffffff000000feffff070000f0ffff3f000000:
+61eace52da5f5ecefafa4f199b077ff64f2e3d2a6ece6f8ec0497826b212ef5f:
+
+# public key on twist
+# acceptable: Twist
+d88a441e706f606ae7f630f8b21f3c2554739e3e549f804118c03771f608017b:
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000:
+ff1b509a0a1a54726086f1e1c0acf040ab463a2a542e5d54e92c6df8126cf636:
+
+# public key on twist
+# acceptable: Twist
+80bbad168222276200aafd36f7f25fdc025632d8bf9f6354bb762e06fb63e250:
+0000000000000000000000000000000000000000000000000000000000800000:
+f134e6267bf93903085117b99932cc0c7ba26f25fca12102a26d7533d9c4272a:
+
+# public key on twist
+# acceptable: Twist
+68e134092e94e622c8a0cd18aff55be23dabd994ebdee982d90601f6f0f4b369:
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1f:
+74bfc15e5597e9f5193f941e10a5c008fc89f051392723886a4a8fe5093a7354:
+
+# public key on twist
+# acceptable: Twist
+e8e43fc1ebac0bbc9b99c8035ee1ac59b90f19a16c42c0b90f96adfcc5fdee78:
+0000000000000000000000000000000000000000000000000000000000000020:
+0d41a5b3af770bf2fcd34ff7972243a0e2cf4d34f2046a144581ae1ec68df03b:
+
+# public key on twist
+# acceptable: Twist
+18bffb16f92680a9e267473e43c464476d5372ddd1f664f3d0678efe7c98bc79:
+000000fcffff070000e0ffff3f000000ffffff010000f8ffff0f0000c0ffff7f:
+5894e0963583ae14a0b80420894167f4b759c8d2eb9b69cb675543f66510f646:
+
+# public key on twist
+# acceptable: Twist
+300305eb002bf86c71fe9c0b311993727b9dc618d0ce7251d0dfd8552d17905d:
+ffffffffffffff00000000000000ffffffffffffff00000000000000ffffff7f:
+f8624d6e35e6c548ac47832f2e5d151a8e53b9290363b28d2ab8d84ab7cb6a72:
+
+# public key on twist
+# acceptable: Twist
+80da9f02842247d4ade5ddbac51dbce55ea7dca2844e7f97ab8987ce7fd8bc71:
+00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffff7f:
+bfe183ba3d4157a7b53ef178613db619e27800f85359c0b39a9fd6e32152c208:
+
+# public key on twist
+# acceptable: Twist
+806e7f26ca3246de8182946cbed09f52b95da626c823c7b50450001a47b7b252:
+edfffffffffffffffffffffffffffeffffffffffffffffffffffffffffffff7f:
+bca4a0724f5c1feb184078448c898c8620e7caf81f64cca746f557dff2498859:
+
+# public key on twist
+# acceptable: Twist
+58354fd64bc022cba3a71b2ae64281e4ea7bf6d65fdbaead1440eeb18604fe62:
+edfffffffffffffeffffffffffffffffffffffffffffffffffffffffffffff7f:
+b3418a52464c15ab0cacbbd43887a1199206d59229ced49202300638d7a40f04:
+
+# public key on twist
+# acceptable: Twist
+f0019cf05159794cc8052b00c2e75b7f46fb6693c4b38c02b12a4fe272e8556a:
+edffffffffffefffffffffffffffffffffffffffffffffffffffffffffffff7f:
+fcde6e0a3d5fd5b63f10c2d3aad4efa05196f26bc0cb26fd6d9d3bd015eaa74f:
+
+# public key on twist
+# acceptable: Twist
+d0fca64cc5f3a0c8e75c824e8b09d1615aa79aeba139bb7302e2bb2fcbe54b40:
+edfeffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+7d62f189444c6231a48afab10a0af2eee4a52e431ea05ff781d616af2114672f:
+
+# public key on twist
+# acceptable: Twist
+d02456e456911d3c6cd054933199807732dfdc958642ad1aebe900c793bef24a:
+eaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+07ba5fcbda21a9a17845c401492b10e6de0a168d5c94b606694c11bac39bea41:
+
+# public key = 0
+# acceptable: SmallPublicKey, LowOrderPublic, ZeroSharedSecret
+88227494038f2bb811d47805bcdf04a2ac585ada7f2f23389bfd4658f9ddd45e:
+0000000000000000000000000000000000000000000000000000000000000000:
+0000000000000000000000000000000000000000000000000000000000000000:
+
+# public key = 1
+# acceptable: SmallPublicKey, LowOrderPublic, ZeroSharedSecret
+48232e8972b61c7e61930eb9450b5070eae1c670475685541f0476217e48184f:
+0100000000000000000000000000000000000000000000000000000000000000:
+0000000000000000000000000000000000000000000000000000000000000000:
+
+# edge case public key
+# valid
+a8386f7f16c50731d64f82e6a170b142a4e34f31fd7768fcb8902925e7d1e25a:
+0400000000000000000000000000000000000000000000000000000000000000:
+34b7e4fa53264420d9f943d15513902342b386b172a0b0b7c8b8f2dd3d669f59:
+
+# edge case public key
+# valid
+d05abd08bf5e62538cb9a5ed105dbedd6de38d07940085072b4311c2678ed77d:
+0001000000000000000000000000000000000000000000000000000000000000:
+3aa227a30781ed746bd4b3365e5f61461b844d09410c70570abd0d75574dfc77:
+
+# edge case public key
+# valid
+f0b8b0998c8394364d7dcb25a3885e571374f91615275440db0645ee7c0a6f6b:
+0000001000000000000000000000000000000000000000000000000000000000:
+97755e7e775789184e176847ffbc2f8ef98799d46a709c6a1c0ffd29081d7039:
+
+# edge case public key
+# valid
+d00c35dc17460f360bfae7b94647bc4e9a7ad9ce82abeadb50a2f1a0736e2175:
+0000000001000000000000000000000000000000000000000000000000000000:
+c212bfceb91f8588d46cd94684c2c9ee0734087796dc0a9f3404ff534012123d:
+
+# edge case public key
+# valid
+385fc8058900a85021dd92425d2fb39a62d4e23aef1d5104c4c2d88712d39e4d:
+ffffffffffff0f00000000000000000000000000000000000000000000000000:
+388faffb4a85d06702ba3e479c6b216a8f33efce0542979bf129d860f93b9f02:
+
+# edge case public key
+# valid
+e0614b0c408af24d9d24c0a72f9137fbd6b16f02ccc94797ea3971ab16073a7f:
+ffffffffffffff00000000000000000000000000000000000000000000000000:
+877fec0669d8c1a5c866641420eea9f6bd1dfd38d36a5d55a8c0ab2bf3105c68:
+
+# edge case public key
+# valid
+f004b8fd05d9fffd853cdc6d2266389b737e8dfc296ad00b5a69b2a9dcf72956:
+0000000000000000010000000000000000000000000000000000000000000000:
+180373ea0f23ea73447e5a90398a97d490b541c69320719d7dd733fb80d5480f:
+
+# edge case public key
+# valid
+e80bf0e609bf3b035b552f9db7e9ecbc44a04b7910b1493661a524f46c3c2277:
+ffffffffffffffffffffffffffff000000000000000000000000000000000000:
+208142350af938aba52a156dce19d3c27ab1628729683cf4ef2667c3dc60cf38:
+
+# edge case public key
+# valid
+48890e95d1b03e603bcb51fdf6f296f1f1d10f5df10e00b8a25c9809f9aa1a54:
+0000000000000000000000000000010000000000000000000000000000000000:
+1c3263890f7a081cefe50cb92abd496582d90dcc2b9cb858bd286854aa6b0a7e:
+
+# edge case public key
+# valid
+a806f1e39b742615a7dde3b29415ed827c68f07d4a47a4d9595c40c7fccb9263:
+ffffffffffffffffffffffffffffffff00000000000000000000000000000000:
+56128e78d7c66f48e863e7e6f2caa9c0988fd439deac11d4aac9664083087f7a:
+
+# edge case public key
+# valid
+9899d5e265e1fc7c32345227d6699a6d6b5517cf33b43ab156ee20df4878794e:
+0000000000000000000000000000000001000000000000000000000000000000:
+30eca56f1f1c2e8ff780134e0e9382c5927d305d86b53477e9aeca79fc9ced05:
+
+# edge case public key
+# valid
+d842316e5476aeaee838204258a06f15de011ba40b9962705e7f6e889fe71f40:
+ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000:
+cb21b7aa3f992ecfc92954849154b3af6b96a01f17bf21c612da748db38eb364:
+
+# edge case public key
+# valid
+a0933ee30512b25ee4e900aaa07f73e507a8ec53b53a44626e0f589af4e0356c:
+ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000:
+c5caf8cabc36f086deaf1ab226434098c222abdf8acd3ce75c75e9debb271524:
+
+# edge case public key
+# valid
+38d6403e1377734cdce98285e820f256ad6b769d6b5612bcf42cf2b97945c073:
+0000000000000000000000000000000000000000000000000000000001000000:
+4d46052c7eabba215df8d91327e0c4610421d2d9129b1486d914c766cf104c27:
+
+# edge case public key
+# valid
+182191b7052e9cd630ef08007fc6b43bc7652913be6774e2fd271b71b962a641:
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03:
+a0e0315175788362d4ebe05e6ac76d52d40187bd687492af05abc7ba7c70197d:
+
+# edge case public key
+# valid
+106221fe5694a710d6e147696c5d5b93d6887d584f24f228182ebe1b1d2db85d:
+ffffff0f000000ffffff0f000000ffffff0f000000ffffff0f000000ffffff0f:
+5e64924b91873b499a5402fa64337c65d4b2ed54beeb3fa5d7347809e43aef1c:
+
+# edge case public key
+# valid
+d035de9456080d85a912083b2e3c7ddd7971f786f25a96c5e782cf6f4376e362:
+000000fcffff030000e0ffff1f000000ffffff000000f8ffff070000c0ffff3f:
+c052466f9712d9ec4ef40f276bb7e6441c5434a83efd8e41d20ce83f2dbf5952:
+
+# edge case public key
+# valid
+a8f37318a4c760f3cb2d894822918735683cb1edacf3e666e15694154978fd6d:
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3f:
+d151b97cba9c25d48e6d576338b97d53dd8b25e84f65f7a2091a17016317c553:
+
+# edge case public key
+# valid
+20d4d624cf732f826f09e8088017742f13f2da98f4dcf4b40519adb790cebf64:
+edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5f:
+5716296baf2b1a6b9cd15b23ba86829743d60b0396569be1d5b40014c06b477d:
+
+# edge case public key
+# valid
+d806a735d138efb3b404683c9d84485ab4af540d0af253b574323d8913003c66:
+edffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fff7f:
+ddbd56d0454b794c1d1d4923f023a51f6f34ef3f4868e3d6659307c683c74126:
+
+# edge case public key
+# valid
+184198c6228177f3ef41dc9a341258f8181ae365fe9ec98d93639b0bbee1467d:
+fffffffffeffff7ffffffffffeffff7ffffffffffeffff7ffffffffffeffff7f:
+8039eebed1a4f3b811ea92102a6267d4da412370f3f0d6b70f1faaa2e8d5236d:
+
+# edge case public key
+# valid
+f0a46a7f4b989fe515edc441109346ba746ec1516896ec5b7e4f4d903064b463:
+edfffffffffffffffffffffffffffffffffffffffffffffffffffffffeffff7f:
+b69524e3955da23df6ad1a7cd38540047f50860f1c8fded9b1fdfcc9e812a035:
+
+# edge case public key
+# valid
+881874fda3a99c0f0216e1172fbd07ab1c7df78602cc6b11264e57aab5f23a49:
+edfffffffffffffffffffffffffffffffffffffffffffffffeffffffffffff7f:
+e417bb8854f3b4f70ecea557454c5c4e5f3804ae537960a8097b9f338410d757:
+
+# edge case public key
+# valid
+b8d0f1ae05a5072831443150e202ac6db00322cdf341f467e9f296588b04db72:
+edfffffffffffffffffffffffffffffffeffffffffffffffffffffffffffff7f:
+afca72bb8ef727b60c530c937a2f7d06bb39c39b903a7f4435b3f5d8fc1ca810:
+
+# edge case public key
+# valid
+c8619ba988859db7d6f20fbf3ffb8b113418cc278065b4e8bb6d4e5b3e7cb569:
+edfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffff7f:
+7e41c2886fed4af04c1641a59af93802f25af0f9cba7a29ae72e2a92f35a1e5a:
+
+# edge case public key
+# valid
+f8d4ca1f37a30ec9acd6dbe5a6e150e5bc447d22b355d80ba002c5b05c26935d:
+edfffffffeffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+dd3abd4746bf4f2a0d93c02a7d19f76d921c090d07e6ea5abae7f28848355947:
+
+# edge case public key
+# valid
+88037ac8e33c72c2c51037c7c8c5288bba9265c82fd8c31796dd7ea5df9aaa4a:
+edffffefffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+8c27b3bff8d3c1f6daf2d3b7b3479cf9ad2056e2002be247992a3b29de13a625:
+
+# edge case public key
+# valid
+5034ee7bf83a13d9167df86b0640294f3620f4f4d9030e5e293f9190824ae562:
+edfffeffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+8e1d2207b47432f881677448b9d426a30de1a1f3fd38cad6f4b23dbdfe8a2901:
+
+# edge case public key
+# valid
+40bd4e1caf39d9def7663823502dad3e7d30eb6eb01e9b89516d4f2f45b7cd7f:
+ebffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+2cf6974b0c070e3707bf92e721d3ea9de3db6f61ed810e0a23d72d433365f631:
+
+# public key with low order
+# acceptable: LowOrderPublic, ZeroSharedSecret
+e0f978dfcd3a8f1a5093418de54136a584c20b7b349afdf6c0520886f95b1272:
+e0eb7a7c3b41b8ae1656e3faf19fc46ada098deb9c32b1fd866205165f49b800:
+0000000000000000000000000000000000000000000000000000000000000000:
+
+# public key with low order
+# acceptable: LowOrderPublic, ZeroSharedSecret
+387355d995616090503aafad49da01fb3dc3eda962704eaee6b86f9e20c92579:
+5f9c95bca3508c24b1d0b1559c83ef5b04445cc4581c8e86d8224eddd09f1157:
+0000000000000000000000000000000000000000000000000000000000000000:
+
+# public key with low order
+# acceptable: LowOrderPublic, Twist, ZeroSharedSecret
+c8fe0df92ae68a03023fc0c9adb9557d31be7feed0d3ab36c558143daf4dbb40:
+ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+0000000000000000000000000000000000000000000000000000000000000000:
+
+# public key with low order
+# acceptable: LowOrderPublic, NonCanonicalPublic, Twist, ZeroSharedSecret
+c8d74acde5934e64b9895d5ff7afbffd7f704f7dfccff7ac28fa62a1e6410347:
+e0eb7a7c3b41b8ae1656e3faf19fc46ada098deb9c32b1fd866205165f49b880:
+0000000000000000000000000000000000000000000000000000000000000000:
+
+# public key with low order
+# acceptable: LowOrderPublic, NonCanonicalPublic, Twist, ZeroSharedSecret
+b85649d5120e01e8ccaf7b2fb8d81b62e8ad6f3d5c0553fdde1906cb9d79c050:
+5f9c95bca3508c24b1d0b1559c83ef5b04445cc4581c8e86d8224eddd09f11d7:
+0000000000000000000000000000000000000000000000000000000000000000:
+
+# public key with low order
+# acceptable: LowOrderPublic, NonCanonicalPublic, ZeroSharedSecret
+2064b2f4c9dc97ec7cf58932fdfa3265ba6ea4d11f0259b8efc8afb35db88c48:
+ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff:
+0000000000000000000000000000000000000000000000000000000000000000:
+
+# public key with low order
+# acceptable: LowOrderPublic, ZeroSharedSecret
+786a33a4f7af297a20e7642925932bf509e7070fa1bc36986af1eb13f4f50b55:
+0000000000000000000000000000000000000000000000000000000000000000:
+0000000000000000000000000000000000000000000000000000000000000000:
+
+# public key with low order
+# acceptable: LowOrderPublic, ZeroSharedSecret
+786a33a4f7af297a20e7642925932bf509e7070fa1bc36986af1eb13f4f50b55:
+0100000000000000000000000000000000000000000000000000000000000000:
+0000000000000000000000000000000000000000000000000000000000000000:
+
+# public key with low order
+# acceptable: LowOrderPublic, ZeroSharedSecret
+786a33a4f7af297a20e7642925932bf509e7070fa1bc36986af1eb13f4f50b55:
+ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+0000000000000000000000000000000000000000000000000000000000000000:
+
+# public key with low order
+# acceptable: LowOrderPublic, ZeroSharedSecret
+786a33a4f7af297a20e7642925932bf509e7070fa1bc36986af1eb13f4f50b55:
+5f9c95bca3508c24b1d0b1559c83ef5b04445cc4581c8e86d8224eddd09f1157:
+0000000000000000000000000000000000000000000000000000000000000000:
+
+# public key with low order
+# acceptable: LowOrderPublic, ZeroSharedSecret
+786a33a4f7af297a20e7642925932bf509e7070fa1bc36986af1eb13f4f50b55:
+e0eb7a7c3b41b8ae1656e3faf19fc46ada098deb9c32b1fd866205165f49b800:
+0000000000000000000000000000000000000000000000000000000000000000:
+
+# public key with low order
+# acceptable: LowOrderPublic, ZeroSharedSecret
+786a33a4f7af297a20e7642925932bf509e7070fa1bc36986af1eb13f4f50b55:
+edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+0000000000000000000000000000000000000000000000000000000000000000:
+
+# public key with low order
+# acceptable: LowOrderPublic, ZeroSharedSecret
+786a33a4f7af297a20e7642925932bf509e7070fa1bc36986af1eb13f4f50b55:
+eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+0000000000000000000000000000000000000000000000000000000000000000:
+
+# public key with low order
+# acceptable: LowOrderPublic, ZeroSharedSecret
+786a33a4f7af297a20e7642925932bf509e7070fa1bc36986af1eb13f4f50b55:
+0000000000000000000000000000000000000000000000000000000000000080:
+0000000000000000000000000000000000000000000000000000000000000000:
+
+# public key with low order
+# acceptable: LowOrderPublic, ZeroSharedSecret
+786a33a4f7af297a20e7642925932bf509e7070fa1bc36986af1eb13f4f50b55:
+0100000000000000000000000000000000000000000000000000000000000080:
+0000000000000000000000000000000000000000000000000000000000000000:
+
+# public key with low order
+# acceptable: LowOrderPublic, ZeroSharedSecret
+786a33a4f7af297a20e7642925932bf509e7070fa1bc36986af1eb13f4f50b55:
+ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff:
+0000000000000000000000000000000000000000000000000000000000000000:
+
+# public key with low order
+# acceptable: LowOrderPublic, ZeroSharedSecret
+786a33a4f7af297a20e7642925932bf509e7070fa1bc36986af1eb13f4f50b55:
+5f9c95bca3508c24b1d0b1559c83ef5b04445cc4581c8e86d8224eddd09f11d7:
+0000000000000000000000000000000000000000000000000000000000000000:
+
+# public key with low order
+# acceptable: LowOrderPublic, ZeroSharedSecret
+786a33a4f7af297a20e7642925932bf509e7070fa1bc36986af1eb13f4f50b55:
+e0eb7a7c3b41b8ae1656e3faf19fc46ada098deb9c32b1fd866205165f49b880:
+0000000000000000000000000000000000000000000000000000000000000000:
+
+# public key with low order
+# acceptable: LowOrderPublic, ZeroSharedSecret
+786a33a4f7af297a20e7642925932bf509e7070fa1bc36986af1eb13f4f50b55:
+edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff:
+0000000000000000000000000000000000000000000000000000000000000000:
+
+# public key with low order
+# acceptable: LowOrderPublic, ZeroSharedSecret
+786a33a4f7af297a20e7642925932bf509e7070fa1bc36986af1eb13f4f50b55:
+eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff:
+0000000000000000000000000000000000000000000000000000000000000000:
+
+# public key = 57896044618658097711785492504343953926634992332820282019728792003956564819949
+# acceptable: SmallPublicKey, LowOrderPublic, ZeroSharedSecret
+40ff586e73d61f0960dc2d763ac19e98225f1194f6fe43d5dd97ad55b3d35961:
+edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+0000000000000000000000000000000000000000000000000000000000000000:
+
+# public key = 57896044618658097711785492504343953926634992332820282019728792003956564819950
+# acceptable: SmallPublicKey, LowOrderPublic, NonCanonicalPublic, ZeroSharedSecret
+584fceaebae944bfe93b2e0d0a575f706ce5ada1da2b1311c3b421f9186c7a6f:
+eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+0000000000000000000000000000000000000000000000000000000000000000:
+
+# non-canonical public key
+# acceptable: NonCanonicalPublic, Twist
+0016b62af5cabde8c40938ebf2108e05d27fa0533ed85d70015ad4ad39762d54:
+efffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+b4d10e832714972f96bd3382e4d082a21a8333a16315b3ffb536061d2482360d:
+
+# non-canonical public key
+# acceptable: NonCanonicalPublic, Twist
+d83650ba7cec115881916255e3fa5fa0d6b8dcf968731bd2c9d2aec3f561f649:
+f0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+515eac8f1ed0b00c70762322c3ef86716cd2c51fe77cec3d31b6388bc6eea336:
+
+# non-canonical public key
+# acceptable: NonCanonicalPublic
+88dd14e2711ebd0b0026c651264ca965e7e3da5082789fbab7e24425e7b4377e:
+f1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+6919992d6a591e77b3f2bacbd74caf3aea4be4802b18b2bc07eb09ade3ad6662:
+
+# non-canonical public key
+# acceptable: NonCanonicalPublic
+98c2b08cbac14e15953154e3b558d42bb1268a365b0ef2f22725129d8ac5cb7f:
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+9c034fcd8d3bf69964958c0105161fcb5d1ea5b8f8abb371491e42a7684c2322:
+
+# non-canonical public key
+# acceptable: NonCanonicalPublic, Twist
+c0697b6f05e0f3433b44ea352f20508eb0623098a7770853af5ca09727340c4e:
+0200000000000000000000000000000000000000000000000000000000000080:
+ed18b06da512cab63f22d2d51d77d99facd3c4502e4abf4e97b094c20a9ddf10:
+
+# non-canonical public key
+# acceptable: NonCanonicalPublic, Twist
+18422b58a18e0f4519b7a887b8cfb649e0bfe4b34d75963350a9944e5b7f5b7e:
+0300000000000000000000000000000000000000000000000000000000000080:
+448ce410fffc7e6149c5abec0ad5f3607dfde8a34e2ac3243c3009176168b432:
+
+# non-canonical public key
+# acceptable: NonCanonicalPublic
+20620d82487707bedf9ee3549e95cb9390d2618f50cf6acba47ffaa103224a6f:
+0400000000000000000000000000000000000000000000000000000000000080:
+03a633df01480d0d5048d92f51b20dc1d11f73e9515c699429b90a4f6903122a:
+
+# non-canonical public key
+# acceptable: NonCanonicalPublic
+285a6a7ceeb7122f2c78d99c53b2a902b490892f7dff326f89d12673c3101b53:
+daffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff:
+9b01287717d72f4cfb583ec85f8f936849b17d978dbae7b837db56a62f100a68:
+
+# non-canonical public key
+# acceptable: NonCanonicalPublic
+c8e0330ae9dceeff887fba761225879a4bd2e0db08799244136e4721b2c88970:
+dbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff:
+dfe60831c9f4f96c816e51048804dbdc27795d760eced75ef575cbe3b464054b:
+
+# non-canonical public key
+# acceptable: NonCanonicalPublic, Twist
+10db6210fc1fb13382472fa1787b004b5d11868ab3a79510e0cee30f4a6df26b:
+dcffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff:
+50bfa826ca77036dd2bbfd092c3f78e2e4a1f980d7c8e78f2f14dca3cce5cc3c:
+
+# non-canonical public key
+# acceptable: NonCanonicalPublic
+9041c6e044a277df8466275ca8b5ee0da7bc028648054ade5c592add3057474e:
+eaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff:
+13da5695a4c206115409b5277a934782fe985fa050bc902cba5616f9156fe277:
+
+# non-canonical public key
+# acceptable: NonCanonicalPublic
+b8d499041a6713c0f6f876db7406587fdb44582f9542356ae89cfa958a34d266:
+ebffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff:
+63483b5d69236c63cddbed33d8e22baecc2b0ccf886598e863c844d2bf256704:
+
+# non-canonical public key
+# acceptable: NonCanonicalPublic
+c85f08e60c845f82099141a66dc4583d2b1040462c544d33d0453b20b1a6377e:
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff:
+e9db74bc88d0d9bf046ddd13f943bccbe6dbb47d49323f8dfeedc4a694991a3c:
+
+# public key = 57896044618658097711785492504343953926634992332820282019728792003956564819968
+# acceptable: SmallPublicKey, LowOrderPublic, NonCanonicalPublic, ZeroSharedSecret
+7887889bac4c629a101d3724f2ed8b98d936fde79e1a1f77d86779626bf8f263:
+0000000000000000000000000000000000000000000000000000000000000080:
+0000000000000000000000000000000000000000000000000000000000000000:
+
+# public key = 57896044618658097711785492504343953926634992332820282019728792003956564819969
+# acceptable: SmallPublicKey, LowOrderPublic, NonCanonicalPublic, Twist, ZeroSharedSecret
+e07971ee820e48b0b266d8be3cdbbb5e900a43f59ee8535c6572418615de4962:
+0100000000000000000000000000000000000000000000000000000000000080:
+0000000000000000000000000000000000000000000000000000000000000000:
+
+# RFC 7748
+# valid
+a046e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449a44:
+e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c:
+c3da55379de9c6908e94ea4df28d084f32eccf03491c71f754b4075577a28552:
+
+# RFC 7748
+# valid
+4866e9d4d1b4673c5ad22691957d6af5c11b6421e0ea01d42ca4169e7918ba4d:
+e5210f12786811d3f4b7959d0538ae2c31dbe7106fc03c3efc4cd549c715a413:
+95cbde9476e8907d7aade45cb4b873f88b595a68799fa152e6f8f7647aac7957:
+
+# RFC 8037, Section A.6
+# valid
+77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a:
+de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f:
+4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742:
+
+# edge case for shared secret
+# acceptable: Twist
+60a3a4f130b98a5be4b1cedb7cb85584a3520e142d474dc9ccb909a073a9767f:
+b7b6d39c765cb60c0c8542f4f3952ffb51d3002d4aeb9f8ff988b192043e6d0a:
+0200000000000000000000000000000000000000000000000000000000000000:
+
+# edge case for shared secret
+# valid
+60a3a4f130b98a5be4b1cedb7cb85584a3520e142d474dc9ccb909a073a9767f:
+3b18df1e50b899ebd588c3161cbd3bf98ebcc2c1f7df53b811bd0e91b4d5153d:
+0900000000000000000000000000000000000000000000000000000000000000:
+
+# edge case for shared secret
+# valid
+60a3a4f130b98a5be4b1cedb7cb85584a3520e142d474dc9ccb909a073a9767f:
+cab6f9e7d8ce00dfcea9bbd8f069ef7fb2ac504abf83b87db601b5ae0a7f7615:
+1000000000000000000000000000000000000000000000000000000000000000:
+
+# edge case for shared secret
+# acceptable: Twist
+60a3a4f130b98a5be4b1cedb7cb85584a3520e142d474dc9ccb909a073a9767f:
+4977d0d897e1ba566590f60f2eb0db6f7b24c13d436918ccfd32708dfad7e247:
+feffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3f:
+
+# edge case for shared secret
+# valid
+60a3a4f130b98a5be4b1cedb7cb85584a3520e142d474dc9ccb909a073a9767f:
+98730bc03e29e8b057fb1d20ef8c0bffc822485d3db7f45f4e3cc2c3c6d1d14c:
+fcffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3f:
+
+# edge case for shared secret
+# acceptable: Twist
+60a3a4f130b98a5be4b1cedb7cb85584a3520e142d474dc9ccb909a073a9767f:
+97b4fff682df7f096cd1756569e252db482d45406a3198a1aff282a5da474c49:
+f9ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3f:
+
+# edge case for shared secret
+# valid
+60a3a4f130b98a5be4b1cedb7cb85584a3520e142d474dc9ccb909a073a9767f:
+317781b0163bae74accc06c0d44ef9a911a22b0d37faf7726621591f9343ea2f:
+f3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3f:
+
+# edge case for shared secret
+# valid
+60a3a4f130b98a5be4b1cedb7cb85584a3520e142d474dc9ccb909a073a9767f:
+7e26f8f24cb590027f9d1bc49b0e1a242c7d8f43624d3e8fab28ee08e02cb45e:
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03:
+
+# edge case for shared secret
+# acceptable: Twist
+60a3a4f130b98a5be4b1cedb7cb85584a3520e142d474dc9ccb909a073a9767f:
+e96d2780e5469a74620ab5aa2f62151d140c473320dbe1b028f1a48f8e76f95f:
+e5ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+
+# edge case for shared secret
+# acceptable: Twist
+60a3a4f130b98a5be4b1cedb7cb85584a3520e142d474dc9ccb909a073a9767f:
+8d612c5831aa64b057300e7e310f3aa332af34066fefcab2b089c9592878f832:
+e3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+
+# edge case for shared secret
+# valid
+60a3a4f130b98a5be4b1cedb7cb85584a3520e142d474dc9ccb909a073a9767f:
+8d44108d05d940d3dfe5647ea7a87be24d0d036c9f0a95a2386b839e7b7bf145:
+ddffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+
+# edge case for shared secret
+# acceptable: Twist
+60a3a4f130b98a5be4b1cedb7cb85584a3520e142d474dc9ccb909a073a9767f:
+21a35d5db1b6237c739b56345a930aeee373cdcfb4701266782a8ac594913b29:
+dbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+
+# edge case for shared secret
+# acceptable: Twist
+60a3a4f130b98a5be4b1cedb7cb85584a3520e142d474dc9ccb909a073a9767f:
+3e5efb63c352ce942762482bc9337a5d35ba55664743ac5e93d11f957336cb10:
+0000000000000000000000000000000000000000000000000000000000000002:
+
+# edge case for shared secret
+# acceptable: Twist
+60a3a4f130b98a5be4b1cedb7cb85584a3520e142d474dc9ccb909a073a9767f:
+8e41f05ea3c76572be104ad8788e970863c6e2ca3daae64d1c2f46decfffa571:
+0000000000000000000000000000000000000000000000000000000000008000:
+
+# special case public key
+# acceptable: SmallPublicKey, LowOrderPublic, ZeroSharedSecret
+c8d07c46bbfb827753b92c70e49583ce8bfa44641a7382258ea903d6a832c96b:
+0000000000000000000000000000000000000000000000000000000000000000:
+0000000000000000000000000000000000000000000000000000000000000000:
+
+# special case public key
+# acceptable: SmallPublicKey, LowOrderPublic, ZeroSharedSecret
+90b7ef237a055f348dcb4c4364a59d7d31edc7ab78f2ca254e2c810975c3f543:
+0100000000000000000000000000000000000000000000000000000000000000:
+0000000000000000000000000000000000000000000000000000000000000000:
+
+# special case public key
+# acceptable: Twist
+e0a8be63315c4f0f0a3fee607f44d30a55be63f09561d9af93e0a1c9cf0ed751:
+0200000000000000000000000000000000000000000000000000000000000000:
+0c50ac2bfb6815b47d0734c5981379882a24a2de6166853c735329d978baee4d:
+
+# special case public key
+# valid
+0840a8af5bc4c48da8850e973d7e14220f45c192cea4020d377eecd25c7c3643:
+1200000000000000000000000000000000000000000000000000000000000000:
+77557137a2a2a651c49627a9b239ac1f2bf78b8a3e72168ccecc10a51fc5ae66:
+
+# special case public key
+# acceptable: Twist
+0092229c753a71284d0853909470ad847ab62f439ea51482fb41d30cc3b44743:
+1400000000000000000000000000000000000000000000000000000000000000:
+c88e719ae5c2248b5f90da346a92ae214f44a5d129fd4e9c26cf6a0da1efe077:
+
+# special case public key
+# valid
+b8da2bd2d7cf25a3e54e5f87ee15911effb9ff86baec4076d56c8e953670bf5b:
+0000000000000000000000000080000000000000000000000000000000000000:
+4bf6789c7ea036f973cde0af02d6fdb9b64a0b957022111439570fad7d7a453f:
+
+# special case public key
+# valid
+684cd420af41abb3d10c61e773238cf729c2155f941ac27e15f4c37f49b29576:
+ffffffffffffffffffffffffffff000000000000000000000000000000000000:
+bcac235ae15cc7148372e11f9315e3bc76ceb904b3d2a8246bd9d9be2082bb62:
+
+# special case public key
+# acceptable: Twist
+38cfacaa4460796b4de434bdd6739f0d043671f97fa829517511e6b47aa93474:
+0100000000000000000000000000010000000000000000000000000000000000:
+5dd7d16fff25cc5fdf9e03c3157cb0a235cea17d618f36e6f13461567edeb943:
+
+# special case public key
+# valid
+30832e8cb627ac195f77b1105258e4bb18b99a5ed944404bfacb3a039fbdb14b:
+0000000000000000000000000000000000000000000000000000004000000000:
+2816fd031d51d6750f9225ede950625cca47441ca97e43092650396991afcb6d:
+
+# special case public key
+# acceptable: Twist
+d818fd6971e546447f361d33d3dbb3eadcf02fb28f246f1d5107b9073a93cd4f:
+0000000000000000000000000000000000000000000000000000008000000000:
+7ed8f2d5424e7ebb3edbdf4abe455447e5a48b658e64abd06c218f33bd151f64:
+
+# special case public key
+# acceptable: Twist
+1021cd8682bdc3f5da9100adff5b2230b3acd836b3a455db8352a2c27e69d17e:
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000:
+e8620ed5ca89c72c5ea5503e6dcd01131cd5e875c30e13d5dc619ce28ec7d559:
+
+# special case public key
+# valid
+20e4c9247102292655d6765d7d84c6fce5309b8004045daea6d7d7dcad462871:
+0100000000000000000000000000000000000000000000000000000001000000:
+ceadb264379dcadd6e3bb8ad24dd653d2a609dd703d41da6caf3ad00f001862c:
+
+# special case public key
+# acceptable: Twist
+90b150d462de512056d5bd55173074969b496f262fb6916b733f6263a8078971:
+a8b9c7372118a53a9de9eaf0868e3b1a3d88e81cb2e407ff7125e9f5c5088715:
+f86cc7bf1be49574fc97a074282e9bb5cd238e002bc8e9a7b8552b2d60eccb52:
+
+# special case public key
+# acceptable: Twist
+9887286b3261c8d857a16f6db21277f75d88d4e861b3ebe7596699047e816668:
+aab9c7372118a53a9de9eaf0868e3b1a3d88e81cb2e407ff7125e9f5c5088715:
+ccbb8fd9dee165a398b2dbd7c8396f81736c1b3da36b35fbec8f326f38f92767:
+
+# special case public key
+# valid
+20ca2c85cc8762e96b7047bf15c71c050ffe0ed1616040a953ae32a1297ad871:
+585007a5930d77623cf29756038ca197d3ebfd9e4c80a69585efe0274092c115:
+46add6f48ffff461777d4f89b6fdf1155aa051a96387d45f3e5e371a236b6e52:
+
+# special case public key
+# valid
+d027656605b10bf18dea28bc52546f9f1f08cef06cafd200fc84f87dbb4ebe46:
+fbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1f:
+1adbe32207e21f71e1af53884d2a2276481e298e557f4dacb3720f2458e3082d:
+
+# special case public key
+# acceptable: Twist
+4867a83ee9d01b7510840867db1af6a6049bdbb056b74443f70c358e162c8867:
+0000000000000000000000000000000000000000000000000000000000000020:
+e12cc58fbeb70a5e35c861c33710be6516a6a92e52376060211b2487db542b4f:
+
+# special case public key
+# valid
+a015970a8add940fca5b1b5d23875397d547d8d494fcb314f2045a67a2d12c4b:
+afa00e4a271beec478e42fad0618432fa7d7fb3d99004d2b0bdfc14f8024832b:
+421bed1b26da1e9adbeada1f32b91a0fb4ced0f1110e0a4a88e735a19ee4571e:
+
+# special case public key
+# valid
+4058cb6b9aaba02a338aaa392dbc10039e26e9e444117e758e24c5d8b232ea5e:
+b1a00e4a271beec478e42fad0618432fa7d7fb3d99004d2b0bdfc14f8024832b:
+d7b47463e2f4ca9a1a7deea098da8e74ac3b4a109083d997259b12992e7e7e06:
+
+# special case public key
+# acceptable: Twist
+b876b05daff0530b139d9e11250563418077178246c5fa7005ba00e9b6647763:
+fbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2f:
+686eb910a937211b9147c8a051a1197906818fdc626668eb5f5d394afd86d41b:
+
+# special case public key
+# valid
+d87fd6aa5d8deef6dee9619a56846a0829620590f2da40835d8e251597e39078:
+22231c64ef73ad62318b8a87bc38e272e1bb8bf1a60d7c00476d0b059d7b3c35:
+09559733b35bcc6bb8ac574b5abe3a4d8841deff051c294a07487e3eec3c5558:
+
+# special case public key
+# valid
+90036321b63751f7622aa93da34d85e59ce81009ac5b9a068921d83bc4715b57:
+f6ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3f:
+f7d5cbcf39eb722b01ed20c85563ebb81d076511aead4ccc429027866b9fd270:
+
+# special case public key
+# acceptable: Twist
+a06781fd4c4a0874e00e72ba131b9dd87a83b2904e294de176e8a9af1f695d67:
+f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3f:
+e995ad6a1ec6c5ab32922cff9d204721704673143c4a11deaa203f3c81989b3f:
+
+# special case public key
+# acceptable: Twist
+b822d72d8b68bdb4fbf67e56a61d672b2c7747e94479fe5ae4072d0accdd6571:
+feffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3f:
+32b6dabe01d13867f3b5b0892fefd80dca666f2edc5afb43cd0baf703c3e6926:
+
+# special case public key
+# valid
+d08ce1237e248d02cdf619d20bea5848ade4f6ffd171b8dee8793fc67c459640:
+0000000000000000000000000000000000000000000000000000000000000040:
+a93d83fc9ea0f6cb0cc8b631da600019b76cbb2ec57222f2e42dd540e3da850b:
+
+# special case public key
+# valid
+180ae3c928514cfb9edd06e7dc1d5d066160e967445a5c58e4463b69ed205e6d:
+cbdce39b108c529dce74757843c71d8d1e44740e59f283ffb892f4fa6284c34a:
+017cbfa2b38e9ef3297a339ecce1a917bdcf7e910036086a41d1e22d04241870:
+
+# special case public key
+# valid
+e881d806a110560cd8fee899d59c0249f1233a4322c41aa369c7a2a99f5b5962:
+3c5ff1b5d8e4113b871bd052f9e7bcd0582804c266ffb2d4f4203eb07fdb7c54:
+71133905b8a57ea8c38de0ecf213699a75b096c2df21f07f7e9eb03e9fa53f5c:
+
+# special case public key
+# valid
+08e410e1d7e8b9411236af4a35d6b62a5d8931478e4c62197cfafb491467b162:
+3e5ff1b5d8e4113b871bd052f9e7bcd0582804c266ffb2d4f4203eb07fdb7c54:
+3dc7b70e110766b2bf525252ebed98a100b2e532dc69544464da1bbab8625f6d:
+
+# special case public key
+# valid
+e02fdf7e0ee3d55b4440f01432dd253c949793bc04da44ddece83e54c8c39b40:
+f2ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5f:
+e317e5cc438b5f79ead5533ac7c45519a117b31033cc2140b19edf8572011240:
+
+# special case public key
+# valid
+f05d18f68ef7a5865c14db3a9c255fdf2dabea2aa36581e94f68b727b582867b:
+f6ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5f:
+d86810516aeddc18061036f599a9eb84d1c6146b0f543652dd4526743ba42c04:
+
+# special case public key
+# acceptable: Twist
+00c103578d5c079d7bcc22c1c31e787c1b15c57fcb493fdafefa20371cfc746b:
+95aff85a6cf2889dc30d68a9fc735e682c140261b37f596a7a101fd8bf6d3e6a:
+dfa988a477003be125b95ccbf2223d97729577d25e1d6e89e3da0afabdd0ae71:
+
+# special case public key
+# acceptable: Twist
+7005bb927485c435642b424a3dde014bcf76345e5be64ae6e9b24db39e1cdb51:
+434638c8dee75ac56216150f7971c4e5c27717e34d1bf8008eda160a3af7786a:
+d450af45b8ed5fe140cc5263ffb7b52e66736899a8b872b6e28552129819b25b:
+
+# special case public key
+# valid
+0822039a5dc13c40fcccf346e2a7769b4fd272052d43260ad626468a50d44162:
+454638c8dee75ac56216150f7971c4e5c27717e34d1bf8008eda160a3af7786a:
+58002c89bf8bc32ae6fc205b796acd13ef7f8476f6492ae4b2be47f1095e8a4f:
+
+# special case public key
+# valid
+40a6349c03f0dc0a42358f6353ca67632af687b14c9dff626c54e211e8fc355a:
+ecfffffffffffffffffffffffffffeffffffffffffffffffffffffffffffff7f:
+7773aad6e72eb1735b65ad51f7dad258c11d7bfff53094424cb103cd6bfb4368:
+
+# special case public key
+# valid
+50696d4d05209971d6ba0676ea274262ba639aac74fa75e5df4570768ad8ae74:
+eefffffffffffffffffffffffffffeffffffffffffffffffffffffffffffff7f:
+c118ddf6462fbea80f14ef1f2972a1ab12cafa511d1323d4d22d0d426d651b5b:
+
+# special case public key
+# valid
+68bb680c853f4e4daa47c586dc886cf4568d7b0383770f6df439a53be4a3236d:
+edffffffffffffffffffffffff7fffffffffffffffffffffffffffffffffff7f:
+cc0775bfd970a2706b11c7222a4436a3d17160382c83b76f89b66192c81b4408:
+
+# special case public key
+# valid
+b0f6c28dbdc647068a76d71805ef770f087cf76b82afdc0d26c45b71ace49768:
+ebffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+f0097fa0ba70d019126277ab15c56ecc170ca88180b2bf9d80fcda3d7d74552a:
+
+# special case public key
+# acceptable: LowOrderPublic, Twist, ZeroSharedSecret
+18630f93598637c35da623a74559cf944374a559114c7937811041fc8605564a:
+ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+0000000000000000000000000000000000000000000000000000000000000000:
+
+# special case for E in multiplication by 2
+# acceptable: Twist
+581ecbda5a4a228044fefd6e03df234558c3c79152c6e2c5e60b142c4f26a851:
+0000000000000000000008000000000000000000000000000000000000000000:
+59e7b1e6f47065a48bd34913d910176b6792a1372aad22e73cd7df45fcf91a0e:
+
+# special case for E in multiplication by 2
+# valid
+b0561a38000795b7cb537b55e975ea452c2118506295d5eb15fd9c83b67f7a50:
+77af0d3897a715dfe25df5d538cf133bc9ab7ad52df6bd922a2fb75621d59901:
+179f6b020748acba349133eaa4518f1bd8bab7bfc4fb05fd4c24e7553da1e960:
+
+# special case for E in multiplication by 2
+# valid
+b00f7df2d47128441c7270b9a87eee45b6056fc64236a57bdf81dbcccf5f5d42:
+4e39866127b6a12a54914e106aab86464af55631f3cb61766d5999aa8d2e070e:
+43c5ee1451f213ef7624729e595a0fee7c9af7ee5d27eb03278ee9f94c202352:
+
+# special case for E in multiplication by 2
+# valid
+c8f7a0c0bfb1e9c72576c534f86854fbe4af521d4fa807f67e2440e100ec8852:
+adc6799ed8495ed5ab6eb1ef955479b9b50aa9ce0c349e8992a6665572d1f811:
+2f350bcf0b40784d1d756c9ca3e38ec9dd68ba80faf1f9847de50779c0d4902a:
+
+# special case for E in multiplication by 2
+# acceptable: Twist
+58181f581aa37022ff71c56c6e68e6175d967c5c995a249885f66565074ded4d:
+770f4218ef234f5e185466e32442c302bbec21bbb6cd28c979e783fe5013333f:
+d5d650dc621072eca952e4344efc7320b2b1459aba48f5e2480db881c50cc650:
+
+# special case for E in multiplication by 2
+# acceptable: Twist
+301c935cae4357070b0adaf9cd6192830b2c989c153729eed99f589eb45f884b:
+5c6118c4c74cfb842d9a87449f9d8db8b992d46c5a9093ce2fcb7a49b535c451:
+909cc57275d54f20c67b45f9af9484fd67581afb7d887bee1db5461f303ef257:
+
+# special case for E in multiplication by 2
+# valid
+d002292d4359a3d42bc8767f1380009332e7a0df2f3379011ab78f789f6baa54:
+4039866127b6a12a54914e106aab86464af55631f3cb61766d5999aa8d2e076e:
+4a7e2c5caf1d8180eb1c4f22692f29a14b4cdc9b193bd1d16e2f27438eef1448:
+
+# special case for E in multiplication by 2
+# acceptable: Twist
+d0c2c49e644ab738270707ff9917065942687e2f12886d961161db46c05b565f:
+078fa523498fb51cba1112d83b20af448b8009d8eea14368564d01b8f9b6086f:
+c0ee59d3685fc2c3c803608b5ee39a7f8da30b48e4293ae011f0ea1e5aeb7173:
+
+# special case for E in multiplication by 2
+# valid
+f087d38b274c1dad1bce6eaa36b48e2190b90b9bf8ca59669cc5e00464534342:
+9fc6799ed8495ed5ab6eb1ef955479b9b50aa9ce0c349e8992a6665572d1f871:
+b252bc8eabfaa68c56e54d61b99061a35d11e3a7b9bda417d90f69b1119bcf45:
+
+# special case for E in multiplication by 2
+# valid
+48dbcc5a695f1514bbbaa6ad00842b69d9ae5216b1963add07fb2947c97b8447:
+7650f2c76858ea201da2022ac730ecc43654852ad209426dd5d048a9de2a667e:
+fbda33bc930c08df837208e19afdc1cfe3fd0f8f0e3976be34775e58a4a7771f:
+
+# D = 0 in multiplication by 2
+# acceptable: LowOrderPublic, ZeroSharedSecret
+5891c9272cf9a197735b701e5715268d36d7436b7e351a3e997a0862e4807d4d:
+e0eb7a7c3b41b8ae1656e3faf19fc46ada098deb9c32b1fd866205165f49b800:
+0000000000000000000000000000000000000000000000000000000000000000:
+
+# D = 0 in multiplication by 2
+# acceptable: LowOrderPublic, ZeroSharedSecret
+c0f9c60aea73731d92ab5ed9f4cea122f9a6eb2577bda72f94948fea4d4cc65d:
+5f9c95bca3508c24b1d0b1559c83ef5b04445cc4581c8e86d8224eddd09f1157:
+0000000000000000000000000000000000000000000000000000000000000000:
+
+# special case for DA - CB in multiplication by 2
+# acceptable: Twist
+0066dd7674fe51f9326c1e239b875f8ac0701aae69a804c25fe43595e8660b45:
+b0224e7134cf92d40a31515f2f0e89c2a2777e8ac2fe741db0dc39399fdf2702:
+8dacfe7beaaa62b94bf6e50ee5214d99ad7cda5a431ea0c62f2b20a89d73c62e:
+
+# special case for DA - CB in multiplication by 2
+# valid
+80067f30f40d61318b420c859fce128c9017ab81b47b76028a57bc30d5856846:
+601e3febb848ec3e57fce64588aad82afc9c2af99bbcdffcc4cd58d4b3d15c07:
+20f1d3fe90e08bc6f152bf5dacc3ed35899785333f1470e6a62c3b8cbe28d260:
+
+# special case for DA - CB in multiplication by 2
+# acceptable: Twist
+584577669d21ce0ae3e30b02c9783ffe97709cbfe396889aa31e8ee43352dc52:
+82a3807bbdec2fa9938fb4141e27dc57456606301f78ff7133cf24f3d13ee117:
+2b28cc5140b816add5ad3a77a81b1c073d67bf51bf95bda2064a14eb12d5f766:
+
+# special case for DA - CB in multiplication by 2
+# valid
+18e597a4e2ccdb5e8052d57c9009938c2d4c43d6d8c9f93c98727b7311035953:
+f329ab2376462e5f3128a2682086253c19222ac1e2bca45692f0c3b528f4c428:
+8392160083b9af9e0ef44fcfce53ba8ff7282ee7a6c71ab66f8843a55d09cd68:
+
+# special case for DA in multiplication by 2
+# valid
+88281cc51d5512d8814ea5249b879dcbad0323d38512dafbdc7ba85bba8c8d5d:
+4fce3bb6c8aaf022dbd100e3cde3941b37d543f00401dba7da9bc143dfc55709:
+42184e22c535530c457bd3b4f1084cbf5e297f502fe136b8d1daecf5334cc96c:
+
+# special case for DA in multiplication by 2
+# valid
+d0e795450df0a813c6573496ec5793ca02e1bdbad10ed08df83fdaed68b3385f:
+15c68851c1db844b5a1ef3456a659f188854b1a75fbdb2f68f514c9289ce711f:
+f654d78e5945b24bc63e3e6d790e0ae986e53937764068b1bce920e1d79b756f:
+
+# special case for DA in multiplication by 2
+# valid
+30b69a1cc1eb2d0b83ea213846e90a2c922088bdf294a6995bf6e6e77c646c41:
+4200a242434337b8914f49345301ed782b13594f9ede089c41fb1e7ea82c9053:
+cd8a09b04795edcc7061867373981aa748651ebdce5ec218a335b878cefe4872:
+
+# special case for DA in multiplication by 2
+# valid
+78b30bb63cd8ade71b7a77d426f4419d05f199ffef349e89faa9d9a5f21f6654:
+baabf0174aaaea4de48cc83adfb0401461a741903ea6fb130d7d64b7bf03a966:
+c9f8258f237db1c80702c5c4d9048dfba9dfe259da4aeee90dc2945526961275:
+
+# special case for x_2 in multiplication by 2
+# valid
+c0b386f4ef0d4698686404977e7b60cb6c1f8b6012a22e29d6224c5947439041:
+f12f18bd59c126348f6a7a9f4a5fdd9fcaf581345073a851fba098e5d64b4a0c:
+6600cbe900616a770a126b8b19156d5e27e1174bd538d0944eb3c0be4899c758:
+
+# special case for x_2 in multiplication by 2
+# acceptable: Twist
+9886602e719bacafea092bb75b51ae7258abe1a364c176857f3dc188c03e6759:
+bee386527b772490aeb96fc4d23b9304037cb4430f64b228f3d8b3b498319f22:
+3fe710d6344ff0cb342e52349e1c5b57b7a271f2a133bb5249bbe40dc86e1b40:
+
+# special case for x_2 in multiplication by 2
+# valid
+b83960f5d0613cdaac6dda690351666e9f277bba6bd406b0e27a1886bb2d3e46:
+cf911ac91b0d944049cec66ae5ef0c4549d1e612e107c68e87263a2fbcf8323f:
+71373ebe67f39a2c230027c7db4b3b74bab80ed212b232679785ee10f47c304e:
+
+# special case for x_2 in multiplication by 2
+# valid
+d03b75f09ac807dfd2ee352c04a1f25984720f785ffaa0af88bc5db6ff9c3453:
+1e6ee536e4f26bbfb63139951a10f3bab62e19ed1ef8397178d9c5d04307cd40:
+238eef43c589822e1d3de41c1cc46dcfec7a93febf37c8546b6625e1a123815d:
+
+# special case for x_2 in multiplication by 2
+# valid
+d036948c0ec223f0ee577e390dbf87222358ed199f2823345ad154bbc4cbcc47:
+2f1c79ad8488db6f5146903b2dc46cfbfc834bbcf09b4dd70c274c4b67ce605d:
+87a79c9c231d3b9526b49bf3d683bf38c3c319af7c7c5d1456487398da535010:
+
+# special case for x_2 in multiplication by 2
+# valid
+d054ded613febf2950ac5c927fcb120c387de0ba61b331cd33024c8b6e737048:
+fccfe742a63ed9cb70958560b5a02260350a7ecbaf8c57ae045f671a29b4b573:
+d683ca6194452d878c12d7da35f22833f99728bba89931a51274f61210336a5f:
+
+# special case for AA in multiplication by 2
+# acceptable: Twist
+e82c480631fb153ba2211fe603032b3e71b162dbd3c11bec03208ffcd510655f:
+cb3d4a90f86b3011da3369d9988597c7fff1499273b4a04f84d0e26ed1683c0d:
+dbf6203516635840cf69a02db87cf0d95dae315da7fc1ec7ce2b29e1f2db6666:
+
+# special case for AA in multiplication by 2
+# acceptable: Twist
+c0c01d28c1cab01f59700aca5f18d2697658b37fdd54a339ff391c0a1a1b1645:
+101e13f7bc0570fa2638caa20a67c6e0c21dab132f4b456191590264c493d018:
+1fe314744390d525278b1f5fbf108101b8ded587081375ed4ac4ac690d92414f:
+
+# special case for AA in multiplication by 2
+# acceptable: Twist
+c82bde72df36479688c485a8bf442f4a34412e429c02db97704f03daf4dfd542:
+dce1ec0843fa8f05d9c7355df598391f3de254ecd0b4ba9e6ea6fd9b3b6c2f67:
+ad454395ee392be677be7b9cb914038d57d2d87ec56cc98678dd84f19920912b:
+
+# special case for AA in multiplication by 2
+# valid
+503f697617fb02a7b8ef00ba34e7fc8ce93f9ec3e1cbfe4bf2c05bcee0cb9757:
+21c2b56f0794cfee25cc9626677a6838000eb66d8c4b5fb07b2f1d912e97c372:
+c6d6499255133398f9dd7f32525db977a538118800bfaf3aad8bcd26f02c3863:
+
+# special case for BB in multiplication by 2
+# valid
+58cd4ca1e4331188de2b2889419ce20ec5ef88a0e93af092099065551b904e41:
+cc3d4a90f86b3011da3369d9988597c7fff1499273b4a04f84d0e26ed1683c0d:
+0d74214da1344b111d59dfad3713eb56effe7c560c59cbbb99ec313962dbba58:
+
+# special case for BB in multiplication by 2
+# acceptable: Twist
+004ea3448b84ca509efec5fcc24c63ee984def63b29deb9037894709709c0957:
+111e13f7bc0570fa2638caa20a67c6e0c21dab132f4b456191590264c493d018:
+7b9dbf8d6c6d65898b518167bf4011d54ddc265d953c0743d7868e22d9909e67:
+
+# special case for BB in multiplication by 2
+# valid
+c8a6eb00a4d74bbdff239522c3c891ed7ce1904be2a329cd0ae0061a253c9542:
+dde1ec0843fa8f05d9c7355df598391f3de254ecd0b4ba9e6ea6fd9b3b6c2f67:
+fb0e0209c5b9d51b401183d7e56a59081d37a62ab1e05753a0667eebd377fd39:
+
+# special case for BB in multiplication by 2
+# valid
+50322ff0d0dcdd6b14f307c04dfecefe5b7cdeaf92bffb919e9d62ed27079040:
+22c2b56f0794cfee25cc9626677a6838000eb66d8c4b5fb07b2f1d912e97c372:
+dbe7a1fe3b337c9720123e6fcc02cf96953a17dc9b395a2206cb1bf91d41756e:
+
+# special case for D in multiplication by 2
+# valid
+e0328c7d188d98faf2ac72d728b7d14f2bbbd7a94d0fbd8e8f79abe0b1fe1055:
+e58baccede32bcf33b3b6e3d69c02af8284a9631de74b6af3f046a9369df040f:
+97bd42093e0d48f973f059dd7ab9f97d13d5b0d5eedffdf6da3c3c432872c549:
+
+# special case for D in multiplication by 2
+# valid
+5017679a17bd23adf95ad47e310fc6526f4ba9ca3b0839b53bd0d92839eb5b4f:
+c6d5c693fc0a4e2df6b290026860566a166b6d7aebe3c98828d492745c8df936:
+99bcbc7b9aa5e25580f92bf589e95dae874b83e420225d8a93e18e96dac00b63:
+
+# special case for D in multiplication by 2
+# valid
+2864aaf61c146df06cc256b065f66b34985cc015da5b1d647a6ed4e2c76bfc43:
+d15f4bf2ef5c7bda4ee95196f3c0df710df5d3d206360fc3174ea75c3aa3a743:
+afa2adb52a670aa9c3ec3020d5fda285474ede5c4f4c30e9238b884a77969443:
+
+# special case for D in multiplication by 2
+# acceptable: Twist
+184a6cfbabcbd1507a2ea41f52796583dbdb851b88a85781ee8e3c28782c3349:
+6dffb0a25888bf23cf1ac701bfbdede8a18e323b9d4d3d31e516a05fce7ce872:
+e6a2fc8ed93ce3530178fef94bb0056f43118e5be3a6eabee7d2ed384a73800c:
+
+# special case for D in multiplication by 2
+# acceptable: Twist
+c85f954b85bc102aca799671793452176538d077862ee45e0b253619767dff42:
+21f86d123c923a92aaf2563df94b5b5c93874f5b7ab9954aaa53e3d72f0ff67e:
+7fc28781631410c5a6f25c9cfd91ec0a848adb7a9eb40bc5b495d0f4753f2260:
+
+# special case for D in multiplication by 2
+# valid
+50e3e5a9a19be2ee3548b0964672fb5e3134cb0d2f7adf000e4556d0ffa37643:
+587c347c8cb249564ab77383de358cc2a19fe7370a8476d43091123598941c7f:
+314d8a2b5c76cc7ee1217df2283b7e6724436e273aeb80628dce0600ab478a63:
+
+# special case for DA + CB in multiplication by 2
+# valid
+08ece580bb6ddf96559b81d7a97dd4531def6cc78d448a70cebabdd26caab146:
+f5c6311a1dd1b9e0f8cfd034ac6d01bf28d9d0f962a1934ae2cb97cb173dd810:
+2bfd8e5308c34498eb2b4daf9ed51cf623da3beaeb0efd3d687f2b8becbf3101:
+
+# special case for DA + CB in multiplication by 2
+# acceptable: Twist
+a886033e9dc2b6a913fffbc2bd402e8c11ec34d49c0dc0fa1429329b694a285f:
+9316c06d27b24abc673ffb5105c5b9a89bdfaa79e81cdbb89556074377c70320:
+d53c3d6f538c126b9336785d1d4e6935dc8b21f3d7e9c25bc240a03e39023363:
+
+# special case for DA + CB in multiplication by 2
+# acceptable: Twist
+98b1cc2020a8ec575d5c46c76024cf7c7ad7628eb909730bc4f460aaf0e6da4b:
+8a4179807b07649e04f711bf9473a79993f84293e4a8b9afee44a22ef1000b21:
+4531881ad9cf011693ddf02842fbdab86d71e27680e9b4b3f93b4cf15e737e50:
+
+# special case for DA + CB in multiplication by 2
+# acceptable: Twist
+c8e193de162aa349a3432c7a0c0521d92cbc5e3bf82615e42955dd67ec12345f:
+a773277ae1029f854749137b0f3a02b5b3560b9c4ca4dbdeb3125ec896b81841:
+7ba4d3de697aa11addf3911e93c94b7e943beff3e3b1b56b7de4461f9e48be6b:
+
+# special case for DA + CB in multiplication by 2
+# acceptable: Twist
+88e01237b336014075676082afbde51d595d47e1fa5214b51a351abbf6491442:
+1eceb2b3763231bc3c99dc62266a09ab5d3661c756524cddc5aabcedee92da61:
+bcf0884052f912a63bbab8c5c674b91c4989ae051fa07fcf30cb5317fb1f2e72:
+
+# special case for DA + CB in multiplication by 2
+# acceptable: Twist
+e82313e451a198dce4ae95c6832a8281d847fc87b28db00fe43757c16cc49c4a:
+9a2acbb3b5a386a6102e3728be3a97de03981d5c71fd2d954604bee3d3d0ce62:
+e5772a92b103ee696a999705cf07110c460f0545682db3fac5d875d69648bc68:
+
+# special case for DA + CB in multiplication by 2
+# acceptable: Twist
+2828594d16768e586df39601ecc86d3fad6389d872b53fca3edcaf6fb958f653:
+27430e1c2d3089708bca56d7a5ad03792828d47685b6131e023dd0808716b863:
+378c29e3be97a21b9f81afca0d0f5c242fd4f896114f77a77155d06ce5fbfa5e:
+
+# special case for z_2 in multiplication by 2
+# valid
+a84f488e193139f986b0e5b249635b137d385e420342aef1f194fcde1fe5e850:
+4ef367901aac8ba90a50e0cf86ca4e4a3ff164fb121605be346e2e48d04ac912:
+7eb48a60b14fb9ea5728f6410aef627d1522fad481b934af64e2c483b64d585f:
+
+# special case for z_2 in multiplication by 2
+# valid
+30fd2a781e095c34a483907b3dd2d8bd2736e279617bfa6b8b4e0e1cf90fbd46:
+d1de303c4ddd05d57c29df92ad172dd8c8f424e63ec93445beaea44f9d124b17:
+b71bdbed78023a06deed1c182e14c98f7cf46bc627a4a2c102ad23c41cf32454:
+
+# special case for z_2 in multiplication by 2
+# valid
+28312e17b47dd32d90561168245187963c7469a31c881e4a5c94384262b71959:
+5bccd739fd7517d9344bf6b2b0f19a1e0c38d9349a25ad1f94af4a2cdcf5e837:
+5bb56877caf2cdac98611b60367fbb74265984614e5e73996e8ea1bd6f749f1a:
+
+# special case for z_2 in multiplication by 2
+# acceptable: Twist
+a87640cf8237b473c638b3e9df08644e8607e563b5964363ccc42133b2996742:
+8a7a939310df7ea768454df51bcd0dfbd7be4fcbb2ffc98429d913ec6911f337:
+b568ed46d04f6291f8c176dca8aff6d221de4c9cce4b404d5401fbe70a324501:
+
+# special case for z_2 in multiplication by 2
+# acceptable: Twist
+780c5b882720d85e5ddfaf1033e9a1385df9e21689eeda4dcc7444ad28330a50:
+fe3590fc382da7a82e28d07fafe40d4afc91183a4536e3e6b550fee84a4b7b4b:
+11fb44e810bce8536a957eaa56e02d04dd866700298f13b04ebeb48e20d93647:
+
+# special case for z_2 in multiplication by 2
+# acceptable: Twist
+209e5e0ae1994bd859ce8992b62ec3a66df2eb50232bcc3a3d27b6614f6b014d:
+fad9ab3e803b49fc81b27ee69db6fc9fdb82e35453b59ef8fab2a3beb5e1134c:
+85d9db8f182bc68db67de3471f786b45b1619aec0f32b108ace30ee7b2624305:
+
+# special case for z_2 in multiplication by 2
+# valid
+806d1dee5ff6aea84a848916991a89ef3625583e1bd4ae0b3dd25c2524a4ff46:
+98bed955f1516c7a442751ac590046d7d52ca64f76df82be09d32e5d33b49073:
+61d4ef71cbe7be3128be829ab26ed3463eb4ab25937c309788e876b23412aa7c:
+
+# special case for z_2 in multiplication by 2
+# valid
+00f98b02ae0df5274cc899f526eb1b877289e0963440a57dd97e414cdd2f7c51:
+e59be4917b3f05b6fc8748c9b90f1b910273c9c6e17ff96ef415ff3d927d987e:
+5ba4394ed1a664811b01557944becf7585652a8acbdbf806742911207bd79346:
+
+# special case for A in multiplication by 2
+# acceptable: Twist
+d86c18f2be396b3bb72f22e6ece22e273af6e1506a1c09ad4d01bdd2f439f843:
+8c9885a26cb334054700a270f7a5f4aac06bad8263b651ebf0712eca1ebb6416:
+a5952588613eb7a5cd49dd526f1f20a4f0ffe9423e82cea302c2dd90ce559955:
+
+# special case for A in multiplication by 2
+# acceptable: Twist
+f81aadb9053eb698996d0f781d9cda67f82ddefa3987d276ff5a94ffdf5d255f:
+f6135fe9741c2c9de7dcf7627ef08832f351cb325dbb3a26f93a2b48620e1727:
+cb6fb623084b6197443ec9ba1050c0923332e5e829ae0194269cfaf920a43601:
+
+# special case for A in multiplication by 2
+# valid
+305b4db4321b4923fc559bf91df677d0e12c3a31b16ec655cb708b759d7c114d:
+f6ffffffffffffffffffffffffffffbfffffffffffffffffffffffffffffff3f:
+9e526079c2fcf12426ae6c2a54b5ffb70f2ec662e29ea5ce0c8385c3b21cd162:
+
+# special case for A in multiplication by 2
+# valid
+900638d1979802db9b52e4dd84fa19579f61cd7bef3c0b62fcccaeaa15fa484d:
+f6ffffffffffffffffffffffffffff3f00000000000000000000000000000040:
+6329c7dc2318ec36153ef4f6f91bc6e7d1e008f5293065d9586ab88abb58f241:
+
+# special case for A in multiplication by 2
+# valid
+38575cf7c8691ecc79cd5f8d7d4703aa48592ff6e7f64731c2d98a19aeae514f:
+f6eba0168be3d3621823089d810f77cd0cae34cda244c5d906c5d4b79df1e858:
+603f4fc410081f880944e0e13d56fc542a430eec813fad302b7c5ac380576f1c:
+
+# special case for A in multiplication by 2
+# acceptable: Twist
+e88bd02c7016547a24f428bc2a9dcccad6c6f880c17bffcf66fc68459627af4e:
+60677a5d934ccbfab8ff5d8f085a0b553f94527d9c49ae140f8ed135e1449b69:
+834bbad5470e1498c4b0148782dfe630e8bfadff1997de802ac8ce302a1bda28:
+
+# special case for B in multiplication by 2
+# acceptable: Twist
+9036ed7d68f7448ac440dc51216b49840dcabd3d5e32e3b4ffc32a5fe9e96742:
+8d9885a26cb334054700a270f7a5f4aac06bad8263b651ebf0712eca1ebb6416:
+ec9070ad3491a5ff50d7d0db6c9c844783dde1c6fbd4fe163e9ade1ce9cd041d:
+
+# special case for B in multiplication by 2
+# acceptable: Twist
+90c55e77aa0fe4afb1287109fd010f526364dea18d88e2fd870ac01b66e3fa4e:
+f7135fe9741c2c9de7dcf7627ef08832f351cb325dbb3a26f93a2b48620e1727:
+dc6d05b92edcdb5dc334b1fc3dff58fe5b24a5c5f0b2d4311555d0fc945d7759:
+
+# special case for B in multiplication by 2
+# valid
+a021ba2fd4e3ad57bcbf204d6f6c3e8018d8978552633b6dff1b7447bf529459:
+f7ffffffffffffffffffffffffffffbfffffffffffffffffffffffffffffff3f:
+1b174b189981d81bc6887932083e8488df8bbbed57f9214c9cfa59d59b572359:
+
+# special case for B in multiplication by 2
+# valid
+3035083e984837587f6b7346af871bf3fc9581c50eb55c83aefabeed68cee349:
+f7ffffffffffffffffffffffffffff3f00000000000000000000000000000040:
+15a052148abaad1b0f2e7481a34edb61403589439b5bd5e5646cecebe2a1be2b:
+
+# special case for B in multiplication by 2
+# valid
+30435ce187f2723f9a3bdea0eef892207e152e4cee8985fa72d2db4147bd2a53:
+f7eba0168be3d3621823089d810f77cd0cae34cda244c5d906c5d4b79df1e858:
+1d048cbe2f8df07c233a8f93706f307d17130c2497fb752eeaa31fe3edfc725a:
+
+# special case for B in multiplication by 2
+# acceptable: Twist
+580f0a9bba7281a30fb033490e0f429f22e3f267852caeacefa3e5291f0e614e:
+61677a5d934ccbfab8ff5d8f085a0b553f94527d9c49ae140f8ed135e1449b69:
+cb92a98b6aa99ac9e3c5750cea6f0846b0181faa5992845b798923d419e82756:
+
+# special case for C in multiplication by 2
+# acceptable: Twist
+709098feb2e25c67b4bfd3be0a01af409adb6da52b3fbe3d970642dd2c983856:
+c8239b710136fe431fb4d98436157e47c9e78a10f09ff92e98baff159926061c:
+f1bd12d9d32c6f4c5b2dcb3a5c52d9fd454d52ca704c2c137956ec8ad9aef107:
+
+# special case for C in multiplication by 2
+# valid
+185ac62e729f88528950926c0de7c481c924bf9cf26a122f443b861e8b6af640:
+b7a2f79e0de9b58147691b5546d9ec463da8325e1440e58bb20aa129d1b97327:
+e6f1c494c9e4bd2325c17183e82d31ab0bbee6c847d4b0e4a99c7c6891117c3f:
+
+# special case for C in multiplication by 2
+# valid
+f03743eead7c2f7719794324f271072817d1a04cbda42b232f3bee43f397cc40:
+2dc624e1663f42a7b9336350f277541b50b8ddc7ee0d86133ad53273aed4e62e:
+aa2a12edf752d279bdb000fb1405a5df8c5f1d41309b4f2bd41aed7ac1ed0149:
+
+# special case for C in multiplication by 2
+# valid
+a8fbb4f90da45794981405d59ef310621e3c3b6b7760b5e30308c7822c88ae5f:
+0e5eceee9104a64f82c9093b9bf7b4076ee5bc70815af7ee9f942ef015756176:
+74d5606ba0b6ad1d8ba36ae6f264d6315f479b3984de573e9b001e0555247c32:
+
+# special case for CB in multiplication by 2
+# acceptable: Twist
+c887886fd07107c7221f6d9dd36c305ec779ceca132ac933ff77dab2beac6345:
+737d45477e2beb77a6c38b98e2a19b05c395df7da998cb91f6dfab5819614f27:
+8cf4538ae5f445cc6d273df4ad300a45d7bb2f6e373a562440f1b37773904e32:
+
+# special case for CB in multiplication by 2
+# valid
+58096ee29361978f630ad1fb00c1267c5a901f99c502f9569b933ad0dcce0f50:
+873f8b260ea9d9ddac08b7b030727bf0072315ab54075ecc393a37a975882b7e:
+d5766753211d9968de4ac2559998f22ef44e8aa879f3328cbc46aa858dcb433c:
+
+# special case for CB in multiplication by 2
+# valid
+0829a49046dce2c07ab28440dbad146453e128960e85dd2e6a69a1512873dd44:
+75e1587c5eefc83715d71020aa6be5347bb9ec9d91ce5b28a9bbb74c92ef407e:
+761d8cecf13f93b379a772e5fac5b9ffe996cad9af06152580afe87ff9651c71:
+
+# special case for x_2 in multiplication by 3
+# acceptable: Twist
+587ac36b9a23594632679adea1a826f2f62d79738220fb487464039f36ca2372:
+f85a06065ea2527238fc5ec1b75ead9262e6b1aed61feff83b91230aeb4b7d01:
+f12acd36f6299a4d192c03aa4efeea7df51e2d15d763172e68accf7bc6f5c230:
+
+# special case for x_2 in multiplication by 3
+# valid
+a8a442b7c0a99227b4cb5c75fb9e5a72cea25eba8a0bdf07271bb4a93c2b6665:
+6e0f1d00b1099d2a71f7be86655feb8988bba5577b02f964043a49f00c749613:
+b2bbbd173f41d952d329251da973a9500300628177ad0fb79d01e2e263905b38:
+
+# special case for x_2 in multiplication by 3
+# acceptable: Twist
+d8f7233e9612c00c9dca2c751ec1d3f5f67bad77c2e714a20e71eb3f220a6671:
+696757ced3097fa960c8390a09e8bd6d390dbde8d1fa170261f3422edc192929:
+45ecfa275f1daa25d3fadf33cdf89a152afea25eae37e68e00b30c367789887a:
+
+# special case for x_2 in multiplication by 3
+# acceptable: Twist
+d80c7c7557c9907e1b11e844bf1369cba669bc38e9b7b253e51f239bda322374:
+fd84b3f2fbfa16aebf40c27f46e18d77bafa0c7971bedde4909212e771bd3c35:
+595e144e07bbe65b38e0e4163d02ad75a65e422e74067db35c90dfa6e055d456:
+
+# special case for x_2 in multiplication by 3
+# acceptable: Twist
+8002a85115ad7b41c50f84f35fac750ee8e19734807102830ff6a306beed4464:
+805485703ccfc4a221ef281267f52b61cebc879f0f13b1e5f521c17352a0784f:
+226e16a279ac81e268437eb3e09e07406324cb72a9d4ee58e4cf009147497201:
+
+# special case for x_2 in multiplication by 3
+# acceptable: Twist
+782db0c8e3e68f106fe0c56415e0bd13d812dea0e94cbd18bdf6761295613a6d:
+80642a3279da6bf5fc13db14a569c7089db014225cfcae7dff5a0d25ecc9235b:
+790d09b1726d210957ce8f65869ca1ec8fa0b2b06b6bcf9483b3eb55e49e9272:
+
+# special case for z_2 in multiplication by 3
+# valid
+909fb0bdbf53a69a2fe39c8b2497abd4fa57d2d54e046b5f514595e2c0f33d63:
+84e827f78cae0cf063e4340198f788c284e07430b3a94a3873df38b1f872ce02:
+684cc83af806bcd9cd251e1858f3c10f0166e0a0cd2be154339a886b13e7c76f:
+
+# special case for z_2 in multiplication by 3
+# valid
+78a67909757248665f79371eb014825ab6bd4af3571f140389c636e004bcf46b:
+d445e1df0083bb6b8e886e6632251807171d4e88c41816fc684373c09d7e5d6e:
+e426e4a3c54d3e77f4f157301e0ac7d9e12337a2b58df16780041cf6d6198c5a:
+
+# special case for z_2 in multiplication by 3
+# acceptable: Twist
+286a302d5b076d2aba7c2a4daf9e7cc9d8539b7c0391307db65a2f4220d30f70:
+f26aa6151a4b22390176f6233e742f40f2ecd5137166fb2e1ec9b2f2454ac277:
+862df92e25277bd94f9af2e1dda51f905a6e2a3f6068a92fabfc6c53da21ec11:
+
+# special case for DA - CB in multiplication by 3
+# valid
+a838b70d17161cb38222f7bc69a3c8576032d580275b3b7d63fba08908cb4879:
+2b02db3c82477fe21aa7a94d85df379f571c8449b43cbd0605d0acc53c472f05:
+3f438dbf03947995c99fd4cb366ca7e00e8cfbce64c3039c26d9fad00fa49c70:
+
+# special case for DA - CB in multiplication by 3
+# acceptable: Twist
+b0733b4203267ab3c94c506acadb949a76cc600486fcd601478fcdef79c29d6c:
+d71dd7db122330c9bbaab5da6cf1f6e1c25345ee6a66b17512b1804ace287359:
+95f3f1849b0a070184e6077c92ae36ba3324bf1441168b89bb4b9167edd67308:
+
+# special case for BB in multiplication by 3
+# acceptable: Twist
+d844a36b58aefdb08b981796029a2766101884b348f70eed947c2541064caf6a:
+737bc07de0729bbcfbee3a08e696f97f3770577e4b01ec108f59caf46406d205:
+6a969af6d236aba08fa83160f699e9ed76fb6355f0662f03dbc5915a3c23063e:
+
+# special case for BB in multiplication by 3
+# valid
+a0b7d312d9b832e124d1bc8cb21db545440e3cf14e7473ee9ccbe9b682f2156c:
+9758061a7b3e2c02fb5c20875ae6b55b11fb6795990a0f4fdcd1147be5521607:
+ab39db4aa29ac4017c7446f1ad0c7daa9a37f1b6b4f2e9d2902ccefb84839d28:
+
+# special case for BB in multiplication by 3
+# acceptable: Twist
+787f1ddd78cc6473d3e63949409ad3f35bfe0ce0738f255dee682f2bfbc80f7f:
+37cd65d33036205f3449e8655a50d4b0c86fec02100b4f2db7da92dcf5e3aa0a:
+13de41659e3e308d6e26c94282fcc3e0364ddf0809ddee6c8e7abb5091b02b00:
+
+# special case for BB in multiplication by 3
+# acceptable: Twist
+4080ae60a85c1fa95aad9beabd98b405e7f28141bf08f2c9a4fdbde1c5680265:
+a9b6e8081460383adc587c8f91a02c59a7a35576ca62436ccd1b5fef1b92545d:
+69ed8a0a27812ae6741474bd5c6a4e683a126649f7245aa0f91a3a384bcde25a:
+
+# special case for E in multiplication by 3
+# valid
+08f9f4a4fac4db413315f74a59818b2452fc7b7685592e26556775f9b86d907f:
+fd1a2cd17a93f850deb8c45a2d34539232dfd8a558304209781c6cb58229870e:
+010218bd67b1b92fee3e7fa4578c13617d73195de10279747e53ba01a254525a:
+
+# special case for E in multiplication by 3
+# valid
+1888cfae3085867657b09435c42b74cc762457839451a3659db218d4214fdd63:
+b88119e5ae6d9e6b912d52524739e612ef19ab7e5dd3d946cb9bc003c378f81f:
+e6b298de9cb6358fbbb00f11890f5714a3858e8f05a2a8d1cf39fe78cc55dd4e:
+
+# special case for E in multiplication by 3
+# valid
+789ce13ed007818d7a5181e629eed944a20a058cfe39669c9831bfa5215a1269:
+7b70e29dce0479cde4a36c7f9786582f104bc0788f046b48af495e67bdb88f36:
+967bbe298494b4a5f95853cfde9dc85970b2a4b5dd2c92782901e853957f5809:
+
+# special case for E in multiplication by 3
+# acceptable: Twist
+00022b43775ab2f4b91bc1cb54c97f78026289eaaf02abeed04ca84f736c686c:
+2a209e2ace0e3d6973ffbf7403f9857ff97a5fdcd27f2c7098b444fc3c166738:
+9f66848681d534e52b659946ea2c92d2fabed43fe6e69032c11153db43dca75b:
+
+# special case for E in multiplication by 3
+# valid
+8097a52fc562e8a516682f5363cc5e7c88e9c78e308df0deef40497b35cc127d:
+f50709aca7f314e8d05b5ff97a427e427bd5e85c4e86712125076a771be21448:
+ea7572e27a9120de1f13b85710ba69a3471b7b3f5d12bc430c12c4bbf8aa3957:
+
+# special case for E in multiplication by 3
+# valid
+4028802030d8a8221a7160eebbf1846116c1c253abc467d6e43cb850f1459860:
+0f13955978b93d7b9f9a2e70d96df922850a8ffd8412e236fb074aef99d37d54:
+e23d63a46be67c7443c07b9371ff6a06afcd7a5794bf2537926074b88190307a:
+
+# special case for E in multiplication by 3
+# valid
+d8515d45c7ab2b9529816543150068b8e4bb614cf2b68a8a99363975af503d74:
+18ffe992a729ce70c3b7cdc55bab55f2210d279134b3082a9f682d3a0b131273:
+33ccaf24e1e26290ed7e462093e9f77607ef52a0626b2cd2511c41cd24c13849:
+
+# special case for AA in multiplication by 3
+# acceptable: Twist
+d8815bd144518fa526befdd373f5f9cff254d5d3c4660e8a90ef2a22c6876a74:
+c3ba28057728d0533965ec34979fe7bd93cf6cb644e8da038baa87997b8dc20e:
+74f95b4700f0185f33c5b5528ed5012a3363f8bbd6f6a840aa1f0f3bdb7c9650:
+
+# special case for AA in multiplication by 3
+# valid
+a82d996093eefdaf283f4049bba4f5af6ecc2e64894f325ee1f9ca1e156d0567:
+4eb095a86d1e781bb182233075ebf1db109d57135bf91d54fdb18eb371427640:
+e9677b854851c41cc489e03981ae78690be6cbf0054ea9834759de3e27bcf03e:
+
+# special case for AA in multiplication by 3
+# acceptable: Twist
+c02609df3d5436c123dcd7ee11f23f1da321666c09f379d37914203340510861:
+83f67d7c92b11c8fb072484642a01f43deb022b54d94a4015e39849a2e2e9555:
+f148716ebe7269a7076f0cf1f22b6978d3c7e3607b0bcc87a8c7a85b9fd20c2f:
+
+# special case for AA in multiplication by 3
+# valid
+a0e3b78c0f3be2a760b2c916f244df219624fdda2e9e31b15328f4a77690296a:
+20cc75d376d8453b9d049c84f58eafcf61126c08a03661e735f0a8be228fd466:
+1d5c123e88e9dc7a3b16ec90b60578dfca7e11eab9b88c6eca7bc33d91fde83b:
+
+# special case for AA in multiplication by 3
+# valid
+701f130a290584cb28c7d6539506a1a054f926a17ef7c568ae43047c05e10f60:
+ef31b43d19c0a5434deb56129c16298a394a7032a2e52cb997476bdeca325b73:
+2fc065ba8f5040a0a659f6f7330554bd1b9d7c893b91e316e0af90c37af4f135:
+
+# special case for AA in multiplication by 3
+# acceptable: Twist
+d0e67f68183a4c1aed9c56864b36278bb7bb75d57a78321bc7c24ff61636607a:
+d8c8e2c6f33a98525df3767d1d04430dab0bda41f1f904c95bc61cc122caca74:
+ef7612c156078dae3a81e50ef33951cab661fb07731d8f419bc0105c4d6d6050:
+
+# special case for AA in multiplication by 3
+# acceptable: Twist
+88eb7775dacc32b045ceb35f261b3616315efa98b780e08c79d544edadb5467d:
+1833619516b80db0c05b225509e6698df028d83b66ed6bac6f0f6308970d2c7d:
+a3cf3d81ec56896a68fca0da6335171d0c622568738c0db26fe117033726a049:
+
+# special case for AA in multiplication by 3
+# valid
+7055b1c0576e7ab6c89fcc1ce49e79c8c371bf9fc2b22b8f8396a9b64c5ae26d:
+e2e989aad2397fc34b6cbe2db27d5ab69b28048383c91d9e8226d548253fab7e:
+e7f45823a45b6a46192b37d73e8609b5bda68cd7cfbdccaa49082080993e640f:
+
+# special case for D in multiplication by 4
+# acceptable: Twist
+906a9bfcfd71014d18967680d4509eaa41c666424af98bf9ff7ff49eb1baba41:
+b9bd793624d6a7e808486110058853edb25e136bd4d6a795d6d2ef53b25e3804:
+7c6148134c9e8b2ba5daeca41e6a1f3a82d8f75d0b292b23c40fe7f5ce0a2b7a:
+
+# special case for D in multiplication by 4
+# acceptable: Twist
+28392b1b035a8465aa22aabb571061c6effeed40cc2530b628e4fd40395ae04a:
+e3f444e208da9043f3f74c20e28d7f404bb687a346709abcd555156f88607820:
+ea5e772bac4693ce69ea3ac761011fa7674037653a433c7f05456e7291cd3c4e:
+
+# special case for D in multiplication by 4
+# acceptable: Twist
+78cbb35204cc88676c14e0ff18171392e998411b23d905d4c4dceab70511f442:
+87b43f90f76d12fb3a469fa8687c27e369d4a82f95cf95e8dc3970de8f86d92b:
+81c395aed5cc5f5e2a206a8a4cacecd501df5b81e49433835ad8a3779edffb30:
+
+# special case for D in multiplication by 4
+# acceptable: Twist
+a8225b49ef7b7330e3de787cbc40479644db7ab126370295c94189673430d745:
+86441ea06c5cd2a34c6b51261e93a2f30ea7db0f74e14c42f0fc443c6735973c:
+513eba5870dc5187e2552fe3ba8292b516d2af9ecb9a9bdc51eac2ce2de40112:
+
+# special case for D in multiplication by 4
+# acceptable: Twist
+0841e1a5c7420b94b6cc6991316ebdd608626339c09d0f67b24088588b9d0d49:
+4624aa4ae9d12725bf92b85f93e3e8cea16b7bd83fda0eb18fab2dbe0e8bf742:
+983b7e236ffaddb4b759b7353fe87846f59fb6f28a3ed65c256176b6609b7c6e:
+
+# special case for D in multiplication by 4
+# valid
+08ecf76e31a23039ea8a15ee474b6251a9d725bff1a5751eb5ecde9d7d4e2f49:
+a625a5b7a04cea462d123b485c39ea44a8079aa223c59e9ca97abcd30b500e4b:
+c941369b085c7465d50d23ceaf6717ab06e24638f217a7b8055ce8ebd3ca1225:
+
+# special case for D in multiplication by 4
+# acceptable: Twist
+6038fb0a830d1001ca8ea74a613ea98f6ab8512644e55e8d45a29071bd4bef45:
+8a5f2063f259f3317ae3e0b459f82c4677666e49a2eb9bf0369aee663631265b:
+a3f7e169db44d0d179c242e66347364ab92744dc6ad80e4775aef7f4ff9d5f34:
+
+# special case for D in multiplication by 4
+# acceptable: Twist
+c04cf129f0b33332e2654f8e45225c042d7fa6cbc793c88bd4c731985289b045:
+54cfb6ad0d03e3115acafee12606397f2bb46a8c5f326a255c494118aead3b62:
+401aabfbb73fe6694c446ecfffb43006427a9d4756e049a1ffc79578d62f1660:
+
+# special case for E in multiplication by 4
+# valid
+3806b036c92d7bc0771998d24dbda2945b601d42449bd3ec4bbf3757d01b894d:
+0ee3bee8cb3a0afcec22fa2233706e8ec29ccf1af212c0a674745ebba34f9d08:
+20322dd024fb5a40f327cf7c00da203734c2a279b9666a9ff7d8527c927b675e:
+
+# special case for E in multiplication by 4
+# valid
+380d9056b5a2f4b3dffb30e6ceb722ac4684245f1befafb5661bc8c7a9ad4c43:
+797ec7512afbf0ad918d0e4947903be95234f3abf36750a8f854888d117b774e:
+46152d59c2d2f3ecf03ce652d2b6978d401d5ede4570a6c911771bdcfb37cd41:
+
+# special case for E in multiplication by 4
+# valid
+384929a42c8d8df146db9508e2f21a4e8cd4d99c1b1338df17a457e88afb0043:
+d570c7810f69e502b355253afa7c667bfa5060d90dc86e358ab445f6381e415d:
+37567f7ec0449c7b823cf7b0e219e9dd880e56a1464d0417a9e67eff42332866:
+
+# special case for E in multiplication by 4
+# valid
+48a986825b2680e2f2547ba75a9599b04ed57f8ed18d98e7099c544efbdf284b:
+2c611cb94448f1c7822425a4cf5356236b90a555b1ed4747820ba7f739c8f57d:
+fbf6587ec181116cf1ace7dcd548029d69c130e50fcf6ad5dfcd25c23ee9f939:
+
+# special case for B in multiplication by 4
+# acceptable: Twist
+98452ad7df4e26bc4b3d403f9ebf72bb2d7b6b7d5860dbf6fb9a4f78dc02704a:
+e559c417da7fd5851352f508b90031d49b5d2d0aac88a9c8b5fb6e80165ac10b:
+c7c6f6d7ce1e4f54c727e5900686c34e6a6953254bd470bbbf0c7c18bbddad73:
+
+# special case for B in multiplication by 4
+# acceptable: Twist
+a8dbc9be5034ed7fe7f469264f2135e9c67cd30f525570d2d841e4bdeac52349:
+746d97e7774292a3d703f604e79d8764c99a6a2fe280eaa9811115f5e038f21a:
+cf7d2a66ea4dfed94469b2d343533ff302a576f8402ed2187904437038e54665:
+
+# special case for B in multiplication by 4
+# valid
+f8d26878dff25ced02d3b27ce74002695bb879b3c4328930934315ecae842b47:
+1f354aa8ffc4eae2b40dad2ebf830db3feb07e2a1a2da39e55df87c8c613de1d:
+b204d3bbcbdc624f9f1a743fa3daa8f4c8785ed088d37d08cd13c601170a461b:
+
+# special case for B in multiplication by 4
+# acceptable: Twist
+d0f5e9c43c95b1ffc36f832b943601d5e17647f7d78e2e7710ace63ff274d447:
+9c3f0023e1a4832586af2483bbec64ce9f06f3ea806d4019a5e4abb1b5627029:
+b9f21465615f39dddcc37520ce9b956f7de9883ac93a870d74e388b8e1775463:
+
+# special case for B in multiplication by 4
+# valid
+700679e8c24df828f2e5212a3263d5e93ea61679988298bab3b480f46f961a48:
+d05656aa014d476022dfc55e8d3b4884ed0bdf85209be8b55351394d52be684b:
+20f1fc613874495f20562c10b7a8be47bfc12c168d829d6321aa2de17060e40d:
+
+# special case for B in multiplication by 4
+# acceptable: Twist
+d0d077c9461f747e5660be85cc620428b4cefe805de0fd254adaa465ea5e784f:
+c4a19b8686e18c29359aa548427f06a368d55a8737483d4893523adac6795a4c:
+652b18ffd41cfb7d1f0b6dc79baa3b2a392ef1617f5cf6259b5b4ff065916a16:
+
+# special case for B in multiplication by 4
+# valid
+00711ac08ef88c3d43a3cbda67b6fe5f34f54723dbe6d725c8a3569070ab9a4e:
+4989de79853ff35be8c9f92fc94674feef38a0e65788471c521f8e259adf015d:
+679825c259392d86f8edb15328d4faf52300779d979a503a76e27be3d7a85e03:
+
+# special case for B in multiplication by 4
+# valid
+989a75b40451139ec36ca6aa043765c61a18be323a5987fcb025c2dad8d4bd40:
+a981483cb0ea4385ffbb552826c3dd110d4ae89ff52ed0cd6018f99d3387987b:
+9cadc14ac153fa383ef66d1833f589100dff90523272e32b06e2c6f1f4424040:
+
+# special case for BB in multiplication by 4
+# acceptable: Twist
+90c3cfedd919a2ccd51fb455649e3ad2da1ef0ff619b59a7f9c55a68a8219645:
+1df3dfdab74ff38177dac294b2da2f49a348bc3b3bc6ce9312bea5ef3ecdd30b:
+bcc95fb4890ed311f3fb4f44c2b60866cdddec97db820a7f79f475337e16284a:
+
+# special case for BB in multiplication by 4
+# valid
+e8fef5c9b60f84984e8836d535acb372096ba8159824a0b49a17eccda843bd41:
+fc6b718ba8b47d24b1cfd6b5d0dd8b20fd920960fabc302dbe4f93bd2a06e933:
+06f1b495b04a0010845c9d39b13bf2784ade860d9632c8847618c0b34297c249:
+
+# special case for BB in multiplication by 4
+# acceptable: Twist
+c0e05bde7727db4e352b5e7f035327b4d86a42d513ca116e22d64a4ede56434a:
+b279b6c065f95c7040f148bcb4a3d310e34bdb005931a879be469573deedd041:
+cce7bb644df94501421db49d15e821c7b0aaabecdf8837ab989b1f23bac08f35:
+
+# special case for BB in multiplication by 4
+# valid
+d87308bf753573f596ac8330b204014b2152dbdfc9881a0d9975058582bdf646:
+98e2cd4c10554e41b0a3e41082c8b6b61b55447d26c0aa97f9a06baeeb54b55b:
+71fdd3405c30805701ae4dfad98c493aecfcf2e3b563e7068373c1b19137c268:
+
+# special case for BB in multiplication by 4
+# acceptable: Twist
+d80059a8a387e16f6ded6e7e980e806d1f78b470bb61103d0ca70623ccee8b4f:
+872897f1bd1885da08b9d03e46811044fbb04186ba30c806f38b94ebdc27186a:
+bf280aeecb74ab34e1310aa6fe8dc972f94dc40c7f88b72137ccfe34ed343c13:
+
+# special case for x_2 in multiplication by 4
+# acceptable: Twist
+b0a4fe63515169bd82639b515ff7e5c4ac85bba0a53bbaca80477eb3b4250d44:
+c08f72760d9cb4a542aad6e2af777920c44563bd90356168c3608c6b9af2ef0f:
+72566a91ccd2bcf38cf639e4a5fcb296f0b67de192c6091242a62fae467fb635:
+
+# special case for x_2 in multiplication by 4
+# valid
+984256b12ef154ff6c2e1d030826164cba3614e3df7688d82b59e16201c9114d:
+4f03849c24d584534d74302220cfdc90e1bc360bb5e297c0fd0fd5f8d799e416:
+24acb4afa63919621df795206c3929b599ec9d253693895d51a0555072e89a34:
+
+# special case for x_2 in multiplication by 4
+# acceptable: Twist
+6847141d5d4377af96a2a647c642ee81600fe48d3467e3a70f3ee312bb621742:
+4959771a931e242d5713d5cb76f33310c6a283df16645604289553809cda6518:
+5ba2112a41b5bb381f202446fa9f23c54d2de149f9ad233753417263840ea432:
+
+# special case for x_2 in multiplication by 4
+# acceptable: Twist
+e85f1164e2ab6faf62667c74b03ce529b49a0e2041b1ac0fa242e522d2b7694c:
+f6fe690cf547049635bb3a7785537b4379c9ee06b46120493b8bdb152e09c81d:
+a87c9fdf40c409b9edab481b2cc69687ee1ab92e340c3db0107d40b5de6e7a20:
+
+# special case for x_2 in multiplication by 4
+# acceptable: Twist
+281e1bbfa711de69921a64c5d2183c338db5504606ce2b6b4ce1cdd54b41e14a:
+b468681a1275850c11d37ec736af939a75a7098514e04cfc1c6ca78239a88426:
+3be98798f01e71639f3cb8fd4a17bf273e10c67f8974dd9802eed59d847d4020:
+
+# special case for x_2 in multiplication by 4
+# valid
+20aacf1902b3cd609d7ee15cc96453cc22e2899d7d17852680f2a728bac6dc4a:
+2d71e8457099e3f445f9e2a14f18b0f5914bb35f482f9c069b64bf63710d4228:
+338c9917dbf11a0cabe8ad4a65959229bc00f99c211e752b20b8b49b87756d0b:
+
+# special case for x_2 in multiplication by 4
+# acceptable: Twist
+009e8e9fa993804dce94cecb96b1de2568245a97059e4d7ae116ecdb1badd141:
+fa8f24e944de5d003746d4630350c0f4f6175a3269c19184824105398fbdd329:
+56e2bfc7f6ab7da8fc734afc515e57d0794d002434f9bc8e18bd0b72c0df3c4a:
+
+# special case for x_2 in multiplication by 4
+# acceptable: Twist
+f01574643f231ffac055bd235ee74dd416b94c8e55a2ab2b4d13a8b788d90148:
+ae4e37ef53c79e25e8275a60f2fc1dfc277ebc5d3b88428c6432c3f98494212c:
+17fa1276d9fd5025172736449a1c0ae33512e5037014a18db5903e47bb3bc950:
+
+# special case for x_2 in multiplication by 4
+# valid
+3800a42659954281ca266d7cf1ea9db6d79891a406a70f9e84c3570a6a12d24e:
+95e56a830792478f7c42504043a9cab8e2eebff5fd90983709e29e03c0a41b64:
+167a3b2fdce9413c89ee892daf9f839a2eea80ea8044924035db1724a5b0217c:
+
+# special case for x_2 in multiplication by 4
+# acceptable: Twist
+70a826b186962218dbafca113319daefb5ddf3cf14e15fe3faadc4c0a2e46648:
+5f16aa7ccabf4da6b686bd28c7460e106bb1b97a823792527765c29a9ad8fc71:
+30a4ba793f2dffe1700c61428b4d84b5fcd0aa99a23b903f84a48eca5cc9fb0a:
+
+# special case for DA + CB in multiplication by 4
+# valid
+a85a5eda0a269500b3ab0b58495fc254c2691028ac533494b5f86d44e9dc654c:
+47fb78111805a11982a3d6c5d83e8e189e7fcc462c9abf805d3625be7a6eac11:
+2bf9ab750bd58ff6f877b783eda45a71a65cc9b7c037fcfef4cb5f4c8842f529:
+
+# special case for DA + CB in multiplication by 4
+# valid
+183f28ec867624ef5eca4827ed0714a5525ef21d5e35038b24d307a3391a2846:
+03b8ca5efd1777d6d625a945db52b81f11214daf015d09fdc9df7d47b9850e31:
+35e9289234bd5e531da65d161a065a14f785076088d741c9a2d886efd7d17921:
+
+# special case for DA + CB in multiplication by 4
+# acceptable: Twist
+888c6444ff5eb482b2b10bd4e8a01bdccb65f32934d8026106f16a91349f484c:
+4eca5f8731b0fa0c106acf578b83a350fa8173a290f1eba803956de34eeb7671:
+833afb867054b8b9ac70d6013c163e8b7676fd45ae49a1325f3acb75975d8c13:
+
+# special case for A in multiplication by 4
+# valid
+c8a85d140ba150f5c6a8d3cb363bcbcb75365e51c61640e974a0725b5e9d5940:
+a5562b4ba86b464dff4c2cfae85b384be211771efe8a9697e51d84de47f1eb14:
+8a914760129575c8ab3270d04b0465fc2f327acaf1676463113803bbb2ec8021:
+
+# special case for A in multiplication by 4
+# acceptable: Twist
+90a3aeb1417c3d61c1efef1ac052218fb55d3a59c4fe930b5a33cc5183b48547:
+88ae1631cd08ab54c24a31e1fec860391fe29bc50db23eb66709362ec4264929:
+c1988b6e1f020151ec913b4fb2695bae2c21cc553d0f91cf0c668623a3e5a43d:
+
+# special case for A in multiplication by 4
+# valid
+b858d7414bd9ab9a3ebea79064ab87bc050e74407f4d4748f62fa4d9d203b640:
+cbc4d55d5bfddd0bc5c5edbe3a04836b2c701d25195b26221cbea19311e55a3d:
+bb24817bd9fff423dc0972908e2c03fddf4dbe100016b459f28fe9594adb3714:
+
+# special case for A in multiplication by 4
+# acceptable: Twist
+f825edf1f79eddd715a72b3ac267d6b2e97e18bb13bcafdac5940370b85ba64b:
+d66a2f9f7577e2df4a56cb51962b3056ff5cc0494c60f39511782e79923edd41:
+b3b4513f8a3102e1ae782fbc69888177f2c24c569303a5d01ab1c3c5e285524a:
+
+# special case for DA - CB in multiplication by 4
+# valid
+b0a710b470e324bb56a7d8ff8788d05eb327616129b84972482425ea4ad4f34b:
+de0fed2fab6e01492675bc75cbe45d7b45b0306cec8dc67611699811c9aaef16:
+471ba91a99634f9acf34fd7fd58f72682be97ee1c821486d62ba4e448cbc0417:
+
+# special case for DA - CB in multiplication by 4
+# acceptable: Twist
+b898f0329794747d33269a3989b67e43a7ab5a55fa1210b0e5dba193f4fa094e:
+6418d49fe440a755c9ff1a3582d35dc9b44c818498f15782c95284fe868a914c:
+cdb3ca02d5fdb536dbc7395bab12bdcfd55b1ae771a4176dedb55eb4d755c752:
+
+# special case for DA - CB in multiplication by 4
+# valid
+a0528ed9a8ec22ebe9cc2e32fafc3f467500a9a22f5377382df6604edcdf4f44:
+a89bcfa236bbccf07c434b59f8655fb085b6cbe5ed6376281df813afba22b752:
+cd3245403fd9edfcf91c9581ebb2eb7c77ad6837fca372479e78de9faf60a34a:
+
+# special case for DA - CB in multiplication by 4
+# valid
+f06888bde75d689d056874f6436000497d22d8ad9b95a1c67de1dda4ada3164d:
+cdb1f95f6eacc24b6d029c6ed976666dc51794db8e4aa966ba850fd7f5048965:
+ab7c47ecb0c0167156f44f66a527264b958fc992c21ce98cef3ae214d66bd82d:
+
+# special case for DA - CB in multiplication by 4
+# valid
+e034fcaa3ae40603f9b22af159fd67ef009380946de92cb1d83cc489e8b35041:
+9491a82744f1cb6105b76b0442e54e605ac67f47a1b2b3b552d486f75bd98e6a:
+1bfa264a7c7229147a20dd021211891e61f5d8c76cd83f0be24bc70e466a815b:
+
+# special case for C in multiplication by 4
+# acceptable: Twist
+702a7448c0ed58e1f4e0e332d096a36360beca2f6955c815bc120b3a691d7742:
+4d19e156e084fe582a0eb79b2f12b61d0b03f3f229227e798a933eea5a1b6129:
+c46057fcf63088b3a80e0be5ce24c8026dfadd341b5d8215b8afcb2a5a02bb2b:
+
+# special case for C in multiplication by 4
+# acceptable: Twist
+50025cb508ad4faa06fafd0f4a33b747ccf1b3573885d3426500d51b56300144:
+cc4729c4eae292e431ec3a5cf5020e19f9bea50ef3218d9a790034526c3ee14a:
+d4361e26127adfbe37c2ed8f42cce4ebab8ab74ed9e74f14c3435d612c1a992a:
+
+# special case for C in multiplication by 4
+# valid
+7082fc53299a4d30e5d0c383c035935b1eeebd9408fe4d04b93eec24be52eb47:
+4a474249af8f771f0cfb1116f24fda4c42f4136d2afb766d1b291c73c6668d5a:
+80dfae7a28bb13d9e51ff199267cec2a19dfc8b6f4974e3446b2f62fe9b62470:
+
+# special case for C in multiplication by 4
+# valid
+98ff7e711d65cc7fd9d0ac12dfe8b894e0a93602ca9e75bf0eabbf0bfe670148:
+0f2a5cbbe503139531ac0529183da8e624d25286f6e35d1407ab1f4d76ebc260:
+7a5c373065e339b26ee537cff1cf4597cfcb4bf2dc7c4bcfec9884443281c273:
+
+# special case for z_2 in multiplication by 4
+# valid
+b080f4ac1e758bbfbfa888a78cb8d624d97b8688002b2017e35f52f3d7c79649:
+2fe11d723dba63559e1b96147893cb7ec862711806316daa86cd4da769d4b22d:
+c5edcc5d447071c08dfa8281414ae6a02de753e2f7bb80af5f6253e56db43422:
+
+# special case for z_2 in multiplication by 4
+# valid
+e815bf9a967e1208af8e74ce9af6d113dab17c01c90f1ae2bc25e3e2f9e3a44a:
+98e1211dcf6651fa9f2d00eb083ae5855869a2a53e835f2e03b30c0a19ba8051:
+263a38fe538b50e8e988bf07ae86f33d49886b14c7143efd1d2025c840e36a25:
+
+# special case for z_2 in multiplication by 4
+# valid
+4051b01cdf90af38f0a96ffb83f8d4133abe4fb035b6fe6f65276447caa7314f:
+2f1b938b81a4c90e1251135ad7fabe835f6a8bc5e22d4b2ab119f6f677877677:
+340acf2801de71c18f4c79cfea372bc354e4c8a5eb5c2cce8b45d885df162f45:
+
+# special case for CB in multiplication by 4
+# acceptable: Twist
+98c092363184e58ad6ce510bd32b309c9d5a46f8d9ee6f64a69d8180bbc6cb45:
+340b9f613550d14e3c6256caf029b31cad3fe6db588294e2d3af37605a68d837:
+9efe5cd71102d899a333a45ea6d2c089604b926db8c2645ce5ff21492f27a314:
+
+# special case for CB in multiplication by 4
+# acceptable: Twist
+686e51c00116d1c191aa9d5823b96e5956102e8fe75f5cf2376d99989f6f4342:
+edfbd6f09aa32435440b0ca8ba436308319613f8f2d501133c526c3ff55c7b3d:
+196182095bcd2ef46b18f64c63607e0ab162a0869e6265ac8ae35e358c3d8a63:
+
+# special case for CB in multiplication by 4
+# acceptable: Twist
+208af2c9442b36b521fc3a1ecefe342aac308bd6e6296ee091c196dc02e7ae40:
+9b0538cd618b0a4de09e45420f84d54d74514fbb1a31c1a4aa1e93306f20723f:
+a3c6b75168211e8e0a49ca815bfe3f469f29864dc8166152b456e7074afa9b5b:
+
+# special case for CB in multiplication by 4
+# valid
+c0d861a6d5ff91f91e3bd05934161ff0ab0f3ce7e4a2b5b4fcb31ae34b46664f:
+ae8cf2fcdde710c2c1184524bc32430874dfa08c125f61d6919daf8e66db415a:
+deaae6c9952844a3a1d01688e7105b0bbeadc160763c2002b6d0bcf35c22d123:
+
+# special case for AA in multiplication by 4
+# valid
+70785cad160972b711318659b47b574f6941ef6da1ea06508b2650f57ec9e54a:
+2a59f478402d2829cd3b62e9f7cc01445e8e73a42cb11af00b6b9a9f0e44cb3b:
+c204bd15f01a11a2efdabe2e902b7cd0aa079316f60e911b3ee5d46262e98631:
+
+# special case for AA in multiplication by 4
+# acceptable: Twist
+60afc8eb1f87df4b55287f3c4698c5f8b997b28a73c573fc273e9c467fb7e44c:
+836c8e45dd890e658c33e69b6f578a5a774c48b435bc3b91ac693df94a055857:
+c5457487e90932f57b94af2e8750403e09c9ac727e2bd213590462b6937b0753:
+
+# special case for AA in multiplication by 4
+# valid
+a83c11b2834136b9aaf0152d90e76e3c27177693a2834e8beda0a3571bce6947:
+59519ead7995a6df89bb54c840d61a8481881098b8a4f83c6a2f6ba800338257:
+4ed6f8d62932541c6bea16e03835f1f758a5c41722b5c9989c9c7cc08e34e37b:
+
+# special case for AA in multiplication by 4
+# acceptable: Twist
+b80d8795735806579e71759894939d758853592127efe84fc82eb7cdee45014f:
+32f34da84ab4bfca369c4b884691becf54be7fbed16449dc86969da7ea9abf62:
+521a5b8149a132d155e6b4ed113900506cfc2f76d2a3e14196d69eb85db3c952:
+
+# special case for AA in multiplication by 4
+# valid
+e08ffa45efbe1f96584c76254554adb9177b58ed09609a6ce499e5bd22d35c45:
+82ae48dcf59bc5e469f9a11b18a32d4753ac818692dfae27d675411a2272b363:
+e831d6cee95ca1b4c96bb89457562fff36cb4d08b81da89b810b425ecdbafd78:
+
+# special case for AA in multiplication by 4
+# valid
+688e1bbb5114f34e8531c278b2d9714ba07c32a7aea6e627135bd1fc65238045:
+b33bd3ad14b66896f971cbdf27785fc3aa3cfb39adc6c29257d22ea4df8cbf63:
+350e3ab9d0dbff78f3f2157428beba189333be274827c10d59673f21c0c48a24:
+
+# special case for AA in multiplication by 4
+# acceptable: Twist
+8036a4e2e93e9ed82d99d71a522aac9289bd9905fe41d01d08a499376a258442:
+18e58df6bfbe184b0e3c7c4bf2a051ed055b793501c0d4fc47bc8a95c4deec7c:
+ade71d6460287fe808e947560e67a9d6ff2f96eaa1355d2e9fbbe549e883381b:
+
+# special case for DA in multiplication by 4
+# valid
+901b20f0cda74076c3d4bf4e02653cd406ed480c355159e22ca44b984f10764f:
+772e31e776e8d4f23b7af2037af28a37e68f61e740b3904f4ec4c90157be1478:
+91a9bec28cf18c7094e2d80d2764df59ada0cb1946be422864bd7ad0e533b663:
+
+# special case for z_2 in multiplication by 5
+# valid
+d83eb7affd1bcc1ec0b4823cee5cf0b15b5f57085aa2708ed437a2925329b550:
+a8d55d5c1137e9bb626557f9d6eea8d3120e9364f8bcd9b67934260b1a091801:
+6c1b8e240edfa5db2abb3dc12bcf9e8ac9ca10dd3507083746f6f36dc035d755:
+
+# special case for z_2 in multiplication by 5
+# acceptable: Twist
+989eee317b9c254dc023f9e35eff0224bc2e0bc871996b946a96970e7506a85e:
+33c94be58b0f0e6cf363e1b12a2ebfb93040715be91518f21df2953eeab5fb01:
+d4c3b3467714f2d105904a84cc7e81d7f291304e908041682d8906a683c12125:
+
+# special case for z_2 in multiplication by 5
+# acceptable: Twist
+b8355455d358f2dd7c5707b2c6973c9c27b99e7d8ac1650c791e5fdbcbea4957:
+a218ae9624b07ce05178b9d0cc1b71dee21f27852a2ceb18610b4052b244f00f:
+1ebe6ca711a649ae487b332747e3dc0306340560cab6bc6029e44f6a7e0ee41c:
+
+# special case for z_2 in multiplication by 5
+# acceptable: Twist
+8065567ef082b16c20853487f54893012ba4762224e5c59f250dfbf82581e85a:
+d7067faeafd3e966e57525f930b3317c9e8b9c9a9ae946e76c1e4602a59a7e33:
+03e7a777e648bdc612189f3cd42d34e35736d3e52e6edc8ac873a58e244a6073:
+
+# special case for z_2 in multiplication by 5
+# acceptable: Twist
+00b51448139a61fe6c5fbf9395877d53d820ef59da3be856458b5eb90985ba53:
+8df9682cbe8802478a8531377e752cdde54738d528d639bea9eaf47702f8bf3b:
+308ef99dae1064a444fa90775b5dd5b1952d7224a0e5ae031df432640f416208:
+
+# special case for z_2 in multiplication by 5
+# valid
+e8eb9f6f62f93dbc325b833aa763a90f13f0acb2c2c4b8b33decd471ce70c45f:
+7d92706868aa09538638d633c255f333b9da03bc74b49b35941c57820cd3fd47:
+f33e2e86443a2c68823b72a2b59d6a028e0a8e283cfe29fea4f7aa22bd1afe72:
+
+# special case for E in multiplication by 5
+# valid
+68a1a7ccc50bab4b01e55e18cbd464aff43131fb0741e68d53cdebfc54f33051:
+dfb1ffc176aff84db30182d2378f83728f83dd1b33d79856f3da5459cf9df907:
+7b535fc31c6c2a3803d8bd45410a1781bd90a09205da28c9df120df23a9fa32d:
+
+# special case for E in multiplication by 5
+# valid
+e075bcfc165a471b2f76c3003fb0172c82f707137de2fa7082e43a87a255935c:
+12e81e838b21eac96dc130432571216d7a9b4a817f1938721d2267dd150ebf20:
+ca23a781da0911e4115a29a9f56447157c23bee187b0c17369c4f7730d781718:
+
+# special case for E in multiplication by 5
+# acceptable: Twist
+c0e19634dbf6460e1486930c46e8556b3c16d6de959904600549bb3e08603455:
+832a46aec02240d716fe22dea94ad566a3fafbeedcce35c83e41e58076c99749:
+cd0686b32ea4cddb8e13ff20a78d380749a5d4f6a3dc55d72f4813d949a0ea57:
+
+# special case for E in multiplication by 5
+# valid
+b84caa18acc3db37225d32cab4f60e6fba4acab1277e20425d30f94cab2e2c55:
+8c8033432bcc12d479f67d6d876b1c8e89f16a234b9b093322effa9dee94554d:
+a950aa57bb2beb9ed5d3228c7ef448dab69552f3d3b1e466accf41bfb6d5b874:
+
+# special case for E in multiplication by 5
+# acceptable: Twist
+2896818cddf572521943e9f0c5e845f530b740427588a0f6de2504bd5bf40c53:
+6df799bba6cdf5f46a57ab227f93fba491dad296a2fdb7e491921d610cce8f5e:
+54f5ae57e676d08c8f8a3cf891e36ddaab751093f92f409060c57e745941700e:
+
+# special case for AA in multiplication by 5
+# valid
+a01f0cad98cf2905b812d3530531bb3ac899391abd1eaf4a3ebed96ac6126f58:
+0c8090e1cfe7f761cfdf08d944d4aeb7a509a07a6101645b9a4c7c9e9c3d4609:
+2d49b09f81f3f6fab2c67e32f1bcead2ad09ac9e0d642b0873becfb64de2ab23:
+
+# special case for AA in multiplication by 5
+# valid
+106b36344cc4a5a389d8168137786806ff03cd4a00f8636bb7e758d456151d59:
+08352936c8afd8543ac95f24bce9a07e3e3235763ea512a584298967b83c070a:
+a199368e683c3036a48f4c5f32b32a547dd39f3d1007ca0a0bebcad0a8ac6f5c:
+
+# special case for AA in multiplication by 5
+# acceptable: Twist
+88f9a0d2354adfcbab2d12a0e09b3c7719c944384edfbaa27fe0731cb9c6fc5a:
+73bdeef8cc044f5ad8d6a241273e1995e0007dc9e6579046df86aa6cd97f5d2a:
+5aa750de4207869ec7fddab34c639559b1eb27ef244aaf2a702c84963b6d6e7c:
+
+# special case for AA in multiplication by 5
+# valid
+0811f2e560a205e96e28bc312bcad45fe8befefb7f6da5faa035311eed80b251:
+7fdd399b6ef4a3f5cade62e74113b29c27db15203f9b8e398d2c6f230051cd2b:
+a6947ee089ff28ce3644ea4c6eb33dbb20c7974fb8d853f4e146e2466177502d:
+
+# special case for DA - CB in multiplication by 5
+# valid
+40ad984066a69080fb4a315878e736096cc577dae4c42c40d893d8c2173b785a:
+f0173a96273c646fb63d13b0c686b89e37676fcc7178faf4a6f4601f3068150d:
+230b6aa1f24df90a60839179ba5e9de673cff11cab59e8020b20626c22090b0a:
+
+# special case for DA - CB in multiplication by 5
+# valid
+48b10cd45639bbbf83a0b28f0dd3ad0b7b00caf48d05534480556a8278116d59:
+255bbe7230cd2bee90d283f418a474ab30146ce5e801a0f5ed60ee8def3e6558:
+2299e384958bedd2c3d367759155136d1ff76e4434dc1d9e8212cdca52ea8421:
+
+# special case for DA - CB in multiplication by 5
+# valid
+e8fad77946e0de4cf4236798490b838948b82cfb29f8e7686001b11e8d961657:
+21accf97b7fee173001ccfcab21637c175ef5186ff0002502b3d52fa8c51e766:
+97fca065acd3b943c654997c0f125767f9abc4b7c9d8b7246942f12be65d9231:
+
+# special case for BB in multiplication by 5
+# valid
+d07babed90b27c4eacafdc871703bd036b720a82b5c094dceb4749eeaeb81052:
+5b40777e80ff6efe378b5e81959ccdcbb4ca04b9d77edc6b3006deb99926fa22:
+f482531e523d058d6e3fe3a427fc40dbce6dd6f18defbc097bfd7d0cdd2f710d:
+
+# special case for BB in multiplication by 5
+# acceptable: Twist
+68a3049aef8c069b906cf743286d3952a888bf2b9b93bc8775fb5adde06e9f53:
+48d952a2924ff167f037707469ec715da72bb65f49aaf4dce7ec5a17039ddb42:
+de88af905d37417d8331105345dabaab9fd2d3cb1ee902911c1c8eae2991d911:
+
+# special case for BB in multiplication by 5
+# valid
+18d8c3d2a4e366185a85c38698d937e13bbbafdbdab1a0a83dbbe89badf70756:
+a5ef265ccbc5c54021d34f82364a4624030f5b9d5ff7e63d7a379e533de5e742:
+075d18ccc984761b70752279e7f6a757208f6c11e29480c32b40aba128a4d52b:
+
+# special case for x_2 in multiplication by 5
+# acceptable: Twist
+18efcd5fe345be4985316695391d2c952eee13b0e1ee7584721fbe8b19d4fc5f:
+9051e55a4050ef4dce0b0c40811f16371e8b16932541da37f069406d848ea424:
+212dbf9bc89b6873a60dfc8731a10be11ab2dca4b172142e6c9f06614cd72852:
+
+# special case for x_2 in multiplication by 5
+# valid
+28ec7c693e222c72ac0815f1fd36661357e0a8da7bc996daeeeafcd21c013451:
+419adb8b1f2f87de016b0c78d1029a210492eb8cadd164b12cd65b1d57bf3634:
+379f9221abebf3582681a0e857f3da578a1b0121982b96f14b94de5dc8b24528:
+
+# special case for x_2 in multiplication by 5
+# valid
+78b35e7ae549308b6414bb610196c04f2af79d4266c86e8a9ce0c02bbdb88d59:
+13e00dae3b1ccc97ccd649088c4a7f32ca9976214d645667bd082039bbd9ab7a:
+cff2596b7afe36f4cab9c70133d7aa0f9914f9abc6c3b9895472e2a5894a8037:
+
+# special case for C in multiplication by 6
+# valid
+f0de9c5f8a9372f30c41ca47a55743ce697d46e32e7a9ae26d32503fd5222767:
+441c487a48f0a4989d931cd77a6142a0a13d1aabad82623ba8d94b5c374f4f08:
+d47c46b4329bedcbc1986b3c6d2aa9bcd027d6b68925175d35bbb536b3440801:
+
+# special case for C in multiplication by 6
+# acceptable: Twist
+686be5a12b310420f9bfb209381fd459a5ccd55c752b88337ebe89e1921ae765:
+0e67ee5c6b65aa802259810b2605f8d7accf9b49bf14cb4a536928e883172915:
+1d730158da880533dbf1e6c64a8e99f9169611660969b0a84fb42dd8dc2efa3d:
+
+# special case for C in multiplication by 6
+# valid
+a0c0337c5bec5ca24dea2f1d701498ae2bad87b8269ac23be113929fe4eb1963:
+dc9d7ef1cb49c191e258663a94e731b9c066c11a17d8b5fdea1987f5d9a00568:
+07732529a628badeb8d74946775ba457c700bf8390f46bc523fb64e471c86a7e:
+
+# special case for C in multiplication by 6
+# valid
+b8824cfce5550b5e17b12f74e28459cab34eb49895cc36bf645a0cf00e3d2d67:
+556b3ee7cd0d37979056ecc1f56a5677a4935be6e49ce28e394f8bfb73d13b6a:
+9e3aae35fa1cc80a359878e212180294ff6608dcb4929e91901abbf976f39c16:
+
+# special case for C in multiplication by 6
+# valid
+e02dba7335af8fb9168de2fcd310c2e2df4a3e25263e0ab9ada87bfb8258a66b:
+1211be5809605b54f5727d233c783a2a199a3db24ed4499d7b48c7603e4ad371:
+880f6dc73220307a597670f3282fc366aa66f04a0a9ca30d895fdde337afe825:
+
+# special case for CB in multiplication by 6
+# valid
+30ce71f856ceb874fe580039ca67e896e6d08207a73cd55db7059127c1342b67:
+505e7851e2352e311ca9536a1fe6c0d95d648197374ce08e4b8a0fbddf62910b:
+ea62b0eda2d7b249a42417675a2b82b1e6c0d69a4e7cef336448844d2f432251:
+
+# special case for CB in multiplication by 6
+# valid
+e881f46d4141ea69a671649b93b63e97dc67c12521d445862f087b2626fa2b6f:
+ddf4e90503dd82610c3a034b925a880b72dbde30c626009202b358c6eb00f418:
+302c4f83b5c5bf30c1e3afd9f643f65bfe56ca1628ee042b1ab7393bafe36c06:
+
+# special case for CB in multiplication by 6
+# acceptable: Twist
+e879752683cd73a834251c65749135e06eb9064d3ae35095d88cde14a02ba366:
+0e9c4431999ef1ce177e900d37ec6ae665e387e2d4fa27cba8e7baebc65c6520:
+8ff2ac65c85ee2fe9452fce460f8c87f9570d769cadddc87fe93ef8b7657c726:
+
+# special case for CB in multiplication by 6
+# acceptable: Twist
+20576ab456da26c18da5fbf06ec4d16564e111bfae2a92b9f6e1927c15770a62:
+5761d6c08624104d4117ff17c75e9211a591c9ca9aecca3a665a7ed844195225:
+97c91a23c3e4f3ff727d188a352b67ad490b62381566fb3e111cb67aa9e3435c:
+
+# special case for CB in multiplication by 6
+# valid
+a8467418b924c2c003c56e1610a35469356360c29d52aa557a2bb30fb8a9a464:
+e92d45b3ec56531266303c5113c46310c41650001065b4d87b02b382fc82662e:
+24346bb133dd9ae3ff02d2f50510b3a92d9030834d60e5af08b0eebbf1d4dd6f:
+
+# special case for CB in multiplication by 6
+# valid
+f0f5e162923d7c299388bed781199417ade097475515162d9590976a196fb16f:
+f38b63459d05e422ad024c2dcea5029a0a7a6b6c4c1d2093ce556aab331e2540:
+b3453c9c82a2d1d956156de2399cb70dd4e1ec53aea967e035753c1cdae13c39:
+
+# special case for CB in multiplication by 6
+# valid
+608fcf787fe789644a09bcab958f0737aa81a9e29d505f51035c78e374b9e46b:
+a7ded0eea45a400b8f5637154d42974aa98c92962314d822ef88b01383a9da4d:
+ebeb0c7b7a4165cd02a278f3a222c236eed83266b806d13494c1c3f98a2f3425:
+
+# special case for CB in multiplication by 6
+# valid
+58a3396d291eb23571b52d98a31549e514e501e8d0958ad9f25fe5a76c503e69:
+7b0ecb4c72ee147789d74813ced3ebe40f45c3da526ed1272952e453e43b796d:
+9213a53f22ff0cb5eca87b27b193c773bfdf4c01a193a11f37c157474e15cb07:
+
+# special case for x_2 in multiplication by 6
+# acceptable: Twist
+d805a7014755dd656f98d2b331f2d2d4912725ef3d03752f26f74dc1ad61666a:
+a244413ddc3a205d038d64266833eea1efba51ba62c9c6cdcdbe943be52bb00c:
+66484a4120e0eb0c7e0505e1d2c5d15de9b52b72e094c9bac88634200c557267:
+
+# special case for x_2 in multiplication by 6
+# valid
+40cb1fe06b08f068f7080ba07c695eda91a2bebeadd4db95c97dd7c91af2566d:
+ec3c8b0c10b1fa65dbbd17cf1ba5f86381284765709b07c5f0428e3d5bcd3920:
+384f2221618e71d456b1551651efdb708a161d7f89f5604b27eb872d4aa93276:
+
+# special case for x_2 in multiplication by 6
+# acceptable: Twist
+8021464c64c9d6d3c0c852f6972d11969b04c9e066562fa7f0d5fa0d98ebad62:
+6330d3e28a8b6126ace165a9dfccc6e4bd40dbc9768cfb16330cb7f27f906230:
+8daf5f4b84730144ea8a53ce39cc907e39a89ed09f0202e7be0d3bda38da663b:
+
+# special case for x_2 in multiplication by 6
+# acceptable: Twist
+707a2d710b32f55c6eba34898020a2fb981d61b1e822fca84c47d9321e279268:
+8678aa29cbc06e78b218d22a3e66c38ec0da8fdb0f2570c585c62517c9704f37:
+da8b7eba6f72c3f3ef33d8982093492e06be39bb0db29c465d95a8e52ef64341:
+
+# special case for x_2 in multiplication by 6
+# acceptable: Twist
+204a43dea79d779577581b8c2a51be66e1effce96425b7422b9ca65bdf1a4867:
+303289c2b1079ea59412faccfeba8c113d2299b9dcfedeabc42697b0829c4658:
+0419a71a08d3fdd574cbc932e8f1605933ddcdd9774f5614269b7ed850c8650e:
+
+# special case for x_2 in multiplication by 6
+# valid
+58e4741735d2589322151947a1ce2f5829908626886941cb1631d25a8a684169:
+3e6e16e02d44ebd94680832e065aeddcbb74af64fbb7c6d8367e7605be13ff5b:
+9f2fcd0c756288c1716ecd1f2a74864b93a7717bfaf5248858dcb6fdbea12864:
+
+# special case for x_2 in multiplication by 6
+# valid
+d0af3428ea5205f6bf8d4f1b4e4903cd76f04236a1c0b3ecfdcaf28b21348e63:
+a7c1716a41ed23a8870438714ff9745fb0e46f7a5baeb37c9a2d83fe477d146c:
+261ab6267c35a9755359e957473870522b7f923fe839f2b155408649cc5e8004:
+
+# special case for DA - CB in multiplication by 6
+# valid
+c0ea97e442e5dc1c8142bfab7089ecb9bb9c5ae372f9907c2825e678defae567:
+dad981552c57541c57ef395ed770ce5edc48f8015461b2ba7aa831ec593ceb15:
+9093bfa3ed3491d0891f02ae466e5e13c980df229db7404c5b9d34e4ed21c653:
+
+# special case for DA - CB in multiplication by 6
+# acceptable: Twist
+b0333f09ac1eaacd3cd617eb8832e9de488b458b735cb4b5345f517130c25d6b:
+c588dfe6e733d90581cbe112079749d8eb30ab8631134ec29abfb98b32e76522:
+6e88bb6bf75596bbe5f1fbe91e365a527a156f4f1b57c13ac1e3e6db93191239:
+
+# special case for DA - CB in multiplication by 6
+# valid
+10719099dc63bcc282ef525845c108897ac9fae9590b593e0d505d1cf167c061:
+0670116a435e8d9b7a12ffc4322fd6b149d0b1dc799b5c0957d9d6e42546e824:
+e6de74d2c5cea54094d7a70af03c768afe05d52a038bb72d56dcacf0ba502d74:
+
+# special case for DA - CB in multiplication by 6
+# valid
+10e20e4fda57084ca90f7ad572a78aa8e6575c659cd01f30c43c58040c20e860:
+8b200dd226c5c0f7e116e5388ba162438caf1dddf4edc3b6ba838c21b5929737:
+78c9c3aff9416a538ce3ea8fa553244528d1fbecbcf91695a33ca464ef76b85a:
+
+# special case for DA - CB in multiplication by 6
+# acceptable: Twist
+a8312df473adfec7171e1635f5bad44f0753a88a6b3174ec5ae762703ae25e60:
+419a076b179f79720096eaabaf03477e8f89d61f885c8d7f58f6eaa4fa77df5f:
+c1a96ccba08bdd82d0fc12e8cde4cc1f25cfd5276dce7f18e407ed0e4a898466:
+
+# special case for DA + CB in multiplication by 6
+# valid
+109697f400210f9a92de80a8bed264097199bc240e22767b54d8bb22050b7a61:
+aa34d772e9ace43c4d92f4f85596ab9ccd8c36c4f4cbddc819afe2a33cb8b216:
+2533b845bb83e3d48cffa8dbd1edd5d601778662d5da03759152a5e0a84b357d:
+
+# special case for DA + CB in multiplication by 6
+# acceptable: Twist
+d036308a53c11bebcb02e83688ad74fec43f8462ef4d806272676637d99b3765:
+1f06cfe464ccc0e27a5ec5f9edd9bc7bc822ad2ff5068ca5c963d20edd1a2d22:
+eb40a3974b1b0310b1597d1f1f4101c08dca727455a9d8224cd061a7aa3cb628:
+
+# special case for DA + CB in multiplication by 6
+# valid
+786e5a5ff37405c769d0d3788c3c1b05a62a8442c385570e4438bc5f2eaacd67:
+9d4b2ed7817132af5830e899627ea97dc39bd3772e82f2d05769a918273dc02e:
+9509757e289553cfa2cc71313473c3ff1eebce484ee237eae554fda3d3d22f0e:
+
+# special case for DA + CB in multiplication by 6
+# valid
+c01f66cb094289d728421dd46c6f9718412e1c546dad70e586851be4da58bf67:
+4e056b317a31dd96f8ec14b48474af587d195efcc2a70f01f052ef882d7b3a45:
+bad9f7b27dac64b0fc980a41f1cefa50c5ca40c714296c0c4042095c2db60e11:
+
+# special case for DA + CB in multiplication by 6
+# valid
+3877d9ce25cededeb572604f2d123df685690c26e181f777ed33302b82082966:
+72c60535e9c423f302d6a10796d954d778032cd4dbd40ca0f359e204d67b6f4c:
+51c359768ab0219003af193e2bdb8e5cc9f8e176b8db49e597afca3e7125e370:
+
+# special case for DA + CB in multiplication by 6
+# valid
+50b84618d073c4618f9aa69a3b8518da76dbb2127286214fb43a2b44503b9969:
+5856358ed420047cd084f17ae696bad79a4d26c6d5bb79bfb82bbc6332442d51:
+fa9fb0df4cfbacd0fbf3262d3a1bf8d7aacb45f73bf94671775e509c8043df7d:
+
+# special case for DA + CB in multiplication by 6
+# acceptable: Twist
+109acfa638e112f6bbec21e352a74e8fc9b7ffe5d9dc28634eeb516e59830a63:
+c31e37b04332abca8315f317171566aef38111f622d8bffa29c23c0151cdad6e:
+91ac72b0ed8d7fc4c8846b8a2530d9fb8f0532064880c00dab100c977697db28:
+
+# special case for z_2 in multiplication by 6
+# acceptable: Twist
+685c0784aa6d194c1b859bda44c4e27cd1dfdf34776e498dd03d09f87ae68a65:
+b775e016b32a97f49971121906763f3a0b41689092b9583b6710cf7dee03a61c:
+11393bb548813e04fb54133edbe0626458e80981885e1fe5f3377e8ebe9afa52:
+
+# special case for z_2 in multiplication by 6
+# acceptable: Twist
+18e9a05a20436cf0dbc3d5b92dac8d996e62ea11fbb3445f29195fc75a8beb69:
+f8bd0e7cf6ec6186f205ab03ab72c8f6b3cde8f6ad9b166916a04d43d1d6d546:
+0a83a224fbfcbc5d0f07f6dd8ebb2e9bbee8134f0fab268002ce837f5495d833:
+
+# special case for z_2 in multiplication by 6
+# valid
+00e099eb23125dab5ec35a419d455d0ba8c01da160f9354e9fb21e6a55d55c64:
+8dfee48ad8b367488ea4dafcf7086e305356a80901f87c720149a5f522337453:
+45dc39831f3471d7466bbe29c8142b1a6d6b00c47fea021be2ffc452d9046806:
+
+# special case for z_2 in multiplication by 6
+# valid
+b0ca251e0dbae7324a6ca0c2c8d6a888edd12d1447d400a47bcba004b648716e:
+8f68bfc57d792c322ebb27f44a37c1c93e7eb15c5d5fcedffc1de850487b3372:
+a29005c6b9dbf1707dc2adce4506b55831e8675b7d2d54b0c1037741e3bc611b:
+
+# special case for D in multiplication by 6
+# valid
+a8b64b8ed397773b8290425ca5c2f7c3e50fac7a4781bd4a54c133781c9a1360:
+ff0f15adeab334afeda3916785ddd38d252dce9876c2357b643b5dc2c06a3b1d:
+9f04e42c1b2f311d87e1470a4708bba25ac6ffd3f7b486f9b6b502ecbb2c004e:
+
+# special case for D in multiplication by 6
+# valid
+d0cd0db51ff232afa0919d3106fcb3a8ae581ef12d09c877aa6f31ef74eed068:
+1076fdc827f2550ee95ff9a15d044aedfac65b5e9ba809f62438ccea54637a29:
+688000bd60af375b4eeac4a7d0e0782c0e6188eabdc608b732f49b4d6ccab44f:
+
+# special case for D in multiplication by 6
+# acceptable: Twist
+204a3b5652854ff48e25cd385cabe6360f64ce44fea5621db1fa2f6e219f3063:
+ed1c82082b74cc2aaebf3dc772ba09557c0fc14139a8814fc5f9370bb8e98858:
+e0a82f313046024b3cea93b98e2f8ecf228cbfab8ae10b10292c32feccff1603:
+
+# special case for D in multiplication by 6
+# acceptable: Twist
+88109b1d0e7bace44d41a15d5bcbcd36968c5b8b47c0a2c606b57c4a68cc5f66:
+12e1589a34094af5f121c9bd3c1119f2b1f05264c573f667a748683c5633a47e:
+1fcc50333eb90706935f25b02f437bfd22b6b16cc375afff8a1aa7432fb86251:
+
+# special case for DA in multiplication by 6
+# valid
+5082e497c42979cdbfdd1b3b0653cfea6f2ceb7d07639ebf3541866bb60edb62:
+151f54a8a899711757b3b118fc5501779d621d25227af53d0af00b7583ba8824:
+fac30a74f4ca99f6cf233065e9acd826690cab364bf69320b58095783ed76e11:
+
+# special case for DA in multiplication by 6
+# acceptable: Twist
+f85a8db44f9e56b11729f51682a9769fc504f93597cbe39444616b224532106e:
+a819c667ed466bd9a69ea0b38642ee8e53f40a50377b051eb590142dd27e3431:
+17f6543c4727e7f129ee82477655577635c125a20c3dc8ba206ca3cc4854ca6c:
+
+# special case for DA in multiplication by 6
+# valid
+505a076641fac398fc7d8c629937f42db559db5e12052ad366d46d7b20e95769:
+40b053d056668982a1f550be95e16348e303945f53a3ac64491a9a56d4095b71:
+889a8d611e0a7da71475e7c93a2d7f6f7228c787a00ee5cf55474adc376ff762:
+
+# special case for DA in multiplication by 6
+# acceptable: Twist
+e8db2bf1af5b8907420789c56e71414706aef0d9f6ffaed0c249c3b7ab14bf65:
+e7dd0549a765bbef34be2e8da18a1bc1b989a8b0614d358ebf38c12a9ca64079:
+37232fb397af27f5fb5ca493284ff1c5d25786b0d716c73b33aca8d42265f318:
+
+# special case for z_2 in multiplication by 7
+# valid
+c006ab1762720882017d106b9a4675fdd47005657155c90ca61d4cbf7cc4f973:
+1ee1b9a74604ac31c3db83280170e3811504fcc78c7626b5b2c07a99d80daa0a:
+a1b30418436ba1908804ffcce1be2cdcf50c61a8e3938d95c790abdb786b8022:
+
+# special case for z_2 in multiplication by 7
+# acceptable: Twist
+d071807d607953da432d8574d5f3f420676dafdbc6a285a36e1d737624d77c75:
+f226c2d6bd7831eda1b51ee5aec29443a507ef9f7a04e2340f349dbf14933844:
+a5976fda89954a81e442107f9e416a2b4b481bbd4654ebc0c7b57a78b45b4979:
+
+# special case for z_2 in multiplication by 7
+# acceptable: Twist
+304b526f6fe994731980c0975529bca4d061017fbec56f6070d42678d3e11177:
+c5197312de3a7a3ee11b29873bae3fc8c85109c66784804f89435db210fcc24b:
+55b5b5eb38b127617ffe00056d84d35a5071d18783e3a82b5f4e131b1538b150:
+
+# special case for z_2 in multiplication by 7
+# acceptable: Twist
+982ddf2c035789379b8a58917d5c3c6c061b503b19a0028e01894c2eb371d079:
+590ed0b879319c38a19962a5d216ff2bfaf33555518877969c20c054cbe43e56:
+0080e5b9985a960a832133812a7ab9951c6b2c75894deb3e35509190a6bdf457:
+
+# special case for z_2 in multiplication by 7
+# valid
+78cc3ec0687e3e53d9cec56b79d11bf049d173f127f5b40fae122a6d0016cd76:
+7c5f0143a6682f60ccad16f21150c7bb5bc6f807254d08b353fc96ce07bceb6f:
+5241222226638c4bbbc98792cdbd74882ca2e08aa2edf313070425031009e925:
+
+# special case for BB in multiplication by 7
+# valid
+c86fc76650cf3b58837aa0f0633560415241c6c4f8f293ba0222b7d6a3875773:
+010850a0974d3e89c029d252b46f739548294c0f9a23183863f9455b9559c211:
+63788190b10d7451f5fc2b82c421151db4f3e22782e392da6d8d3aba2c344306:
+
+# special case for BB in multiplication by 7
+# valid
+888d51c0a2230369e5b65a814b3213dde2e62f2eb95d0971486b733e4f90c174:
+ad1dd82c23d6a0d5fe0f2a4561d1c16733a3e1e6afa6d902dd077dc43a961628:
+e4b40974a166ac49ed831715c071c751752744b891465e6c45001855aacdc362:
+
+# special case for BB in multiplication by 7
+# valid
+68bed425d534315584d80f79da6eab9b7e6036b51fe62e1ad933e266640b4673:
+d0c0d6393c41f4d7e0d5e850b7716f401eda1e028a4ed4a05bea8bf81acfd930:
+514a4cd0676f1c3101c8c45c17ad416bd33e20a405544fc1a60449abb22fa104:
+
+# special case for E in multiplication by 7
+# acceptable: Twist
+98ff2856ef44b4fa14d86782ea793828bdf6f1ef9b669cac1aae338a7bb69376:
+0f460100d88a1d316dff02d1b22ffb2e42d99d0b92474fc3ec7d62567d0cf112:
+ed83e810ce5ff0868f8589623bb13478dec1c22326c92765ae5e48c84bbabb24:
+
+# special case for E in multiplication by 7
+# valid
+b0cdbfdd98bd988d7c6a530455c51c57dd33fd2c7aee3961971bd3a31388fc71:
+13756a411ff3ae0c39222dde0810f08c432463162d81ef061071249a48439e15:
+ff94862117d3c6edc9dd5f4852fa8a589452b924ca8a75cb23b3d68dfed88c4b:
+
+# special case for E in multiplication by 7
+# valid
+e0677644ed4935f01e052e9967302d0fb78ff22bb92fbae0605f3ee54e2f6878:
+8fc1fae969a6185404db22749ef6d225de86773a4d1bf3857eb8fbbd829a1b47:
+1c94868bc8acb3137498209b2812feb53501389f5aa37fecbfd5cb54e1358e0e:
+
+# special case for E in multiplication by 7
+# valid
+887b61553843ca99ad1ca92253a6fe082b82494752513fd53ff6530f54c40572:
+7bab0891ecb9e72a15771f0a4fff90547024206339c340b1a2fdb53bcfb86b59:
+adbf3b439b16dbc653578f53374ed3a86f9c0bf1f736573349773bc3b8d60734:
+
+# special case for AA in multiplication by 7
+# acceptable: Twist
+00615e4697014fc12484ef53a1440206410a8df78caa0bfff82161db83fea574:
+102e95eadca7c3c28e5d52336c857bad99ea246f299b06334f401276f49ca814:
+3952efb93573ae9ce2162d10e4b8c46435859f3f2778db89f72bc579e695cb51:
+
+# special case for AA in multiplication by 7
+# acceptable: Twist
+58175113550faad56458fb375a6cb3f05df2f6ff3c4ee09d4a6ba643e022d17a:
+3548c16bf31afdcd445ad9bef0e60d7bd6195aa591ca8c82813cd7d446226720:
+96128f929fc03c1269d429f609a1a8acac7a758e3446a125ecf4a359a0e37b73:
+
+# special case for AA in multiplication by 7
+# valid
+009738e1e6efef9e2cad8b416fe90a098eb5cb0199f2df5218166c7b181ea079:
+ba74e766d44855ec93bd441aa41058a4c4ad2be63c639a3f9a87bde51eeaba20:
+fec3e94cb5f316625b090c2c820828ce0f3ee431e8d6e12abccc7ef2bd0be81a:
+
+# special case for AA in multiplication by 7
+# valid
+c82019159be792747a39f388ea48a8c568594e3383273e51100721b376e8ba73:
+9a5a1d37e5010c356aa80afb347c3d613542ddfa0be7abb8e8cdcd6674411449:
+96903bac9dc60b6178d734890c25db4bed9ea4dbcf6fcbcdc90e6f5694c8b21c:
+
+# special case for AA in multiplication by 7
+# valid
+10ac9f8383262ef280faac1e4da15a7de4f2cb74af33b50e0d82dcb85d8bcb70:
+630847e28274dbae5491210303c85a359074ee742957b0fc3c9ff55d9e019a50:
+50050d0ab1ddd2dd90c460ab8f09e1f80e37cae57d4231adae10c10a4a2b003e:
+
+# special case for AA in multiplication by 7
+# valid
+b84c098382f6e37d510cc33e62ddc664e02c8bb6ed9ed0e5fa78cc099a26fe73:
+11749b00a45067af2c7e7d50f8d178d5a9fedb8f1b69b239763885bc611b136c:
+9170c4c628d5fcfd0ec719cf6e1796dab0a69e46d6379fffa247d444a0056041:
+
+# special case for AA in multiplication by 7
+# valid
+78cde8930a1d81aef6601f71409728854987578b0f8349588c04adbe2c1f6e74:
+df1021d8f95950afde77c86ba5ee2f5876ef778376a7fdc7efb8dff0e4836e7b:
+d7d2a82953f680cee0c81c4d00fe628ac530ce682eb7fb3b0af24f804a58ef5c:
+
+# special case for x_2 in multiplication by 7
+# acceptable: Twist
+b0fe7b06b9950600b3a7ce1d7bb2a1d984194cc9d6c8964504c364dd5c875b74:
+2743ba408d5f68c65324a485086a004b6bbf784cc9e8b1a7dbeb8c4b9414b018:
+a6b97da989dccf730f122d455152328051c8ed9abc1815c19eec6501d6cfc77c:
+
+# special case for x_2 in multiplication by 7
+# valid
+f0c9c3984854d5bd599d3819738a023eb795e93586dc0e5e29b1c870c612d178:
+cc275a2cdd9125e52f20ce2abad41f920afa5a643fb7f276ef416f761d689f1e:
+b210e368729501d9f9b6ebefbebae38f195f91eaf2a5a3a49288bb615ff2216c:
+
+# special case for x_2 in multiplication by 7
+# valid
+906c2f12be89702db26fa7ee905ce36525d2dee4e96a879ca07da097a6aa5075:
+4929543101ee7ae239059cd134c35d400e50d0821441351d0fa6c3d54efb342e:
+b9e3796c58701ded4237c52994501cee14e18f2fb02b781a8400923484bd4a6c:
+
+# special case for x_2 in multiplication by 7
+# acceptable: Twist
+f026031ea373e1d16e6e7e0357bc96bc093f4b6bb76a738cbb54fe6cfd2ea271:
+1324e0368597b3181555bb5b2cc7b7ebba46931aeabb6f05ababd4240f0fb933:
+6dcdf8e86903b0caded124d8a7da18e623430ca869aaf267d31029d93de99e66:
+
+# special case for x_2 in multiplication by 7
+# acceptable: Twist
+703f4ac8667d77f9536045cf748f18d42345e39ccab10c18dde0f5170d307f73:
+c7f3842297d6941cac63d6f1bdaea0709437c82dbc9161fc1bae6c79d668eb44:
+385ddbf2505ebf537bf5e976b61a4b69d190ae965b7e4a81ae4e1c16b7148748:
+
+# special case for x_2 in multiplication by 7
+# valid
+c8a96ae4e77271a0680dd24fcb09f9c5d3ee8316536eec7cc2276597e50fe37f:
+1e4660ba865fb8085afd4692885d74237fa3bca5af4b84ba3de400f16a5ac45c:
+0fbaea73f9518795e026c1fc1079c3738aeb9ee9c8dc9761d65bbf8f94e30154:
+
+# special case for x_2 in multiplication by 7
+# acceptable: Twist
+d0dde8eda38c3783442864c0cb46a0e9832dcf784c21268a21bed2cace87cd70:
+2488bb6fadb79d46585ff01c160c5b4172799d92bd168edceb65cededc492762:
+510c64151e5d0737fc324bd15fb5d3966908751cd1a06954b556196655ee5540:
+
+# special case for x_2 in multiplication by 7
+# acceptable: Twist
+c09cd47e1ce53604f14e4e13426c8f08962f556bcd81f8d75375b1507c6fda78:
+a0c1087811af1491171bc51691b8ca84716af36c4baa764ec536280cc1983d6d:
+23ef825e1c8e6e64428001a7463e32a9701c81cf78203e6ae753740c91570e6b:
+
+# special case for x_2 in multiplication by 7
+# acceptable: Twist
+e09a5f74f318f02303857aa0208d76913d9e240a80549d12013118bad620597f:
+cc5c97934607d8b981bce1d6a232bb3aecc3001f698ae1ae84938fbf2861077b:
+0e55a7ec1a2ddbea1ac5981200812232f7f4c3a60ee3c9ab09f2163bd13da329:
+
+# special case for DA - CB in multiplication by 7
+# acceptable: Twist
+706cee5f9b357c03b2f1913294f6e4f0ca5a190a87d30268327d0cb6bdd5bc79:
+238de7fcc8a3f194c3554c328efb1215d0640ac674b61a98ef934ec004cfd73b:
+0681036a0d27583ba6f2be7630613171a33fb8a6c8991c53b379999f0f15923b:
+
+# special case for DA - CB in multiplication by 7
+# valid
+40e300cb1ff260574f85b3f04aac478464a86e6203b3d4656418f4305157877b:
+ac9fd80a45da109fa2329390e5a951cfc03065d7bb4a7855826ccb22c3bfeb3d:
+67b88774f19bd1081d6f23656a135803e34ae1cdcae10818124a78569c299f42:
+
+# special case for DA - CB in multiplication by 7
+# valid
+882f78b4558b7faa835904c9235e32f300fc8b5ef0a718406a5c8520ca54d071:
+a45ab1dc2fa2c50718fb4985d9791401e8d2d34ffe3cd93cffb4e870cce5e855:
+a512e864bd898a5ba6551adcebd836c6a78e7871728e1b8ee528d483af276104:
+
+# special case for DA - CB in multiplication by 7
+# valid
+d8649b735590a17d0fc4c378fbf4c2f7d6600569b2e84cbe0ff7bcdbac0b5f71:
+1761d3d50ba46b446655aa6a8d9b8b75aa5bb24a7953208d5b69fcc38f18ec7a:
+518b778cf5e976c60235abcf6211a18bad2a8e693ab261074c7fab43dbb5da27:
+
+# special case for D in multiplication by 8
+# acceptable: Twist
+a8edec59ae6ba23813ec54d66df152e0626762b97d4b0c20e0dd8a5695d86e47:
+dc99ad0031463e4537c01e16629966d1b962c0b4e4872f067ca3c26ccc957001:
+6cfa935f24b031ff261a7cd3526660fd6b396c5c30e299575f6a322281191e03:
+
+# special case for D in multiplication by 8
+# valid
+1098723ffe567ea6dcc8d04ecc01efafeea0aee44e1c733be8b1e5d97c8b8041:
+b32750fd80d2d7c62c6b8e39670654baea5719a3e072e99507fd5bcb23898264:
+c623e2d2083f18110a525f2b66d89ed82d313b6a2dd082f6b7a6e733134f5a06:
+
+# special case for D in multiplication by 8
+# acceptable: Twist
+a0f20df98b49218ac832f26fa8c218a0d6872eb7aea07c1d43c9ff699b465b47:
+e7b3205777b375f1b1515a50a16a6067953ff221e12b4f416d74fb28c1c85865:
+388ea421650a8d837bad8904018195e99ef494c2d170b93ee721a67d2c108729:
+
+# special case for DA + CB in multiplication by 8
+# valid
+30473a77a98374f67d5bd43df231ce142916aea0d271e72333fa47dc441a0247:
+21cc338d7869e5863349cc739c8a6946cfc797cb82fbf62dcd2154844b106003:
+b9e5728b37435b1d339988f93267d59f3bd1c517851c5a258e74cb64aea73d2d:
+
+# special case for DA + CB in multiplication by 8
+# valid
+d8657be3a30fc85fb2f3a68e92ace1b31b26e76e6bdb6727aea507cb7c10dc45:
+c34217c02072d7e2bca0454525030780cfb60215d7ca82dbec8f4a59034c5f43:
+20b67b205e22ce87fd44a8e8fd10a6d8890b9270b60e1c6a68b4aa78e6e37961:
+
+# special case for DA + CB in multiplication by 8
+# acceptable: Twist
+882f5578ae4a13d8f5af473bdde1709bf2e059df809ee05b505f34de857c3447:
+8abb8cfd60c6f8a4d84d0750d3b40a4f846b30edf2052fef7df84142cd0d9e47:
+5faba645fc21f9421ebd35c69bdb1d85b46f95e3746ff7f4886bc280a9ab2522:
+
+# special case for DA + CB in multiplication by 8
+# acceptable: Twist
+98294db7cbf4958bfb3ed21d5d5c91e13cc8dc27b3c716c86f7167a4819f8741:
+9fd7b49a08f206688d72db737df8e517aa7b764f5de7c9a2b1c3fcbaa985f64c:
+9cb8a0f4ad86a27b96ca61242eab198db2767d3862dd323e41368fcdcc5fab68:
+
+# special case for DA + CB in multiplication by 8
+# acceptable: Twist
+789bc4047ad81b9b6656eef298b766e8763a2f8ea64e374a603dc1fdf2eee146:
+c4fefac7acd448e8fd4d6ac4f5dd1bc21f2c67d638444060918fb344aa77e757:
+4b42fcf84b51b2b82f1f70b3cf49bd9dc6ab2672920a8de37e81ba7e99acf734:
+
+# special case for DA + CB in multiplication by 8
+# valid
+801ffe4e0f6eeb8a50c8fe79663ff585f9d6aebcfbf4b7edc676c693900cb141:
+a8341deecc0be6db11401ef7f884ac3ade35650cc21f14b5cdb0a5cf0ee6b15a:
+e55fc931669bd02d1c64689eda62648212b1078c43b5caf97cf9763ff87a3455:
+
+# special case for DA + CB in multiplication by 8
+# valid
+e04e412383a63b338b70e1be5fd75995350321dee428aa4f3ba62a50a3b0de44:
+55a0e6631a52f29fb90a1777ccbc69ff94547459d541f72e8316e4d616535a67:
+87f7976a17f3e03a7f1eb74e6db950b8c0994f40b7903495599d227725809e01:
+
+# special case for DA + CB in multiplication by 8
+# acceptable: Twist
+382dbe9f10158bfbb7d1d79a35a7809214899a6b8572b35b55875d79bd2f1640:
+7976d520f1a2512d564af41c68313f5351b0156d5118be4817f192798ae9777d:
+3bb3e30105a71901b115065e39bdb3e053d387b39027b12c92cdf4c638adf00d:
+
+# special case for AA in multiplication by 8
+# valid
+60c9af7f4d03136a6034ae52deadfd9d4f274ad8122812eb92a53169c8354141:
+a26a722f7ba71ccfc96ed8e108d7c9f842d17f92051ee7d429ea7fa7908ab907:
+f5cb3a1b76185a29a6360b2142feebb11f3d08f4fd8d73df3a5228624a521c02:
+
+# special case for AA in multiplication by 8
+# valid
+283fae8bd8b294de2848056449751965abb5c7fa86ba4c2c5cdc3bb524dad140:
+ca3a2d96f5dda482b002324cbbdcf1dacc9815eab797c7151c3a88c75cded621:
+b0b47868e70465ee2dd737f1ba5a6399e09cd813d72da7585ab45c946cc28d4d:
+
+# special case for AA in multiplication by 8
+# acceptable: Twist
+401539703ca4980db4ba42c59fc29e83b4189f2ddea53ba54ca966c06898a640:
+eebd858850b56febb707f27a7aad5ff5ab4b0e0c73b9c86ec4ca0f42e7f38e75:
+581e4b12b0f39a7cc42dee4513ecfdd20b595f905f17ad8c1fbf1b5cb2068b31:
+
+# special case for z_2 in multiplication by 8
+# valid
+c8eb056286e098e6b2c79e42f007ebc6ab3705346cdbdace949b5de1e8c36743:
+c800bf799783275eb93312b43dc032ccdfb00a4b77c8b3772cd2fec8db7e4a09:
+6bf264532fc70a6a7e459f4579eca6b84f8f76ab85c3264b20bca725a6eb6c40:
+
+# special case for z_2 in multiplication by 8
+# valid
+487882956c49c69fd0e2d7277a24fb1dbe4b0365b36a13f63440248bca2fbb42:
+7bbc504e04d134eedc13f06dfdfc69c518257a3f374040a49a8d21dac109110c:
+690305c9e192cd8a513f705b3f101ecdf3db1ea15a09c4a1bce3a8cdc3a1a93f:
+
+# special case for z_2 in multiplication by 8
+# valid
+9876010f4d64c77ffc4d7dccd72b9ac82078deb883609650b8cff8a686719d46:
+132533db62aff4fa06e96314383bf58ebdec5183a19f2e4cb17552ae19a3366e:
+c58591b33e490e4766ff7addff570ce4e89a98338015a55df3d2f232aea3fc4f:
+
+# special case for B in multiplication by 8
+# valid
+a8a5d4f7894a519537babfac736de36054f508dae434b4fe63cd5633846a2647:
+ceb90c56508cf330c7f25bab42b05b5612a8310690107ac63a404c0ade788009:
+3d145851b6ff2b92b5807ed1df21eb50c9f24c4474d4721db3abb7356df7b764:
+
+# special case for B in multiplication by 8
+# acceptable: Twist
+f83e4647e82c560aa082c59641e13bf366be8f24dc01d14801e67841160bed47:
+66a09767a0d83bb18d404e1200375a745d1f1f749d5dc6f84a205efa6a11bc65:
+1401829aac4e64bcfa297a7effc60477090d3627a64a35b872ae055d2091785f:
+
+# special case for B in multiplication by 8
+# valid
+58c6b94bce9b15f64946c2aa6a4e383b0b2d4365b7997eb2310ac4eef1803145:
+39d431316307c85747bd2bcf4f9e0f8892ee45df15f7806ce65147d97f503478:
+a0ebe6908c5472f937769b9aeb313224437fc5d73f4f866fe7ef41f30e359e09:
+
+# special case for C in multiplication by 8
+# acceptable: Twist
+786a97207adbd4b0d6bfc9f49b18660ad3606c12e325044b8690b4fa07874641:
+84c92d8ecf3d0cb22dde7d721f04140c2d9c179cc813ce6cf8db2dce6168880d:
+07538f1b6583041c4949fafae3349d62f9dd302d3d86857af0dedc0d5ad6741f:
+
+# special case for C in multiplication by 8
+# acceptable: Twist
+282310210e575a59393cf19bbe6e24752dc247706f1e0031e5d39b2de4fff745:
+a9cedb9e942a47221e4296953220d10007db327d2acb68da6ef3a4f877b8ef1e:
+1223505fbb534c1bc6108e6b98b4f0af29e11158c02d333d6559beecd6d3e558:
+
+# special case for C in multiplication by 8
+# acceptable: Twist
+c8bf2fd4c40d00f1465aada682b12fa92dec10343484ab62b8871337de1d3345:
+64e1c0c5f59405bbc6c7db41a3485cc9f91c183b0f2b7e1894a7abd8fbbeeb23:
+ee031868165f456f75907bf39742b820e0f8e6df9f9768d757d408e1cc92ff7b:
+
+# special case for C in multiplication by 8
+# acceptable: Twist
+c06a4a4b70f613136f18c0f88e2245086c3d1a52717210a21ac9d63682f2e740:
+a68d2f55e60eac7983926310f4fae13f95b2bbf140be5ea91751884d900ab44d:
+c954fa7b042c32943e03191e367d54be0085fa8950ef2bec99620df79ecbea4b:
+
+# special case for x_2 in multiplication by 8
+# valid
+20596e1dc56596823d37698dfa699c79874aaefde797f863ef92135980fb2043:
+6d3cd623f26a7453fa05a01ae758ba84d3c58d93d60ce32735a15e0d053d5b12:
+7c3219b3c1fae1f95590ac843efd2084a1f4bd3efa2f592f022032db64ebcd77:
+
+# special case for x_2 in multiplication by 8
+# acceptable: Twist
+38141518e8e5efa1d031c6c4d95480239f6c30b8ccd8c751a9e04bd3aec17342:
+8f195547346b3d53b7ea4f742b22f1ef7b3cc01a7d3dcd19aa7c5b03f31bd214:
+a31f6b249d64a87c4aed329c6c05c3f2240b3ca938ccdc920ba8016c1aeaeb45:
+
+# special case for x_2 in multiplication by 8
+# acceptable: Twist
+207147f2b68fef1efc10a04f988f0eb18b273b0b5ed17aa7af32c90480e19b43:
+ffc4fe2c2127a309c739565651e9812f834a86dbadbb78776977f786ecdb0217:
+4cff9f53ce82064882329a18ea4e4d0bc6d80a631c87c9e6fdc918f9c1bda34a:
+
+# special case for x_2 in multiplication by 8
+# acceptable: Twist
+488084537b840f9c93ca57b3ee80491418d44221113e03f56355302604d03547:
+8475babeeab9980d426abd5323dfb335b219e129bddae4d6cebcda50754a6825:
+248d3d1a49b7d173eb080ab716ac8fde6bd1c3ed8e7fd5b448af21bcdc2c1616:
+
+# special case for x_2 in multiplication by 8
+# valid
+28cfc1d03f5c7428ff3e20b137268b33ccc74db03582d2127c566df4ac99f441:
+81f90a2f6633d30c2b72a25795d2a49463a80b6b0edc5aa68bae4bf738185539:
+66c6e70cf630be90a2c88fcde7f58cff3868660fa96406e8df4ac677dbd85f50:
+
+# special case for x_2 in multiplication by 8
+# valid
+c8e37d10f3d03db3f43e467bddf98f595cb529ad253c20d491282d1400b9e740:
+41626e33b3c8f48bd19e49ded307f2b63bde705c4f3cdf9d4f92bf37c48cba42:
+06283fcf69dc83e99d92e5336f499a1d8fa75ed2c819b5ae6ea8094454324b27:
+
+# special case for x_2 in multiplication by 8
+# valid
+00237e91406a7b4db61e780c5976fbb926cdace2fbdfdbcfce65e6dbe7782a42:
+ebb32f781c0e89b252e611f9d8f79f8567874c966598314b2f16aa44cfc07843:
+7d2affb43355f5db1294daff55f59b1f17e7d25bca20746f12484d78e5015517:
+
+# special case for x_2 in multiplication by 8
+# valid
+489c4184a23a8f5eec68a31b41aa2c0392cd6fb123f10acdb4de75292b4b9a43:
+fa75e6f08ca815b4e42af24a8e057c9e00e828e33d12c0e94d1012a758336744:
+ef8e78cab091d667888489fd3a2ec93fb633427d02eb77b328d556f2b2b0e266:
+
+# special case for x_2 in multiplication by 8
+# acceptable: Twist
+c05957fbc3a0e2c22a2aef627651ca1e99307b82a0c6170f7950a334f3004941:
+4d96320cdb0ca52655e91118c33f93afe4ae69e9e513ff4506750b8ea784ce46:
+c8d85bfa74b4b26461297b350c975183fea9d33ba29c3a4934509c2ecda58a79:
+
+# special case for x_2 in multiplication by 8
+# acceptable: Twist
+60111c6629f73635985be964b845f87a88ae5652d45bb1451ce8cfd2ea45fe41:
+c0ef1b7c20237db370501f24274e4eba91998ae4545f937007e1c4a2eab63365:
+22557e0d8741ed2a63afd5e313aa1579fc0c88c7772e23a676c94b60c89df577:
+
+# special case for x_2 in multiplication by 8
+# valid
+58785889a216d15456582d4e1e3de9e9ca4a432954416d81caf52b2b434c1746:
+d534d8ff4d56a73ef7615e94523b17e35edb3d0fb87e98c68536f63f114a8d6c:
+54d7fc17bad00296ba50b0f3d5bf8fb83f82d571952a5fdb5a494120cc61446b:
+
+# special case for x_2 in multiplication by 8
+# valid
+60bef38a3890ec1ed05c299fceb77db5ead4b88d9e931b0f21d664f77df9b544:
+733a711ba01b6e9b64a0be4cdca8c7cf3c66df2435d5248fb4413fec6ee03f70:
+db6851b12585bc11be9362c96a545c6f2ba55f04009792463b96a38cb9b3f07c:
+
+# special case for x_2 in multiplication by 8
+# acceptable: Twist
+5854ee566878ef8b7ebaf5a058306f250edf0c84fd52af2d74b7ce3c1edda746:
+35738dd539d60f69cd1a1cffc8a42b6af68fe7de45392d02831e2a77500ea278:
+f6d1a664257fa5de3d4d57f04eda2976bf1e35cc3ac513e1ee84d57d2135ed13:
+
+# special case for x_2 in multiplication by 8
+# acceptable: Twist
+985b551261fce38ddc8ff3add32f5c26811d271b9a1794e249dd76a38df28446:
+ce932b5af4be4721f96f7b79ba1c43b20687d4af49c37b58dc894279e04bb578:
+f8f7625ac5bde63f753a9bb4aefbfb9c4647207708af9d774ef08ff1b1e5a354:
+
+# special case for E in multiplication by 8
+# acceptable: Twist
+8815052344dcad97efd1341e9072a808cf999e46e52cf04e0cfbcd9901e18d43:
+e3655448339e4850806eb58abba0c89185511ea72c37c49e9583ee6dd235d213:
+5e10dfbff4443efcae2ccc78c289a41460d5a82f79df726b8824ccbef7146d40:
+
+# special case for E in multiplication by 8
+# acceptable: Twist
+b8e032e9e5ffbaa004390f3a0b900bc7cf5d11238b7ec964afc4bda2aa6c3444:
+4d16965b1637e9d7ae8feb499ed0553962a9aa0022d1620c928072f6501bc41b:
+19d7b44c1847c44e8f37a22ab69c180fd9d787f204123013e1b16800b9cd0f57:
+
+# special case for E in multiplication by 8
+# valid
+7012852211f6536fca79937e7e316c9149b0e20ea03f951e1bb072895ca0e044:
+c6b9e6288737ad40452cec1022871d90af1642d10bd0a97792b1a9c8998e2220:
+db990d979f4f22f766e7826d93554e771b361de461274d6c37baadeb8ef7be4e:
+
+# special case for E in multiplication by 8
+# acceptable: Twist
+d039c1b9ec4763e0ad8a0ef2b0870297d0f8b487e660595a484105d180e14a47:
+d566fab505ac4c7a3dc3b9403ef121392cbbe21216e5bcb8eab2dc9408986e34:
+6d7fc5d4a8f534b1bc0fa5e078104234675c02664736957abdb27df6faf07c00:
+
+# special case for E in multiplication by 8
+# valid
+58efcbc8777c1b54f09c61a216efd427292eb12312dbb3b32bd45254a6683e47:
+468d35ecfb6d9b7272523276cc5e13760519667f0e1e3888da4c56955fe91151:
+539c8d629ab51c2f3ea7278fd5f1c31b6c150a82fe3f786b93ffa159fd6d9316:
+
+# special case for E in multiplication by 8
+# valid
+c8d73446026cd0ea795773c2eb7b16348cd5f228e352dbc77328c2d8b9cde240:
+1929538743977dfea20bf4927ddabb2f3bb15cac2461054508849718854b5568:
+dee3fd19c8f296415448b21af44385ec46727bbe67d4839b93efe2f680e76d34:
+
+# special case for E in multiplication by 8
+# acceptable: Twist
+98b559523bc778b0418af53c0c32f6ff5cf771ff5df8ae7cbf7c3b72aedb5b43:
+2d7ab4c6f59865355ee8e9de57db19aadf7708b7c1d1a818487c340623badc6d:
+2a0340aaafa05d00529c09057ed0145f34d2de66a3e149cf084ea97168914f39:
+
+# special case for E in multiplication by 8
+# valid
+589815027caf82714e96c9f91bace66ec4ba3e92df3fa14b9b8fe503556e4543:
+43839f4a6aa206c82c5a73f49d8c9e573826b3ba7235d312987c17aebee62776:
+00313717d33e3b41a0865986157582e053502a172b88d01bb7b10831a9fc4e6c:
+
+# special case for E in multiplication by 8
+# valid
+80715f67270c99789855ceaea99b9957ccda33326f76bb4474ab52ab1ec37041:
+3c321e7f0b9e555bc264a2cea617e6b2b562ebab21fe0c226c3e487b7df9a27d:
+9b6be9e6f2fdb5d3321842225d3e91d14828cc53ba6654dabe190b0c3edeb309:
+
+# special case for DA - CB in multiplication by 8
+# acceptable: Twist
+101b990bd83d684126ff047d930c27d086a588dd19683d2629f0e34f4374ab41:
+42e5a6b8e9654bb4ad624af3f491877977513cc8775c8fb312ad19dbf3903a28:
+223f1eb552308373026d11c954684ce6db870b638b190b9443e50aae219f4e3e:
+
+# special case for DA - CB in multiplication by 8
+# acceptable: Twist
+200089b712d9a2050597779d463712fcd223e3d67879c0fb7606f8f5f0efee40:
+0a51dd90ab985f6deaf72f16c45014da26df848697f6582d75688f5223342b51:
+fb95ce4a3c1f325638b7d47f4216d39a7c6c5da9a01caa297c37b62816555b2a:
+
+# special case for DA - CB in multiplication by 8
+# valid
+f04f87f4e623af4c31ceca0bb87fac2d5b12517b5a7284902ad75838e65f1e41:
+8842317357bde825ef438a1c53906fb8b04ea360f7ef338c78e668586047936a:
+488b8341c9cb1bbf124510b9f8dae4faf2e0dca9b84e00e952a63b5aa328a860:
+
+# special case for DA - CB in multiplication by 8
+# valid
+383cbd5a3dd0901d09a3cac3d3a77a979cecf15e206a553e4ca3f24b90783945:
+c71d92d3c92dbfaed755fb32797b667cc86b0e79362498e2aca38c689713b16e:
+1129eae97bf75f7314f2e1b403b18737ad830c80429e2ba0d4866b362399855f:
+
+# special case for DA - CB in multiplication by 8
+# valid
+701df09e57b98aec375745df147b72949a6b2bb2ca3a34881512ee31e790ad42:
+3a21d1cf7b3744d1ad26197335844982c2a0c6a5aa835492bd03c401a4fe6778:
+072f51d94727f392d59dc7caff1f4460452352ec39c32a1c9f071e388833da56:
+
+# special case for CB in multiplication by 8
+# acceptable: Twist
+b0ffa5f4922bb117ad75ff43acac62331efaa45536fe88306e4a4cb58db73a47:
+d128ea3e13325ed6ebd6533a9fd3045a55f25ad8b67def30912843504c1aab29:
+30512142d3e3a4cad6726d9d35f2e043fca9dfb750884ae22b2547c840f3587b:
+
+# special case for CB in multiplication by 8
+# acceptable: Twist
+685e3271d2015741756612a930e858b930acf2018145f382c83d8cced2e22044:
+e079c8f8423165c7e0a2c48b4abe90aece4e6d903d7a5a1625fad0410cd55b32:
+5b81b3761a66d199e8ef99d2494bd57a0229d4564a7f6d6055f22aa48681bd3a:
+
+# special case for BB in multiplication by 8
+# valid
+f8e161d69297e017d7c51b1b1ff3ba703d4c4cf8fc2b8ff47f74c3ff8c7d3541:
+65922a06e9be4e8a5e8aceb1a4e08fe90f01e10ef2dd27315427cedfcf95ec32:
+038de7fdb9cc0030f5c11dda00589f0a95f65658815b06ed013553a02b6c5017:
+
+# special case for BB in multiplication by 8
+# valid
+105d7589f8abef0acf0940da84a69e8f2f306fa73c9afd27342287c1dba80044:
+d36a240e972dc16e9b97a997ada337f02760d05c46d7f8d7b4e9ea9a635c7c64:
+22b0dea3b3b7ca55eceeaae6443426548c7c15cc7ddf31780318d1c23879c16a:
+
+# special case for BB in multiplication by 8
+# acceptable: Twist
+1893d4388b0e90f0b50208aa8f0cc24f576d03641baf1c3eddb2a3efa69c9d40:
+4f5b8b9892b8a46df08d76a4745b1c58d4e7a394905435875688ca11f1e9d86a:
+a25e1306684ad7870a31f0404566e8d28f2d83d4b9497822c57f8781b18fec20:
+
+# special case for BB in multiplication by 8
+# acceptable: Twist
+0065171301bf6b90fb16efa35509161f1bd6b3b93130d490af9fe224dd155f45:
+aa2f02628269139a7a8a16fde95c9bad7da7ffbd5439c396a7d77b6c3213e67f:
+bb4431bea7a5871c1be27a2674094627eaaa4425c99cd3fa41bd7e13cbd7bf7e:
+
+# special case for A in multiplication by 8
+# valid
+10c81a4e78d82145b266e1d74b3869bf1c27427803ebb11c92ff8073d1e4cc46:
+d995cb287e9a9c5791f3cae3d494a5b516a1e26cbc930f43e73c8b70b69d783b:
+330f5d0b5bccc90f7694dfdd9c6449a62d93af8840eaf571e3e0610e0198b03f:
+
+# special case for A in multiplication by 8
+# acceptable: Twist
+48b98b4a99eadd73012c07fe5c4a0b9590ac55e821353b41d5f665e17188bc41:
+479afb1e73dc77c3743e51e9ec0bcc61ce66ed084dc10bfa2794b4c3e4953769:
+bdef00caa514b2f8ab1fb2241e83787a02601ecdff6cf166c4210f8c1ade4211:
+
+# special case for DA in multiplication by 8
+# acceptable: Twist
+1897678e38222a61fe105dc6643c1eb5940e8dbc73ed6c00f25a34328f43a641:
+378eda41470b0f238a200f80809ad562ca41e62411a61feb7f7e9b752b554642:
+bfd5b5acd2d89f213a26caf54062f9a24e6f6fd8ddd0cd2e5e47b7fea4a9c537:
+
+# special case for DA in multiplication by 8
+# valid
+a898af8138e11ae45bbcefa737182a571885f92d515c32056c7cb0d7deac4741:
+0cad7545ade2fd93fcae007c97648348f26d85829bdb7223a63eccb84e56d475:
+c8085877800c175e949cdd88e196eb9c4841da2ac446dfed9085bda5bbec265d:
+
+# special case for AA in multiplication by 9
+# valid
+b0bfef6ec095b5a1f93917d32f16a21d0462c1fde17446f5a590232d9c895f4a:
+60f27ed0a27804ced237cf3c1cc776650fb320bae6d5acb564e97b56cba25210:
+4c300895827382a9d1079028bd6f694a7a12ddac9c76abac6fdf5d29457a3310:
+
+# special case for AA in multiplication by 9
+# acceptable: Twist
+60497d4464ed8823c50fbc6b68620826c4f629c1d9193058df6bf857c6aecc4b:
+f93a73270ac19194b8e4ffd02be4b1438525f84a76224688ea89a9dd6a1bd623:
+7285fbb3f76340a979ab6e288727a2113332cf933809b018b8739a796a09d00b:
+
+# special case for AA in multiplication by 9
+# acceptable: Twist
+08c6cbe03792a3829f06e8ad54c55db113236ac0dcc9ab6a9a6b10eed1041b48:
+cf80c30fcbfd535666ca1da499e2e99cc537063e2de19458fcf92f5ee34acf47:
+dabc3bd49f19cf7071802e43c863ed0b1d93a841588098b98a0c581bf4fe0a11:
+
+# special case for AA in multiplication by 9
+# valid
+50044da3315dd082e9dfb6a1994aabb331f53e0d1c12633383b2a3c8678cfe4c:
+698effe0ad42e15ee1f46fde6fc5074ffda183bcf1b2db8647f561ddd191dd60:
+a61a3b150b4770532373676298c9a5da28adcc4365b06fe07c959ca80e477a57:
+
+# special case for AA in multiplication by 9
+# valid
+285640da7a48252e35ddce60c14addb73097fbc9ac2f87c8d2772ce89aa6be4d:
+bd1565b4a3f8515dff577be6dcb414511d3d4ec2de15e0bd45b28e9cc4caef60:
+916ab4f3bfc8321e1087d9c5444f8f7a43e9ca6d29e7ba98a19dc05fff34ed4c:
+
+# special case for AA in multiplication by 9
+# acceptable: Twist
+783271c21199ba2e94ead92cd9dd79f70aab378b59497455d327a5907dafcb4a:
+b8649e13843f80cf5702398e4a9a8c378f29da96dfd6579f1eb4f7ea34df6765:
+844a5dd5139554ca7b41cbe6a4796193912e7aa4e201cc68944ce2a55774a10f:
+
+# special case for AA in multiplication by 9
+# valid
+d0676a0b9a046c62d5b2e740d9cc43fa37965dea93c23254f7bf569f2bebaa4a:
+c396938737abdf791e09a97eba577c437d9b67c2dae94e13eab7296ec0fc737e:
+10780333b2a6170136265bb5ebc6c818817f2e48ae372528c8f34433fdd6215a:
+
+# special case for DA - CB in multiplication by 9
+# acceptable: Twist
+608c84d2b76fccda579e974db3d3b2ce39a6bc0dad440599db22411b60467849:
+557b825012d98f065bb95a2ab9b2d2d8b83fd2037912508c263f86d7e36c4f24:
+5ce84842dbae8b795b3d545343558045508f271383bfb3dd3943f4101398c864:
+
+# special case for z_2 in multiplication by 9
+# valid
+80f233936a8821936d39114c84d929e79760b27680779e5009e1709410dd8e4f:
+ae98296d4a2fbcbb40b472f4063231608bb1465c226c8a4a2dff29afd915882a:
+4f11aa0c313195f96f25cadcbf49f06a932d8b051879ea537d1c6dfee7f36d35:
+
+# special case for z_2 in multiplication by 9
+# valid
+c8d80b1a34f21194f047a6f0328bb947e2e7aff6a043553aa07f2abf99aaf048:
+8b9d249829fbe81333d85050da88998f63fac665679e27dbbe21b745dd14e145:
+1d619070bf5626064be10025e74e336c81ef3166b743f99c751fb90587c31d7e:
+
+# special case for z_2 in multiplication by 9
+# valid
+9021477b452361580059364c6f94f4981ee94ea3f9b7d37439bc82ae45816f4d:
+61896093e2697c78230afdda12639cbe4342827b8d2b093281f148eb60b9034b:
+532e797861db56b9d5db8825fb72f8629c2422f8abea721ad2d7b9e77a95b576:
+
+# special case for z_2 in multiplication by 9
+# acceptable: Twist
+6079dae04c40a59ea4e0c8c17092e4c85ea9133d143307363487836df4e30349:
+ccc1dc186229dba9a9360a0f7ff00247a3732625acaacd18ea13a9a8b40fac4f:
+4f678b64fd1f85cbbd5f7e7f3c8ac95ec7500e102e9006d6d42f48fb2473ab02:
+
+# special case for z_2 in multiplication by 9
+# valid
+281db6a5ac9a47d4a7b2b91a87f6536ce62d4e5129b8d647b97f9c504014894c:
+69e368c0b7e78eb9f3a53bf458f6e79dc4883bf9458f04a8c12c4ddd94d62151:
+e069fd06702f10f33adb8cf0766880634865b510e2da409241fb5f178050514a:
+
+# special case for z_2 in multiplication by 9
+# valid
+d830f3c4785829a0f945857e0e85e0ae723702b57783b933cd2a2ad05484fe49:
+f21f9badd98dd8a103cc2ab5484fac6c2bfdd2671ee6e674134a86b89cee9160:
+fee218eb1f92864486e83c1731f04bb8c7e6d7143e3915bcbf80fe03ff69dc77:
+
+# special case for E in multiplication by 9
+# acceptable: Twist
+10230bd0721f4c8c4b921881dd88c603af501ee80e2102f8acc30cf8b2acd349:
+e853062b2d6f38d021d645163ea208d0e193a479f11f99971b98e21188fd0b2c:
+64bdfa0207a174ca17eeba8df74d79b25f54510e6174923034a4d6ee0c167e7b:
+
+# special case for E in multiplication by 9
+# valid
+f0a34d6d76896e17cb8f66feda23115ffb96f246b823bb63dec08335787de74c:
+362eb92dab9fb29f7ed0e03843dcc15797928c2b4e51ec260204179c1c12945f:
+d7f4583ee4fe86af3a3f1dfcb295ba3a3e37bced7b9c6f000a95336530318902:
+
+# special case for E in multiplication by 9
+# acceptable: Twist
+9073c1d0a173c7ff02dc966a165993d9c4c9357514f7a6bb7aaa4b0827718948:
+ff543f1e81996e88631f030ceba7e603b13033efd205e68bd36b28468134aa73:
+c1b5e5f4401c98fa14eba8aafae30a641bfd8fb132be03413f3bf29290d49e0b:
+
+# special case for x_2 in multiplication by 9
+# valid
+b0c1822566e016c12ae35ec035edd09af3cb7a48f55c9028e05e1178a8c3824e:
+90ef70844ead1613f69df7d78c057813f866c0d95e6d22caee4a012b9c1c4b33:
+9369ebb3d2b744341cba77302719a4b2d63aff612872f86d9877a76bc919ca1c:
+
+# special case for x_2 in multiplication by 9
+# acceptable: Twist
+e06fe64e2117796f997bbcd3bcad3067cf1291640a3a643fb359809a4016834d:
+88c1ae575ad073dda66c6eacb7b7f436e1f8ad72a0db5c04e5660b7b719e4c4b:
+335394be9c154901c0b4063300001804b1cd01b27fa562e44f3302168837166e:
+
+# special case for x_2 in multiplication by 9
+# acceptable: Twist
+707ee81f113a244c9d87608b12158c50f9ac1f2c8948d170ad16ab0ad866d74b:
+dcffc4c1e1fba5fda9d5c98421d99c257afa90921bc212a046d90f6683e8a467:
+7ecdd54c5e15f7b4061be2c30b5a4884a0256581f87df60d579a3345653eb641:
+
+# special case for BB in multiplication by 9
+# valid
+7089654baacbb65bd00cd8cb9de4680e748075e8842ca69d448fb50fea85e74e:
+6c0044cd10578c5aff1ff4917b041b76c9a9ae23664eb8cf978bd7aa192cf249:
+0d8c21fa800ee63ce5e473d4c2975495062d8afa655091122cb41799d374594f:
+
+# special case for BB in multiplication by 9
+# valid
+8089784c52cd67e4536e568218c7b7033b28413f942fca24ed69e43496efa14b:
+d9089de902e143dcd9107e5a3393a3f7fe05d926c357b47e307a236cb590fd64:
+db6fec44bf118316a6bdfbae9af447baede4d82daa16bed596ea6f05d4a51400:
+
+# special case for BB in multiplication by 9
+# valid
+00e73e4e013148b9f05273bad626bb126a40ec4558f5425096b48947e0a9de4a:
+8c4a26aa319c2cc4a4158c2bc69a0d5b340b60628a14cf31bb0ae5ddc38ae866:
+ecc1204bc753c4cec4c9059fd7b504944ebf995ab1b1d49f0b3b325353be3a15:
+
+# special case for BB in multiplication by 9
+# valid
+78ed4c9bf9f44db8d93388985191ecf59226b9c1205fe7e762c327581c75884e:
+ce7295d1227c9062aab9cf02fc5671fb81632e725367f131d4122824a6132d68:
+3740de297ff0122067951e8985247123440e0f27171da99e263d5b4450f59f3d:
+
+# private key == -1 (mod order)
+# valid
+a023cdd083ef5bb82f10d62e59e15a6800000000000000000000000000000050:
+6c05871352a451dbe182ed5e6ba554f2034456ffe041a054ff9cc56b8e946376:
+6c05871352a451dbe182ed5e6ba554f2034456ffe041a054ff9cc56b8e946376:
+
+# private key == 1 (mod order) on twist
+# acceptable: Twist
+58083dd261ad91eff952322ec824c682ffffffffffffffffffffffffffffff5f:
+2eae5ec3dd494e9f2d37d258f873a8e6e9d0dbd1e383ef64d98bb91b3e0be035:
+2eae5ec3dd494e9f2d37d258f873a8e6e9d0dbd1e383ef64d98bb91b3e0be035:
+
+# special case private key
+# valid
+4855555555555555555555555555555555555555555555555555555555555555:
+3e3e7708ef72a6dd78d858025089765b1c30a19715ac19e8d917067d208e0666:
+63ef7d1c586476ec78bb7f747e321e01102166bf967a9ea9ba9741f49d439510:
+
+# special case private key
+# valid
+4855555555555555555555555555555555555555555555555555555555555555:
+9f40bb30f68ab67b1c4b8b664982fdab04ff385cd850deac732f7fb705e6013a:
+8b98ef4d6bf30df7f88e58d51505d37ed6845a969fe598747c033dcd08014065:
+
+# special case private key
+# valid
+4855555555555555555555555555555555555555555555555555555555555555:
+be3b3edeffaf83c54ae526379b23dd79f1cb41446e3687fef347eb9b5f0dc308:
+cfa83e098829fe82fd4c14355f70829015219942c01e2b85bdd9ac4889ec2921:
+
+# special case private key
+# valid
+b8aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa6a:
+3e3e7708ef72a6dd78d858025089765b1c30a19715ac19e8d917067d208e0666:
+4782036d6b136ca44a2fd7674d8afb0169943230ac8eab5160a212376c06d778:
+
+# special case private key
+# valid
+b8aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa6a:
+9f40bb30f68ab67b1c4b8b664982fdab04ff385cd850deac732f7fb705e6013a:
+65fc1e7453a3f8c7ebcd577ade4b8efe1035efc181ab3bdb2fcc7484cbcf1e4e:
+
+# special case private key
+# valid
+b8aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa6a:
+be3b3edeffaf83c54ae526379b23dd79f1cb41446e3687fef347eb9b5f0dc308:
+e3c649beae7cc4a0698d519a0a61932ee5493cbb590dbe14db0274cc8611f914:
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/gen/x25519.c b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/x25519.c
new file mode 100644
index 0000000..4ab1f8c
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/x25519.c
@@ -0,0 +1,83 @@
+// This file is dual-licensed. Choose whichever licence you want from
+// the two licences listed below.
+//
+// The first licence is a regular 2-clause BSD licence. The second licence
+// is the CC-0 from Creative Commons. It is intended to release Monocypher
+// to the public domain. The BSD licence serves as a fallback option.
+//
+// SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+//
+// ------------------------------------------------------------------------
+//
+// Copyright (c) 2017-2019, Loup Vaillant
+// All rights reserved.
+//
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// ------------------------------------------------------------------------
+//
+// Written in 2017-2019 by Loup Vaillant
+//
+// To the extent possible under law, the author(s) have dedicated all copyright
+// and related neighboring rights to this software to the public domain
+// worldwide. This software is distributed without any warranty.
+//
+// You should have received a copy of the CC0 Public Domain Dedication along
+// with this software. If not, see
+// <https://creativecommons.org/publicdomain/zero/1.0/>
+
+#include <sodium.h>
+#include "utils.h"
+
+static void test()
+{
+ RANDOM_INPUT(sk1, 32);
+ RANDOM_INPUT(sk2, 32);
+ u8 pk1[32], pk2[32], shared[32];
+
+ crypto_scalarmult_base(pk1, sk1);
+ crypto_scalarmult_base(pk2, sk2);
+ if (crypto_scalarmult(shared, sk1, pk2)) {
+ fprintf(stderr, "libsodium rejected the public key\n");
+ printf(":deadbeef:\n"); // prints a canary to fail subsequent tests
+ }
+
+ print_vector(sk1 , 32);
+ print_vector(pk2 , 32);
+ print_vector(shared, 32);
+ printf("\n");
+ print_vector(sk2 , 32);
+ print_vector(pk1 , 32);
+ print_vector(shared, 32);
+ printf("\n");
+}
+
+int main(void)
+{
+ SODIUM_INIT;
+ FOR (i, 0, 50) { test(); }
+ return 0;
+}
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/gen/x25519_pk.c b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/x25519_pk.c
new file mode 100644
index 0000000..231a90f
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/x25519_pk.c
@@ -0,0 +1,79 @@
+// This file is dual-licensed. Choose whichever licence you want from
+// the two licences listed below.
+//
+// The first licence is a regular 2-clause BSD licence. The second licence
+// is the CC-0 from Creative Commons. It is intended to release Monocypher
+// to the public domain. The BSD licence serves as a fallback option.
+//
+// SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+//
+// ------------------------------------------------------------------------
+//
+// Copyright (c) 2017-2019, Loup Vaillant
+// All rights reserved.
+//
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// ------------------------------------------------------------------------
+//
+// Written in 2017-2019 by Loup Vaillant
+//
+// To the extent possible under law, the author(s) have dedicated all copyright
+// and related neighboring rights to this software to the public domain
+// worldwide. This software is distributed without any warranty.
+//
+// You should have received a copy of the CC0 Public Domain Dedication along
+// with this software. If not, see
+// <https://creativecommons.org/publicdomain/zero/1.0/>
+
+#include <sodium.h>
+#include "utils.h"
+
+static void test(u8 sk[32])
+{
+ u8 pk[32];
+ crypto_scalarmult_base(pk, sk);
+
+ print_vector(sk, 32);
+ print_vector(pk, 32);
+ printf("\n");
+}
+
+int main(void)
+{
+ SODIUM_INIT;
+
+ // random secret keys
+ FOR (i, 0, 50) {
+ RANDOM_INPUT(sk, 32);
+ test(sk);
+ }
+ // zero secret key
+ u8 sk[32] = {0};
+ test(sk);
+
+ return 0;
+}
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/gen/xchacha20.c b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/xchacha20.c
new file mode 100644
index 0000000..e088153
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/gen/xchacha20.c
@@ -0,0 +1,82 @@
+// This file is dual-licensed. Choose whichever licence you want from
+// the two licences listed below.
+//
+// The first licence is a regular 2-clause BSD licence. The second licence
+// is the CC-0 from Creative Commons. It is intended to release Monocypher
+// to the public domain. The BSD licence serves as a fallback option.
+//
+// SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+//
+// ------------------------------------------------------------------------
+//
+// Copyright (c) 2017-2019, Loup Vaillant
+// All rights reserved.
+//
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// ------------------------------------------------------------------------
+//
+// Written in 2017-2019 by Loup Vaillant
+//
+// To the extent possible under law, the author(s) have dedicated all copyright
+// and related neighboring rights to this software to the public domain
+// worldwide. This software is distributed without any warranty.
+//
+// You should have received a copy of the CC0 Public Domain Dedication along
+// with this software. If not, see
+// <https://creativecommons.org/publicdomain/zero/1.0/>
+
+#include <sodium.h>
+#include "utils.h"
+
+static void test(size_t size, u64 ctr)
+{
+ RANDOM_INPUT(key , 32);
+ RANDOM_INPUT(nonce, 24);
+ RANDOM_INPUT(in , 128); // size <= 128
+ u8 out [128]; // size <= 128
+
+ crypto_stream_xchacha20_xor_ic(out, in, size, nonce, ctr, key);
+
+ print_vector(key , 32);
+ print_vector(nonce , 24);
+ print_vector(in , size);
+ print_number(ctr );
+ print_vector(out, size);
+ printf("\n");
+}
+
+int main(void)
+{
+ SODIUM_INIT;
+ // regular tests
+ FOR (size, 0, 128) { test(size, rand64()); }
+ // counter overflow (should wrap around)
+ test(128, -1);
+ test(128, -2);
+ test(128, -3);
+ return 0;
+}
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/speed/README.md b/lib/Utils.Cryptography/monocypher/vendor/tests/speed/README.md
new file mode 100644
index 0000000..6b27d34
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/speed/README.md
@@ -0,0 +1,31 @@
+Speed benchmarks
+================
+
+ $ cd tests/speed
+ $ make speed
+
+This will give you an idea how fast Monocypher is on your machine. Make
+sure you run it on the target platform if performance is a concern. If
+Monocypher is too slow, try libsodium. If you're not sure, you can
+always switch later.
+
+Note: the speed benchmark currently requires the POSIX
+`clock_gettime()` function.
+
+There are similar benchmarks for libsodium, TweetNaCl, LibHydrogen,
+c25519, and ed25519-donna (the portable, 32-bit version):
+
+ $ make speed-sodium
+ $ make speed-tweetnacl
+ $ make speed-hydrogen
+ $ make speed-c25519
+ $ make speed-donna
+
+(The `speed-hydrogen` target assumes it has pkg-config installed. Try
+`make pkg-config-libhydrogen` as root if it is not.)
+
+You can also adjust the optimisation options for Monocypher, TweetNaCl,
+and c25519 (the default is `-O3 march=native`):
+
+ $ make speed CFLAGS="-O2"
+ $ make speed-tweetnacl CFLAGS="-O2"
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/speed/libhydrogen.pc b/lib/Utils.Cryptography/monocypher/vendor/tests/speed/libhydrogen.pc
new file mode 100644
index 0000000..30cd39e
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/speed/libhydrogen.pc
@@ -0,0 +1,12 @@
+prefix=PREFIX
+exec_prefix=${prefix}
+libdir=${exec_prefix}/lib
+includedir=${prefix}/include
+
+Name: libhydrogen
+Version: git-HEAD
+Description: Small, easy-to-use,
+hard-to-misuse cryptographic library.
+
+Libs: -L${libdir} -lhydrogen
+Cflags: -I${includedir}
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/speed/makefile b/lib/Utils.Cryptography/monocypher/vendor/tests/speed/makefile
new file mode 100644
index 0000000..3934bac
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/speed/makefile
@@ -0,0 +1,208 @@
+# This file is dual-licensed. Choose whichever licence you want from
+# the two licences listed below.
+#
+# The first licence is a regular 2-clause BSD licence. The second licence
+# is the CC-0 from Creative Commons. It is intended to release Monocypher
+# to the public domain. The BSD licence serves as a fallback option.
+#
+# SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+#
+# ------------------------------------------------------------------------
+#
+# Copyright (c) 2023, Loup Vaillant
+# All rights reserved.
+#
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# ------------------------------------------------------------------------
+#
+# Written in 2023 by Loup Vaillant
+#
+# To the extent possible under law, the author(s) have dedicated all copyright
+# and related neighboring rights to this software to the public domain
+# worldwide. This software is distributed without any warranty.
+#
+# You should have received a copy of the CC0 Public Domain Dedication along
+# with this software. If not, see
+# <https://creativecommons.org/publicdomain/zero/1.0/>
+
+CC ?= gcc -std=gnu99
+CFLAGS ?= -pedantic -Wall -Wextra -O3 -march=native
+
+.PHONY: speed speed-sodium speed-hydrogen speed-tweetnacl speed-c25519 \
+ speed-donna \
+ pkg-config-libhydrogen \
+ clean
+
+##################
+## Main targets ##
+##################
+all: speed
+
+speed : speed.out
+ ./$<
+speed-sodium : speed-sodium.out
+ ./$<
+speed-hydrogen : speed-hydrogen.out
+ ./$<
+speed-tweetnacl: speed-tweetnacl.out
+ ./$<
+speed-c25519 : speed-c25519.out
+ ./$<
+speed-donna : speed-donna.out
+ ./$<
+speed-tinyssh : speed-tinyssh.out
+ ./$<
+
+clean:
+ rm -f *.o *.out
+
+####################
+## Base libraries ##
+####################
+
+# Test utils
+utils.o: ../utils.c ../utils.h
+ $(CC) -c $(CFLAGS) -I .. $< -o $@
+
+# Monocypher
+monocypher.o: ../../src/monocypher.c ../../src/monocypher.h
+ $(CC) -c $(CFLAGS) -I .. -I ../../src/ $< -o $@
+monocypher-ed25519.o: ../../src/optional/monocypher-ed25519.c \
+ ../../src/optional/monocypher-ed25519.h \
+ ../../src/monocypher.h
+ $(CC) -c $(CFLAGS) -I .. -I ../../src/ -I ../../src/optional $< -o $@
+
+# TweetNaCl
+tweetnacl.o: ../externals/tweetnacl/tweetnacl.c \
+ ../externals/tweetnacl/tweetnacl.h
+ $(CC) -c $(CFLAGS) -I .. $< -o $@
+
+# C25519
+C25519 = c25519 edsign ed25519 morph25519 fprime f25519 sha512
+C25519_HEADERS = $(patsubst %, ../externals/c25519/%.h, $(C25519))
+C25519_OBJECTS = $(patsubst %, %.o, $(C25519))
+c25519.o : ../externals/c25519/c25519.c $(C25519_HEADERS)
+ed25519.o : ../externals/c25519/ed25519.c $(C25519_HEADERS)
+edsign.o : ../externals/c25519/edsign.c $(C25519_HEADERS)
+f25519.o : ../externals/c25519/f25519.c $(C25519_HEADERS)
+fprime.o : ../externals/c25519/fprime.c $(C25519_HEADERS)
+morph25519.o: ../externals/c25519/morph25519.c $(C25519_HEADERS)
+sha512.o : ../externals/c25519/sha512.c $(C25519_HEADERS)
+$(C25519_OBJECTS):
+ $(CC) -c $(CFLAGS) -I ../externals/c25519/ -o $@ $<
+
+# libhydrogen (only installs pkg-config)
+DESTDIR =
+PREFIX = /usr/local
+PKGCONFIGDIR = $(LIBDIR)/pkgconfig
+pkg-config-libhydrogen:
+ mkdir -p $(DESTDIR)$(PKGCONFIGDIR)
+ sed "s|PREFIX|$(PREFIX)|" libhydrogen.pc \
+ > $(DESTDIR)$(PKGCONFIGDIR)/libhydrogen.pc
+
+# Donna
+DONNA_HEADERS=$(wildcard ../externals/ed25519-donna/*.h)
+donna.o: ../externals/ed25519-donna/ed25519.c $(DONNA_HEADERS)
+ $(CC) $(CFLAGS) -c $< -o$@ \
+ -DED25519_CUSTOMHASH \
+ -DED25519_TEST \
+ -DED25519_NO_INLINE_ASM \
+ -DED25519_FORCE_32BIT
+
+# Tinyssh
+TSSH =../externals/tinyssh
+TSSH_O = \
+ cleanup.o crypto_hash_sha512.o crypto_onetimeauth_poly1305.o \
+ crypto_scalarmult_curve25519.o crypto_sign_ed25519.o \
+ crypto_stream_chacha20.o crypto_verify_32.o fe25519.o fe.o ge25519.o \
+ randombytes.o sc25519.o uint32_pack.o uint32_unpack.o verify.o
+TSSH_H = \
+ $(TSSH)/cleanup.h $(TSSH)/crypto_hash_sha512.h $(TSSH)/crypto_int64.h \
+ $(TSSH)/crypto_onetimeauth_poly1305.h \
+ $(TSSH)/crypto_scalarmult_curve25519.h $(TSSH)/crypto_sign_ed25519.h \
+ $(TSSH)/crypto_stream_chacha20.h $(TSSH)/crypto_uint32.h \
+ $(TSSH)/crypto_uint64.h $(TSSH)/crypto_verify_32.h $(TSSH)/fe25519.h \
+ $(TSSH)/fe.h $(TSSH)/ge25519.h $(TSSH)/sc25519.h $(TSSH)/uint32_pack.h \
+ $(TSSH)/uint32_unpack.h $(TSSH)/verify.h
+
+cleanup.o : $(TSSH)/cleanup.c $(TSSH_H)
+crypto_hash_sha512.o : $(TSSH)/crypto_hash_sha512.c $(TSSH_H)
+crypto_onetimeauth_poly1305.o : $(TSSH)/crypto_onetimeauth_poly1305.c $(TSSH_H)
+crypto_scalarmult_curve25519.o: $(TSSH)/crypto_scalarmult_curve25519.c $(TSSH_H)
+crypto_sign_ed25519.o : $(TSSH)/crypto_sign_ed25519.c $(TSSH_H)
+crypto_stream_chacha20.o : $(TSSH)/crypto_stream_chacha20.c $(TSSH_H)
+crypto_verify_32.o : $(TSSH)/crypto_verify_32.c $(TSSH_H)
+fe25519.o : $(TSSH)/fe25519.c $(TSSH_H)
+fe.o : $(TSSH)/fe.c $(TSSH_H)
+ge25519.o : $(TSSH)/ge25519.c $(TSSH_H)
+randombytes.o : $(TSSH)/randombytes.c $(TSSH_H)
+sc25519.o : $(TSSH)/sc25519.c $(TSSH_H)
+uint32_pack.o : $(TSSH)/uint32_pack.c $(TSSH_H)
+uint32_unpack.o : $(TSSH)/uint32_unpack.c $(TSSH_H)
+verify.o : $(TSSH)/verify.c $(TSSH_H)
+$(TSSH_O):
+ $(CC) -c $(CFLAGS) -I ../externals/tinyssh/ -o $@ $<
+
+
+######################
+## Speed benchmarks ##
+######################
+speed.o : speed.c speed.h ../utils.h
+ $(CC) -c $(CFLAGS) $< -o $@ -I .. -I ../../src/ -I ../../src/optional
+speed-sodium.o : speed-sodium.c speed.h ../utils.h
+ $(CC) -c $(CFLAGS) $< -o $@ -I ..
+speed-hydrogen.o : speed-hydrogen.c speed.h ../utils.h
+ $(CC) -c $(CFLAGS) $< -o $@ -I ..
+speed-tweetnacl.o : speed-tweetnacl.c speed.h ../utils.h $(TWEET_HEADERS)
+ $(CC) -c $(CFLAGS) $< -o $@ -I .. -I ../externals/tweetnacl
+speed-c25519.o : speed-c25519.c speed.h ../utils.h $(C25519_HEADERS)
+ $(CC) -c $(CFLAGS) $< -o $@ -I .. -I ../externals/c25519
+speed-donna.o : speed-donna.c speed.h ../utils.h $(DONNA_HEADERS)
+ $(CC) -c $(CFLAGS) $< -o $@ -I .. -I ../externals/ed25519-donna
+speed-tinyssh.o : speed-tinyssh.c speed.h ../utils.h $(TSSH_H)
+ $(CC) -c $(CFLAGS) $< -o $@ -I .. -I $(TSSH)
+
+speed.out: speed.o utils.o monocypher.o monocypher-ed25519.o
+ $(CC) $(CFLAGS) -o $@ $^
+speed-sodium.out: speed-sodium.o utils.o
+ $(CC) $(CFLAGS) -o $@ $^ \
+ `pkg-config --cflags libsodium` \
+ `pkg-config --libs libsodium`
+speed-donna.out: speed-donna.o donna.o utils.o
+ $(CC) $(CFLAGS) -o $@ $^ \
+ `pkg-config --cflags libsodium` \
+ `pkg-config --libs libsodium`
+speed-hydrogen.out: speed-hydrogen.o utils.o
+ $(CC) $(CFLAGS) -o $@ $^ \
+ `pkg-config --cflags libhydrogen` \
+ `pkg-config --libs libhydrogen`
+speed-tweetnacl.out: speed-tweetnacl.o tweetnacl.o utils.o
+ $(CC) $(CFLAGS) -o $@ $^
+speed-c25519.out : speed-c25519.o $(C25519_OBJECTS) utils.o
+ $(CC) $(CFLAGS) -o $@ $^
+speed-tinyssh.out : speed-tinyssh.o $(TSSH_O) utils.o
+ $(CC) $(CFLAGS) -o $@ $^
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/speed/speed-c25519.c b/lib/Utils.Cryptography/monocypher/vendor/tests/speed/speed-c25519.c
new file mode 100644
index 0000000..534ba49
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/speed/speed-c25519.c
@@ -0,0 +1,123 @@
+// This file is dual-licensed. Choose whichever licence you want from
+// the two licences listed below.
+//
+// The first licence is a regular 2-clause BSD licence. The second licence
+// is the CC-0 from Creative Commons. It is intended to release Monocypher
+// to the public domain. The BSD licence serves as a fallback option.
+//
+// SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+//
+// ------------------------------------------------------------------------
+//
+// Copyright (c) 2017-2019, Loup Vaillant
+// All rights reserved.
+//
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// ------------------------------------------------------------------------
+//
+// Written in 2017-2019 by Loup Vaillant
+//
+// To the extent possible under law, the author(s) have dedicated all copyright
+// and related neighboring rights to this software to the public domain
+// worldwide. This software is distributed without any warranty.
+//
+// You should have received a copy of the CC0 Public Domain Dedication along
+// with this software. If not, see
+// <https://creativecommons.org/publicdomain/zero/1.0/>
+
+#include "speed.h"
+#include "utils.h"
+#include "c25519.h"
+#include "edsign.h"
+
+static u64 x25519(void)
+{
+ u8 in [32] = {9};
+ u8 out[F25519_SIZE];
+ FOR (i, 0, F25519_SIZE) {
+ out[i] = c25519_base_x[i];
+ }
+
+ TIMING_START {
+ c25519_prepare(in);
+ c25519_smult(out, out, in);
+ }
+ TIMING_END;
+}
+
+void edsign_sec_to_pub(uint8_t *pub, const uint8_t *secret);
+
+/* Produce a signature for a message. */
+#define EDSIGN_SIGNATURE_SIZE 64
+
+void edsign_sign(uint8_t *signature, const uint8_t *pub,
+ const uint8_t *secret,
+ const uint8_t *message, size_t len);
+
+/* Verify a message signature. Returns non-zero if ok. */
+uint8_t edsign_verify(const uint8_t *signature, const uint8_t *pub,
+ const uint8_t *message, size_t len);
+
+static u64 edDSA_sign(void)
+{
+ RANDOM_INPUT(sk , 32);
+ RANDOM_INPUT(message, 64);
+ u8 pk [32];
+ u8 sig[64];
+ edsign_sec_to_pub(pk, sk);
+
+ TIMING_START {
+ edsign_sign(sig, pk, sk, message, 64);
+ }
+ TIMING_END;
+}
+
+static u64 edDSA_check(void)
+{
+ RANDOM_INPUT(sk , 32);
+ RANDOM_INPUT(message, 64);
+ u8 pk [32];
+ u8 sig[64];
+ edsign_sec_to_pub(pk, sk);
+ edsign_sign(sig, pk, sk, message, 64);
+
+ TIMING_START {
+ if (!edsign_verify(sig, pk, message, 64)) {
+ printf("c25519 verification failed\n");
+ }
+ }
+ TIMING_END;
+}
+
+int main()
+{
+ print("x25519 ", x25519() , "exchanges per second");
+ print("EdDSA(sign) ", edDSA_sign() , "signatures per second");
+ print("EdDSA(check)", edDSA_check(), "checks per second");
+ printf("\n");
+ return 0;
+}
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/speed/speed-donna.c b/lib/Utils.Cryptography/monocypher/vendor/tests/speed/speed-donna.c
new file mode 100644
index 0000000..f089780
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/speed/speed-donna.c
@@ -0,0 +1,92 @@
+// This file is dual-licensed. Choose whichever licence you want from
+// the two licences listed below.
+//
+// The first licence is a regular 2-clause BSD licence. The second licence
+// is the CC-0 from Creative Commons. It is intended to release Monocypher
+// to the public domain. The BSD licence serves as a fallback option.
+//
+// SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+//
+// ------------------------------------------------------------------------
+//
+// Copyright (c) 2020, Loup Vaillant
+// All rights reserved.
+//
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// ------------------------------------------------------------------------
+//
+// Written in 2020 by Loup Vaillant
+//
+// To the extent possible under law, the author(s) have dedicated all copyright
+// and related neighboring rights to this software to the public domain
+// worldwide. This software is distributed without any warranty.
+//
+// You should have received a copy of the CC0 Public Domain Dedication along
+// with this software. If not, see
+// <https://creativecommons.org/publicdomain/zero/1.0/>
+
+#include "speed.h"
+#include "ed25519.h"
+
+static u64 edDSA_sign(void)
+{
+ u8 pk [32];
+ u8 signature[64];
+ RANDOM_INPUT(sk , 32);
+ RANDOM_INPUT(message, 64);
+ ed25519_publickey(sk, pk);
+
+ TIMING_START {
+ ed25519_sign(message, 64, sk, pk, signature);
+ }
+ TIMING_END;
+}
+
+static u64 edDSA_check(void)
+{
+ u8 pk [32];
+ u8 signature[64];
+ RANDOM_INPUT(sk , 32);
+ RANDOM_INPUT(message, 64);
+ ed25519_publickey(sk, pk);
+ ed25519_sign(message, 64, sk, pk, signature);
+
+ TIMING_START {
+ if (ed25519_sign_open(message, 64, pk, signature)) {
+ printf("Donna verification failed\n");
+ }
+ }
+ TIMING_END;
+}
+
+int main()
+{
+ print("EdDSA(sign) ",edDSA_sign() , "signatures per second");
+ print("EdDSA(check)",edDSA_check(), "checks per second");
+ printf("\n");
+ return 0;
+}
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/speed/speed-hydrogen.c b/lib/Utils.Cryptography/monocypher/vendor/tests/speed/speed-hydrogen.c
new file mode 100644
index 0000000..e11c4e2
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/speed/speed-hydrogen.c
@@ -0,0 +1,129 @@
+// This file is dual-licensed. Choose whichever licence you want from
+// the two licences listed below.
+//
+// The first licence is a regular 2-clause BSD licence. The second licence
+// is the CC-0 from Creative Commons. It is intended to release Monocypher
+// to the public domain. The BSD licence serves as a fallback option.
+//
+// SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+//
+// ------------------------------------------------------------------------
+//
+// Copyright (c) 2017-2019, Loup Vaillant
+// All rights reserved.
+//
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// ------------------------------------------------------------------------
+//
+// Written in 2017-2019 by Loup Vaillant
+//
+// To the extent possible under law, the author(s) have dedicated all copyright
+// and related neighboring rights to this software to the public domain
+// worldwide. This software is distributed without any warranty.
+//
+// You should have received a copy of the CC0 Public Domain Dedication along
+// with this software. If not, see
+// <https://creativecommons.org/publicdomain/zero/1.0/>
+
+#include "speed.h"
+#include "utils.h"
+#include "hydrogen.h"
+
+static u64 hydro_random(void)
+{
+ u8 out[SIZE];
+ RANDOM_INPUT(key , 32);
+ RANDOM_INPUT(nonce, 8);
+
+ TIMING_START {
+ hydro_random_buf_deterministic(out, SIZE, key);
+ }
+ TIMING_END;
+}
+
+static u64 authenticated(void)
+{
+ u8 out[SIZE + hydro_secretbox_HEADERBYTES];
+ RANDOM_INPUT(in , SIZE + 32);
+ RANDOM_INPUT(key, 32);
+ TIMING_START {
+ hydro_secretbox_encrypt(out, in, SIZE, 0, "Benchmark", key);
+ }
+ TIMING_END;
+}
+
+static u64 hash(void)
+{
+ u8 hash[32];
+ RANDOM_INPUT(in, SIZE);
+
+ TIMING_START {
+ hydro_hash_hash(hash, 32, in, SIZE, "Benchmark", 0);
+ }
+ TIMING_END;
+}
+
+static u64 sign(void)
+{
+ RANDOM_INPUT(message, 64);
+ hydro_sign_keypair key_pair;
+ hydro_sign_keygen(&key_pair);
+ uint8_t sig[hydro_sign_BYTES];
+
+ TIMING_START {
+ hydro_sign_create(sig, message, 64, "Benchmark", key_pair.sk);
+ }
+ TIMING_END;
+}
+
+static u64 check(void)
+{
+ RANDOM_INPUT(message, 64);
+ hydro_sign_keypair key_pair;
+ hydro_sign_keygen(&key_pair);
+ uint8_t sig[hydro_sign_BYTES];
+ hydro_sign_create(sig, message, 64, "Benchmark", key_pair.sk);
+
+ TIMING_START {
+ if (hydro_sign_verify(sig, message, 64, "Benchmark", key_pair.pk)) {
+ printf("LibHydrogen verification failed\n");
+ }
+ }
+ TIMING_END;
+}
+
+int main()
+{
+ hydro_init();
+ print("Random ",hydro_random() *MUL,"megabytes per second");
+ print("Auth'd encryption",authenticated()*MUL,"megabytes per second");
+ print("Hash ",hash() *MUL,"megabytes per second");
+ print("sign ",sign() ,"signatures per second");
+ print("check ",check() ,"checks per second");
+ printf("\n");
+ return 0;
+}
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/speed/speed-sodium.c b/lib/Utils.Cryptography/monocypher/vendor/tests/speed/speed-sodium.c
new file mode 100644
index 0000000..25bf61e
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/speed/speed-sodium.c
@@ -0,0 +1,191 @@
+// This file is dual-licensed. Choose whichever licence you want from
+// the two licences listed below.
+//
+// The first licence is a regular 2-clause BSD licence. The second licence
+// is the CC-0 from Creative Commons. It is intended to release Monocypher
+// to the public domain. The BSD licence serves as a fallback option.
+//
+// SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+//
+// ------------------------------------------------------------------------
+//
+// Copyright (c) 2017-2019, Loup Vaillant
+// All rights reserved.
+//
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// ------------------------------------------------------------------------
+//
+// Written in 2017-2019 by Loup Vaillant
+//
+// To the extent possible under law, the author(s) have dedicated all copyright
+// and related neighboring rights to this software to the public domain
+// worldwide. This software is distributed without any warranty.
+//
+// You should have received a copy of the CC0 Public Domain Dedication along
+// with this software. If not, see
+// <https://creativecommons.org/publicdomain/zero/1.0/>
+
+#include "speed.h"
+#include "sodium.h"
+
+static u64 chacha20(void)
+{
+ u8 out[SIZE];
+ RANDOM_INPUT(in , SIZE);
+ RANDOM_INPUT(key , 32);
+ RANDOM_INPUT(nonce, 8);
+
+ TIMING_START {
+ crypto_stream_chacha20_xor(out, in, SIZE, nonce, key);
+ }
+ TIMING_END;
+}
+
+static u64 poly1305(void)
+{
+ u8 out[16];
+ RANDOM_INPUT(in , SIZE);
+ RANDOM_INPUT(key, 32);
+
+ TIMING_START {
+ crypto_onetimeauth(out, in, SIZE, key);
+ }
+ TIMING_END;
+}
+
+static u64 authenticated(void)
+{
+ u8 out[SIZE];
+ u8 mac[crypto_aead_xchacha20poly1305_ietf_ABYTES];
+ RANDOM_INPUT(in , SIZE);
+ RANDOM_INPUT(key , 32);
+ RANDOM_INPUT(nonce, 24);
+
+ TIMING_START {
+ crypto_aead_xchacha20poly1305_ietf_encrypt_detached(
+ out, mac, 0, in, SIZE, 0, 0, 0, nonce, key);
+ }
+ TIMING_END;
+}
+
+static u64 blake2b(void)
+{
+ u8 hash[64];
+ RANDOM_INPUT(in , SIZE);
+ RANDOM_INPUT(key, 32);
+
+ TIMING_START {
+ crypto_generichash(hash, 64, in, SIZE, key, 32);
+ }
+ TIMING_END;
+}
+
+static u64 sha512(void)
+{
+ u8 hash[64];
+ RANDOM_INPUT(in, SIZE);
+
+ TIMING_START {
+ crypto_hash_sha512(hash, in, SIZE);
+ }
+ TIMING_END;
+}
+
+static u64 argon2i(void)
+{
+ u8 hash [32];
+ RANDOM_INPUT(password, 16);
+ RANDOM_INPUT(salt , 16);
+
+ TIMING_START {
+ if (crypto_pwhash(hash, 32, (char*)password, 16, salt,
+ 3, SIZE, crypto_pwhash_ALG_ARGON2I13)) {
+ fprintf(stderr, "Argon2i failed.\n");
+ }
+ }
+ TIMING_END;
+}
+
+static u64 x25519(void)
+{
+ u8 in [32] = {9};
+ u8 out[32] = {9};
+
+ TIMING_START {
+ if (crypto_scalarmult(out, out, in)) {
+ fprintf(stderr, "libsodium rejected the public key\n");
+ }
+ }
+ TIMING_END;
+}
+
+static u64 edDSA_sign(void)
+{
+ u8 sk [64];
+ u8 pk [32];
+ u8 signature[64];
+ RANDOM_INPUT(message, 64);
+ crypto_sign_keypair(pk, sk);
+
+ TIMING_START {
+ crypto_sign_detached(signature, 0, message, 64, sk);
+ }
+ TIMING_END;
+}
+
+static u64 edDSA_check(void)
+{
+ u8 sk [64];
+ u8 pk [32];
+ u8 signature[64];
+ RANDOM_INPUT(message, 64);
+ crypto_sign_keypair(pk, sk);
+ crypto_sign_detached(signature, 0, message, 64, sk);
+
+ TIMING_START {
+ if (crypto_sign_verify_detached(signature, message, 64, pk)) {
+ printf("libsodium verification failed\n");
+ }
+ }
+ TIMING_END;
+}
+
+int main()
+{
+ SODIUM_INIT;
+ print("Chacha20 ",chacha20() *MUL,"megabytes per second");
+ print("Poly1305 ",poly1305() *MUL,"megabytes per second");
+ print("Auth'd encryption",authenticated()*MUL,"megabytes per second");
+ print("BLAKE2b ",blake2b() *MUL,"megabytes per second");
+ print("SHA-512 ",sha512() *MUL,"megabytes per second");
+ print("Argon2i, 3 passes",argon2i() *MUL,"megabytes per second");
+ print("x25519 ",x25519() ,"exchanges per second");
+ print("EdDSA(sign) ",edDSA_sign() ,"signatures per second");
+ print("EdDSA(check) ",edDSA_check() ,"checks per second");
+ printf("\n");
+ return 0;
+}
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/speed/speed-tinyssh.c b/lib/Utils.Cryptography/monocypher/vendor/tests/speed/speed-tinyssh.c
new file mode 100644
index 0000000..9ac1a33
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/speed/speed-tinyssh.c
@@ -0,0 +1,159 @@
+// This file is dual-licensed. Choose whichever licence you want from
+// the two licences listed below.
+//
+// The first licence is a regular 2-clause BSD licence. The second licence
+// is the CC-0 from Creative Commons. It is intended to release Monocypher
+// to the public domain. The BSD licence serves as a fallback option.
+//
+// SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+//
+// ------------------------------------------------------------------------
+//
+// Copyright (c) 2017-2019, Loup Vaillant
+// All rights reserved.
+//
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// ------------------------------------------------------------------------
+//
+// Written in 2017-2019 by Loup Vaillant
+//
+// To the extent possible under law, the author(s) have dedicated all copyright
+// and related neighboring rights to this software to the public domain
+// worldwide. This software is distributed without any warranty.
+//
+// You should have received a copy of the CC0 Public Domain Dedication along
+// with this software. If not, see
+// <https://creativecommons.org/publicdomain/zero/1.0/>
+
+#include "speed.h"
+#include "utils.h"
+
+int crypto_stream_chacha20_tinyssh(unsigned char *,
+ unsigned long long,
+ const unsigned char *,
+ const unsigned char *);
+
+int crypto_stream_chacha20_tinyssh_xor(unsigned char *,
+ const unsigned char *,
+ unsigned long long,
+ const unsigned char *,
+ const unsigned char *);
+
+static u64 chacha20(void)
+{
+ u8 out[SIZE];
+ RANDOM_INPUT(in , SIZE);
+ RANDOM_INPUT(key , 32);
+ RANDOM_INPUT(nonce, 8);
+
+ TIMING_START {
+ crypto_stream_chacha20_tinyssh_xor(out, in, SIZE, nonce, key);
+ }
+ TIMING_END;
+}
+
+static u64 poly1305(void)
+{
+ u8 out[16];
+ RANDOM_INPUT(in , SIZE);
+ RANDOM_INPUT(key, 32);
+
+ TIMING_START {
+ crypto_onetimeauth_poly1305_tinyssh(out, in, SIZE, key);
+ }
+ TIMING_END;
+}
+
+static u64 sha512(void)
+{
+ u8 hash[64];
+ RANDOM_INPUT(in, SIZE);
+
+ TIMING_START {
+ crypto_hash_sha512_tinyssh(hash, in, SIZE);
+ }
+ TIMING_END;
+}
+
+static u64 x25519(void)
+{
+ u8 in [32] = {9};
+ u8 out[32] = {9};
+
+ TIMING_START {
+ crypto_scalarmult_curve25519_tinyssh(out, out, in);
+ }
+ TIMING_END;
+}
+
+static u64 edDSA_sign(void)
+{
+ u8 sk [ 64];
+ u8 pk [ 32];
+ u8 signed_msg[128];
+ unsigned long long sig_size;
+ RANDOM_INPUT(message, 64);
+ crypto_sign_ed25519_tinyssh_keypair(pk, sk);
+
+ TIMING_START {
+ crypto_sign_ed25519_tinyssh(signed_msg, &sig_size, message, 64, sk);
+ }
+ TIMING_END;
+}
+
+static u64 edDSA_check(void)
+{
+ u8 sk [ 64];
+ u8 pk [ 32];
+ u8 signed_msg[128];
+ u8 out_msg [128];
+ unsigned long long sig_size;
+ unsigned long long msg_size;
+ RANDOM_INPUT(message, 64);
+ crypto_sign_ed25519_tinyssh_keypair(pk, sk);
+ crypto_sign_ed25519_tinyssh(signed_msg, &sig_size, message, 64, sk);
+
+ TIMING_START {
+ if (crypto_sign_ed25519_tinyssh_open(out_msg, &msg_size,
+ signed_msg, sig_size, pk)) {
+ printf("TweetNaCl verification failed\n");
+ }
+ }
+ TIMING_END;
+}
+
+int main()
+{
+ print("Chacha20 ",chacha20() *MUL ,"megabytes per second");
+ print("Poly1305 ",poly1305() *MUL ,"megabytes per second");
+ print("SHA-512 ",sha512() *MUL ,"megabytes per second");
+ print("x25519 ",x25519() ,"exchanges per second");
+ print("EdDSA(sign) ",edDSA_sign() ,"signatures per second");
+ print("EdDSA(check)",edDSA_check() ,"checks per second");
+ printf("\n");
+ return 0;
+}
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/speed/speed-tweetnacl.c b/lib/Utils.Cryptography/monocypher/vendor/tests/speed/speed-tweetnacl.c
new file mode 100644
index 0000000..6f2ea6f
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/speed/speed-tweetnacl.c
@@ -0,0 +1,169 @@
+// This file is dual-licensed. Choose whichever licence you want from
+// the two licences listed below.
+//
+// The first licence is a regular 2-clause BSD licence. The second licence
+// is the CC-0 from Creative Commons. It is intended to release Monocypher
+// to the public domain. The BSD licence serves as a fallback option.
+//
+// SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+//
+// ------------------------------------------------------------------------
+//
+// Copyright (c) 2017-2019, Loup Vaillant
+// All rights reserved.
+//
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// ------------------------------------------------------------------------
+//
+// Written in 2017-2019 by Loup Vaillant
+//
+// To the extent possible under law, the author(s) have dedicated all copyright
+// and related neighboring rights to this software to the public domain
+// worldwide. This software is distributed without any warranty.
+//
+// You should have received a copy of the CC0 Public Domain Dedication along
+// with this software. If not, see
+// <https://creativecommons.org/publicdomain/zero/1.0/>
+
+#include "speed.h"
+#include "utils.h"
+#include "tweetnacl.h"
+
+// TweetNaCl needs to link with this
+// Not really random, but we don't care for those benchmarks.
+void randombytes(u8 *stream, u64 size)
+{
+ p_random(stream, (size_t)size);
+}
+
+static u64 salsa20(void)
+{
+ u8 out[SIZE];
+ RANDOM_INPUT(in , SIZE);
+ RANDOM_INPUT(key , 32);
+ RANDOM_INPUT(nonce, 8);
+
+ TIMING_START {
+ crypto_stream_salsa20_xor(out, in, SIZE, nonce, key);
+ }
+ TIMING_END;
+}
+
+static u64 poly1305(void)
+{
+ u8 out[16];
+ RANDOM_INPUT(in , SIZE);
+ RANDOM_INPUT(key, 32);
+
+ TIMING_START {
+ crypto_onetimeauth(out, in, SIZE, key);
+ }
+ TIMING_END;
+}
+
+static u64 authenticated(void)
+{
+ u8 out[SIZE + 32];
+ RANDOM_INPUT(in , SIZE + 32);
+ RANDOM_INPUT(key , 32);
+ RANDOM_INPUT(nonce, 24);
+
+ TIMING_START {
+ crypto_secretbox(out, in, SIZE + 32, nonce, key);
+ }
+ TIMING_END;
+}
+
+static u64 sha512(void)
+{
+ u8 hash[64];
+ RANDOM_INPUT(in, SIZE);
+
+ TIMING_START {
+ crypto_hash(hash, in, SIZE);
+ }
+ TIMING_END;
+}
+
+static u64 x25519(void)
+{
+ u8 in [32] = {9};
+ u8 out[32] = {9};
+
+ TIMING_START {
+ crypto_scalarmult(out, out, in);
+ }
+ TIMING_END;
+}
+
+static u64 edDSA_sign(void)
+{
+ u8 sk [ 64];
+ u8 pk [ 32];
+ u8 signed_msg[128];
+ unsigned long long sig_size;
+ RANDOM_INPUT(message, 64);
+ crypto_sign_keypair(pk, sk);
+
+ TIMING_START {
+ crypto_sign(signed_msg, &sig_size, message, 64, sk);
+ }
+ TIMING_END;
+}
+
+static u64 edDSA_check(void)
+{
+ u8 sk [ 64];
+ u8 pk [ 32];
+ u8 signed_msg[128];
+ u8 out_msg [128];
+ unsigned long long sig_size;
+ unsigned long long msg_size;
+ RANDOM_INPUT(message, 64);
+ crypto_sign_keypair(pk, sk);
+ crypto_sign(signed_msg, &sig_size, message, 64, sk);
+
+ TIMING_START {
+ if (crypto_sign_open(out_msg, &msg_size, signed_msg, sig_size, pk)) {
+ printf("TweetNaCl verification failed\n");
+ }
+ }
+ TIMING_END;
+}
+
+int main()
+{
+ print("Salsa20 ",salsa20() *MUL,"megabytes per second");
+ print("Poly1305 ",poly1305() *MUL,"megabytes per second");
+ print("Auth'd encryption",authenticated()*MUL,"megabytes per second");
+ print("SHA-512 ",sha512() *MUL,"megabytes per second");
+ print("x25519 ",x25519() ,"exchanges per second");
+ print("EdDSA(sign) ",edDSA_sign() ,"signatures per second");
+ print("EdDSA(check) ",edDSA_check() ,"checks per second");
+ printf("\n");
+ return 0;
+}
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/speed/speed.c b/lib/Utils.Cryptography/monocypher/vendor/tests/speed/speed.c
new file mode 100644
index 0000000..1a7e9dd
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/speed/speed.c
@@ -0,0 +1,270 @@
+// This file is dual-licensed. Choose whichever licence you want from
+// the two licences listed below.
+//
+// The first licence is a regular 2-clause BSD licence. The second licence
+// is the CC-0 from Creative Commons. It is intended to release Monocypher
+// to the public domain. The BSD licence serves as a fallback option.
+//
+// SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+//
+// ------------------------------------------------------------------------
+//
+// Copyright (c) 2017-2019, Loup Vaillant
+// All rights reserved.
+//
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// ------------------------------------------------------------------------
+//
+// Written in 2017-2019 by Loup Vaillant
+//
+// To the extent possible under law, the author(s) have dedicated all copyright
+// and related neighboring rights to this software to the public domain
+// worldwide. This software is distributed without any warranty.
+//
+// You should have received a copy of the CC0 Public Domain Dedication along
+// with this software. If not, see
+// <https://creativecommons.org/publicdomain/zero/1.0/>
+
+#include "speed.h"
+#include "monocypher.h"
+#include "monocypher-ed25519.h"
+#include "utils.h"
+
+static u64 chacha20(void)
+{
+ u8 out[SIZE];
+ RANDOM_INPUT(in , SIZE);
+ RANDOM_INPUT(key , 32);
+ RANDOM_INPUT(nonce, 8);
+
+ TIMING_START {
+ crypto_chacha20_djb(out, in, SIZE, key, nonce, 0);
+ }
+ TIMING_END;
+}
+
+static u64 poly1305(void)
+{
+ u8 out[16];
+ RANDOM_INPUT(in , SIZE);
+ RANDOM_INPUT(key, 32);
+
+ TIMING_START {
+ crypto_poly1305(out, in, SIZE, key);
+ }
+ TIMING_END;
+}
+
+static u64 authenticated(void)
+{
+ u8 out[SIZE];
+ u8 mac[ 16];
+ RANDOM_INPUT(in , SIZE);
+ RANDOM_INPUT(key , 32);
+ RANDOM_INPUT(nonce, 24);
+
+ TIMING_START {
+ crypto_aead_lock(mac, out, key, nonce, 0, 0, in, SIZE);
+ }
+ TIMING_END;
+}
+
+static u64 blake2b(void)
+{
+ u8 hash[64];
+ RANDOM_INPUT(in , SIZE);
+ RANDOM_INPUT(key, 32);
+
+ TIMING_START {
+ crypto_blake2b_keyed(hash, 64, key, 32, in, SIZE);
+ }
+ TIMING_END;
+}
+
+static u64 blake2b_small(void)
+{
+ u8 hash[64];
+ RANDOM_INPUT(input, 128*2);
+
+ TIMING_START {
+ FOR (i, 0, 128*2) {
+ crypto_blake2b_ctx ctx;
+ crypto_blake2b_init (&ctx, 64);
+ crypto_blake2b_update(&ctx, input , i);
+ crypto_blake2b_update(&ctx, input + i, 128*2 - i);
+ crypto_blake2b_final (&ctx, hash);
+ }
+ }
+ TIMING_END;
+}
+
+static u64 sha512(void)
+{
+ u8 hash[64];
+ RANDOM_INPUT(in, SIZE);
+
+ TIMING_START {
+ crypto_sha512(hash, in, SIZE);
+ }
+ TIMING_END;
+}
+
+static u64 sha512_small(void)
+{
+ u8 hash[64];
+ RANDOM_INPUT(input, 128*2);
+
+ TIMING_START {
+ FOR (i, 0, 128*2) {
+ crypto_sha512_ctx ctx;
+ crypto_sha512_init (&ctx);
+ crypto_sha512_update(&ctx, input , i);
+ crypto_sha512_update(&ctx, input + i, 128*2 - i);
+ crypto_sha512_final (&ctx, hash);
+ }
+ }
+ TIMING_END;
+}
+
+static u64 argon2i(void)
+{
+ u64 work_area[SIZE / 8];
+ u8 hash [32];
+ RANDOM_INPUT(pass, 16);
+ RANDOM_INPUT(salt, 16);
+
+ crypto_argon2_config config;
+ config.algorithm = CRYPTO_ARGON2_I;
+ config.nb_blocks = (u32)(SIZE / 1024);
+ config.nb_passes = 3;
+ config.nb_lanes = 1;
+
+ crypto_argon2_inputs inputs;
+ inputs.pass = pass;
+ inputs.salt = salt;
+ inputs.pass_size = sizeof(pass);
+ inputs.salt_size = sizeof(salt);
+
+ TIMING_START {
+ crypto_argon2(hash, sizeof(hash), work_area,
+ config, inputs, crypto_argon2_no_extras);
+ }
+ TIMING_END;
+}
+
+static u64 x25519(void)
+{
+ u8 in [32] = {9};
+ u8 out[32] = {9};
+
+ TIMING_START {
+ crypto_x25519(out, out, in);
+ }
+ TIMING_END;
+}
+
+static u64 edDSA_sign(void)
+{
+ u8 sk [64];
+ u8 pk [32];
+ u8 signature[64];
+ RANDOM_INPUT(seed , 32);
+ RANDOM_INPUT(message, 64);
+ crypto_eddsa_key_pair(sk, pk, seed);
+
+ TIMING_START {
+ crypto_eddsa_sign(signature, sk, message, 64);
+ }
+ TIMING_END;
+}
+
+static u64 edDSA_check(void)
+{
+ u8 sk [64];
+ u8 pk [32];
+ u8 signature[64];
+ RANDOM_INPUT(seed , 32);
+ RANDOM_INPUT(message, 64);
+ crypto_eddsa_key_pair(sk, pk, seed);
+ crypto_eddsa_sign(signature, sk, message, 64);
+
+ TIMING_START {
+ if (crypto_eddsa_check(signature, pk, message, 64)) {
+ printf("Monocypher verification failed\n");
+ }
+ }
+ TIMING_END;
+}
+
+static u64 x25519_inverse(void)
+{
+ u8 in [32] = {9};
+ u8 out[32] = {9};
+
+ TIMING_START {
+ crypto_x25519_inverse(out, out, in);
+ }
+ TIMING_END;
+}
+
+static u64 x25519_sp_fast(void)
+{
+ RANDOM_INPUT(sk, 32);
+ TIMING_START {
+ crypto_x25519_dirty_fast(sk, sk);
+ }
+ TIMING_END;
+}
+
+static u64 x25519_sp_small(void)
+{
+ RANDOM_INPUT(sk, 32);
+ TIMING_START {
+ crypto_x25519_dirty_small(sk, sk);
+ }
+ TIMING_END;
+}
+
+int main()
+{
+ print("Chacha20 ",chacha20() *MUL ,"megabytes per second");
+ print("Poly1305 ",poly1305() *MUL ,"megabytes per second");
+ print("Auth'd encryption ",authenticated()*MUL ,"megabytes per second");
+ print("BLAKE2b ",blake2b() *MUL ,"megabytes per second");
+ print("BLAKE2b (small) ",blake2b_small() ,"cycles per second");
+ print("SHA-512 ",sha512() *MUL ,"megabytes per second");
+ print("SHA-512 (small) ",sha512_small() ,"cycles per second");
+ print("Argon2i, 3 passes ",argon2i() *MUL ,"megabytes per second");
+ print("x25519 ",x25519() ,"exchanges per second");
+ print("EdDSA(sign) ",edDSA_sign() ,"signatures per second");
+ print("EdDSA(check) ",edDSA_check() ,"checks per second");
+ print("x25519 inverse ",x25519_inverse() ,"scalar inv per second");
+ print("x25519 dirty fast ",x25519_sp_fast() ,"scalar inv per second");
+ print("x25519 dirty small ",x25519_sp_small() ,"scalar inv per second");
+ printf("\n");
+ return 0;
+}
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/speed/speed.h b/lib/Utils.Cryptography/monocypher/vendor/tests/speed/speed.h
new file mode 100644
index 0000000..824bc91
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/speed/speed.h
@@ -0,0 +1,105 @@
+// This file is dual-licensed. Choose whichever licence you want from
+// the two licences listed below.
+//
+// The first licence is a regular 2-clause BSD licence. The second licence
+// is the CC-0 from Creative Commons. It is intended to release Monocypher
+// to the public domain. The BSD licence serves as a fallback option.
+//
+// SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+//
+// ------------------------------------------------------------------------
+//
+// Copyright (c) 2017-2019, Loup Vaillant
+// All rights reserved.
+//
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// ------------------------------------------------------------------------
+//
+// Written in 2017-2019 by Loup Vaillant
+//
+// To the extent possible under law, the author(s) have dedicated all copyright
+// and related neighboring rights to this software to the public domain
+// worldwide. This software is distributed without any warranty.
+//
+// You should have received a copy of the CC0 Public Domain Dedication along
+// with this software. If not, see
+// <https://creativecommons.org/publicdomain/zero/1.0/>
+
+#include <time.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "utils.h"
+
+typedef struct timespec timespec;
+
+// TODO: provide a user defined buffer size
+#define KILOBYTE 1024
+#define MEGABYTE 1024 * KILOBYTE
+#define SIZE (256 * KILOBYTE)
+#define MUL (MEGABYTE / SIZE)
+#define BILLION 1000000000
+
+// Difference in nanoseconds
+static u64 diff(timespec start, timespec end)
+{
+ return (u64)((end.tv_sec - start.tv_sec ) * BILLION +
+ (end.tv_nsec - start.tv_nsec));
+}
+
+static u64 min(u64 a, u64 b)
+{
+ return a < b ? a : b;
+}
+
+static void print(const char *name, u64 duration, const char *unit)
+{
+ if (duration == 0) {
+ printf("%s: too fast to be measured\n", name);
+ } else {
+ u64 speed_hz = BILLION / duration;
+ printf("%s: %5" PRIu64 " %s\n", name, speed_hz, unit);
+ }
+}
+
+// Note: not all systems will work well with CLOCK_PROCESS_CPUTIME_ID.
+// If you get weird timings on your system, you may want to replace it
+// with another clock id. Perhaps even replace clock_gettime().
+#define TIMESTAMP(t) \
+ timespec t; \
+ clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &t)
+
+#define TIMING_START \
+ u64 duration = (u64)-1; \
+ FOR (i, 0, 2000) { \
+ TIMESTAMP(start);
+
+#define TIMING_END \
+ TIMESTAMP(end); \
+ duration = min(duration, diff(start, end)); \
+ } /* end FOR*/ \
+ return duration
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/test.c b/lib/Utils.Cryptography/monocypher/vendor/tests/test.c
new file mode 100644
index 0000000..98bd9b1
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/test.c
@@ -0,0 +1,1252 @@
+// This file is dual-licensed. Choose whichever licence you want from
+// the two licences listed below.
+//
+// The first licence is a regular 2-clause BSD licence. The second licence
+// is the CC-0 from Creative Commons. It is intended to release Monocypher
+// to the public domain. The BSD licence serves as a fallback option.
+//
+// SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+//
+// ------------------------------------------------------------------------
+//
+// Copyright (c) 2017-2020, Loup Vaillant and Richard Walmsley
+// All rights reserved.
+//
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// ------------------------------------------------------------------------
+//
+// Written in 2017-2020 by Loup Vaillant and Richard Walmsley
+//
+// To the extent possible under law, the author(s) have dedicated all copyright
+// and related neighboring rights to this software to the public domain
+// worldwide. This software is distributed without any warranty.
+//
+// You should have received a copy of the CC0 Public Domain Dedication along
+// with this software. If not, see
+// <https://creativecommons.org/publicdomain/zero/1.0/>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "monocypher.h"
+#include "monocypher-ed25519.h"
+#include "utils.h"
+#include "vectors.h"
+
+#define VECTORS(n) ASSERT_OK(vector_test(n, #n, nb_##n##_vectors, n##_vectors))
+
+////////////
+/// Wipe ///
+////////////
+static void test_wipe(void)
+{
+ printf("\tcrypto_wipe\n");
+ u8 zeroes[50] = {0};
+ FOR (i, 0, 50) {
+ RANDOM_INPUT(buf, 50);
+ crypto_wipe(buf, i);
+ ASSERT_EQUAL(zeroes, buf, i);
+ }
+}
+
+////////////////////////////////
+/// Constant time comparison ///
+////////////////////////////////
+static void p_verify(unsigned size, int (*compare)(const u8*, const u8*))
+{
+ printf("\tcrypto_verify%u\n", size);
+ u8 a[64]; // size <= 64
+ u8 b[64]; // size <= 64
+ FOR (i, 0, 2) {
+ FOR (j, 0, 2) {
+ // Set every byte to the chosen value, then compare
+ FOR (k, 0, size) {
+ a[k] = (u8)i;
+ b[k] = (u8)j;
+ }
+ int cmp = compare(a, b);
+ if (i == j) { ASSERT(cmp == 0); }
+ else { ASSERT(cmp != 0); }
+ // Set only two bytes to the chosen value, then compare
+ FOR (k, 0, size / 2) {
+ FOR (l, 0, size) {
+ a[l] = 0;
+ b[l] = 0;
+ }
+ a[k] = (u8)i; a[k + size/2 - 1] = (u8)i;
+ b[k] = (u8)j; b[k + size/2 - 1] = (u8)j;
+ cmp = compare(a, b);
+ if (i == j) { ASSERT(cmp == 0); }
+ else { ASSERT(cmp != 0); }
+ }
+ }
+ }
+}
+
+static void test_verify(void)
+{
+ p_verify(16, crypto_verify16);
+ p_verify(32, crypto_verify32);
+ p_verify(64, crypto_verify64);
+}
+
+////////////////
+/// Chacha20 ///
+////////////////
+#define CHACHA_BLOCK_SIZE 64
+
+static void chacha20(vector_reader *reader)
+{
+ vector key = next_input(reader);
+ vector nonce = next_input(reader);
+ vector plain = next_input(reader);
+ u64 ctr = load64_le(next_input(reader).buf);
+ vector out = next_output(reader);
+ u64 nb_blocks = plain.size / 64 + (plain.size % 64 != 0);
+ u64 new_ctr = crypto_chacha20_djb(out.buf, plain.buf, plain.size,
+ key.buf, nonce.buf, ctr);
+ ASSERT(new_ctr - ctr == nb_blocks);
+}
+
+static void ietf_chacha20(vector_reader *reader)
+{
+ vector key = next_input(reader);
+ vector nonce = next_input(reader);
+ vector plain = next_input(reader);
+ u32 ctr = load32_le(next_input(reader).buf);
+ vector out = next_output(reader);
+ u32 nb_blocks = (u32)(plain.size / 64 + (plain.size % 64 != 0));
+ u32 new_ctr = crypto_chacha20_ietf(out.buf, plain.buf, plain.size,
+ key.buf, nonce.buf, ctr);
+ ASSERT(new_ctr - ctr == nb_blocks);
+}
+
+static void xchacha20(vector_reader *reader)
+{
+ vector key = next_input(reader);
+ vector nonce = next_input(reader);
+ vector plain = next_input(reader);
+ u64 ctr = load64_le(next_input(reader).buf);
+ vector out = next_output(reader);
+ u64 nb_blocks = plain.size / 64 + (plain.size % 64 != 0);
+ u64 new_ctr = crypto_chacha20_x(out.buf, plain.buf, plain.size,
+ key.buf, nonce.buf, ctr);
+ ASSERT(new_ctr - ctr == nb_blocks);
+}
+
+static void hchacha20(vector_reader *reader)
+{
+ vector key = next_input(reader);
+ vector nonce = next_input(reader);
+ vector out = next_output(reader);
+ crypto_chacha20_h(out.buf, key.buf, nonce.buf);
+}
+
+static void test_chacha20(void)
+{
+ VECTORS(chacha20);
+ printf("\tChacha20 (ctr)\n");
+ {
+ RANDOM_INPUT(key , 32);
+ RANDOM_INPUT(nonce, 24);
+ RANDOM_INPUT(plain, 128);
+ u8 out_full[128];
+ u8 out1 [64];
+ u8 out2 [64];
+ crypto_chacha20_djb(out_full, plain , 128, key, nonce, 0);
+ crypto_chacha20_djb(out1 , plain + 0, 64, key, nonce, 0);
+ crypto_chacha20_djb(out2 , plain + 64, 64, key, nonce, 1);
+ ASSERT_EQUAL(out_full , out1, 64);
+ ASSERT_EQUAL(out_full + 64, out2, 64);
+ }
+
+ printf("\tChacha20 (nullptr == zeroes)\n");
+#define INPUT_SIZE (CHACHA_BLOCK_SIZE * 2 + 1)
+ FOR (i, 0, INPUT_SIZE) {
+ u8 output_normal[INPUT_SIZE];
+ u8 output_stream[INPUT_SIZE];
+ u8 zeroes [INPUT_SIZE] = {0};
+ RANDOM_INPUT(key , 32);
+ RANDOM_INPUT(nonce, 8);
+ crypto_chacha20_djb(output_normal, zeroes, i, key, nonce, 0);
+ crypto_chacha20_djb(output_stream, 0 , i, key, nonce, 0);
+ ASSERT_EQUAL(output_normal, output_stream, i);
+ }
+
+ printf("\tChacha20 (output == input)\n");
+ {
+#undef INPUT_SIZE
+#define INPUT_SIZE (CHACHA_BLOCK_SIZE * 4) // total input size
+ u8 output[INPUT_SIZE];
+ RANDOM_INPUT(input, INPUT_SIZE);
+ RANDOM_INPUT(key , 32);
+ RANDOM_INPUT(nonce, 8);
+ crypto_chacha20_djb(output, input, INPUT_SIZE, key, nonce, 0);
+ crypto_chacha20_djb(input , input, INPUT_SIZE, key, nonce, 0);
+ ASSERT_EQUAL(output, input, INPUT_SIZE);
+ }
+
+ VECTORS(ietf_chacha20);
+ printf("\tietf Chacha20 (ctr)\n");
+ {
+ RANDOM_INPUT(key , 32);
+ RANDOM_INPUT(nonce, 24);
+ RANDOM_INPUT(plain, 128);
+ u8 out_full[128];
+ u8 out1 [64];
+ u8 out2 [64];
+ crypto_chacha20_ietf(out_full, plain , 128, key, nonce, 0);
+ crypto_chacha20_ietf(out1 , plain + 0, 64, key, nonce, 0);
+ crypto_chacha20_ietf(out2 , plain + 64, 64, key, nonce, 1);
+ ASSERT_EQUAL(out_full , out1, 64);
+ ASSERT_EQUAL(out_full + 64, out2, 64);
+ }
+
+ VECTORS(xchacha20);
+ printf("\tXChacha20 (ctr)\n");
+ {
+ RANDOM_INPUT(key , 32);
+ RANDOM_INPUT(nonce, 24);
+ RANDOM_INPUT(plain, 128);
+ u8 out_full[128];
+ u8 out1 [64];
+ u8 out2 [64];
+ crypto_chacha20_x(out_full, plain , 128, key, nonce, 0);
+ crypto_chacha20_x(out1 , plain + 0, 64, key, nonce, 0);
+ crypto_chacha20_x(out2 , plain + 64, 64, key, nonce, 1);
+ ASSERT_EQUAL(out_full , out1, 64);
+ ASSERT_EQUAL(out_full + 64, out2, 64);
+ }
+
+ VECTORS(hchacha20);
+ printf("\tHChacha20 (overlap)\n");
+ FOR (i, 0, 100) {
+ RANDOM_INPUT(buffer, 80);
+ size_t out_idx = rand64() % 48;
+ size_t key_idx = rand64() % 48;
+ size_t in_idx = rand64() % 64;
+ u8 key[32]; FOR (j, 0, 32) { key[j] = buffer[j + key_idx]; }
+ u8 in [16]; FOR (j, 0, 16) { in [j] = buffer[j + in_idx]; }
+
+ // Run with and without overlap, then compare
+ u8 out[32];
+ crypto_chacha20_h(out, key, in);
+ crypto_chacha20_h(buffer + out_idx, buffer + key_idx, buffer + in_idx);
+ ASSERT_EQUAL(out, buffer + out_idx, 32);
+ }
+}
+
+/////////////////
+/// Poly 1305 ///
+/////////////////
+#define POLY1305_BLOCK_SIZE 16
+
+static void poly1305(vector_reader *reader)
+{
+ vector key = next_input(reader);
+ vector msg = next_input(reader);
+ vector out = next_output(reader);
+ crypto_poly1305(out.buf, msg.buf, msg.size, key.buf);
+}
+
+static void test_poly1305(void)
+{
+ VECTORS(poly1305);
+
+ printf("\tPoly1305 (incremental)\n");
+#undef INPUT_SIZE
+#define INPUT_SIZE (POLY1305_BLOCK_SIZE * 4) // total input size
+ FOR (i, 0, INPUT_SIZE) {
+ // outputs
+ u8 mac_chunk[16];
+ u8 mac_whole[16];
+ // inputs
+ RANDOM_INPUT(input, INPUT_SIZE);
+ RANDOM_INPUT(key , 32);
+
+ // Authenticate bit by bit
+ crypto_poly1305_ctx ctx;
+ crypto_poly1305_init(&ctx, key);
+ crypto_poly1305_update(&ctx, input , i);
+ crypto_poly1305_update(&ctx, input + i, INPUT_SIZE - i);
+ crypto_poly1305_final(&ctx, mac_chunk);
+
+ // Authenticate all at once
+ crypto_poly1305(mac_whole, input, INPUT_SIZE, key);
+
+ // Compare the results
+ ASSERT_EQUAL(mac_chunk, mac_whole, 16);
+ }
+
+ printf("\tPoly1305 (overlapping i/o)\n");
+#undef INPUT_SIZE
+#define INPUT_SIZE (POLY1305_BLOCK_SIZE + (2 * 16)) // total input size
+ FOR (i, 0, POLY1305_BLOCK_SIZE + 16) {
+ RANDOM_INPUT(input, INPUT_SIZE);
+ RANDOM_INPUT(key , 32);
+ u8 mac [16];
+ crypto_poly1305(mac , input + 16, POLY1305_BLOCK_SIZE, key);
+ crypto_poly1305(input+i, input + 16, POLY1305_BLOCK_SIZE, key);
+ ASSERT_EQUAL(mac, input + i, 16);
+ }
+}
+
+////////////////////////////////
+/// Authenticated encryption ///
+////////////////////////////////
+static void aead_ietf(vector_reader *reader)
+{
+ vector key = next_input(reader);
+ vector nonce = next_input(reader);
+ vector ad = next_input(reader);
+ vector text = next_input(reader);
+ vector out = next_output(reader);
+ crypto_aead_lock(out.buf + 16, out.buf, key.buf, nonce.buf,
+ ad.buf, ad.size, text.buf, text.size);
+}
+
+static void aead_8439(vector_reader *reader)
+{
+ vector key = next_input(reader);
+ vector nonce = next_input(reader);
+ vector ad = next_input(reader);
+ vector text = next_input(reader);
+ vector out = next_output(reader);
+ crypto_aead_ctx ctx;
+ crypto_aead_init_ietf(&ctx, key.buf, nonce.buf);
+ crypto_aead_write(&ctx, out.buf + 16, out.buf, ad.buf, ad.size,
+ text.buf, text.size);
+}
+
+static void test_aead(void)
+{
+ VECTORS(aead_ietf);
+ VECTORS(aead_8439);
+
+ printf("\taead (roundtrip)\n");
+ FOR (i, 0, 1000) {
+ RANDOM_INPUT(key , 32);
+ RANDOM_INPUT(nonce , 24);
+ RANDOM_INPUT(ad , 4);
+ RANDOM_INPUT(plaintext, 8);
+ u8 box[24];
+ u8 out[8];
+ // AEAD roundtrip
+ crypto_aead_lock(box+16, box, key, nonce, ad, 4, plaintext, 8);
+ ASSERT_OK(crypto_aead_unlock(out, box, key, nonce, ad, 4, box+16, 8));
+ ASSERT_EQUAL(plaintext, out, 8);
+ box[0]++;
+ ASSERT_KO(crypto_aead_unlock(out, box, key, nonce, ad, 4, box+16, 8));
+ }
+
+ printf("\taead incr (roundtrip)\n");
+ FOR (i, 0, 50) {
+ RANDOM_INPUT(key , 32);
+ RANDOM_INPUT(nonce , 24);
+ crypto_aead_ctx ctx_xa;
+ crypto_aead_ctx ctx_xb;
+ crypto_aead_ctx ctx_da;
+ crypto_aead_ctx ctx_db;
+ crypto_aead_ctx ctx_ia;
+ crypto_aead_ctx ctx_ib;
+ crypto_aead_init_x (&ctx_xa, key, nonce);
+ crypto_aead_init_x (&ctx_xb, key, nonce);
+ crypto_aead_init_djb (&ctx_da, key, nonce);
+ crypto_aead_init_djb (&ctx_db, key, nonce);
+ crypto_aead_init_ietf(&ctx_ia, key, nonce);
+ crypto_aead_init_ietf(&ctx_ib, key, nonce);
+
+ FOR (j, 0, 10) {
+ RANDOM_INPUT(ad, 4); // additional data
+ RANDOM_INPUT(pt, 8); // plaintext
+ u8 mac[16];
+ u8 ct [ 8];
+ u8 pt2[ 8];
+ // AEAD roundtrip (happy path)
+ crypto_aead_write (&ctx_xa, ct , mac, ad, 4, pt, 8);
+ ASSERT_OK(crypto_aead_read(&ctx_xb, pt2, mac, ad, 4, ct, 8));
+ ASSERT_EQUAL(pt, pt2, 8);
+ ASSERT_EQUAL(&ctx_xa, &ctx_xb, sizeof(crypto_aead_ctx));
+
+ crypto_aead_write (&ctx_da, ct , mac, ad, 4, pt, 8);
+ ASSERT_OK(crypto_aead_read(&ctx_db, pt2, mac, ad, 4, ct, 8));
+ ASSERT_EQUAL(pt, pt2, 8);
+
+ crypto_aead_write (&ctx_ia, ct , mac, ad, 4, pt, 8);
+ ASSERT_OK(crypto_aead_read(&ctx_ib, pt2, mac, ad, 4, ct, 8));
+ ASSERT_EQUAL(pt, pt2, 8);
+ }
+ }
+ printf("\n");
+}
+
+///////////////
+/// Blake2b ///
+///////////////
+#define BLAKE2B_BLOCK_SIZE 128
+
+static void blake2b(vector_reader *reader)
+{
+ vector msg = next_input(reader);
+ vector key = next_input(reader);
+ vector out = next_output(reader);
+ crypto_blake2b_keyed(out.buf, out.size,
+ key.buf, key.size,
+ msg.buf, msg.size);
+}
+
+static void test_blake2b(void)
+{
+ VECTORS(blake2b);
+
+ printf("\tBLAKE2b (zero_input)\n");
+ {
+ RANDOM_INPUT(key, 32);
+ u8 hash_chunk[64];
+ u8 hash_whole[64];
+ crypto_blake2b_ctx ctx;
+
+ // With key
+ memset(&ctx, 0x5c, sizeof(ctx));
+ crypto_blake2b_keyed_init(&ctx, 64, key, 32);
+ crypto_blake2b_final (&ctx, hash_chunk);
+ crypto_blake2b_keyed(hash_whole, 64, key, 32, 0, 0);
+ ASSERT_EQUAL(hash_chunk, hash_whole, 64);
+
+ // Without key
+ memset(&ctx, 0x5c, sizeof(ctx));
+ crypto_blake2b_init (&ctx, 64);
+ crypto_blake2b_final(&ctx, hash_chunk);
+ crypto_blake2b(hash_whole, 64, 0, 0);
+ ASSERT_EQUAL(hash_chunk, hash_whole, 64);
+ }
+
+ printf("\tBLAKE2b (incremental)\n");
+ // Note: I figured we didn't need to test keyed mode, or different
+ // hash sizes, a second time. This test sticks to the simplified
+ // interface.
+#undef INPUT_SIZE
+#define INPUT_SIZE (BLAKE2B_BLOCK_SIZE * 3) // total input size
+ {
+ RANDOM_INPUT(input, INPUT_SIZE);
+
+ // hash at once
+ u8 hash_whole[64];
+ crypto_blake2b(hash_whole, 64, input, INPUT_SIZE);
+
+ FOR (j, 0, INPUT_SIZE) {
+ FOR (i, 0, j+1) {
+ // Hash bit by bit
+ u8 *mid_input = j - i == 0 ? NULL : input + i; // NULL update
+ u8 hash_chunk[64];
+ crypto_blake2b_ctx ctx;
+ crypto_blake2b_init (&ctx, 64);
+ crypto_blake2b_update(&ctx, input , i);
+ crypto_blake2b_update(&ctx, mid_input, j - i);
+ crypto_blake2b_update(&ctx, input + j, INPUT_SIZE - j);
+ crypto_blake2b_final (&ctx, hash_chunk);
+
+ // Compare the results (must be the same)
+ ASSERT_EQUAL(hash_chunk, hash_whole, 64);
+ }
+ }
+ }
+
+ printf("\tBLAKE2b (overlapping i/o)\n");
+#undef INPUT_SIZE
+#define INPUT_SIZE (BLAKE2B_BLOCK_SIZE + (2 * 64)) // total input size
+ FOR (i, 0, BLAKE2B_BLOCK_SIZE + 64) {
+ u8 hash [64];
+ RANDOM_INPUT(input, INPUT_SIZE);
+ crypto_blake2b(hash , 64, input + 64, BLAKE2B_BLOCK_SIZE);
+ crypto_blake2b(input+i, 64, input + 64, BLAKE2B_BLOCK_SIZE);
+ ASSERT_EQUAL(hash, input + i, 64);
+ }
+}
+
+///////////////
+/// SHA 512 ///
+///////////////
+#define SHA_512_BLOCK_SIZE 128
+
+static void sha512(vector_reader *reader)
+{
+ vector in = next_input(reader);
+ vector out = next_output(reader);
+ crypto_sha512(out.buf, in.buf, in.size);
+}
+
+static void sha512_hmac(vector_reader *reader)
+{
+ vector key = next_input(reader);
+ vector msg = next_input(reader);
+ vector out = next_output(reader);
+ crypto_sha512_hmac(out.buf, key.buf, key.size, msg.buf, msg.size);
+}
+
+static void sha512_hkdf(vector_reader *reader)
+{
+ vector ikm = next_input(reader);
+ vector salt = next_input(reader);
+ vector info = next_input(reader);
+ vector okm = next_output(reader);
+ crypto_sha512_hkdf(okm .buf, okm .size,
+ ikm .buf, ikm .size,
+ salt.buf, salt.size,
+ info.buf, info.size);
+}
+
+static void test_sha512(void)
+{
+ VECTORS(sha512);
+ VECTORS(sha512_hmac);
+ VECTORS(sha512_hkdf);
+
+ printf("\tSHA-512 (incremental)\n");
+#undef INPUT_SIZE
+#define INPUT_SIZE (SHA_512_BLOCK_SIZE * 4 - 32) // total input size
+ {
+ RANDOM_INPUT(input, INPUT_SIZE);
+
+ // hash at once
+ u8 hash_whole[64];
+ crypto_sha512(hash_whole, input, INPUT_SIZE);
+
+ FOR (j, 0, INPUT_SIZE) {
+ FOR (i, 0, j+1) {
+ // Hash bit by bit
+ u8 *mid_input = j - i == 0 ? NULL : input + i; // NULL update
+ u8 hash_chunk[64];
+ crypto_sha512_ctx ctx;
+ crypto_sha512_init (&ctx);
+ crypto_sha512_update(&ctx, input , i);
+ crypto_sha512_update(&ctx, mid_input, j - i);
+ crypto_sha512_update(&ctx, input + j, INPUT_SIZE - j);
+ crypto_sha512_final (&ctx, hash_chunk);
+
+ // Compare the results (must be the same)
+ ASSERT_EQUAL(hash_chunk, hash_whole, 64);
+ }
+ }
+ }
+
+ printf("\tSHA-512 (overlapping i/o)\n");
+#undef INPUT_SIZE
+#define INPUT_SIZE (SHA_512_BLOCK_SIZE + (2 * 64)) // total input size
+ FOR (i, 0, SHA_512_BLOCK_SIZE + 64) {
+ u8 hash [64];
+ RANDOM_INPUT(input, INPUT_SIZE);
+ crypto_sha512(hash , input + 64, SHA_512_BLOCK_SIZE);
+ crypto_sha512(input+i, input + 64, SHA_512_BLOCK_SIZE);
+ ASSERT_EQUAL(hash, input + i, 64);
+ }
+
+ printf("\tHMAC SHA-512 (incremental)\n");
+#undef INPUT_SIZE
+#define INPUT_SIZE (SHA_512_BLOCK_SIZE * 4 - 32) // total input size
+ FOR (i, 0, INPUT_SIZE) {
+ // outputs
+ u8 hash_chunk[64];
+ u8 hash_whole[64];
+ // inputs
+ RANDOM_INPUT(key , 32);
+ RANDOM_INPUT(input, INPUT_SIZE);
+
+ // Authenticate bit by bit
+ crypto_sha512_hmac_ctx ctx;
+ crypto_sha512_hmac_init(&ctx, key, 32);
+ crypto_sha512_hmac_update(&ctx, input , i);
+ crypto_sha512_hmac_update(&ctx, input + i, INPUT_SIZE - i);
+ crypto_sha512_hmac_final(&ctx, hash_chunk);
+
+ // Authenticate all at once
+ crypto_sha512_hmac(hash_whole, key, 32, input, INPUT_SIZE);
+
+ // Compare the results (must be the same)
+ ASSERT_EQUAL(hash_chunk, hash_whole, 64);
+ }
+
+ printf("\tHMAC SHA-512 (overlapping i/o)\n");
+#undef INPUT_SIZE
+#define INPUT_SIZE (SHA_512_BLOCK_SIZE + (2 * 64)) // total input size
+ FOR (i, 0, SHA_512_BLOCK_SIZE + 64) {
+ u8 hash [64];
+ RANDOM_INPUT(key , 32);
+ RANDOM_INPUT(input, INPUT_SIZE);
+ crypto_sha512_hmac(hash , key, 32, input + 64, SHA_512_BLOCK_SIZE);
+ crypto_sha512_hmac(input+i, key, 32, input + 64, SHA_512_BLOCK_SIZE);
+ ASSERT_EQUAL(hash, input + i, 64);
+ }
+}
+
+
+//////////////
+/// Argon2 ///
+//////////////
+static void argon2(vector_reader *reader)
+{
+ crypto_argon2_config config;
+ config.algorithm = load32_le(next_input(reader).buf);
+ config.nb_blocks = load32_le(next_input(reader).buf);
+ config.nb_passes = load32_le(next_input(reader).buf);
+ config.nb_lanes = load32_le(next_input(reader).buf);
+
+ vector pass = next_input(reader);
+ vector salt = next_input(reader);
+ vector key = next_input(reader);
+ vector ad = next_input(reader);
+ vector out = next_output(reader);
+ void *work_area = alloc((size_t)config.nb_blocks * 1024);
+
+ crypto_argon2_inputs inputs;
+ inputs.pass = pass.buf;
+ inputs.salt = salt.buf;
+ inputs.pass_size = (u32)pass.size;
+ inputs.salt_size = (u32)salt.size;
+
+ crypto_argon2_extras extras;
+ extras.key = key.buf;
+ extras.ad = ad.buf;
+ extras.key_size = (u32)key.size;
+ extras.ad_size = (u32)ad.size;
+
+ crypto_argon2(out.buf, (u32)out.size, work_area, config, inputs, extras);
+ free(work_area);
+}
+
+static void test_argon2(void)
+{
+ VECTORS(argon2);
+
+ printf("\tArgon2 (overlapping i/o)\n");
+ u8 *work_area = (u8*)alloc(8 * 1024);
+ u8 *clean_work_area = (u8*)alloc(8 * 1024);
+ FOR (i, 0, 10) {
+ p_random(work_area, 8 * 1024);
+ u32 hash_offset = rand64() % 64;
+ u32 pass_offset = rand64() % 64;
+ u32 salt_offset = rand64() % 64;
+ u32 key_offset = rand64() % 64;
+ u32 ad_offset = rand64() % 64;
+ u8 hash1[32];
+ u8 *hash2 = work_area + hash_offset;
+ u8 pass[16]; FOR (j, 0, 16) { pass[j] = work_area[j + pass_offset]; }
+ u8 salt[16]; FOR (j, 0, 16) { salt[j] = work_area[j + salt_offset]; }
+ u8 key [32]; FOR (j, 0, 32) { key [j] = work_area[j + key_offset]; }
+ u8 ad [32]; FOR (j, 0, 32) { ad [j] = work_area[j + ad_offset]; }
+
+ crypto_argon2_config config;
+ config.algorithm = CRYPTO_ARGON2_I;
+ config.nb_blocks = 8;
+ config.nb_passes = 1;
+ config.nb_lanes = 1;
+
+ crypto_argon2_inputs inputs;
+ inputs.pass = pass;
+ inputs.salt = salt;
+ inputs.pass_size = sizeof(pass);
+ inputs.salt_size = sizeof(salt);
+
+ crypto_argon2_extras extras;
+ extras.key = key;
+ extras.ad = ad;
+ extras.key_size = sizeof(key);
+ extras.ad_size = sizeof(ad);
+
+ crypto_argon2(hash1, 32, clean_work_area, config, inputs, extras);
+
+ // with overlap
+ inputs.pass = work_area + pass_offset;
+ inputs.salt = work_area + salt_offset;
+ extras.key = work_area + key_offset;
+ extras.ad = work_area + ad_offset;
+ crypto_argon2(hash2, 32, work_area, config, inputs, extras);
+
+ ASSERT_EQUAL(hash1, hash2, 32);
+ }
+ free(work_area);
+ free(clean_work_area);
+}
+
+//////////////
+/// X25519 ///
+//////////////
+static void x25519(vector_reader *reader)
+{
+ vector scalar = next_input(reader);
+ vector point = next_input(reader);
+ vector out = next_output(reader);
+ crypto_x25519(out.buf, scalar.buf, point.buf);
+}
+
+static void x25519_pk(vector_reader *reader)
+{
+ vector in = next_input(reader);
+ vector out = next_output(reader);
+ crypto_x25519_public_key(out.buf, in.buf);
+}
+
+static void iterate_x25519(u8 k[32], u8 u[32])
+{
+ u8 tmp[32];
+ crypto_x25519(tmp , k, u);
+ memcpy(u, k , 32);
+ memcpy(k, tmp, 32);
+}
+
+static void test_x25519(void)
+{
+ VECTORS(x25519);
+ VECTORS(x25519_pk);
+
+ {
+ printf("\tx25519 1\n");
+ u8 _1 [32] = {
+ 0x42, 0x2c, 0x8e, 0x7a, 0x62, 0x27, 0xd7, 0xbc,
+ 0xa1, 0x35, 0x0b, 0x3e, 0x2b, 0xb7, 0x27, 0x9f,
+ 0x78, 0x97, 0xb8, 0x7b, 0xb6, 0x85, 0x4b, 0x78,
+ 0x3c, 0x60, 0xe8, 0x03, 0x11, 0xae, 0x30, 0x79
+ };
+ u8 k[32] = {9};
+ u8 u[32] = {9};
+ crypto_x25519_public_key(k, u);
+ ASSERT_EQUAL(k, _1, 32);
+
+ printf("\tx25519 1K\n");
+ u8 _1k [32] = {
+ 0x68, 0x4c, 0xf5, 0x9b, 0xa8, 0x33, 0x09, 0x55,
+ 0x28, 0x00, 0xef, 0x56, 0x6f, 0x2f, 0x4d, 0x3c,
+ 0x1c, 0x38, 0x87, 0xc4, 0x93, 0x60, 0xe3, 0x87,
+ 0x5f, 0x2e, 0xb9, 0x4d, 0x99, 0x53, 0x2c, 0x51
+ };
+ FOR (i, 1, 1000) { iterate_x25519(k, u); }
+ ASSERT_EQUAL(k, _1k, 32);
+
+ // too long; didn't run
+ //printf("\tx25519 1M\n");
+ //u8 _1M[32] = {
+ // 0x7c, 0x39, 0x11, 0xe0, 0xab, 0x25, 0x86, 0xfd,
+ // 0x86, 0x44, 0x97, 0x29, 0x7e, 0x57, 0x5e, 0x6f,
+ // 0x3b, 0xc6, 0x01, 0xc0, 0x88, 0x3c, 0x30, 0xdf,
+ // 0x5f, 0x4d, 0xd2, 0xd2, 0x4f, 0x66, 0x54, 0x24
+ //};
+ //FOR (i, 1000, 1000000) { iterate_x25519(k, u); }
+ //ASSERT_EQUAL(k, _1M, 32);
+ }
+
+ printf("\tx25519 (overlapping i/o)\n");
+ FOR (i, 0, 62) {
+ u8 overlapping[94];
+ u8 separate[32];
+ RANDOM_INPUT(sk, 32);
+ RANDOM_INPUT(pk, 32);
+ memcpy(overlapping + 31, sk, 32);
+ crypto_x25519(overlapping + i, overlapping + 31, pk);
+ crypto_x25519(separate, sk, pk);
+ ASSERT_EQUAL(separate, overlapping + i, 32);
+ }
+
+ printf("\tx25519_inverse\n");
+ {
+ RANDOM_INPUT(b, 32);
+ u8 base[32]; // random point (cofactor is cleared).
+ crypto_x25519_public_key(base, b);
+ // check round trip
+ FOR (i, 0, 50) {
+ RANDOM_INPUT(sk, 32);
+ u8 pk [32];
+ u8 blind[32];
+ crypto_x25519(pk, sk, base);
+ crypto_x25519_inverse(blind, sk, pk);
+ ASSERT_EQUAL(blind, base, 32);
+ }
+
+ // check cofactor clearing
+ // (Multiplying by a low order point yields zero
+ u8 low_order[4][32] = {
+ {0}, {1},
+ {0x5f, 0x9c, 0x95, 0xbc, 0xa3, 0x50, 0x8c, 0x24,
+ 0xb1, 0xd0, 0xb1, 0x55, 0x9c, 0x83, 0xef, 0x5b,
+ 0x04, 0x44, 0x5c, 0xc4, 0x58, 0x1c, 0x8e, 0x86,
+ 0xd8, 0x22, 0x4e, 0xdd, 0xd0, 0x9f, 0x11, 0x57,},
+ {0xe0, 0xeb, 0x7a, 0x7c, 0x3b, 0x41, 0xb8, 0xae,
+ 0x16, 0x56, 0xe3, 0xfa, 0xf1, 0x9f, 0xc4, 0x6a,
+ 0xda, 0x09, 0x8d, 0xeb, 0x9c, 0x32, 0xb1, 0xfd,
+ 0x86, 0x62, 0x05, 0x16, 0x5f, 0x49, 0xb8, 0x00,},
+ };
+ u8 zero[32] = {0};
+ FOR (i, 0, 32) {
+ u8 blind[32];
+ RANDOM_INPUT(sk, 32);
+ crypto_x25519_inverse(blind, sk, low_order[i%4]);
+ ASSERT_EQUAL(blind, zero, 32);
+ }
+ }
+
+ printf("\tx25519 inverse (overlapping i/o)\n");
+ FOR (i, 0, 62) {
+ u8 overlapping[94];
+ u8 separate[32];
+ RANDOM_INPUT(sk, 32);
+ RANDOM_INPUT(pk, 32);
+ memcpy(overlapping + 31, sk, 32);
+ crypto_x25519_inverse(overlapping + i, overlapping + 31, pk);
+ crypto_x25519_inverse(separate, sk, pk);
+ ASSERT_EQUAL(separate, overlapping + i, 32);
+ }
+}
+
+///////////////////
+/// EdDSA utils ///
+///////////////////
+
+// Adds X time L to the input
+static void add_xl(u8 out[32], u8 in[32], unsigned factor)
+{
+ static const u8 L[32] = {
+ 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58,
+ 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+ };
+ ASSERT(factor <= 8);
+ unsigned acc = 0;
+ FOR(i, 0, 32) {
+ acc += in[i] + L[i] * factor;
+ out[i] = acc & 0xff;
+ acc >>= 8;
+ }
+ ASSERT(acc == 0); // No carry is remaining
+}
+
+static void test_edDSA_utils(void)
+{
+ printf("\tEdDSA (scalarbase)\n");
+ FOR (i, 0, 50) {
+ RANDOM_INPUT(scalar, 32);
+ u8 scalar_plus[32];
+ u8 point [32];
+ u8 point_plus [32];
+
+ // Equivalent (yet different) scalars
+ scalar[31] &= 0xf; // trim the scalar below 252 bits
+ add_xl(scalar_plus, scalar, 8); // 8*L == curve order
+ ASSERT_DIFFERENT(scalar, scalar_plus, 32);
+
+ // Bit-for-bit identical points
+ crypto_eddsa_scalarbase(point , scalar);
+ crypto_eddsa_scalarbase(point_plus, scalar_plus);
+ ASSERT_EQUAL(point, point_plus, 32);
+ }
+}
+
+/////////////
+/// EdDSA ///
+/////////////
+static void edDSA(vector_reader *reader)
+{
+ vector secret_k = next_input(reader);
+ vector public_k = next_input(reader);
+ vector msg = next_input(reader);
+ vector out = next_output(reader);
+ u8 fat_secret_key[64];
+ memcpy(fat_secret_key , secret_k.buf, 32);
+ memcpy(fat_secret_key + 32, public_k.buf, 32);
+ crypto_eddsa_sign(out.buf, fat_secret_key, msg.buf, msg.size);
+}
+
+static void edDSA_pk(vector_reader *reader)
+{
+ vector in = next_input(reader);
+ vector out = next_output(reader);
+ u8 seed [32];
+ u8 secret_key[64];
+ u8 public_key[32];
+ memcpy(seed, in.buf, 32);
+ crypto_eddsa_key_pair(secret_key, public_key, seed);
+ memcpy(out.buf, public_key, 32);
+
+ u8 zeroes[32] = {0};
+ ASSERT_EQUAL(seed , zeroes , 32);
+ ASSERT_EQUAL(secret_key , in.buf , 32);
+ ASSERT_EQUAL(secret_key + 32, public_key, 32);
+}
+
+static void test_edDSA(void)
+{
+ VECTORS(edDSA);
+ VECTORS(edDSA_pk);
+
+ printf("\tEdDSA (roundtrip)\n");
+#define MESSAGE_SIZE 30
+ FOR (i, 0, MESSAGE_SIZE) {
+ RANDOM_INPUT(message, MESSAGE_SIZE);
+ RANDOM_INPUT(seed, 32);
+ u8 sk [64];
+ u8 pk [32];
+ u8 signature[64];
+ crypto_eddsa_key_pair(sk, pk, seed);
+ crypto_eddsa_sign(signature, sk, message, i);
+ ASSERT_OK(crypto_eddsa_check(signature, pk, message, i));
+
+ // reject forgeries
+ u8 zero [64] = {0};
+ ASSERT_KO(crypto_eddsa_check(zero , pk, message, i));
+ FOR (j, 0, 64) {
+ u8 forgery[64];
+ memcpy(forgery, signature, 64);
+ forgery[j] = signature[j] + 1;
+ ASSERT_KO(crypto_eddsa_check(forgery, pk, message, i));
+ }
+ }
+
+ printf("\tEdDSA (random)\n");
+ {
+ // Verifies that random signatures are all invalid. Uses random
+ // public keys to see what happens outside of the curve (it should
+ // yield an invalid signature).
+ FOR (i, 0, 100) {
+ RANDOM_INPUT(message, MESSAGE_SIZE);
+ RANDOM_INPUT(pk, 32);
+ RANDOM_INPUT(signature , 64);
+ ASSERT_KO(crypto_eddsa_check(signature, pk, message, MESSAGE_SIZE));
+ }
+ // Testing S == L (for code coverage)
+ RANDOM_INPUT(message, MESSAGE_SIZE);
+ RANDOM_INPUT(pk, 32);
+ static const u8 signature[64] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58,
+ 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+ };
+ ASSERT_KO(crypto_eddsa_check(signature, pk, message, MESSAGE_SIZE));
+ }
+
+ printf("\tEdDSA (overlap)\n");
+ FOR(i, 0, MESSAGE_SIZE + 64) {
+#undef INPUT_SIZE
+#define INPUT_SIZE (MESSAGE_SIZE + (2 * 64)) // total input size
+ RANDOM_INPUT(input, INPUT_SIZE);
+ RANDOM_INPUT(seed, 32);
+ u8 sk [64];
+ u8 pk [32];
+ u8 signature[64];
+ crypto_eddsa_key_pair(sk, pk, seed);
+ crypto_eddsa_sign(signature, sk, input + 64, MESSAGE_SIZE);
+ crypto_eddsa_sign(input+i , sk, input + 64, MESSAGE_SIZE);
+ ASSERT_EQUAL(signature, input + i, 64);
+ }
+}
+
+///////////////
+/// Ed25519 ///
+///////////////
+static void ed_25519(vector_reader *reader)
+{
+ vector secret_k = next_input(reader);
+ vector public_k = next_input(reader);
+ vector msg = next_input(reader);
+ vector out = next_output(reader);
+ u8 fat_secret_key[64];
+ memcpy(fat_secret_key , secret_k.buf, 32);
+ memcpy(fat_secret_key + 32, public_k.buf, 32);
+ crypto_ed25519_sign(out.buf, fat_secret_key, msg.buf, msg.size);
+}
+
+static void ed_25519_pk(vector_reader *reader)
+{
+ vector in = next_input(reader);
+ vector out = next_output(reader);
+ u8 seed [32];
+ u8 secret_key[64];
+ u8 public_key[32];
+ memcpy(seed, in.buf, 32);
+ crypto_ed25519_key_pair(secret_key, public_key, seed);
+ memcpy(out.buf, public_key, 32);
+
+ u8 zeroes[32] = {0};
+ ASSERT_EQUAL(seed , zeroes , 32);
+ ASSERT_EQUAL(secret_key , in.buf , 32);
+ ASSERT_EQUAL(secret_key + 32, public_key, 32);
+}
+
+static void ed_25519_check(vector_reader *reader)
+{
+ vector public_k = next_input(reader);
+ vector msg = next_input(reader);
+ vector sig = next_input(reader);
+ vector out = next_output(reader);
+ out.buf[0] = (u8)crypto_ed25519_check(sig.buf, public_k.buf,
+ msg.buf, msg.size);
+}
+
+static void ed_25519ph(vector_reader *reader)
+{
+ vector sk = next_input(reader);
+ vector pk = next_input(reader);
+ vector msg = next_input(reader);
+ vector out = next_output(reader);
+
+ // Test that we generate the correct public key
+ uint8_t secret_key[64];
+ uint8_t public_key[32];
+ crypto_ed25519_key_pair(secret_key, public_key, sk.buf);
+ ASSERT_EQUAL(public_key, pk.buf, 32);
+ ASSERT_EQUAL(public_key, secret_key + 32, 32);
+
+ // Generate output signature for comparison
+ uint8_t digest[64];
+ crypto_sha512(digest, msg.buf, msg.size);
+ crypto_ed25519_ph_sign(out.buf, secret_key, digest);
+
+ // Test that the correct signature is accepted
+ ASSERT_OK(crypto_ed25519_ph_check(out.buf, pk.buf, digest));
+
+ // Test that corrupted signatures are rejected
+ for (size_t i = 0; i < 64; i++) {
+ uint8_t corrupt_signature[64];
+ memcpy(corrupt_signature, out.buf, 64);
+ corrupt_signature[i] ^= 1; // corrupt one bit
+ ASSERT_KO(crypto_ed25519_ph_check(corrupt_signature, pk.buf, digest));
+ }
+}
+
+static void test_ed25519(void)
+{
+ VECTORS(ed_25519);
+ VECTORS(ed_25519_pk);
+ VECTORS(ed_25519_check);
+ VECTORS(ed_25519ph);
+}
+
+/////////////////
+/// Elligator ///
+/////////////////
+static void elligator_dir(vector_reader *reader)
+{
+ vector in = next_input(reader);
+ vector out = next_output(reader);
+ crypto_elligator_map(out.buf, in.buf);
+}
+
+static void elligator_inv(vector_reader *reader)
+{
+ vector point = next_input(reader);
+ u8 tweak = next_input(reader).buf[0];
+ u8 failure = next_input(reader).buf[0];
+ vector out = next_output(reader);
+ int check = crypto_elligator_rev(out.buf, point.buf, tweak);
+ ASSERT((u8)check == failure);
+}
+
+static void test_elligator(void)
+{
+ VECTORS(elligator_dir);
+
+ printf("\telligator direct (msb)\n");
+ FOR (i, 0, 20) {
+ RANDOM_INPUT(r, 32);
+ u8 r1[32]; memcpy(r1, r, 32); r1[31] = (r[31] & 0x3f) | 0x00;
+ u8 r2[32]; memcpy(r2, r, 32); r2[31] = (r[31] & 0x3f) | 0x40;
+ u8 r3[32]; memcpy(r3, r, 32); r3[31] = (r[31] & 0x3f) | 0x80;
+ u8 r4[32]; memcpy(r4, r, 32); r4[31] = (r[31] & 0x3f) | 0xc0;
+ u8 u [32]; crypto_elligator_map(u , r );
+ u8 u1[32]; crypto_elligator_map(u1, r1);
+ u8 u2[32]; crypto_elligator_map(u2, r2);
+ u8 u3[32]; crypto_elligator_map(u3, r3);
+ u8 u4[32]; crypto_elligator_map(u4, r4);
+ ASSERT_EQUAL(u, u1, 32);
+ ASSERT_EQUAL(u, u2, 32);
+ ASSERT_EQUAL(u, u3, 32);
+ ASSERT_EQUAL(u, u4, 32);
+ }
+
+ printf("\telligator direct (overlapping i/o)\n");
+ FOR (i, 0, 62) {
+ u8 overlapping[94];
+ u8 separate[32];
+ RANDOM_INPUT(r, 32);
+ memcpy(overlapping + 31, r, 32);
+ crypto_elligator_map(overlapping + i, overlapping + 31);
+ crypto_elligator_map(separate, r);
+ ASSERT_EQUAL(separate, overlapping + i, 32);
+ }
+
+ VECTORS(elligator_inv);
+
+ printf("\telligator inverse (overlapping i/o)\n");
+ FOR (i, 0, 62) {
+ u8 overlapping[94];
+ u8 separate[32];
+ RANDOM_INPUT(pk, 33);
+ u8 tweak = pk[32];
+ memcpy(overlapping + 31, pk, 32);
+ int a = crypto_elligator_rev(overlapping+i, overlapping+31, tweak);
+ int b = crypto_elligator_rev(separate, pk, tweak);
+ ASSERT(a == b);
+ if (a == 0) {
+ // The buffers are the same only if written to to begin with
+ ASSERT_EQUAL(separate, overlapping + i, 32);
+ }
+ }
+
+ printf("\telligator x25519\n");
+ FOR (i, 0, 64) {
+ RANDOM_INPUT(sk1, 32);
+ RANDOM_INPUT(sk2, 32);
+ u8 skc [32]; memcpy(skc, sk1, 32); skc[0] &= 248;
+ u8 pks [32]; crypto_x25519_dirty_small(pks , sk1);
+ u8 pksc[32]; crypto_x25519_dirty_small(pksc, skc);
+ u8 pkf [32]; crypto_x25519_dirty_fast (pkf , sk1);
+ u8 pkfc[32]; crypto_x25519_dirty_fast (pkfc, skc);
+ u8 pk1 [32]; crypto_x25519_public_key (pk1 , sk1);
+
+ // Both dirty functions behave the same
+ ASSERT_EQUAL(pks, pkf, 32);
+
+ // Dirty functions behave cleanly if we clear the 3 lsb first
+ ASSERT_EQUAL(pksc, pk1, 32);
+ ASSERT_EQUAL(pkfc, pk1, 32);
+
+ // Dirty functions behave the same as the clean one if the lsb
+ // are 0, differently if it is not
+ if ((sk1[0] & 7) == 0) { ASSERT_EQUAL (pk1, pkf, 32); }
+ else { ASSERT_DIFFERENT(pk1, pkf, 32); }
+
+ // Maximise tweak diversity.
+ // We want to set the bits 1 (sign) and 6-7 (padding)
+ u8 tweak = (u8)((i & 1) + (i << 5));
+ u8 r[32];
+ if (crypto_elligator_rev(r, pkf, tweak)) {
+ i--; // Cancel tweak increment
+ continue; // retry untill success
+ }
+ // Verify that the tweak's msb are copied to the representative
+ ASSERT((tweak >> 6) == (r[31] >> 6));
+
+ // Round trip
+ u8 pkr[32]; crypto_elligator_map(pkr, r);
+ ASSERT_EQUAL(pkr, pkf, 32);
+
+ // Dirty and safe keys are compatible
+ u8 e1 [32]; crypto_x25519(e1, sk2, pk1);
+ u8 e2 [32]; crypto_x25519(e2, sk2, pkr);
+ ASSERT_EQUAL(e1, e2, 32);
+ }
+
+ printf("\telligator key pair\n");
+ FOR(i, 0, 32) {
+ RANDOM_INPUT(seed, 32);
+ RANDOM_INPUT(sk2 , 32);
+ u8 r [32];
+ u8 sk1[32]; crypto_elligator_key_pair(r, sk1, seed);
+ u8 pkr[32]; crypto_elligator_map(pkr, r);
+ u8 pk1[32]; crypto_x25519_public_key(pk1, sk1);
+ u8 e1 [32]; crypto_x25519(e1, sk2, pk1);
+ u8 e2 [32]; crypto_x25519(e2, sk2, pkr);
+ ASSERT_EQUAL(e1, e2, 32);
+ }
+
+ printf("\telligator key pair (overlapping i/o)\n");
+ FOR (i, 0, 94) {
+ u8 over[158];
+ u8 sep [ 64];
+ RANDOM_INPUT(s1, 32);
+ u8 *s2 = over + 63;
+ memcpy(s2, s1, 32);
+ crypto_elligator_key_pair(sep , sep + 32, s1);
+ crypto_elligator_key_pair(over + i, over + i + 32, s2);
+ ASSERT_EQUAL(sep, over + i, 64);
+ }
+}
+
+////////////////////////
+/// X25519 <-> EdDSA ///
+////////////////////////
+static void test_conversions(void)
+{
+ printf("\tX25519 <-> EdDSA\n");
+ FOR (i, 0, 32) {
+ RANDOM_INPUT(e_seed, 32);
+ u8 secret [64];
+ u8 e_public1[32]; crypto_eddsa_key_pair(secret, e_public1, e_seed);
+ u8 x_private[64]; crypto_blake2b(x_private, 64, secret, 32);
+ u8 x_public1[32]; crypto_eddsa_to_x25519 (x_public1, e_public1);
+ u8 x_public2[32]; crypto_x25519_public_key(x_public2, x_private);
+ ASSERT_EQUAL(x_public1, x_public2, 32);
+
+ u8 e_public2[32]; crypto_x25519_to_eddsa (e_public2, x_public1);
+ ASSERT((e_public2[31] & 0x80) == 0); // x coordinate always positive
+
+ e_public1[31] &= 0x7f; // y coordinate back to original
+ ASSERT_EQUAL(e_public1, e_public2, 32);
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ if (argc > 1) {
+ sscanf(argv[1], "%" PRIu64 "", &random_state);
+ }
+ printf("\nRandom seed = %" PRIu64 "\n\n", random_state);
+
+ printf("Wipe: \n");
+ test_wipe();
+
+ printf("Comparisons:\n");
+ test_verify();
+
+ printf("Encryption:\n");
+ test_chacha20();
+ test_aead();
+
+ printf("Hashes:\n");
+ test_poly1305();
+ test_blake2b();
+ test_sha512();
+ test_argon2();
+
+ printf("X25519:\n");
+ test_x25519();
+
+ printf("EdDSA:\n");
+ test_edDSA_utils();
+ test_edDSA();
+ test_ed25519();
+
+ printf("Elligator:\n");
+ test_elligator();
+
+ printf("Curve25519 conversions:\n");
+ test_conversions();
+
+ printf("\nAll tests OK!\n");
+ return 0;
+}
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/test.sh b/lib/Utils.Cryptography/monocypher/vendor/tests/test.sh
new file mode 100644
index 0000000..8129823
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/test.sh
@@ -0,0 +1,69 @@
+#! /bin/sh
+
+# This file is dual-licensed. Choose whichever licence you want from
+# the two licences listed below.
+#
+# The first licence is a regular 2-clause BSD licence. The second licence
+# is the CC-0 from Creative Commons. It is intended to release Monocypher
+# to the public domain. The BSD licence serves as a fallback option.
+#
+# SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+#
+# ------------------------------------------------------------------------
+#
+# Copyright (c) 2017-2019, Loup Vaillant
+# All rights reserved.
+#
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# ------------------------------------------------------------------------
+#
+# Written in 2017-2019 by Loup Vaillant
+#
+# To the extent possible under law, the author(s) have dedicated all copyright
+# and related neighboring rights to this software to the public domain
+# worldwide. This software is distributed without any warranty.
+#
+# You should have received a copy of the CC0 Public Domain Dedication along
+# with this software. If not, see
+# <https://creativecommons.org/publicdomain/zero/1.0/>
+
+set -e
+
+CC="clang -std=c99"
+CFLAGS="-pedantic -Wall -Wextra -g -O2"
+
+make clean; make tis-ci
+make clean; make test
+make clean; make test CC="$CC" CFLAGS="$CFLAGS -DBLAKE2_NO_UNROLLING"
+make clean; make test CC="$CC" CFLAGS="$CFLAGS -fsanitize=address"
+make clean; make test CC="$CC" CFLAGS="$CFLAGS -fsanitize=memory"
+make clean; make test CC="$CC" CFLAGS="$CFLAGS -fsanitize=undefined"
+make clean; make test.out CC="gcc -std=c99"; valgrind ./test.out
+
+echo
+echo "All sanitisers passed!"
+echo
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/tis-ci-gen-config.sh b/lib/Utils.Cryptography/monocypher/vendor/tests/tis-ci-gen-config.sh
new file mode 100644
index 0000000..5c8c754
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/tis-ci-gen-config.sh
@@ -0,0 +1,114 @@
+#! /bin/sh
+
+# This file is dual-licensed. Choose whichever licence you want from
+# the two licences listed below.
+#
+# The first licence is a regular 2-clause BSD licence. The second licence
+# is the CC-0 from Creative Commons. It is intended to release Monocypher
+# to the public domain. The BSD licence serves as a fallback option.
+#
+# SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+#
+# ------------------------------------------------------------------------
+#
+# Copyright (c) 2020, Loup Vaillant
+# All rights reserved.
+#
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# ------------------------------------------------------------------------
+#
+# Written in 2020 by Loup Vaillant
+#
+# To the extent possible under law, the author(s) have dedicated all copyright
+# and related neighboring rights to this software to the public domain
+# worldwide. This software is distributed without any warranty.
+#
+# You should have received a copy of the CC0 Public Domain Dedication along
+# with this software. If not, see
+# <https://creativecommons.org/publicdomain/zero/1.0/>
+
+DIR=$(dirname "$0")
+TIS_CONFIG=$DIR/../tis.config
+
+echo "// auto generated with $0" > $TIS_CONFIG
+echo "[" >> $TIS_CONFIG
+
+for entry_point in \
+ "p_wipe" \
+ "v_chacha20" \
+ "v_ietf_chacha20" \
+ "v_hchacha20" \
+ "v_xchacha20" \
+ "v_poly1305" \
+ "v_aead_ietf" \
+ "v_blake2b" \
+ "v_sha512" \
+ "v_sha512_hmac" \
+ "v_sha512_hkdf" \
+ "v_argon2" \
+ "v_x25519" \
+ "v_edDSA" \
+ "v_edDSA_pk" \
+ "v_ed_25519" \
+ "v_ed_25519_check" \
+ "v_elligator_dir" \
+ "v_elligator_inv" \
+ "p_eddsa_x25519" \
+ "p_dirty" \
+ "p_x25519_inverse" \
+ "p_verify16" \
+ "p_verify32" \
+ "p_verify64"
+do
+ for platform in \
+ "x86_16" \
+ "sparc_32" \
+ "x86_32" \
+ "rv64ifdq" \
+ "mips_64"
+ do
+ echo '{ "name" :' "\"$entry_point - $platform\"" >> $TIS_CONFIG
+ echo ', "files" :' >> $TIS_CONFIG
+ echo ' [ "src/monocypher.c"' >> $TIS_CONFIG
+ echo ' , "src/optional/monocypher-ed25519.c"' >> $TIS_CONFIG
+ echo ' , "tests/utils.c"' >> $TIS_CONFIG
+ echo ' , "tests/tis-ci.c"' >> $TIS_CONFIG
+ echo ' ]' >> $TIS_CONFIG
+ echo ', "cpp-extra-args":
+ "-Isrc -Isrc/optional -Itests -Dvolatile=
+ -DCLOCK_PROCESS_CPUTIME_ID=3 -DCLOCK_THREAD_CPUTIME_ID=4"' \
+ >> $TIS_CONFIG
+ echo ', "machdep" :' "\"$platform\"" >> $TIS_CONFIG
+ echo ', "no-results" : true' >> $TIS_CONFIG
+ echo ', "main" :' "\"$entry_point\"" >> $TIS_CONFIG
+ echo '},' >> $TIS_CONFIG
+ done
+done
+sed -i '$ d' $TIS_CONFIG
+
+echo "}" >> $TIS_CONFIG
+echo "]" >> $TIS_CONFIG
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/tis-ci-vectors.h b/lib/Utils.Cryptography/monocypher/vendor/tests/tis-ci-vectors.h
new file mode 100644
index 0000000..b3505d7
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/tis-ci-vectors.h
@@ -0,0 +1,532 @@
+// Generated with hard coded official vectors, and
+// random vectors with libsodium and ed25519-donna.
+// Download Monocypher's git repository to regenerate.
+#include <inttypes.h>
+#include <stddef.h>
+
+static const char *chacha20_vectors[]={
+ "e4c4054fe35a75d9c0f679ad8770d8227e68e4c1e68ce67ee88e6be251a20748",
+ "b3753cff3a6d9901",
+ "",
+ "e4b5efc932fb5798",
+ "",
+ "b181071f299aa254a4606ab6a058e0c6fb5598218db71deb473f7d04c152e7e8",
+ "57736715dc7b788a",
+ "ca",
+ "f6f5808bdc50fb80",
+ "c1",
+ "9f40d6c8348c353b00172655236cddcd1879ca1f04b35f91adab70b81f504035",
+ "fc169964a5ae985e",
+ "6c11b0b7bb18a51fd77fbffd722aa220efdd8947ca5a5c7fb1c2ebdb9ad1f603801ff22e80314f716af9c22022fa159dbb4b4d3153f999b20ab4769eb1d01c",
+ "593e47059549b141",
+ "907aae5d8cea5ca4cc0842dd58a333bcffcd8f2a234ab46a7dc78c3d690a3f01f89aa75426cec8469f36e2b4c41fdba7290a18cef9b39f807a20f1b6933807",
+ "80bd73e9ca43cdd4eb7173476862df6d2458d6c74739a0ad2169b9c89edd74e1",
+ "6fbcecc748c25dc3",
+ "38041fc34af0f1bda20eaf3fff7b372aa801eb98a1298bc61028073750831c8cb43cd6822bf3f6fae0801cb6c843d8066b07346635365fb7d6ee54e5c9cd6f05",
+ "29958874e0842c12",
+ "c44c93948a3ccc5d473d1319efb42d1944e734fc5b613953845be858c5df073e6448a6e442378d631e9705e0efe3e8d7309458542a715453174f21b4ca3562e9",
+ "df1a2d6a963a79c58401770a383248b5d70bb4adedcbe520fed634f513b8c2ea",
+ "6ab37fe633ba7302",
+ "a5db6c2aa209e24478fa1bd6f6ffabe98555e034342cbec07364c54d1e407e282ef08edbfdbde936c9d42df58ae15889f5c939a3087eaeac1f2a58e2c2763d01b5",
+ "69239a9ce179621b",
+ "fd09781721c44cadcc4286a6c06f1831934c371e56f66f7e30f28425c65c28b7673bfd8a3f924c4db345b15b385e05b1d8262935f73b26bffa8c327be97fae7749",
+ "ddf049c971cd99f694e3b2a5e25fa37aedf01bf32e7c679a3187e22a635d301c",
+ "e98ad000ca301049",
+ "f2e891e403250c3358fc2030b227bb96e93b88f419afe9f9d660e013761228051ec5a8f0c093b33fc60e2cd7a9c845434e95d4319d79d1bdaa8f73853fbd9958e9ffc23a0ecbb7b48dbba63672d582bb83d92249800324cbc9a6e5b37d36887e7c79093f58ef8f1a001585321bfee1714260dd6130cc768d20b14d3850f0ee",
+ "7e3639fb14f22b46",
+ "2bb10ad9f818fa3928d24eff4b44db7fbad65b78d0c9022c0748cff53ddc9dbf158987739cb3779ebe1b877febcd8ba25f0e0dc5afbde8a550c30059ef72bf9ca8ec166bcf015d95e6a327da53ea626d71e7b8ff61f1780ef4ba9a8e7fd6e92c762834ba57cc8bdd952a8fbb99f415ce4999fce4d5a314d62288544048edcc",
+ "f349110e751c16cdb5ed05516df17479937d942c90eb1fb1813062bd3f3f6b76",
+ "68cd8fd3afce0cc7",
+ "529b87dfc58eceb951e1e53d9e94793329199c42d004bc0f0dab3adf0cd702e99efa5ef6e59d3b201680f8e2d5a4ef7f23f1b6a8e102670a3829a995ae23fbc3a5639e028cd2b5f71bb90c7a1e4a8a05017d26e3afc3a88541f6c3f45d71f8a3cc31a063ea4aad1b4d00db6f5228e9b9b1561a7f61812b8b79e6af4292580d02",
+ "f8f7da8f9106fe6a",
+ "95548a60e1774d3814da2f4e6d05f71463396f3b02dcfe4f47ce9ec0d88485396ea51ef6164758dbfef8425bd303a5328f79cdc5cdcc27a533134bde8bbd5b67d54af624827cab5454128e3000bb655e2f402b5fed18cad64a679e0966a9a14bb69312b0e6cd922c90778629163e9635a3610986ce9eea32d613a1674e438f0d",
+ "ea4f6266d04244303304510272e383eaa51a8ea7099a74bafa3375b210653a0d",
+ "2f40b15afd725cf5",
+ "065066be1cb803dc158865ed8d7cca72dcf2b7c6b5d0d045bf32b063d3da484ba1843e071b61c49ce7f30ba18a4f7ef2730ecd785494839966f593168e17311913753c59593fc66cb664c1572251132fc28bf37fd8e96f2327cf7948a1126fd37175a91f483d6b3ad92308df7e6daa8bf3efde75f80ad72a49ae0794009e21ad",
+ "ffffffffffffffff",
+ "9e3d7360a50fffcae4e9ec400fe957a4fb41bf1751bcdf55ddd09355cdd4bf1c0d01dfc30f33f84bfc067b7b5509e5c7edc4c44493e6b83d92cbb868193f7c6a1b919c1b7bf15e8365e9d254da9a73471b956bb1f4e18ac40ab7b732b33a5a20ee113146e6c8a1cc9380ca4b53d17fa0f73a4d09d13aa47bbf57a3ae1e8472cc",
+};
+static size_t nb_chacha20_vectors=40;
+static const char *hchacha20_vectors[]={
+ "e4e4c4054fe35a75d9c0f679ad8770d8227e68e4c1e68ce67ee88e6be251a207",
+ "48b3753cff3a6d990163e6b60da1e4e5",
+ "d805447c583fd97a07a2b7ab66be621ad0fa32d63d86ac20588da90b87c1907b",
+};
+static size_t nb_hchacha20_vectors=3;
+static const char *xchacha20_vectors[]={
+ "e4c4054fe35a75d9c0f679ad8770d8227e68e4c1e68ce67ee88e6be251a20748",
+ "b3753cff3a6d990163e6b60da1e4e5d6a2df78c16c96a52d",
+ "",
+ "e4b5efc932fb5798",
+ "",
+ "fb5598218db71deb473f7d04c152e7e857736715dc7b788aca39a3c96a878019",
+ "e8999c815c5723dbfbde05e6c71f118afc0dedb5b9f8dea3",
+ "98",
+ "c6f8a1251f9ad994",
+ "ce",
+ "fc169964a5ae985e6c11b0b7bb18a51fd77fbffd722aa220efdd8947ca5a5c7f",
+ "b1c2ebdb9ad1f603801ff22e80314f716af9c22022fa159d",
+ "bb4b4d3153f999b20ab4769eb1d01c057c5295ed042b4536561dce32478b113adb5b605cac75bcfcacb5e3e811b78e72e398fdd118bf04c6a7ed0756a3533e",
+ "35641c67031a10fe",
+ "dfd9414fa3546744b8fb2b4f7c83d8fcdb452b7f07704916e17bac8b7696c54ccfa3401a6bfcbebacffd1559db8150ceb7ea2a963ac1f434b498b1a79d2fc2",
+ "a20eaf3fff7b372aa801eb98a1298bc61028073750831c8cb43cd6822bf3f6fa",
+ "e0801cb6c843d8066b07346635365fb7d6ee54e5c9cd6f05",
+ "d76b2bd4caec8d80b58235cb4268543ab0eb865a948cc5b5f6e31f05f8146bd9495acc459d6d200005ee72c3bc3e4ae3badfd79adfe46b2ae1045f78382e04c9",
+ "bde0e2149cc1f90e",
+ "f90ab4866767e8686ae1cddd6a607dd8c733522163c4584af07db2e0211d2f81eb4a52b87acfa895188d10ec16c9d21a0b7f20a82342e15a0f23de0d773a8f1f",
+ "7364c54d1e407e282ef08edbfdbde936c9d42df58ae15889f5c939a3087eaeac",
+ "1f2a58e2c2763d01b55744c4a65f4db93adff0078c63f090",
+ "fb607a90c87defd622e5f55977877cec9ed88312b0411228540cd6dde6e84cd2da59b1871db119e3298e3c12fe8200a47eddf049c971cd99f694e3b2a5e25fa37a",
+ "c0a356c9d7da2928",
+ "1fa0dc38852769722f14441e859df73a36ae6f6b256c425216a513e8a79b665e8204b68f8b5b382f0e75691fbdfa6a10e907f30ae0b1f22c9414cc8bd1e4ec926b",
+ "c60e2cd7a9c845434e95d4319d79d1bdaa8f73853fbd9958e9ffc23a0ecbb7b4",
+ "8dbba63672d582bb83d92249800324cbc9a6e5b37d36887e",
+ "7c79093f58ef8f1a001585321bfee1714260dd6130cc768d20b14d3850f0eec0f8f349110e751c16cdb5ed05516df17479937d942c90eb1fb1813062bd3f3f6b7668cd8fd3afce0cc7529b87dfc58eceb951e1e53d9e94793329199c42d004bc0f0dab3adf0cd702e99efa5ef6e59d3b201680f8e2d5a4ef7f23f1b6a8e102",
+ "3f21afec4e3df4a4",
+ "524ebd3d892718d9555adc88e62237fa93ec714653e2d0cb84a88a46a0f6865240e9123983b8cfa41eb0c2b9aa4ee27a5e602336a9b1d54a52c31b25dade057f3321110ff8ede0c19cf7bfadabef7a5a7ada92bf56eeaee9e93c888776776520bd31ceb14516c6dc4e25d17c46782521d623abce87d6b9d988c540ffd5668d",
+ "3829a995ae23fbc3a5639e028cd2b5f71bb90c7a1e4a8a05017d26e3afc3a885",
+ "41f6c3f45d71f8a3cc31a063ea4aad1b4d00db6f5228e9b9",
+ "b1561a7f61812b8b79e6af4292580d02ea4f6266d04244303304510272e383eaa51a8ea7099a74bafa3375b210653a0d2f40b15afd725cf5065066be1cb803dc158865ed8d7cca72dcf2b7c6b5d0d045bf32b063d3da484ba1843e071b61c49ce7f30ba18a4f7ef2730ecd785494839966f593168e17311913753c59593fc66c",
+ "0afe555385d4d096",
+ "5a5cf61ddefcff1426cfc248bd07216e213c6cbeb856764392a54beacd598af988fddaf75a609627199ff7844e6ed02d7dbd9b9291e0b80766fd26081051a32acfe495d7b5591a6877711f32f32504aa09d083f000dd3af4ade4c220232f2a27e34c0ec37fe6a23a0907c21c5bae0d8e665d958a33c97e3cd14ebe1628780afb",
+ "b664c1572251132fc28bf37fd8e96f2327cf7948a1126fd37175a91f483d6b3a",
+ "d92308df7e6daa8bf3efde75f80ad72a49ae0794009e21ad",
+ "33fa4141fe5fa79fed12f6a20f51614dc130f45598e92549b113ed6185724507e7fa5a7e8a75b2c7a3ad700919f36a46ea0ffa680857e30188f8a03c7c4b6c11bc39aececec26687233682d31887277028e2fd286f2654c681efd9e7ed6b340874e897337d4dcc672811a6cf4b69086e0a57c266424dc1d10ecbaf0c822cce9e",
+ "ffffffffffffffff",
+ "a083f3ceb75dc72484a0c11be30aaf42f1a0b009c9ada2da6e70fbd976e246783cd3124a46abfdc15c526ec66f2bd56dc585e419388e246ebe42dd93727f32cd463b6613563bc4aacbc55c4715ca9a8327310bdc06ed6f93e0e10d96a2f52a41af8d371f3f5bb5530ebf4ed47b9eab99d188b00db9b904c17c3a4cb67eed39c8",
+};
+static size_t nb_xchacha20_vectors=40;
+static const char *ietf_chacha20_vectors[]={
+ "e4c4054fe35a75d9c0f679ad8770d8227e68e4c1e68ce67ee88e6be251a20748",
+ "b3753cff3a6d990163e6b60d",
+ "",
+ "e4b5efc900000000",
+ "",
+ "299aa254a4606ab6a058e0c6fb5598218db71deb473f7d04c152e7e857736715",
+ "dc7b788aca39a3c96a878019",
+ "e8",
+ "1ff716fb00000000",
+ "6d",
+ "00172655236cddcd1879ca1f04b35f91adab70b81f504035fc169964a5ae985e",
+ "6c11b0b7bb18a51fd77fbffd",
+ "722aa220efdd8947ca5a5c7fb1c2ebdb9ad1f603801ff22e80314f716af9c22022fa159dbb4b4d3153f999b20ab4769eb1d01c057c5295ed042b4536561dce",
+ "3b6ce3b400000000",
+ "73d5bf251bb890245618a856cb3af96b306aa9febdca3718b4e1ae73a2131ebec185c7c130ffb0f071effed10dfe02e6662b78717580588ac79184e2809743",
+ "6862df6d2458d6c74739a0ad2169b9c89edd74e16fbcecc748c25dc338041fc3",
+ "4af0f1bda20eaf3fff7b372a",
+ "a801eb98a1298bc61028073750831c8cb43cd6822bf3f6fae0801cb6c843d8066b07346635365fb7d6ee54e5c9cd6f05d76b2bd4caec8d80b58235cb4268543a",
+ "47fc612f00000000",
+ "0924676a2306556857bc3a0ca6b9f2444acc66a89a0135538bd1fc61f09c7d11a973e75b6a76162f9a5a592b40094953594c659eab3ec361217879039d8f8ed0",
+ "d70bb4adedcbe520fed634f513b8c2ea6ab37fe633ba7302a5db6c2aa209e244",
+ "78fa1bd6f6ffabe98555e034",
+ "342cbec07364c54d1e407e282ef08edbfdbde936c9d42df58ae15889f5c939a3087eaeac1f2a58e2c2763d01b55744c4a65f4db93adff0078c63f090fb607a90c8",
+ "b5be810500000000",
+ "204f9f415e1fab31f4b743d4b21f0089828eea2709dd31ca4a5071bbfd9820a64e1cda8ab1bfcb1f850064ae630d5225e2cf7e74935b19e9710f6ebc484bde29c2",
+ "2e7c679a3187e22a635d301ce98ad000ca301049f2e891e403250c3358fc2030",
+ "b227bb96e93b88f419afe9f9",
+ "d660e013761228051ec5a8f0c093b33fc60e2cd7a9c845434e95d4319d79d1bdaa8f73853fbd9958e9ffc23a0ecbb7b48dbba63672d582bb83d92249800324cbc9a6e5b37d36887e7c79093f58ef8f1a001585321bfee1714260dd6130cc768d20b14d3850f0eec0f8f349110e751c16cdb5ed05516df17479937d942c90eb",
+ "f3eb9eb500000000",
+ "fc5cce90cf9e250d87703d4fee5b2089821b7d2c5c1620c0a157090831735e156a42a5c97c2d3a2a939f85eea8d013c859bd21827be0db1393e5f977f8f261c413934c84e7d2e9297958bf608a8b82825690bd25bb6d6938c3c60a0cf541191a03f9c8e78151fccd55ed0b73f30dda9561fae06eac7c4e286950e609633282",
+ "813062bd3f3f6b7668cd8fd3afce0cc7529b87dfc58eceb951e1e53d9e947933",
+ "29199c42d004bc0f0dab3adf",
+ "0cd702e99efa5ef6e59d3b201680f8e2d5a4ef7f23f1b6a8e102670a3829a995ae23fbc3a5639e028cd2b5f71bb90c7a1e4a8a05017d26e3afc3a88541f6c3f45d71f8a3cc31a063ea4aad1b4d00db6f5228e9b9b1561a7f61812b8b79e6af4292580d02ea4f6266d04244303304510272e383eaa51a8ea7099a74bafa3375b2",
+ "b105c7d100000000",
+ "83824a7cc37786be9e636041aa7bb26f3dfe8ac826f43be45d7af3295093eea6a9bad5a097ba87d1604efb35e400234ddebc6d5a9c54e2de8d070d399602d5dfce8c74d1a2902d48ee4b9e430f2a12ed03290f8176e39f4dda73c71bdc03bf0c91d5d59f45fb3cd841adea8371820cc1c097b3291777ff0b5f6e7b60dfad863f",
+};
+static size_t nb_ietf_chacha20_vectors=35;
+static const char *aead_ietf_vectors[]={
+ "e4e4c4054fe35a75d9c0f679ad8770d8227e68e4c1e68ce67ee88e6be251a207",
+ "48b3753cff3a6d990163e6b60da1e4e5d6a2df78c16c96a5",
+ "",
+ "",
+ "b5ed4c7e63a144f105dbe2b039c7e805",
+ "8019e8999c815c5723dbfbde05e6c71f118afc0dedb5b9f8dea398b2d764bca6",
+ "8dfc023a9821939d389e38a072cf1b413bb1517c3fe83abe",
+ "",
+ "86",
+ "374190382975907a68e8a341faa0772aa0",
+ "f999b20ab4769eb1d01c057c5295ed042b4536561dce32478b113adb5b605cac",
+ "75bcfcacb5e3e811b78e72e398fdd118bf04c6a7ed0756a3",
+ "",
+ "6862df6d2458d6c74739a0ad2169b9c89edd74e16fbcecc748c25dc338041fc34af0f1bda20eaf3fff7b372aa801eb98a1298bc61028073750831c8cb43cd6",
+ "9ef6887763d27d843103a44f9b2427e70769050e09c5a6453280159a6eef522bf4540e3d559aeaace7b339c98520921d380faf3c64b2593792b2a7d53d42ed738df4a729d618649a190338bc41e4a5",
+ "9d6d200005ee72c3bc3e4ae3badfd79adfe46b2ae1045f78382e04c969df1a2d",
+ "6a963a79c58401770a383248b5d70bb4adedcbe520fed634",
+ "",
+ "34342cbec07364c54d1e407e282ef08edbfdbde936c9d42df58ae15889f5c939a3087eaeac1f2a58e2c2763d01b55744c4a65f4db93adff0078c63f090fb607a",
+ "01c2a664d680021a34b1353258d2a8d16773c68db39d8c0de0dce962a5f0ddc13f78a1a6fa74cf500e78820c19252c4a2a1ecf987de69651a31bb390f3319ad658e136a56e0a0140cef60e9af8ad7392",
+ "1bf32e7c679a3187e22a635d301ce98ad000ca301049f2e891e403250c3358fc",
+ "2030b227bb96e93b88f419afe9f9d660e013761228051ec5",
+ "",
+ "c23a0ecbb7b48dbba63672d582bb83d92249800324cbc9a6e5b37d36887e7c79093f58ef8f1a001585321bfee1714260dd6130cc768d20b14d3850f0eec0f8f349",
+ "d00030016722e4e1c20592a0f643bbe63cfa22b937430eaca5058f19cc86f45269785e8a6fb2247b1beb510ac1b3b5d8ddf42eb175c95c9d0d9603189f8f41c850c875a2f9ab9451f418f1c102e64d5fe0",
+ "ab3adf0cd702e99efa5ef6e59d3b201680f8e2d5a4ef7f23f1b6a8e102670a38",
+ "29a995ae23fbc3a5639e028cd2b5f71bb90c7a1e4a8a0501",
+ "",
+ "561a7f61812b8b79e6af4292580d02ea4f6266d04244303304510272e383eaa51a8ea7099a74bafa3375b210653a0d2f40b15afd725cf5065066be1cb803dc158865ed8d7cca72dcf2b7c6b5d0d045bf32b063d3da484ba1843e071b61c49ce7f30ba18a4f7ef2730ecd785494839966f593168e17311913753c59593fc66c",
+ "4c56ae846df2a22857d81f76a6dd614c09ca92cbfbbe7423e4a6a1fe4dd6faa31bbce300be08b2ffe49f186214675e36a25d57c74611534dee35b301ee5e00657911b161a3060bea0871cc726db66d11e1dbbd5def385dc0c953914ca8eac6129563ac4bc47e39e65d8d276eb0b099576b542f2ff787c27789e565c4fbe46da193c11495f10a08f64fb026b482da54",
+ "64c1572251132fc28bf37fd8e96f2327cf7948a1126fd37175a91f483d6b3ad9",
+ "2308df7e6daa8bf3efde75f80ad72a49ae0794009e21ad33",
+ "",
+ "fa5a7e8a75b2c7a3ad700919f36a46ea0ffa680857e30188f8a03c7c4b6c11bc39aececec26687233682d31887277028e2fd286f2654c681efd9e7ed6b340874e897337d4dcc672811a6cf4b69086e0a57c266424dc1d10ecbaf0c822cce9e4f17b19e0ece39c180a4c756c03c19900280ff6cdebe5174d507c6e0860c38c353",
+ "e16c5303bff1085eae99ecfcca64e07ec76709b336598c9c4276a88e2ac3106630ec7b0f4fa2b455fd448945fe65798da3c8715df79b27f94dafd5a27ca47b6672149962cf8b8f019c4a93c71902dd3b2b8d9cc4bf2ff30d50f18480120bc638c6fa7397691aae3898bdf0a0f3dcbd749d03b8429cc1eb624c67d1acbce58a32a8adcb5bd809bbbb960f3fa8bf380e9f",
+ "7176c58965b74a56c52b3151bb8a149cf4f82158d57c823f3a90c6b427912226",
+ "ff604d9abee1fb8c8d35530a0cd5808e53e308ac580f7318",
+ "",
+ "6477fbb05c7c35956c3c0c5f342355fa",
+ "cb399b45596ac537bdb1cae9d439e26ba530343ebb3bebb73a238af37efe26fc",
+ "543894006b73f3d70fc04b15d0c2a5dfa650be5044fb5061811b866be7f9d623",
+ "fcb077ee19421610aeb263c57faef00662d424c07a7aa500",
+ "50",
+ "ab2911b42074414e387d7247fa505548",
+ "edeb2fdf5d7d9bf5d638973886aaf2b1ee4fc2a15ebc04c8a6339b1c3344ece0",
+ "62d3d607d6bf63c6760b802483b0e3aaa9dd4f79c6c5e93e6b51da45018c6bde",
+ "108f81f9abfa23640b83cfe3fed34bcf6640bf0baf647daf",
+ "e9bc99acee972b5a152efa3e69e50f",
+ "3786aca4c6b7e224163ea928771fde37",
+ "bbab31c2ba755007513a20995cc9d43998f7d9395a83284ddf4348ecb4830859",
+ "c2f8b252a18a29c44dbfbb62cbe6c3dfd4db55378734d8110b8f20f1d1ada6dd",
+ "d4da48fb09c06580eb46bbc5ca62bfab40b184271b73b710",
+ "d40cb63435042c9b526d1e5c3a77bfc5",
+ "11dd1e876f527d81ec81df06c7e426b7",
+ "c5023859611cf67a39bffa690d2f839429b23f99a17ec58e5d43b3e1eefc35c3",
+ "820032e031949f1e97e8ad5eb5a75cc805900850969de48e74267873d65e0d67",
+ "482d1c6f9a22450bff02814b8626a89534495c3bc3c8897a",
+ "096fbc2f9e50fda78ee3c8b0fb60231ae5",
+ "01ee35b10ac1efa06855ef67ece02508",
+ "0e9772515b51f4e6fa8195611dfafa65146bc05c66f1e8e0be1f1678a1e101d9",
+ "9849fcae816135f8ff7c83156a36aebdd8b11b679e1325659890870da65bd4c7",
+ "90ceb7351cdf29dbda3e68c2d64c04c7da7340fd622e6be1",
+ "4bd10d4003b8cf7e956bc847cfb0dea015d884f5761e9dfb9b2cfc2a8b4032",
+ "2aa92e5bd6515817db7d15af98806caa",
+ "17c4b7fa1f5bf1e69e882d760b303c74590a31d338c87d608786cc6443c8d32a",
+ "b118784e65a1f1d1964af9a24f53e3bcfe779241591e2c385be3b579780c5cc0",
+ "c490bc2ed9f06e129c52d57da020389a30134a40ddbf13e7",
+ "16a1f84335380b528cd7b6d29fbb5d7f97699f3c6d9284e1ef22fa05ad1f6ab7",
+ "99f2ed1a1d0611de572c0e8623d674bd",
+ "77b0a34ca0404238bdbe8e82a0b52a3cb62d441b580a49e81027fed18514c7d5",
+};
+static size_t nb_aead_ietf_vectors=70;
+static const char *poly1305_vectors[]={
+ "e4e4c4054fe35a75d9c0f679ad8770d8227e68e4c1e68ce67ee88e6be251a207",
+ "",
+ "227e68e4c1e68ce67ee88e6be251a207",
+ "81ac001b08d6577bd91ce991c4c45c46bc84d5465fc9139bf17042ae7313181f",
+ "7a",
+ "403bd4853fd1c55af2077780de9c1284",
+ "4a70a7e992b43e0b18578e892e954c40a51abdb5a85d300c32f391c45d6ef4db",
+ "043ddcf4214f24ea6ef6b181071f29",
+ "ff3de42a679eb874a5d4525abf3078fc",
+ "1deb473f7d04c152e7e857736715dc7b788aca39a3c96a878019e8999c815c57",
+ "23dbfbde05e6c71f118afc0dedb5b9f8",
+ "1d07a51dfe091076038f397099d15eb0",
+ "389e38a072cf1b413bb1517c3fe83abebb1cdf3a218abb1b0c01da64c24f59ee",
+ "d19cfb8cb3940aba546f0be57895e2cc86",
+ "320f841c889560a5dbee77df34ecd50e",
+ "e5d73f1c8c5376c1220ff3d9d53eeb65cc53599f40d6c8348c353b0017265523",
+ "6cddcd1879ca1f04b35f91adab70b81f504035fc169964a5ae985e6c11b0b7",
+ "32cefab76877cdd41a99c813d0a1ab15",
+ "18a51fd77fbffd722aa220efdd8947ca5a5c7fb1c2ebdb9ad1f603801ff22e80",
+ "314f716af9c22022fa159dbb4b4d3153f999b20ab4769eb1d01c057c5295ed04",
+ "6909e2774445104a4a0bc810da0ceb0d",
+};
+static size_t nb_poly1305_vectors=21;
+static const char *blake2b_vectors[]={
+ "",
+ "",
+ "cae66941d9efbd404e4d88758ea67670",
+ "e5",
+ "",
+ "2a294c4a9c276126c47e584eaf7e3396",
+ "f8146bd9495acc459d6d200005ee72c3bc3e4ae3badfd79adfe46b2ae1045f78382e04c969df1a2d6a963a79c58401770a383248b5d70bb4adedcbe520fed634f513b8c2ea6ab37fe633ba7302a5db6c2aa209e24478fa1bd6f6ffabe98555e034342cbec07364c54d1e407e282ef08edbfdbde936c9d42df58ae15889f5c9",
+ "",
+ "b28674d2dfede11f76e50f0e3081d74c",
+ "a63672d582bb83d92249800324cbc9a6e5b37d36887e7c79093f58ef8f1a001585321bfee1714260dd6130cc768d20b14d3850f0eec0f8f349110e751c16cdb5ed05516df17479937d942c90eb1fb1813062bd3f3f6b7668cd8fd3afce0cc7529b87dfc58eceb951e1e53d9e94793329199c42d004bc0f0dab3adf0cd702e99e",
+ "",
+ "663115a7fe0e0085cadf1818fa03421d",
+ "f593168e17311913753c59593fc66cb664c1572251132fc28bf37fd8e96f2327cf7948a1126fd37175a91f483d6b3ad92308df7e6daa8bf3efde75f80ad72a49ae0794009e21ad33fa4141fe5fa79fed12f6a20f51614dc130f45598e92549b113ed6185724507e7fa5a7e8a75b2c7a3ad700919f36a46ea0ffa680857e30188f8",
+ "",
+ "ff0a0433af77b0676a43e1e69b9294d7",
+ "6477fbb05c7c35956c3c0c5f342355fa0850307998642501c025e3873ebac3ccd749d8379ae6d830f785ec104897bd723d34ad20c9d36bfe371df46aebc6d4595d490a770bee4dd0be6a5a0b5e95645c7dcbc03c27010df3320fe75b0a3ecc8983ad94217e80348fd0f3f54e54b95bb548dc2225a264443732b41b861590358d543894006b73f3d70fc04b15d0c2a5dfa650be5044fb5061811b866be7f9d623fcb077ee19421610aeb263c57faef00662d424c07a7aa5005068b262251c0667a4e2e4b12f5df7f509564517887e370b425fabab1ce9e733ab2911b42074414e387d7247fa5055489bbd4b7d4de256de723566c1c2d3ecee8c10e7d98233db",
+ "",
+ "fa15fe1df94964869810a57fa2c9f82f",
+ "7c12457eb5614f87f1fdc40118906d02c602059d48ae05ae62d3d607d6bf63c6760b802483b0e3aaa9dd4f79c6c5e93e6b51da45018c6bde108f81f9abfa23640b83cfe3fed34bcf6640bf0baf647dafe9bc99acee972b5a152efa3e69e50f343bc12887fec8e70db73b4b48dce564d83786aca4c6b7e224163ea928771fde3778c453b35d98deced812fc5685843565b73d097601d3558278bd9d7327de5fdaa2b842050b370e837ef811a496169d5ff768878766c08c45561fdc2aad6469c11380c3d3f873c7233c541ea4c43824ecd8bf7e11ac8486208fb685218d46736e51103d1fae0e8e368f25480ee7328381c2f8b252a18a29c44dbfbb62cbe6c3df",
+ "",
+ "50089bdcf51629a715eb1b3345a0c2fc",
+ "b3451318590c84e311dd1e876f527d81",
+ "",
+ "13e40814a705dac02c3a1de24eb9e6cf",
+ "8a52102e2903352b5ec66cbed7474a91",
+ "96",
+ "ef0733ef5b4381bad3b00a6269bbc282",
+ "97699f3c6d9284e1ef22fa05ad1f6ab7",
+ "0d200c182251f5a9cafbc17c4bdacb3411651e4088dec905251ae93c899860061d340da02e519a254e109592caae83d46aad5dd4338e034f0660693ea9e691",
+ "6318f617c6c8788bcedb7177635a449e",
+ "5cd890b165ef0445d3b75055261be279",
+ "5c9fc34bf3b7633130b5341dc0560406d0f4ab5110a8ab1417e4127d459157b58b20256edf901d5a8bc0f71f6898a6b1d0818edb2f561d3219752a709abaa318",
+ "264f2e37d05f658f60d69b312abb90e8",
+ "b5f0c69568656661fbcd3bca40b22c65",
+ "",
+ "",
+ "aeb71797e433c16ed303017030b2d85b",
+ "",
+ "01",
+ "7c72d9947280f5c974ff04857caecab0",
+ "",
+ "2bfb488870d7a53f5bb5f3bc72b1433ae7908408d237fb4601141e3f07e0e445a8725bd48c0d4f1ba8a7c4923258d6ef90d598af6020a1a3e5eddb5c51cfbd",
+ "48fbca32ec758a3b09ebd2a19e6d91ae",
+ "",
+ "6111d2b0526416d0aac7112a7003391899c7eae8615d2778f3d053d6eab255bbcc2186267a67b540e5825f6d5d950c2f36d5588b45b6a113908ad73f6da77ff8",
+};
+static size_t nb_blake2b_vectors=45;
+static const char *sha512_vectors[]={
+ "",
+ "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e",
+ "38",
+ "bc23b8b01772d2dd67efb8fe1a5e6bd0f44b97c36101be6cc09f253b53e68d67a22e4643068dfd1341980134ea57570acf65e306e4d96cef4d560384894c88a4",
+ "ca43cdd4eb7173476862df6d2458d6c74739a0ad2169b9c89edd74e16fbcecc748c25dc338041fc34af0f1bda20eaf3fff7b372aa801eb98a1298bc61028073750831c8cb43cd6822bf3f6fae0801cb6c843d8066b07346635365fb7d6ee54e5c9cd6f05d76b2bd4caec8d80b58235cb4268543ab0eb865a948cc5b5f6e31f",
+ "0c7ea31f5fa48e7c869feea1ae0069f7327d1189019576688f76a222558ed18fc18e420655adac27f7e1659a8b196b30a6c705a99878219f90da7f2ecc6a8c0f",
+ "a3087eaeac1f2a58e2c2763d01b55744c4a65f4db93adff0078c63f090fb607a90c87defd622e5f55977877cec9ed88312b0411228540cd6dde6e84cd2da59b1871db119e3298e3c12fe8200a47eddf049c971cd99f694e3b2a5e25fa37aedf01bf32e7c679a3187e22a635d301ce98ad000ca301049f2e891e403250c3358fc",
+ "39b3208cddc3275ec7857fb8fc9e48540977ea6c0665248f7164f87b5a640ef300d7bb21d82db9b5b585b5ce82dcbcb7ae4d6883a6bd6e3175b9a6249c8a6d88",
+ "ed05516df17479937d942c90eb1fb1813062bd3f3f6b7668cd8fd3afce0cc7529b87dfc58eceb951e1e53d9e94793329199c42d004bc0f0dab3adf0cd702e99efa5ef6e59d3b201680f8e2d5a4ef7f23f1b6a8e102670a3829a995ae23fbc3a5639e028cd2b5f71bb90c7a1e4a8a05017d26e3afc3a88541f6c3f45d71f8a3cc31",
+ "8df0329b3dcb8510808919ddf8064b96bb641cad8160a22e7abfdad9433a86c62edbd2b6a46ee18c5e0391c06c51d96e3240028c7c4aa2c25dc77c1b72a2e0ed",
+ "f593168e17311913753c59593fc66cb664c1572251132fc28bf37fd8e96f2327cf7948a1126fd37175a91f483d6b3ad92308df7e6daa8bf3efde75f80ad72a49ae0794009e21ad33fa4141fe5fa79fed12f6a20f51614dc130f45598e92549b113ed6185724507e7fa5a7e8a75b2c7a3ad700919f36a46ea0ffa680857e30188f8a03c7c4b6c11bc39aececec26687233682d31887277028e2fd286f2654c681efd9e7ed6b340874e897337d4dcc672811a6cf4b69086e0a57c266424dc1d10ecbaf0c822cce9e4f17b19e0ece39c180a4c756c03c19900280ff6cdebe5174d507c6e0860c38c3537176c58965b74a56c52b3151bb8a149cf4f82158d57c82",
+ "1afec592c116573a7acea54c46ad42c5e589a546d0afbe7dcabaacaedf163c3f9432b525be87813744b88c9b7b7f640735ff6de8f5e968e2c8de289785fa1641",
+ "3a90c6b427912226ff604d9abee1fb8c8d35530a0cd5808e53e308ac580f7318fe2ab2a4933b5d90db718aa3440fbe9ba17f09716219bdffc93a189e410a6a3e6477fbb05c7c35956c3c0c5f342355fa0850307998642501c025e3873ebac3ccd749d8379ae6d830f785ec104897bd723d34ad20c9d36bfe371df46aebc6d4595d490a770bee4dd0be6a5a0b5e95645c7dcbc03c27010df3320fe75b0a3ecc8983ad94217e80348fd0f3f54e54b95bb548dc2225a264443732b41b861590358d543894006b73f3d70fc04b15d0c2a5dfa650be5044fb5061811b866be7f9d623fcb077ee19421610aeb263c57faef00662d424c07a7aa5005068b262251c0667",
+ "4bf909661a603c30199c63eefe96ac7b5489b2790c47db8f97b99cbc0fb4701831f7682d34302415974ff3f8e43f2592c6ce2c6e8a5518c3468a4cad6699ec35",
+};
+static size_t nb_sha512_vectors=14;
+static const char *sha512_hmac_vectors[]={
+ "",
+ "389e38a072cf1b413bb1517c3fe83abe",
+ "9689b839211c1751e1faee45edd4662c6102049ba76c3eef46a28cc268818cc54b8955b68dfd17d6f0993844bf9952f6158aa2c3fe780e6a89d975597a504ada",
+ "ca",
+ "a3087eaeac1f2a58e2c2763d01b55744",
+ "3c0119c12ed65c15b5343bcbf0d04a1b22c9957f3aedfb07d1d3dea5158c4f133efddbbff90e17733d5853818c9af7fafec2dd280f0e27855dac473cf30abe0c",
+ "ed05516df17479937d942c90eb1fb1813062bd3f3f6b7668cd8fd3afce0cc7529b87dfc58eceb951e1e53d9e94793329199c42d004bc0f0dab3adf0cd702e9",
+ "f593168e17311913753c59593fc66cb6",
+ "a62e149fef7b91b9c7f327847d81179a4bec216d30bc005d7a4708f84e2cd35ddc3ea8eb51e1bff209d07deaf5e88ae0900c7203db57dd372ada435a5518e2b6",
+ "3a90c6b427912226ff604d9abee1fb8c8d35530a0cd5808e53e308ac580f7318fe2ab2a4933b5d90db718aa3440fbe9ba17f09716219bdffc93a189e410a6a3e",
+ "a4e2e4b12f5df7f509564517887e370b",
+ "276785363a14f38d660d635dfa42ff079af139e9901f91f29240275fbf290a7320e1df5778a9239bade44c90bfe5e3d50d99fdc0570359a472bc931a123a7e19",
+ "78c453b35d98deced812fc5685843565b73d097601d3558278bd9d7327de5fdaa2b842050b370e837ef811a496169d5ff768878766c08c45561fdc2aad6469c113",
+ "60fa0114802ee333d7c49ccaad8108db",
+ "d31bba716cf3bb1d322ce9e4e6cda884845a16db546a90dd5bef2fe7bb836bad8e995f743a978dab6b11ee31b6c8bff2f2d747408bc54c7a75c049e243565470",
+ "8a52102e2903352b5ec66cbed7474a91d7ca3f49fdc859b3e1705e1e05b124789849fcae816135f8ff7c83156a36aebdd8b11b679e1325659890870da65bd4c790ceb7351cdf29dbda3e68c2d64c04c7da7340fd622e6be14bd10d4003b8cf7e956bc847cfb0dea015d884f5761e9dfb9b2cfc2a8b40325a2aa92e5bd65158",
+ "964af9a24f53e3bcfe779241591e2c38",
+ "3cb55d24a444711f3312818fb019b9c29842271896abd68413aaa6d13771c9a9997e332e36bc6cd8882dda982ee8ba1e102a6f01a996bef3bf8ce3393cb02b4d",
+ "f9b8e57564807df84a1d2143003c7c31c1ecfb0fa02c0a88f9b13f45f06f30ca463cba3d090f62651ef12368bee0db5fba7b79b95fb51289e4ba9be86c19cb700d200c182251f5a9cafbc17c4bdacb3411651e4088dec905251ae93c899860061d340da02e519a254e109592caae83d46aad5dd4338e034f0660693ea9e6914e",
+ "23ca891e5af07c3e5c47a168e79af48f",
+ "36e2a5fd3e8b2560e24ba08002469a98c50f56080e4cb18665dc1c7dadd9ec73664298a0d852504f5b3c1633247a41e47744915780d899e3e2afe14b86ab29ed",
+ "96fce921032289e9e686d8f207c5b4e7273feadd17d02148810c33e07dc7d92b6b034b4c953b7e0900da7170bbca5c72ebbb007959720860a69357ca495148faa1e5924ab091d3fb4996c3efc3c48b123a08998c55223a940e3fa0bbe1b1f4bf2ec798c3209c6cde322b5b08a73544e078286a8e5b7177019b72dcbe98d2a1280b",
+ "aeb71797e433c16ed303017030b2d85b",
+ "5c87ad41b5e45e91fce3a756fdb2382916fc2c7d6c00277db52bc4c3d8d1a93ebfd18497af4186e7f2d3c40de52094100681fe58a5fded5510b5dff983e75db6",
+ "",
+ "",
+ "b936cee86c9f87aa5d3c6f2e84cb5a4239a5fe50480a6ec66b70ab5b1f4ac6730c6c515421b327ec1d69402e53dfb49ad7381eb067b338fd7b0cb22247225d47",
+ "",
+ "dc",
+ "cfd55a01855eddd5746c64f58ce5fc5e002cd28632c3224288dbe816ce8fb370b2b355ca7ea0eda2a4f75395db7b94b2b06688811f0d7733122189589f82b437",
+ "",
+ "481e1604d2e5dfcf0d9943ae21d6efab804755197bff9f24eee982b0f9089288cf7b4570ac320b344f4f70f31f530c2312db5b7241651d361a91f7986db3922aabcd660b88d14c1c1601492321379521c1e4274d661113338c8a5b98d6c12d985f1b73d5b3d7592b2d0ea7be0181ae20d09d6051782c35c8537a597818b5a8",
+ "8fe0c5422e148c351107dda1e696bccbfdacd9c4b21a63b0ecb36d45864eaa72963c0be609fa9ca9500171ac785c19e5929c141cd1f6cee605f05bab8809ef66",
+ "",
+ "a46ff45937e5f0c485c88631147283987321c85d4a447015bdb4c7921a6e927b6c8b7f7e40a17eb87f1874b7c50225d8544a01cc2cf0ed8c30c3dcf2ca6ff3ef75798ff9253562ecba3e7e42a43c6fd74a3c4330ea178daafa0532305e8356f1aa5f91ca91dcda75d7167e1585e0211eb3b78e6be0cf50209ab6747b4a24c053",
+ "03017550f2050653118444fc09e828f9d8d7fc6f245bd96ac82d20d4c40b31bb7d3237df3f22d129de5cebd8b91b1a69bb7050373532293bf35f66a06da43a95",
+ "",
+ "d4aa41c8434e57b47edf32f6cf6ed1bed6c383e898df44d84558837a0178af8b11417eda347fc40c678121bf0067eb4677a84f442fac0f3ada2412a69794c521b769a9e4a3b0c80bba876e96ac0eeb9194cb23669cfe964d087f33f4366d4bdd721907f828f383c11bb6d956d64db4a8eaad21ac20d2c31fc52f08d756be446b99",
+ "dd87e1b28bffc10ec0a4bd8e2808f003fdeefa822f25ccabb6a7d4c0381499ce4413de701771ab3172e4777ebdf1999d27dc1941a5c3cc0ac156b7cb67552a27",
+ "",
+ "f606ac7b059ba616ec1e952227f31cf0a83dcb66613c012cdea2a3776961f0efd398712051b7e7b8500ecbd030d2c6a0012b8eaeeabbcc0d6f1e03f4acf709b3bde30f4e8aa3ebb0e8f75158be727463e25d2b3f02db5cf3342581ce7279c118bb8b0d496b610c2d51967d12821cf86d796b7cd7ad2cbd5c0f165b232f281464e48f0b0d2577542ad3465bf6c063435390470388a27d938b113c74cf1d962c864f2971a0b18808649f978cc94de8b8f70fa5cf3ec0bad1a92499b68660c1fd2f809bb26aee29f93ab4484694506fae71d307ac45239a431f3f51285aba0dbd3afdae0231c4a1fc14b21ba2f1c27548d4c259544e80b94696da838ad6186b2e",
+ "800ab7f4817cf9a1a7d7d711ea097709ed18be383e7caaf6da72bc9e486dacb2894a3e20e0759cec7ec0550da76cf613d02e10ec2c4c697648998586d107ce64",
+ "",
+ "6ab33d45513b7013624e01e15f616a3436caa8813c863a13eb85e06a973f95204b265c9f76496407bdd1bd16b7f6ea3e97f3346e63d5e05f9896b1821e3dbe382a8849e3e27e05c8572140297d86473e720d62e6c7ef1766e4aff8313c688b6b91667b20ccfc055f0d7917eff1c713f3712d948055a3139e6d758a308322503f4f28977329a2153bd6a8c1d47e8877a4abfcef83cdff4daa74845384d8bdcac050bddc4bfa7cdc185d3b2528559936510bfe814ae162eaddf609992f6796654a59a66323292142ca499c44cb95bc308c10d44aa534066efb413fbd7e622fb2a2366b20439156728d7753c598106508878bbf4467d9c7812ea686683580365a50",
+ "ffb3011fcde35b8ff8c09a62fe02e7f17aefd1f458f3c01caa2d57b77699dd335f9670d359fc99c72b30ad3e92c9d39000b127967284cca14b759275531eaba2",
+};
+static size_t nb_sha512_hmac_vectors=45;
+static const char *sha512_hkdf_vectors[]={
+ "15b607ad7a0be00fab2b557e9a55ba304fe6d04e0e828ca83dbc4373ca84e59b220bb1a2e47c9a74bddcaad2db6239b4f538e12459bd9440d09644148e90c6d53b0d8c02eb9eeec77d33995008208f96a923d2702f69255be6d55e92f1c73353816b30ba59723c9e39f0941ef19ad6023eecd70d3295c0d05331b315caad52",
+ "01b56e40efba58a21e398e351e0c2600ef4a57e144bab0cdeb02c131c89ac632c222aa93994ae8042a68237a82abd2337be60e5fd85532ff68fdbada5f7215d974591123c90abd908d901c969445883ba195678158cca17c2bff4a33526da645bf61352d0567c1e5cf641f036f2d5ce7df45c894a8eca8882ff7905480f6c8",
+ "16a2ca0477d8d5c7531469ada982369eb3b2e27e537050af1fa7b82a16064396bb8cd0589d1be5850f22a168ef3753a3c43908047f67baaa851d4de0ed5f58b3c596d01387b44cd553f4211f285fdc27ae33661b32b10b7a1c729b26b2c23b8cda89d7a07543b6ce8a8600ed78205769f31952c9404e43570f06f5b0f8a85d",
+ "c3adb005347e78273a62a79d1be677fd6fef9875e18556daabc8b84cffa0a481f28d0f2d06e86cf2d36b8b2be83e75ea04ae33b621155fdce91734cf6a1ebfafead9a9f3503f11586809670edf031005c7399b8443675df1502ee1fa7f6729569113f15aceccf8e4cc456dae78740589d90dc5d7b8d839fe191fd267729e44",
+ "76f2008619c417a3b43f8225774a2f736d01931e17a36f436cc47af3e95bd0f5af832d45694a8be6a01e87217b87a8bb24c45f37b4a06e0ceb1b0af6b4e09346939e244b61b2fe471297db7eb27adb8e63086b8fc391c4dfc97e94c1d153866b268e497bf752a3980e9376c68acb2a0b7a13dbd9ad4f3702055b915af095ab4a",
+ "baff250589242160421dc33cef55a11962a28287beafacfd7c5ee112117beec1d1f24dd0ec42a495034cec9f74ac62e2b3524b5a9953666196065b85353486f680cc449fee5872f2ddff16341eb3f2d4afe083db244589f8160a678627f8ae17c3622aa7d6ff6b330245f93b5c51cc0b4a25faefe4e5b93478ca14105ef6b470",
+ "a2564fb6ccdc4cac30bca1b44d7be37c6c8ef7aa2de91b327c253a0a2a6c9b692a163d1442de8ddaee8eacba3d437e77c30089c14173c68c5622ac06ac00566d2702f38d6d72a0296bd4899172ac01c4e2b95da3d7299d48b555af8ad6644d9ec6399b18b85d4c79983e3ad238e7c9cfd923d0f37e810446a271bfe45b0648e7",
+ "c57429d66d9c29f977bf3cef2ffb1b3dde08e2ed19ac22ecce9cca0c3e0391d956d41759dd421d7fb4db8fbc6b7d9099547d92b26d214b20aeed8ff8622d66fed4b13a76e50eb452b782894b568fa9b16fc7bf4c86187c214d258846fb5ff4fb39d088b9b662d05a8bb37640a89d4ffb95a613aaa4efe589e315dbd3a71b3a96",
+ "5eedb3f58206d94977f1d3bbc8ca33c75d3fb51a0852a54861278fa7dce088be88c2c6530c6e6b69f61d1d3d8f9656dfb1039bdf76f9e5c7004c204dc6edcb921233bc331aff02d0f76cf2b0e2d6c971d000526dba8d9edacdf67314e42b263582f5236b38652c9aa0fb37629f1391798581bfa4c608b61ad2dd1aa1bfe0c1e5cc",
+ "55879d5e0164b75fc4cf92a55dccb2c2a5ecf783b73f5262e60a46b38c8c5f1c7374258b1f9bfdd0d62b37c1b074c16d83ba66ab8e51c9baa95f5e632978e1d512bf4582d2daa48d95ef9fe1e3fd0e250ed375c111f4efbbc4f16acad358c29d30a694305719f4a59ca964fb379caa654d1eba55f7fc68f9bb38e8d12b3a0e8207",
+ "55dd06136ae6732c4600b9a04cdb9362de8a19d9bbe2bee477eeba530c2552e1582714a10c96dc25496325ce16f60a5291e098cdb89fc9af488f92610aca213bf4716014fac914fdb976b4e3fc8f54cbf889584917faf47880a853879fa49d4f0ade8c81a27c8f28158479851bc9d52ca0a9068f339275875b6cb053b0e314fd9d",
+ "be696a270482f9f8f6bc3b9bbe4f91b1b6a857efb5b926e7a07cdb2cd7af9a4a65085f21afd7f781320cb79c65766922ffa2e08a5f9238d186e932ad50cfec5aa826acb2595580fcdc1e43d59d2df3d1ee00c2cf0729dabe12a2f330989169a515d1b9e8fcfdb33299a9b46710234c46defcc29f1ad58c66c8cc44663fc63f3108",
+};
+static size_t nb_sha512_hkdf_vectors=12;
+static const char *argon2_vectors[]={
+ "0100000000000000",
+ "0800000000000000",
+ "0300000000000000",
+ "0100000000000000",
+ "e4e4c4054fe35a75d9c0f679ad8770d8",
+ "227e68e4c1e68ce67ee88e6be251a207",
+ "",
+ "",
+ "2a2ec585be2ec27c215f677e947c212b1b85de797167d4950e29987977c941117c4c5f6f6f547e62d76b88fa121781986a37ea14dc394917af5396ea58915d",
+ "0100000000000000",
+ "1000000000000000",
+ "0300000000000000",
+ "0200000000000000",
+ "0101010101010101010101010101010101010101010101010101010101010101",
+ "02020202020202020202020202020202",
+ "0303030303030303",
+ "040404040404040404040404",
+ "a5a960b03adf92c4bc18628f1e23192d3544b91ab57024abc7dc3aed52b807d4",
+};
+static size_t nb_argon2_vectors=18;
+static const char *edDSA_vectors[]={
+ "50831c8cb43cd6822bf3f6fae0801cb6c843d8066b07346635365fb7d6ee54e5",
+ "b600ab324d70d2372f3ba5a0d8bdd8b8e797f780b642bd56e69a18db74c389bc",
+ "c9cd6f05d76b2bd4caec8d80b58235cb42",
+ "0bfa8d629fe89bd9591f20575144f0445958fd3574179ec4a9b6ee85787c23d69b4f009d3ed3bd2bb62226638602b95bc4719a1d2c60afb07ed95c959628ff0c",
+};
+static size_t nb_edDSA_vectors=4;
+static const char *edDSA_pk_vectors[]={
+ "e4e4c4054fe35a75d9c0f679ad8770d8227e68e4c1e68ce67ee88e6be251a207",
+ "61435d557c6bedda3b9d652b98982c227ffedb203fc2357cabe8075508f4e6f0",
+};
+static size_t nb_edDSA_pk_vectors=2;
+static const char *ed_25519_vectors[]={
+ "50831c8cb43cd6822bf3f6fae0801cb6c843d8066b07346635365fb7d6ee54e5",
+ "38bfc0b57ba86490aa2f41a3209e360ea4df055f22c07c7f54326d36780f42f6",
+ "c9cd6f05d76b2bd4caec8d80b58235cb42",
+ "428bda84b67e78d45c5531e194d1caee74b6242417c0237d34132546f7c0e70d8af611ef57248e0437241f5c3592063b5d13b94b78fadc39cf9a703a6920660a",
+};
+static size_t nb_ed_25519_vectors=4;
+static const char *ed_25519_check_vectors[]={
+ "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa",
+ "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f60",
+ "7bdc3f9919a05f1d5db4a3ada896094f6871c1f37afc75db82ec3147d84d6f237b7e5ecc26b59cfea0c7eaf1052dc427b0f724615be9c3d3e01356c65b9b5109",
+ "00",
+ "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa",
+ "ffffffffffffffffffffffffffffffff",
+ "5dbd7360e55aa38e855d6ad48c34bd35b7871628508906861a7c4776765ed7d1e13d910faabd689ec8618b78295c8ab8f0e19c8b4b43eb8685778499e943ae04",
+ "00",
+ "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa",
+ "3f",
+ "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "ff",
+};
+static size_t nb_ed_25519_check_vectors=12;
+static const char *x25519_vectors[]={
+ "e4e4c4054fe35a75d9c0f679ad8770d8227e68e4c1e68ce67ee88e6be251a207",
+ "6531e5010ab797ec0dc3c7038a94cbfcbb8ff1d1aad061b802b3c3232a42b352",
+ "600e94ef1d60878dd40c330704b7648bdd32901bbfdbdef0e59e600229384642",
+};
+static size_t nb_x25519_vectors=3;
+static const char *elligator_inv_vectors[]={
+ "2920d46f2f37b04d00ff73df4115fda3876810c2144e94a7e6d0c09290ff7359",
+ "d5",
+ "ff",
+ "00",
+ "70e7a067416c79ca10ea92e00b0e15cd50569e3298b6358ad6b016826b1a5b2b",
+ "dd",
+ "ff",
+ "00",
+ "89bbc72dc9f7f5b863489c606514a39f4e844061ba5c9dec8095fa8c8e657170",
+ "2e",
+ "ff",
+ "00",
+ "df1d73ff8919c4795a72077558dde8a99163591bfe015147548708e067f47e28",
+ "48",
+ "00",
+ "7c0e535eb69f95f02c4639e1d9668ce0c78b17d94e09a08756ec8ff266595076",
+ "c74d0b2a03a3e2d5138e4eb0378c1b13dc2dfe145b62fbd4bb476014bfcd4034",
+ "57",
+ "00",
+ "b48cfc36901caa3fd2d3997075c716b33165d7e60ed1770007289245d6a70946",
+ "3bd31879f188a6111d3633c8b1053138eaf8f11423c779f23288821b58181856",
+ "b6",
+ "00",
+ "19288fbd99b6a33e3374aed8faea2fb3356c2965c11ed9d09043b27f3d8f8796",
+ "a23740a8663e73d9b9e8c11fd0991efad5735f9533550b61a058b60acb3ada1f",
+ "13",
+ "00",
+ "34e6d2b0a37d4719a71b918a7095e42f7b2d0a51473704d2a942a10baee08705",
+ "3338ab54956d68a9186bdf5b97f03762bdde1551fde608885b035fc854177259",
+ "4e",
+ "00",
+ "43e97d6b5ddcf115d66341d293e627918299a171e04637f32b9b09505a971c64",
+ "06a64676b6b162cf03ae11efec6a07a8205638523ca2631519d18ba3a8858568",
+ "6b",
+ "00",
+ "d72d68c2e7f8fff0a946f8120b3004831e1e194369ae20d67cd1e1da3a534b54",
+ "77b951a3bf0ad919a950bcd1fdcffd2a659a1ce7d95557a71b9fc4cbd1ab3a65",
+ "a4",
+ "00",
+ "282ae366b62e6d3043735d989dfb7455bab90ba17018827c4df05b14c964d6af",
+ "f7d574f5cd7847043acc1f8cd2a4c1325e6a97281c099dac93ddc54fc0c63e0b",
+ "23",
+ "00",
+ "62323f31d49906ef7422aa0a3015491dd463ddbe0b440efeb9574277eab63d39",
+ "67e965bac8b9406bb5048c6e30b895e142424a54fcc0c2a21e45fa5a6ff96d45",
+ "12",
+ "00",
+ "92259700a11805a3a74e5fca9979ffb83853bba64d13398c0c8d0e577c3c4117",
+ "8199de6f012e0ca8ea05f1767592466cbdcd9c1402a727da4288a8d7075f6e21",
+ "05",
+ "00",
+ "318a4c9b941b54bb679e0ecbcfdf19abe2929143ed39abdad6e672d45edbcf34",
+ "5ba0832ca17067095ca32b74a0d134bd09b21b5dce536a4a1f3c41298c97893d",
+ "0c",
+ "00",
+ "1950ba33c7d6f56945fcf47ebaf88e003c34c2f70f080dbf410f8985440f2a0b",
+ "32d57bcd24f11916e7b96b7814598b15ea609258b40dde23eb0b64734878cf5f",
+ "49",
+ "00",
+ "c2d517d0bf0e573034ee0d297923b4965f6b75c6bc7888e0c8078e3a9fe92e74",
+ "aeb757f254b6dfe33e1df62e2d85c6fac47d5f3535f969de6882fac2bf0a4f19",
+ "9e",
+ "00",
+ "58daf8d2ab3bff7fd1d99e462b5b7bc34d63dafecf43c3bdf925d1f919216392",
+ "732f35e5f3fbac1edad39eef1c4633251d4b8a070712a91b1d4ab860ce68c16a",
+ "83",
+ "00",
+ "3f436796492ea02bb04fa7bee3d3c51b254c1003d943c984eb59a580a7e1ea84",
+ "9fa8d210f4e00b37444d24567e72d019e32f271954a080371a88875d4911555d",
+ "4a",
+ "00",
+ "515b649d380b9e4e3583025f360bf27331ce267f85f3509c10a0dc429ff39b60",
+ "af935c1ac0e61cdcaf16f8b2df6f6eed49805d5025ef6f2ddfe2bb358ab35e35",
+ "51",
+ "00",
+ "0892930b2fa529e56758523552d6cc33fe488f0a2d106124c1ded9c35d6c965b",
+};
+static size_t nb_elligator_inv_vectors=76;
+static const char *elligator_dir_vectors[]={
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "0000000000000000000000000000000000000000000000000000000000000040",
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "0000000000000000000000000000000000000000000000000000000000000080",
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "00000000000000000000000000000000000000000000000000000000000000c0",
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "673a505e107189ee54ca93310ac42e4545e9e59050aaac6f8b5f64295c8ec02f",
+ "242ae39ef158ed60f20b89396d7d7eef5374aba15dc312a6aea6d1e57cacf85e",
+ "922688fa428d42bc1fa8806998fbc5959ae801817e85a42a45e8ec25a0d7545a",
+ "696f341266c64bcfa7afa834f8c34b2730be11c932e08474d1a22f26ed82410b",
+ "0d3b0eb88b74ed13d5f6a130e03c4ad607817057dc227152827c0506a538bbba",
+ "0b00df174d9fb0b6ee584d2cf05613130bad18875268c38b377e86dfefef177f",
+ "01a3ea5658f4e00622eeacf724e0bd82068992fae66ed2b04a8599be16662ef5",
+ "7ae4c58bc647b5646c9f5ae4c2554ccbf7c6e428e7b242a574a5a9c293c21f7e",
+ "69599ab5a829c3e9515128d368da7354a8b69fcee4e34d0a668b783b6cae550f",
+ "09024abaaef243e3b69366397e8dfc1fdc14a0ecc7cf497cbe4f328839acce69",
+ "9172922f96d2fa41ea0daf961857056f1656ab8406db80eaeae76af58f8c9f50",
+ "beab745a2a4b4e7f1a7335c3ffcdbd85139f3a72b667a01ee3e3ae0e530b3372",
+ "6850a20ac5b6d2fa7af7042ad5be234d3311b9fb303753dd2b610bd566983281",
+ "1287388eb2beeff706edb9cf4fcfdd35757f22541b61528570b86e8915be1530",
+ "84417826c0e80af7cb25a73af1ba87594ff7048a26248b5757e52f2824e068f1",
+ "51acd2e8910e7d28b4993db7e97e2b995005f26736f60dcdde94bdf8cb542251",
+ "b0fbe152849f49034d2fa00ccc7b960fad7b30b6c4f9f2713eb01c147146ad31",
+ "98508bb3590886af3be523b61c3d0ce6490bb8b27029878caec57e4c750f993d",
+ "a0ca9ff75afae65598630b3b93560834c7f4dd29a557aa29c7becd49aeef3753",
+ "3c5fad0516bb8ec53da1c16e910c23f792b971c7e2a0ee57d57c32e3655a646b",
+};
+static size_t nb_elligator_dir_vectors=28;
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/tis-ci.c b/lib/Utils.Cryptography/monocypher/vendor/tests/tis-ci.c
new file mode 100644
index 0000000..2e6438e
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/tis-ci.c
@@ -0,0 +1,474 @@
+// This file is dual-licensed. Choose whichever licence you want from
+// the two licences listed below.
+//
+// The first licence is a regular 2-clause BSD licence. The second licence
+// is the CC-0 from Creative Commons. It is intended to release Monocypher
+// to the public domain. The BSD licence serves as a fallback option.
+//
+// SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+//
+// ------------------------------------------------------------------------
+//
+// Copyright (c) 2020, Mike Pechkin and Loup Vaillant
+// All rights reserved.
+//
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// ------------------------------------------------------------------------
+//
+// Written in 2017-2020 by Mike Pechkin and Loup Vaillant
+//
+// To the extent possible under law, the author(s) have dedicated all copyright
+// and related neighboring rights to this software to the public domain
+// worldwide. This software is distributed without any warranty.
+//
+// You should have received a copy of the CC0 Public Domain Dedication along
+// with this software. If not, see
+// <https://creativecommons.org/publicdomain/zero/1.0/>
+
+#include "monocypher.h"
+#include "monocypher-ed25519.h"
+#include "utils.h"
+#include "tis-ci-vectors.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static void chacha20(vector_reader *reader)
+{
+ vector key = next_input(reader);
+ vector nonce = next_input(reader);
+ vector plain = next_input(reader);
+ u64 ctr = load64_le(next_input(reader).buf);
+ vector out = next_output(reader);
+ u64 nb_blocks = plain.size / 64 + (plain.size % 64 != 0);
+ u64 new_ctr = crypto_chacha20_djb(out.buf, plain.buf, plain.size,
+ key.buf, nonce.buf, ctr);
+ if (new_ctr - ctr != nb_blocks) {
+ printf("FAILURE: Chacha20 returned counter not correct: ");
+ }
+}
+
+static void ietf_chacha20(vector_reader *reader)
+{
+ vector key = next_input(reader);
+ vector nonce = next_input(reader);
+ vector plain = next_input(reader);
+ u64 ctr = load64_le(next_input(reader).buf);
+ vector out = next_output(reader);
+ u32 nb_blocks = (u32)(plain.size / 64 + (plain.size % 64 != 0));
+ u32 new_ctr = crypto_chacha20_ietf(out.buf, plain.buf, plain.size,
+ key.buf, nonce.buf, (u32)ctr);
+ if (new_ctr - ctr != nb_blocks) {
+ printf("FAILURE: IETF Chacha20 returned counter not correct: ");
+ }
+}
+
+static void hchacha20(vector_reader *reader)
+{
+ vector key = next_input(reader);
+ vector nonce = next_input(reader);
+ vector out = next_output(reader);
+ crypto_chacha20_h(out.buf, key.buf, nonce.buf);
+}
+
+static void xchacha20(vector_reader *reader)
+{
+ vector key = next_input(reader);
+ vector nonce = next_input(reader);
+ vector plain = next_input(reader);
+ u64 ctr = load64_le(next_input(reader).buf);
+ vector out = next_output(reader);
+ u64 nb_blocks = plain.size / 64 + (plain.size % 64 != 0);
+ u64 new_ctr = crypto_chacha20_x(out.buf, plain.buf, plain.size,
+ key.buf, nonce.buf, ctr);
+ if (new_ctr - ctr != nb_blocks) {
+ printf("FAILURE: XChacha20 returned counter not correct: ");
+ }
+}
+
+static void poly1305(vector_reader *reader)
+{
+ vector key = next_input(reader);
+ vector msg = next_input(reader);
+ vector out = next_output(reader);
+ crypto_poly1305(out.buf, msg.buf, msg.size, key.buf);
+}
+
+static void aead_ietf(vector_reader *reader)
+{
+ vector key = next_input(reader);
+ vector nonce = next_input(reader);
+ vector ad = next_input(reader);
+ vector text = next_input(reader);
+ vector out = next_output(reader);
+ crypto_aead_lock(out.buf + 16, out.buf, key.buf, nonce.buf,
+ ad.buf, ad.size, text.buf, text.size);
+}
+
+static void blake2b(vector_reader *reader)
+{
+ vector msg = next_input(reader);
+ vector key = next_input(reader);
+ vector out = next_output(reader);
+ crypto_blake2b_keyed(out.buf, out.size,
+ key.buf, key.size,
+ msg.buf, msg.size);
+}
+
+static void sha512(vector_reader *reader)
+{
+ vector in = next_input(reader);
+ vector out = next_output(reader);
+ crypto_sha512(out.buf, in.buf, in.size);
+}
+
+static void sha512_hmac(vector_reader *reader)
+{
+ vector key = next_input(reader);
+ vector msg = next_input(reader);
+ vector out = next_output(reader);
+ crypto_sha512_hmac(out.buf, key.buf, key.size, msg.buf, msg.size);
+}
+
+static void sha512_hkdf(vector_reader *reader)
+{
+ vector ikm = next_input(reader);
+ vector salt = next_input(reader);
+ vector info = next_input(reader);
+ vector okm = next_output(reader);
+ crypto_sha512_hkdf(okm .buf, okm .size,
+ ikm .buf, ikm .size,
+ salt.buf, salt.size,
+ info.buf, info.size);
+}
+
+static void argon2(vector_reader *reader)
+{
+ crypto_argon2_config config;
+ config.algorithm = load32_le(next_input(reader).buf);
+ config.nb_blocks = load32_le(next_input(reader).buf);
+ config.nb_passes = load32_le(next_input(reader).buf);
+ config.nb_lanes = load32_le(next_input(reader).buf);
+
+ vector pass = next_input(reader);
+ vector salt = next_input(reader);
+ vector key = next_input(reader);
+ vector ad = next_input(reader);
+ vector out = next_output(reader);
+ void *work_area = alloc(config.nb_blocks * 1024);
+
+ crypto_argon2_inputs inputs;
+ inputs.pass = pass.buf;
+ inputs.salt = salt.buf;
+ inputs.pass_size = (u32)pass.size;
+ inputs.salt_size = (u32)salt.size;
+
+ crypto_argon2_extras extras;
+ extras.key = key.buf;
+ extras.ad = ad.buf;
+ extras.key_size = (u32)key.size;
+ extras.ad_size = (u32)ad.size;
+
+ crypto_argon2(out.buf, (u32)out.size, work_area, config, inputs, extras);
+ free(work_area);
+}
+
+static void x25519(vector_reader *reader)
+{
+ vector scalar = next_input(reader);
+ vector point = next_input(reader);
+ vector out = next_output(reader);
+ crypto_x25519(out.buf, scalar.buf, point.buf);
+}
+
+static void edDSA(vector_reader *reader)
+{
+ vector secret_k = next_input(reader);
+ vector public_k = next_input(reader);
+ vector msg = next_input(reader);
+ vector out = next_output(reader);
+ u8 fat_secret_key[64];
+ memcpy(fat_secret_key , secret_k.buf, 32);
+ memcpy(fat_secret_key + 32, public_k.buf, 32);
+ crypto_eddsa_sign(out.buf, fat_secret_key, msg.buf, msg.size);
+}
+
+static void edDSA_pk(vector_reader *reader)
+{
+ vector in = next_input(reader);
+ vector out = next_output(reader);
+ u8 seed [32];
+ u8 secret_key[64];
+ u8 public_key[32];
+ memcpy(seed, in.buf, 32);
+ crypto_eddsa_key_pair(secret_key, public_key, seed);
+ memcpy(out.buf, public_key, 32);
+
+ u8 zeroes[32] = {0};
+ ASSERT_EQUAL(seed , zeroes , 32);
+ ASSERT_EQUAL(secret_key , in.buf , 32);
+ ASSERT_EQUAL(secret_key + 32, public_key, 32);
+}
+
+static void ed_25519(vector_reader *reader)
+{
+ vector secret_k = next_input(reader);
+ vector public_k = next_input(reader);
+ vector msg = next_input(reader);
+ vector out = next_output(reader);
+ u8 fat_secret_key[64];
+ memcpy(fat_secret_key , secret_k.buf, 32);
+ memcpy(fat_secret_key + 32, public_k.buf, 32);
+ crypto_ed25519_sign(out.buf, fat_secret_key, msg.buf, msg.size);
+}
+
+static void ed_25519_check(vector_reader *reader)
+{
+ vector public_k = next_input(reader);
+ vector msg = next_input(reader);
+ vector sig = next_input(reader);
+ vector out = next_output(reader);
+ out.buf[0] = (u8)crypto_ed25519_check(sig.buf, public_k.buf,
+ msg.buf, msg.size);
+}
+
+static void elligator_dir(vector_reader *reader)
+{
+ vector in = next_input(reader);
+ vector out = next_output(reader);
+ crypto_elligator_map(out.buf, in.buf);
+}
+
+static void elligator_inv(vector_reader *reader)
+{
+ vector point = next_input(reader);
+ u8 tweak = next_input(reader).buf[0];
+ u8 failure = next_input(reader).buf[0];
+ vector out = next_output(reader);
+ int check = crypto_elligator_rev(out.buf, point.buf, tweak);
+ ASSERT((u8)check == failure);
+ if (check) {
+ out.buf[0] = 0;
+ }
+}
+
+//@ ensures \result == 0;
+static int p_wipe(void)
+{
+ printf("\tcrypto_wipe\n");
+ u8 zeroes[50] = {0};
+ FOR (i, 0, 50) {
+ RANDOM_INPUT(buf, 50);
+ crypto_wipe(buf, i);
+ ASSERT_EQUAL(zeroes, buf, i);
+ }
+ return 0;
+}
+
+//@ ensures \result == 0;
+static int p_eddsa_x25519(void)
+{
+ RANDOM_INPUT(e_seed, 32);
+ u8 secret [64];
+ u8 e_public1[32]; crypto_eddsa_key_pair(secret, e_public1, e_seed);
+ u8 x_private[64]; crypto_blake2b(x_private, 64, secret, 32);
+ u8 x_public1[32]; crypto_eddsa_to_x25519 (x_public1, e_public1);
+ u8 x_public2[32]; crypto_x25519_public_key(x_public2, x_private);
+ ASSERT_EQUAL(x_public1, x_public2, 32);
+
+ u8 e_public2[32]; crypto_x25519_to_eddsa (e_public2, x_public1);
+ ASSERT((e_public2[31] & 0x80) == 0); // x coordinate always positive
+
+ e_public1[31] &= 0x7f; // y coordinate back to original
+ ASSERT_EQUAL(e_public1, e_public2, 32);
+ return 0;
+}
+
+//@ ensures \result == 0;
+static int p_dirty(void)
+{
+ int status = 0;
+
+ RANDOM_INPUT(sk1, 32); sk1[0] |= 1; // make sure it's dirty
+ u8 skc [32]; memcpy(skc, sk1, 32); skc[0] &= 248; // make sure it's clean
+ u8 pks [32]; crypto_x25519_dirty_small(pks , sk1);
+ u8 pksc[32]; crypto_x25519_dirty_small(pksc, skc);
+ u8 pkf [32]; crypto_x25519_dirty_fast (pkf , sk1);
+ u8 pkfc[32]; crypto_x25519_dirty_fast (pkfc, skc);
+ u8 pk1 [32]; crypto_x25519_public_key (pk1 , sk1);
+
+ // Both dirty functions behave the same
+ status |= memcmp(pks, pkf, 32);
+
+ // Dirty functions behave cleanly if we clear the 3 msb first
+ status |= memcmp(pksc, pk1, 32);
+ status |= memcmp(pkfc, pk1, 32);
+
+ printf("%s: x25519 dirty\n", status != 0 ? "FAILED" : "OK");
+ return status;
+}
+
+//@ ensures \result == 0;
+static int p_x25519_inverse(void)
+{
+ int status = 0;
+ RANDOM_INPUT(b, 32);
+ u8 base[32]; // random point (cofactor is cleared).
+ crypto_x25519_public_key(base, b);
+ // check round trip
+ RANDOM_INPUT(sk, 32);
+ u8 pk [32];
+ u8 blind[32];
+ crypto_x25519(pk, sk, base);
+ crypto_x25519_inverse(blind, sk, pk);
+ status |= memcmp(blind, base, 32);
+
+ // check cofactor clearing
+ // (Multiplying by a low order point yields zero
+ u8 low_order[32] = {
+ 0x5f, 0x9c, 0x95, 0xbc, 0xa3, 0x50, 0x8c, 0x24,
+ 0xb1, 0xd0, 0xb1, 0x55, 0x9c, 0x83, 0xef, 0x5b,
+ 0x04, 0x44, 0x5c, 0xc4, 0x58, 0x1c, 0x8e, 0x86,
+ 0xd8, 0x22, 0x4e, 0xdd, 0xd0, 0x9f, 0x11, 0x57,
+ };
+ u8 zero[32] = {0};
+ crypto_x25519_inverse(blind, sk, low_order);
+ status |= memcmp(blind, zero, 32);
+ printf("%s: x25519_inverse\n", status != 0 ? "FAILED" : "OK");
+ return status;
+}
+
+//@ ensures \result == 0;
+static int p_verify(size_t size, int (*compare)(const u8*, const u8*))
+{
+ int status = 0;
+ u8 a[64]; // size <= 64
+ u8 b[64]; // size <= 64
+ FOR (i, 0, 2) {
+ FOR (j, 0, 2) {
+ // Set every byte to the chosen value, then compare
+ FOR (k, 0, size) {
+ a[k] = (u8)i;
+ b[k] = (u8)j;
+ }
+ int cmp = compare(a, b);
+ status |= (i == j ? cmp : ~cmp);
+ // Set only two bytes to the chosen value, then compare
+ FOR (k, 0, size / 2) {
+ FOR (l, 0, size) {
+ a[l] = 0;
+ b[l] = 0;
+ }
+ a[k] = (u8)i; a[k + size/2 - 1] = (u8)i;
+ b[k] = (u8)j; b[k + size/2 - 1] = (u8)j;
+ cmp = compare(a, b);
+ status |= (i == j ? cmp : ~cmp);
+ }
+ }
+ }
+ printf("%s: crypto_verify%zu\n", status != 0 ? "FAILED" : "OK", size);
+ return status;
+}
+//@ ensures \result == 0;
+static int p_verify16(void){ return p_verify(16, crypto_verify16); }
+//@ ensures \result == 0;
+static int p_verify32(void){ return p_verify(32, crypto_verify32); }
+//@ ensures \result == 0;
+static int p_verify64(void){ return p_verify(64, crypto_verify64); }
+
+#define TEST(name) \
+ int v_##name(void) { \
+ return vector_test(name, #name, nb_##name##_vectors, name##_vectors); \
+ }
+
+//@ ensures \result == 0;
+TEST(chacha20)
+//@ ensures \result == 0;
+TEST(ietf_chacha20)
+//@ ensures \result == 0;
+TEST(hchacha20)
+//@ ensures \result == 0;
+TEST(xchacha20)
+//@ ensures \result == 0;
+TEST(poly1305)
+//@ ensures \result == 0;
+TEST(aead_ietf)
+//@ ensures \result == 0;
+TEST(blake2b)
+//@ ensures \result == 0;
+TEST(sha512)
+//@ ensures \result == 0;
+TEST(sha512_hmac)
+//@ ensures \result == 0;
+TEST(sha512_hkdf)
+//@ ensures \result == 0;
+TEST(argon2)
+//@ ensures \result == 0;
+TEST(x25519)
+//@ ensures \result == 0;
+TEST(edDSA)
+//@ ensures \result == 0;
+TEST(edDSA_pk)
+//@ ensures \result == 0;
+TEST(ed_25519)
+//@ ensures \result == 0;
+TEST(ed_25519_check)
+//@ ensures \result == 0;
+TEST(elligator_dir)
+//@ ensures \result == 0;
+TEST(elligator_inv)
+
+//@ ensures \result == 0;
+int main(void) {
+ ASSERT(v_chacha20 () == 0);
+ ASSERT(v_ietf_chacha20 () == 0);
+ ASSERT(v_hchacha20 () == 0);
+ ASSERT(v_xchacha20 () == 0);
+ ASSERT(v_poly1305 () == 0);
+ ASSERT(v_aead_ietf () == 0);
+ ASSERT(v_blake2b () == 0);
+ ASSERT(v_sha512 () == 0);
+ ASSERT(v_sha512_hmac () == 0);
+ ASSERT(v_sha512_hkdf () == 0);
+ ASSERT(v_argon2 () == 0);
+ ASSERT(v_x25519 () == 0);
+ ASSERT(v_edDSA () == 0);
+ ASSERT(v_edDSA_pk () == 0);
+ ASSERT(v_ed_25519 () == 0);
+ ASSERT(v_ed_25519_check() == 0);
+ ASSERT(v_elligator_dir () == 0);
+ ASSERT(v_elligator_inv () == 0);
+
+ ASSERT(p_wipe () == 0);
+ ASSERT(p_eddsa_x25519 () == 0);
+ ASSERT(p_dirty () == 0);
+ ASSERT(p_x25519_inverse() == 0);
+ ASSERT(p_verify16 () == 0);
+ ASSERT(p_verify32 () == 0);
+ ASSERT(p_verify64 () == 0);
+ return 0;
+}
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/utils.c b/lib/Utils.Cryptography/monocypher/vendor/tests/utils.c
new file mode 100644
index 0000000..16c1d55
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/utils.c
@@ -0,0 +1,176 @@
+// This file is dual-licensed. Choose whichever licence you want from
+// the two licences listed below.
+//
+// The first licence is a regular 2-clause BSD licence. The second licence
+// is the CC-0 from Creative Commons. It is intended to release Monocypher
+// to the public domain. The BSD licence serves as a fallback option.
+//
+// SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+//
+// ------------------------------------------------------------------------
+//
+// Copyright (c) 2017-2019, 2023 Loup Vaillant
+// All rights reserved.
+//
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// ------------------------------------------------------------------------
+//
+// Written in 2017-2019, 2023 by Loup Vaillant
+//
+// To the extent possible under law, the author(s) have dedicated all copyright
+// and related neighboring rights to this software to the public domain
+// worldwide. This software is distributed without any warranty.
+//
+// You should have received a copy of the CC0 Public Domain Dedication along
+// with this software. If not, see
+// <https://creativecommons.org/publicdomain/zero/1.0/>
+
+#include "utils.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+u32 load32_le(const u8 s[4])
+{
+ return
+ ((u32)s[0] << 0) |
+ ((u32)s[1] << 8) |
+ ((u32)s[2] << 16) |
+ ((u32)s[3] << 24);
+}
+
+u64 load64_le(const u8 s[8])
+{
+ return load32_le(s) | ((u64)load32_le(s+4) << 32);
+}
+
+// Must be seeded with a nonzero value.
+// Accessible from the outside so we can modify it
+u64 random_state = 12345;
+
+// Pseudo-random 64 bit number, based on xorshift*
+u64 rand64(void)
+{
+ random_state ^= random_state >> 12;
+ random_state ^= random_state << 25;
+ random_state ^= random_state >> 27;
+ return random_state * 0x2545F4914F6CDD1D; // magic constant
+}
+
+void p_random(u8 *stream, size_t size)
+{
+ FOR (i, 0, size) {
+ stream[i] = (u8)rand64();
+ }
+}
+
+void* alloc(size_t size)
+{
+ if (size == 0) {
+ // Some systems refuse to allocate zero bytes.
+ // So we don't. Instead, we just return a non-sensical pointer.
+ // It shouldn't be dereferenced anyway.
+ return NULL;
+ }
+ void *buf = malloc(size);
+ ASSERT(buf != NULL);
+ return buf;
+}
+
+static int to_num(char c)
+{
+ return c >= '0' && c <= '9' ? c - '0'
+ : c >= 'a' && c <= 'f' ? c - 'a' + 10
+ : c - 'A' + 10;
+}
+
+static vector vector_of_string(const char *s)
+{
+ vector v;
+ v.size = strlen(s) / 2;
+ v.buf = v.size == 0 ? 0 : (u8*)alloc(v.size);
+ FOR (i, 0, v.size) {
+ int msb = to_num(*s); s++;
+ int lsb = to_num(*s); s++;
+ v.buf[i] = (u8)(msb * 16 + lsb);
+ }
+ return v;
+}
+
+vector next_input(vector_reader *reader)
+{
+ ASSERT(reader->size > 0);
+ ASSERT(reader->nb_inputs < 10);
+
+ const char *next = *(reader->next);
+ vector *input = reader->inputs + reader->nb_inputs;
+ reader->next++;
+ reader->size--;
+ *input = vector_of_string(next);
+ reader->nb_inputs++;
+ return *input;
+}
+
+vector next_output(vector_reader *reader)
+{
+ ASSERT(reader->size > 0);
+ ASSERT(reader->nb_inputs < 10);
+
+ const char *next = *(reader->next);
+ reader->next++;
+ reader->size--;
+ reader->expected = vector_of_string(next);
+ reader->out.size = reader->expected.size;
+ reader->out.buf = (u8*)alloc(reader->out.size);
+ return reader->out;
+}
+
+int vector_test(void (*f)(vector_reader*),
+ const char *name, size_t nb_vectors, const char *vectors[])
+{
+ int status = 0;
+ printf("\t%s\n", name);
+
+ vector_reader in;
+ in.size = nb_vectors;
+ in.next = vectors;
+
+ while (in.size > 0) {
+ in.nb_inputs = 0;
+ f(&in);
+ if (in.expected.size != 0) {
+ status |= memcmp(in.out.buf, in.expected.buf, in.expected.size);
+ }
+ FOR (i, 0, in.nb_inputs) {
+ free(in.inputs[i].buf);
+ }
+ free(in.out.buf);
+ free(in.expected.buf);
+ }
+ return status;
+}
diff --git a/lib/Utils.Cryptography/monocypher/vendor/tests/utils.h b/lib/Utils.Cryptography/monocypher/vendor/tests/utils.h
new file mode 100644
index 0000000..4588256
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vendor/tests/utils.h
@@ -0,0 +1,107 @@
+// This file is dual-licensed. Choose whichever licence you want from
+// the two licences listed below.
+//
+// The first licence is a regular 2-clause BSD licence. The second licence
+// is the CC-0 from Creative Commons. It is intended to release Monocypher
+// to the public domain. The BSD licence serves as a fallback option.
+//
+// SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+//
+// ------------------------------------------------------------------------
+//
+// Copyright (c) 2017-2019, 2023 Loup Vaillant
+// All rights reserved.
+//
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// ------------------------------------------------------------------------
+//
+// Written in 2017-2019, 2023 by Loup Vaillant
+//
+// To the extent possible under law, the author(s) have dedicated all copyright
+// and related neighboring rights to this software to the public domain
+// worldwide. This software is distributed without any warranty.
+//
+// You should have received a copy of the CC0 Public Domain Dedication along
+// with this software. If not, see
+// <https://creativecommons.org/publicdomain/zero/1.0/>
+
+#ifndef UTILS_H
+#define UTILS_H
+
+#include <inttypes.h>
+#include <stddef.h>
+
+typedef int8_t i8;
+typedef uint8_t u8;
+typedef uint32_t u32;
+typedef int32_t i32;
+typedef int64_t i64;
+typedef uint64_t u64;
+
+#define FOR(i, start, end) for (size_t i = (start); i < (end); i++)
+#define SODIUM_INIT ASSERT(sodium_init() != -1)
+#define RANDOM_INPUT(name, size) u8 name[size]; p_random(name, size)
+#define ASSERT(condition) do { \
+ if (!(condition)) { \
+ fprintf(stderr, "Assert failure(%s, %d): %s\n", \
+ __FILE__, __LINE__, #condition); \
+ exit(1); \
+ } \
+ } while (0)
+#define ASSERT_EQUAL(a, b, size) ASSERT(memcmp(a, b, size) == 0)
+#define ASSERT_DIFFERENT(a, b, size) ASSERT(memcmp(a, b, size) != 0)
+#define ASSERT_OK(exp) ASSERT((exp) == 0)
+#define ASSERT_KO(exp) ASSERT((exp) != 0)
+
+extern u64 random_state; // state of the RNG
+
+typedef struct {
+ u8 *buf;
+ size_t size;
+} vector;
+
+typedef struct {
+ const char **next;
+ size_t size;
+ vector inputs[10];
+ size_t nb_inputs;
+ vector expected;
+ vector out;
+} vector_reader;
+
+u64 load64_le(const u8 s[8]);
+u32 load32_le(const u8 s[4]);
+u64 rand64(void); // Pseudo-random 64 bit number, based on xorshift*
+void p_random(u8 *stream, size_t size);
+void* alloc(size_t size);
+
+vector next_input (vector_reader *vectors);
+vector next_output(vector_reader *vectors);
+int vector_test(void (*f)(vector_reader*),
+ const char *name, size_t nb_vectors, const char *vectors[]);
+
+#endif // UTILS_H
diff --git a/lib/Utils.Cryptography/monocypher/vnlib_monocypher.c b/lib/Utils.Cryptography/monocypher/vnlib_monocypher.c
new file mode 100644
index 0000000..7178ef1
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vnlib_monocypher.c
@@ -0,0 +1,119 @@
+/*
+* Copyright (c) 2023 Vaughn Nugent
+*
+* vnlib_monocypher is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published
+* by the Free Software Foundation, either version 2 of the License,
+* or (at your option) any later version.
+*
+* vnlib_monocypher is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with vnlib_monocypher. If not, see http://www.gnu.org/licenses/.
+*/
+
+
+#if 0
+#include <monocypher.h>
+#include "vnlib_monocypher.h"
+
+#define AEAD_MAX_NONCE_SIZE 24
+#define AEAD_MAX_KEY_SIZE 32
+
+#define AEAD_RESULT_SUCCESS 0
+
+typedef struct ChaChaStreamStruct {
+ uint8_t nonceCounter[8];
+ uint8_t secretKey[32];
+ uint8_t mac[16];
+} ChaChaStream;
+
+static int32_t _incrementNonce(ChaChaStream* stream)
+{
+ /*
+ * The once will be incremented by 1 for each call to lock/unlock
+ * if the nonce will overflow, then return 0 to indicate an error
+ */
+
+ VALIDATE_PTR(stream);
+
+ /* increment the nonce */
+
+ uint64_t* nonce;
+ uint64_t value;
+
+ nonce = (uint64_t*)stream->nonceCounter;
+ value = *nonce;
+
+ /* increment the nonce */
+ if(++value == 0)
+ {
+ /* nonce overflow */
+ return FALSE;
+ }
+
+ /* assign the value back */
+ *nonce = value;
+ return TRUE;
+}
+
+uint32_t AeadStreamStructSize(void)
+{
+ return sizeof(ChaChaStream);
+}
+
+int32_t AeadUpdateKey(ChaChaStream* stream, const uint8_t key[32])
+{
+ VALIDATE_PTR(stream);
+ VALIDATE_PTR(key);
+
+ /* copy the key to the structure key */
+ _memmove(stream->secretKey, key, 32);
+ return TRUE;
+}
+
+int32_t AeadUpdateMac(ChaChaStream* stream, const uint8_t mac[16])
+{
+ VALIDATE_PTR(stream);
+ VALIDATE_PTR(mac);
+
+ /* copy the mac to the structure mac */
+ _memmove(stream->mac, mac, 16);
+ return TRUE;
+}
+
+int32_t AeadInitStream(ChaChaStream* stream, const uint8_t key[32], const uint8_t startingNonce[8], const uint8_t mac[16])
+{
+ VALIDATE_PTR(stream);
+ VALIDATE_PTR(key);
+ VALIDATE_PTR(startingNonce);
+ VALIDATE_PTR(mac);
+
+ /* clear stream before using */
+ crypto_wipe(stream, sizeof(ChaChaStream));
+
+ /* copy the key to the structure key */
+ _memmove(stream->secretKey, key, 32);
+
+ /* copy the nonce to the structure nonce */
+ _memmove(stream->nonceCounter, startingNonce, 8);
+
+ /* copy the mac to the structure mac */
+ _memmove(stream->mac, mac, 16);
+ return TRUE;
+}
+
+int32_t AeadEncrypt(ChaChaStream* stream, const uint8_t* plainText, uint32_t plainTextSize, uint8_t* cipherText, uint8_t* tag)
+{
+ VALIDATE_PTR(stream);
+ VALIDATE_PTR(plainText);
+ VALIDATE_PTR(cipherText);
+ VALIDATE_PTR(tag);
+}
+
+#else
+typedef int something_to_stop_compiler_err_while_in_dev;
+#endif \ No newline at end of file
diff --git a/lib/Utils.Cryptography/monocypher/vnlib_monocypher.h b/lib/Utils.Cryptography/monocypher/vnlib_monocypher.h
new file mode 100644
index 0000000..920def9
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vnlib_monocypher.h
@@ -0,0 +1,24 @@
+/*
+* Copyright (c) 2023 Vaughn Nugent
+*
+* vnlib_monocypher is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published
+* by the Free Software Foundation, either version 2 of the License,
+* or (at your option) any later version.
+*
+* vnlib_monocypher is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with vnlib_monocypher. If not, see http://www.gnu.org/licenses/.
+*/
+
+#pragma once
+#ifndef VNLIB_MONOCYPHER_H
+#define VNLIB_MONOCYPHER_H
+
+#include "util.h"
+
+#endif \ No newline at end of file
diff --git a/lib/Utils.Cryptography/monocypher/vnlib_monocypher.vcxitems b/lib/Utils.Cryptography/monocypher/vnlib_monocypher.vcxitems
new file mode 100644
index 0000000..6fc55c7
--- /dev/null
+++ b/lib/Utils.Cryptography/monocypher/vnlib_monocypher.vcxitems
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup Label="Globals">
+ <MSBuildAllProjects Condition="'$(MSBuildVersion)' == '' Or '$(MSBuildVersion)' &lt; '16.0'">$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
+ <HasSharedItems>true</HasSharedItems>
+ <ItemsProjectGuid>{194aad38-05ab-4715-a367-190b3da78899}</ItemsProjectGuid>
+ </PropertyGroup>
+ <ItemDefinitionGroup>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory)</AdditionalIncludeDirectories>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ProjectCapability Include="SourceItemsFromImports" />
+ </ItemGroup>
+ <ItemGroup>
+ <Text Include="$(MSBuildThisFileDirectory)build.readme.txt" />
+ <Text Include="$(MSBuildThisFileDirectory)CMakeLists.txt" />
+ <Text Include="$(MSBuildThisFileDirectory)license.txt" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="$(MSBuildThisFileDirectory)vnlib_rpmalloc.c" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="$(MSBuildThisFileDirectory)package.json" />
+ <None Include="$(MSBuildThisFileDirectory)Taskfile.yaml" />
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/lib/Utils/README.md b/lib/Utils/README.md
index 29ccc50..f5b1244 100644
--- a/lib/Utils/README.md
+++ b/lib/Utils/README.md
@@ -29,9 +29,8 @@ The software in this repository is licensed under the GNU GPL version 2.0 (or an
- VNLib.Utils.Resources - Abstractions and base data structures for holding and accessing resources.
## Recommended 3rd Party Libs
-This library does not require any direct dependencies, however there are some optional ones that are recommended for higher performance. This library does not, modify, contribute, or affect the functionality of any of the 3rd party libraries recommended below.
-
-[**RPMalloc**](https://github.com/mjansson/rpmalloc) By Mattias Jansson - VNlib.Utils.Memory (and sub-classes) may load and bind function calls to this native library determined by environment variables. To use RPMalloc as the default unmanaged allocator simply add the dynamic library to the native lib search path, such as in the executable directory, and set the allocator environment variable as instructed below. I maintain a compatible Windows x64 [dll library](../WinRpMalloc/README.md) on my website and in this repository, that conforms to the [NativeHeap](../NativeHeapApi/README.md) api required for runtime loading.
+The [Utils.Memory](../Utils.Memory) namespace includes vendored and wrapped versions of recommended unmanaged heap allocator libraries to link at runtime.
+Read [this document](https://www.vaughnnugent.com/resources/software/articles?tags=docs&search=native+heap) for more information on vendored libraries and instructions on how to build them.
## Other notes
Generally for internal library data structures that require memory allocation, a constructor override or a static method will consume a heap instance so you may pass your own heap instance or the Shared heap.
diff --git a/lib/Utils/src/Async/AsyncAccessSerializer.cs b/lib/Utils/src/Async/AsyncAccessSerializer.cs
index 83cc127..76532bc 100644
--- a/lib/Utils/src/Async/AsyncAccessSerializer.cs
+++ b/lib/Utils/src/Async/AsyncAccessSerializer.cs
@@ -235,7 +235,7 @@ namespace VNLib.Utils.Async
wait = new();
}
- //Init wait with session
+ //Init wait with moniker
wait.Prepare(moniker);
}
@@ -246,7 +246,7 @@ namespace VNLib.Utils.Async
/// <param name="entry">The entry to return to the pool</param>
protected virtual void ReturnEntry(WaitEntry entry)
{
- //Remove session ref
+ //Remove ref
entry.Prepare(default);
if (EntryPool.Count < MaxPoolSize)
@@ -391,7 +391,7 @@ namespace VNLib.Utils.Async
/// <summary>
/// Prepres a new <see cref="WaitEntry"/> for
- /// its new session.
+ /// its new moniker object.
/// </summary>
/// <param name="moniker">The referrence to the moniker to hold</param>
public void Prepare(TMoniker? moniker)
@@ -516,15 +516,13 @@ namespace VNLib.Utils.Async
* will be thrown if this doesnt work
*/
- if (_nextWaiter.Status == TaskStatus.Created)
+ switch (_nextWaiter.Status)
{
- _nextWaiter.Start();
- return true;
- }
-
- if(_nextWaiter.Status == TaskStatus.Canceled)
- {
- return false;
+ case TaskStatus.Canceled:
+ return false;
+ case TaskStatus.Created:
+ _nextWaiter.Start();
+ return true;
}
Debug.Fail($"Next waiting task is in an invalid state: {_nextWaiter.Status}");
diff --git a/lib/Utils/src/VnEncoding.cs b/lib/Utils/src/VnEncoding.cs
index 9eb60df..3e895bc 100644
--- a/lib/Utils/src/VnEncoding.cs
+++ b/lib/Utils/src/VnEncoding.cs
@@ -587,16 +587,31 @@ namespace VNLib.Utils
* intial buffer, we get the exact size of the buffer needed to
* percent encode.
*/
-
int count = 0, len = utf8Bytes.Length;
+
fixed (byte* utfBase = &MemoryMarshal.GetReference(utf8Bytes))
{
- //Find all unsafe characters and add the entropy size
- for (int i = 0; i < len; i++)
+ if (allowedChars.IsEmpty)
{
- if (!IsUrlSafeChar(utfBase[i], allowedChars))
+ //Find all unsafe characters and add the entropy size
+ for (int i = 0; i < len; i++)
{
- count += 2;
+ if (!IsUrlSafeChar(utfBase[i]))
+ {
+ count += 2;
+ }
+ }
+ }
+ else
+ {
+ //Find all unsafe characters and add the entropy size
+ for (int i = 0; i < len; i++)
+ {
+ //Check if value is url safe or is allowed by the allowed chars argument
+ if (!(IsUrlSafeChar(utfBase[i]) || allowedChars.Contains(utfBase[i])))
+ {
+ count += 2;
+ }
}
}
}
@@ -617,30 +632,57 @@ namespace VNLib.Utils
int outPos = 0, len = utf8Bytes.Length;
ReadOnlySpan<byte> lookupTable = HexToUtf8Pos.Span;
- for (int i = 0; i < len; i++)
+ if (allowedChars.IsEmpty)
{
- byte value = utf8Bytes[i];
- //Check if value is url safe
- if(IsUrlSafeChar(value, allowedChars))
+ for (int i = 0; i < len; i++)
{
- //Skip
- utf8Output[outPos++] = value;
+ byte value = utf8Bytes[i];
+ //Check if value is url safe
+ if (IsUrlSafeChar(value))
+ {
+ //Skip
+ utf8Output[outPos++] = value;
+ }
+ else
+ {
+ //Percent encode
+ utf8Output[outPos++] = 0x25; // '%'
+ //Calc and store the encoded by the upper 4 bits
+ utf8Output[outPos++] = lookupTable[(value & 0xf0) >> 4];
+ //Store lower 4 bits in encoded value
+ utf8Output[outPos++] = lookupTable[value & 0x0f];
+ }
}
- else
+ }
+ else
+ {
+ for (int i = 0; i < len; i++)
{
- //Percent encode
- utf8Output[outPos++] = 0x25; // '%'
- //Calc and store the encoded by the upper 4 bits
- utf8Output[outPos++] = lookupTable[(value & 0xf0) >> 4];
- //Store lower 4 bits in encoded value
- utf8Output[outPos++] = lookupTable[value & 0x0f];
+ byte value = utf8Bytes[i];
+ //Check if value is url safe
+ if (IsUrlSafeChar(value) || allowedChars.Contains(value))
+ {
+ //Skip
+ utf8Output[outPos++] = value;
+ }
+ else
+ {
+ //Percent encode
+ utf8Output[outPos++] = 0x25; // '%'
+ //Calc and store the encoded by the upper 4 bits
+ utf8Output[outPos++] = lookupTable[(value & 0xf0) >> 4];
+ //Store lower 4 bits in encoded value
+ utf8Output[outPos++] = lookupTable[value & 0x0f];
+ }
}
}
+
//Return the size of the output buffer
return outPos;
}
- private static bool IsUrlSafeChar(byte value, ReadOnlySpan<byte> allowedChars)
+
+ private static bool IsUrlSafeChar(byte value)
{
return
// base10 digits
@@ -652,9 +694,8 @@ namespace VNLib.Utils
// Uppercase letters
|| value > 0x40 && value < 0x5b
// lowercase letters
- || value > 0x60 && value < 0x7b
- // Check allowed characters
- || allowedChars.Contains(value);
+ || value > 0x60 && value < 0x7b;
+
}
//TODO: Implement decode with better performance, lookup table or math vs searching the table
@@ -998,7 +1039,6 @@ namespace VNLib.Utils
Base64ToUrlSafeInPlace(nonPadded);
return nonPadded.Length;
}
-
}
/// <summary>
@@ -1103,11 +1143,26 @@ namespace VNLib.Utils
/// <returns>The number characters written to the buffer, or <see cref="ERRNO.E_FAIL"/> if a error occured.</returns>
public static ERRNO Base64UrlEncode(ReadOnlySpan<byte> input, Span<byte> output, bool includePadding)
{
- //Write the input buffer to the output buffer
- input.CopyTo(output);
+ //Do bsae64 encoding avoiding the tripple copy
+ if (Base64.EncodeToUtf8(input, output, out _, out int bytesWritten) != OperationStatus.Done)
+ {
+ return ERRNO.E_FAIL;
+ }
+
+ if (includePadding)
+ {
+ //Url encode in place
+ Base64ToUrlSafeInPlace(output[..bytesWritten]);
+ return bytesWritten;
+ }
+ else
+ {
+ //Remove padding bytes from base64 encode
+ Span<byte> nonPadded = output[..bytesWritten].TrimEnd((byte)0x3d);
- //encode in place
- return Base64UrlEncodeInPlace(output, input.Length, includePadding);
+ Base64ToUrlSafeInPlace(nonPadded);
+ return nonPadded.Length;
+ }
}
/// <summary>