diff options
Diffstat (limited to 'lib/Utils.Cryptography/monocypher')
174 files changed, 33529 insertions, 0 deletions
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)' < '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 |